#emc-devel | Logs for 2008-01-29

[00:10:15] <micges> alex_joni: hi
[02:23:12] <jmkasunich> there - complete builds for all 4 systems on the farm site now
[02:23:28] <jmkasunich> so anyone who wants to count warnings can knock themselves out
[02:25:14] <SWPadnos> hmmm. there are a rash of linker warnings when you do an incremental build - missing symbols and the like
[02:25:31] <SWPadnos> (I don't remember the warnings exactly, but I remember seeing them when building the power supply code)
[03:02:09] <cradek> jepler: I think your program doesn't make a hexagon - distances from center to the corners aren't all the same
[03:02:26] <SWPadnos> it's six sided though
[03:02:36] <jepler> cradek: yeah I probably need sqrt(3)/2 in there somewhere
[03:02:45] <jepler> bah, I did the hard part :-P now you savage me in public for making a tiny error
[03:02:53] <SWPadnos> heh
[03:06:00] <SWPadnos_> SWPadnos_ is now known as SWPLinux
[03:19:17] <SWPLinux> this may seem like a stupid question, but how do you get a debug build? make -V or similar?
[03:19:30] <jmkasunich> a debug build?
[03:19:38] <cradek> I think emc is always built with -g
[03:19:41] <SWPLinux> verbose build output
[03:19:50] <cradek> oh
[03:19:50] <SWPLinux> oh, is that stuff just in a log file then?
[03:19:50] <jmkasunich> the output from the farm is verbose
[03:20:01] <SWPLinux> the output from acemi is more verbose
[03:20:12] <jmkasunich> thats cause he used a 4.x gcc
[03:20:25] <SWPLinux> no, I think it's in the build system
[03:20:29] <jmkasunich> (I've been unable to open his log file, so I can't actually see the details)
[03:20:45] <jmkasunich> well, those 2000 warnings are almost certainly a gcc version thing
[03:20:45] <SWPLinux> weird - I've loaded it here twice, on two different computers
[03:20:58] <SWPLinux> they're mostly a c++ warning
[03:22:01] <jmkasunich> the same "mistake" in 2000 places?
[03:23:30] <SWPLinux> http://www.linuxcnc.org/wiki/uploads/emc_make.log
[03:23:35] <SWPLinux> yes, many were
[03:23:50] <SWPLinux> there aer a few problems with .c files - pci_find_device and a couple of constant redefinitions
[03:23:51] <SWPLinux> are
[03:24:05] <cradek> jmkasunich: yes it's almost entirely one warning
[03:24:23] <cradek> emc/rs274ngc/rs274ngc_pre.cc:206: warning: deprecated conversion from string constant to ‘char*’
[03:24:50] <jmkasunich> heh, the first instances of the string constant conversion warning are in libnml
[03:24:51] <cradek> strange - sometimes it prints the same warning dozens/hundreds of times for the same line of code
[03:24:52] <SWPLinux> I think that needs const char * msg in all those places, but I want to see the warnings before I test that change
[03:25:37] <jmkasunich> cradek: where are you seeing multiple messages for the same line?
[03:25:47] <SWPLinux> I see a lot of them for different lines in the same file, but no duplicates jump out at me
[03:26:03] <cradek> emc/rs274ngc/rs274ngc_errors.cc:274: warning: deprecated conversion from string constant to ‘char*’
[03:26:10] <jmkasunich> I supposed there might be lines like "char *foo="FOO", *bar="BAR";
[03:26:50] <jmkasunich> I bet you line 274 defines an array of char * with a bunch of error messages in it
[03:26:57] <cradek> chris@rover:~/Desktop$ zgrep warning emc_make.log.gz |sort|uniq -c|sort -n|tail -3
[03:27:00] <cradek> 58 emc/usr_intf/axis/extensions/emcmodule.cc:399: warning: deprecated conversion from string constant to ‘char*’
[03:27:03] <cradek> 77 emc/usr_intf/emcrsh.cc:475: warning: deprecated conversion from string constant to ‘char*’
[03:27:06] <cradek> 241 emc/rs274ngc/rs274ngc_errors.cc:274: warning: deprecated conversion from string constant to ‘char*’
[03:27:35] <cradek> no wonder they add up to thousands
[03:27:38] <SWPLinux> hmmm. that part isn't built with kbuild
[03:28:23] <jmkasunich> rs274ngc_errors.cc is exactly what I thought
[03:28:31] <jmkasunich> char * _rs274ngc_errors[] = {
[03:28:51] <SWPLinux> /* insert 1 line for each numbered error code */
[03:30:00] <jmkasunich> I suggest that we insert a compiler flag to turn off that warning
[03:30:00] <cradek> so we could fix it by sprinkling some consts here and there, or wait until the 'fixed' compiler turns that warning back off?
[03:30:20] <cradek> jmkasunich: did you see http://www.mail-archive.com/debian-gcc@lists.debian.org/msg26242.html
[03:30:34] <SWPLinux> consts aren't incorrect, and would make sure that any future compiler shouldn't emit those warnings
[03:31:39] <jepler> jmkasunich: that's what I tried in http://pastebin.ca/876837 but acemi reported it didn't help
[03:31:47] <jmkasunich> cradek: I saw the bug report, you pointed me at something that says its fixed?
[03:31:59] <cradek> oh guess so
[03:32:00] <jepler> SWPLinux: I agree, anybody who wants to add consts to 2.3/TRUNK should go ahead
[03:32:03] <cradek> I clicked ... something
[03:32:24] <SWPLinux> I'm willing, but I need to be able to see a log similar to acemi's before I'll start that
[03:32:25] <cradek> I guess it was a bug that anyone who didn't ask for it ever saw that warning
[03:32:49] <jmkasunich> these words make me think just adding const isn't the answer: "These warnings will help you find at compile time code
[03:32:49] <jmkasunich> #
[03:32:49] <jmkasunich> that can try to write into a string constant, but only if you have
[03:32:49] <jmkasunich> #
[03:32:49] <jmkasunich> been very careful about using `const' in declarations and
[03:32:51] <jmkasunich> #
[03:32:53] <jmkasunich> prototypes. "
[03:32:56] <cradek> because it's just "a nuisance" (says the gcc info)
[03:33:20] <jepler> ah, I spotted the typo in my patch -- write-strings, not write_strings
[03:33:22] <jmkasunich> we have NOT been "very carefull" about using const in declarations and prototypes, and will be seeing this stupid warning for years if we attack them one at a time
[03:33:25] <cradek> down the const path may lie madness, but anyone should feel free to try it
[03:33:27] <jepler> SWPLinux: try adding -Wwrite-strings to DEBUG
[03:33:32] <SWPLinux> ok
[03:34:31] <SWPLinux> yay - thanks :)
[03:34:49] <jmkasunich> that made it better?
[03:35:02] <SWPLinux> that made me see the warnings
[03:35:10] <SWPLinux> so now I know if I'm getting rid of them
[03:35:33] <jmkasunich> are you getting rid of them by adding const in places, or by turning off the warning in the makefile?
[03:36:03] <SWPLinux> I turned on the warning so I could see that const (or whatever) fixes the source of the problem
[03:36:13] <jmkasunich> I have a bad feeling about const
[03:36:18] <SWPLinux> so I'm fixing the code
[03:36:31] <jmkasunich> I don't think its gonna fix anything
[03:36:34] <SWPLinux> no - c++ needs it because the compiler won't let you write to a const char *
[03:36:36] <SWPLinux> it'
[03:36:41] <jmkasunich> you won't get a complaint when you are declaring things
[03:36:44] <SWPLinux> it's the correct way to get rid of that warning
[03:37:00] <jmkasunich> but you will get a complaint when you pass one of those const char * to a function that takes char *
[03:37:07] <jepler> jmkasunich: yes, you will
[03:37:08] <SWPLinux> no - the warning is when you declare a char * then assign a string literal to it
[03:37:11] <cradek> that's what I meant by madness
[03:37:29] <jmkasunich> SWPLinux: I'm not communicating the issue very well
[03:37:40] <SWPLinux> no no - the form I saw was a local variable that was not declared const, but was assigned to a literal
[03:37:40] <cradek> jmkasunich: he'll see soon enough :-)
[03:37:41] <jmkasunich> yes, you will make the original warning go away (the one at the declaration)
[03:37:55] <SWPLinux> I know what you're saying, and I don't have an answer for that yet ;)
[03:37:57] <jmkasunich> you will just cause warnings elsewhere, where the declared objects are used
[03:38:17] <SWPLinux> look at libnml/inifile/inifile.cc:541
[03:38:29] <SWPLinux> that's the kind of warning that can be trivially fixed with const
[03:38:38] <SWPLinux> and there are a lot of them
[03:38:55] <SWPLinux> so that's the solution to some fraction of the "problems"
[03:39:15] <jmkasunich> I assume that fprintf is declared to accept const char *, not char *?
[03:39:35] <SWPLinux> I think it can accept either, but I'm not sure
[03:39:38] <jmkasunich> oh, nevermind, fprintf uses va_args, you could pass it anything
[03:39:42] <SWPLinux> right
[03:39:42] <jepler> jmkasunich: yes if the header files are ANSI C compliant
[03:40:06] <jmkasunich> ok, I agree that the "right" thing is to add const
[03:40:29] <jmkasunich> but I'm afraid we'll find ourselves fixing a lot of function prototypes right after we get done adding const
[03:40:56] <SWPLinux> heh - that would need to be part of the same patch, so fear not - it won't be any worse once I start than it is now
[03:41:07] <cradek> (everyone remember that our very knowledge of the existence of this warning is because of a compiler bug)
[03:41:11] <SWPLinux> and it's only bad now if you explicitly turn that warning on, or you have a buggy compiler
[03:41:12] <jmkasunich> this seems like divisible labor
[03:41:26] <SWPLinux> heh - yep
[03:41:39] <jmkasunich> IOW, tell me a file or group of files that you _aren't_ gonna touch
[03:42:05] <SWPLinux> oh - I don't know yet. I can tell you soon though
[03:42:17] <jmkasunich> what about rs274_errors?
[03:42:25] <jmkasunich> I can fix that, and chase down anything that fix breaks
[03:42:32] <SWPLinux> I'll take a look - I haven't opened that file yet
[03:42:34] <SWPLinux> ok
[03:42:41] <jmkasunich> don't open it, leave that one for me
[03:42:43] <SWPLinux> ok
[03:42:57] <SWPLinux> I'll start in the libnml files
[03:43:41] <SWPLinux> ok, what am I doing wrong: make -j8 2>&1 > make.log
[03:43:53] <SWPLinux> shouldn't that capture stderr to the log file as well?
[03:44:20] <cradek> >log 2>&1
[03:44:33] <SWPLinux> ?
[03:44:46] <jepler> || emc/usr_intf/emcsh.cc: In function 'int emc_plat(void*, Tcl_Interp*, int, Tcl_Obj* const*)':
[03:44:49] <jepler> Here's a problem
[03:44:51] <jepler> /home/jepler/emc2.src/src/emc/usr_intf/emcsh.cc|378| warning: deprecated conversion from string constant to 'char*''
[03:44:54] <jepler> the source code line is:
[03:44:57] <jepler> Tcl_SetResult(interp, "Linux", TCL_VOLATILE);
[03:45:07] <jepler> but Tcl_SetResult apparently doesn't specify the argument to be of type 'const char *'
[03:45:53] <jmkasunich> and since we don't own Tcl_SetResult, we can't fix that
[03:46:04] <jmkasunich> there's a reason -Wall doesn't turn on that warning
[03:46:28] <jepler> (though some TCL APIs modify the string arguements just to be surprising, I don't think that is one; Tcl_Eval is)
[03:47:18] <SWPLinux> some type of cast (static_cast<> probably) should fix that
[03:47:34] <SWPLinux> but that's a royal PITA if it occurs in many places
[03:47:54] <cradek> madddddddness
[03:47:58] <SWPLinux> heh
[03:48:00] <jepler> http://www.tcl.tk/cgi-bin/tct/tip/27.html
[03:48:01] <SWPLinux> preciousssss
[03:48:01] <cradek> just stop
[03:49:49] <jmkasunich> I think we should turn that warning off in the makefile, with a note that it is supposed to be off but some buggy compilers turn it on
[03:50:05] <jmkasunich> instead of touching the code in dozens or hundreds of places
[03:50:10] <SWPLinux> that's the easy way, and in many places it will be the best way
[03:50:15] <cradek> as you might guess, I agree
[03:50:18] <jepler> the documentation says it is turned off by default :-P
[03:50:28] <cradek> even with -Wall
[03:50:32] <SWPLinux> heh - yeah, I had to turn it on :)
[03:50:32] <jepler> I think that with the - instead of _ fix, though, that it might be "fixed" on acemi's system
[03:50:32] <jmkasunich> so it is clearly a compiler bug
[03:50:43] <jmkasunich> workarounds for bugs in specific compiler versions are NOT a cop-out
[03:50:44] <jepler> 'night all
[03:50:50] <jepler> (did I say that already once?)
[03:50:55] <cradek> g'night
[03:51:01] <jmkasunich> goodnight
[03:51:02] <SWPLinux> it is, but it also shows a possible coding error - it is legal to write to a char *, whereas in c++, it's not legal to write to a const char *
[03:51:09] <SWPLinux> see you jepler
[03:51:55] <jmkasunich> SWPLinux: did you read http://www.tcl.tk/cgi-bin/tct/tip/27.html
[03:52:05] <SWPLinux> yes, the first part anyway
[03:52:16] <jmkasunich> this is not a new issue - and there are libraries that we have no control over that will continue to spew warnings no matter what you do
[03:52:27] <SWPLinux> I understand
[03:52:45] <SWPLinux> I added const to line 541 in inifile.cc, and it fixed the problem there
[03:53:05] <SWPLinux> for the files where it's an easy fix, I'll do that (shouldn't be more than 20 or so lines to change, I think)
[03:53:11] <jmkasunich> that only leaves 2299 other places to fix
[03:53:34] <SWPLinux> if the only fix for other places is const_cast<char*>(blah), I'll leave those alone
[03:53:50] <SWPLinux> I'd rather fix as much as possible, then turn off the warning ;)
[03:54:06] <jmkasunich> there are literally hundreds of them
[03:54:16] <jmkasunich> the places where one line will fix a bunch are few and far between
[03:54:23] <SWPLinux> one down, hundreds to go ;)
[03:54:49] <cradek> you know that will mean you are the last one who touched all that very old source code
[03:54:59] <SWPLinux> hmmm. good point
[03:56:06] <SWPLinux> turning off a warning in these simple cases just seems wrong though:
[03:56:14] <SWPLinux> --- libnml/inifile/inifile.cc 23 Jun 2007 23:36:18 -0000 1.27
[03:56:16] <SWPLinux> +++ libnml/inifile/inifile.cc 29 Jan 2008 03:55:43 -0000
[03:56:18] <SWPLinux> @@ -534,7 +534,7 @@
[03:56:19] <SWPLinux> void
[03:56:22] <SWPLinux> IniFile::Exception::Print(FILE *fp)
[03:56:23] <SWPLinux> {
[03:56:25] <SWPLinux> - char *msg;
[03:56:27] <SWPLinux> + const char *msg;
[03:56:29] <SWPLinux> switch(errCode){
[03:56:31] <SWPLinux> case ERR_NONE:
[04:00:55] <Roguish_> 'motion delay in spindle startup' --->>>> classicladder
[04:01:20] <jmkasunich> yes, but it would need some request/reply hooks to connect that to EMC itself
[04:02:25] <SWPLinux> you could emulate that with the "wait for input" M codes
[04:02:29] <Roguish_> on my old mill, i just use a preset time amount ~~~ 5 seconds.
[04:02:36] <Roguish_> no big deal.
[04:02:45] <cradek> does your spindle drive have an "at speed" output? that's the real answer
[04:02:53] <Roguish_> no.
[04:03:04] <SWPLinux> window comparator and feedback could provide that in HAL
[04:03:10] <cradek> also true
[04:03:16] <jmkasunich> SWPLinux: I'm guessing the original poster wanted it automatic, not in the g-code
[04:03:26] <jmkasunich> otherwise, just use G4 delays
[04:03:31] <SWPLinux> yep - I figured that as well
[04:03:42] <SWPLinux> M66 or whatever would actually wait until the spindle is at speed though
[04:03:48] <SWPLinux> rather than a preset amount
[04:03:54] <jmkasunich> as long as they remember to use it
[04:03:57] <SWPLinux> heh
[04:04:08] <Roguish_> ya only forget once....
[04:04:22] <cradek> doesn't belong in the gcode
[04:04:44] <cradek> (heh, I use G4)
[04:04:47] <SWPLinux> no - we had discussed adding a spindle-at-speed input pin
[04:04:58] <cradek> 's1000 m3 g4 p1'
[04:05:18] <SWPLinux> but there are potential problems, like if you change speeds during a move
[04:05:34] <SWPLinux> (the machine would try to halt then continue, rather than decel/accel smoothly)
[04:06:04] <jmkasunich> you mean if you tied it to feedhold?
[04:06:17] <SWPLinux> hmmm. (char *) seems to work instead of const_cast< char * >("blah")
[04:06:22] <jmkasunich> I'm thinking more of a "spindle-run" from EMC, and a "spindle-running" into EMC
[04:06:28] <SWPLinux> jmkasunich: yes - that would be the default thing to do
[04:06:43] <cradek> I bet there's a warning you could turn on that would bug you about C-style casts too
[04:06:48] <jmkasunich> tie them together by default, use a delay or ladder or at-speed or whatever floats your boat
[04:06:51] <SWPLinux> heh - probably ;)
[04:06:59] <Roguish_> that's why it's hardwired (or hard timed) outside of gcode
[04:07:50] <SWPLinux> CL or HAL blocks could also assert feedhold only when the spindle is turned on (off->on transitions), rather than for any speed change where at-speed may go false
[04:08:34] <jmkasunich> well, if we had "spindle-run" and "spindle-running", then a canonical "start spindle" command wouldn't return until running became true
[04:08:52] <jmkasunich> and "stop spindle" wouldn't return until it became false
[04:08:57] <jmkasunich> the rest of the time it would be ignored
[04:09:18] <SWPLinux> sure - so as long as "running" means "at speed" for that command, it would be fine
[04:09:35] <jmkasunich> what running means is up to the integrator
[04:09:48] <SWPLinux> ah - righto
[04:09:51] <jmkasunich> by default spindle-run would loop back to running, and there would be no delay or interlocking
[04:10:13] <cradek> I think I would actually use that (probably just a fixed delay)
[04:11:04] <jmkasunich> "MODULE_DESCRIPTION("Motion Controller for EMC");" ----> emc/motion/motion.c:40: warning: initialization discards qualifiers from pointer target type
[04:11:15] <jmkasunich> another annoyance, probably also related to const pointers
[04:12:06] <jmkasunich> mot_comp_id = hal_init("motmod"); --> emc/motion/motion.c:194: warning: passing argument 1 of ‘hal_init’ discards qualifiers from pointer target type
[04:13:03] <jmkasunich> I guess hal.h should be changed, "extern int hal_init(char *name);" to "extern int hal_init(const char *name);"
[04:13:14] <SWPLinux> hmmm. depends
[04:13:24] <SWPLinux> halcmd uses different names for different instances
[04:13:39] <SWPLinux> so that can't be const (unless you cast it)
[04:13:54] <jmkasunich> you can pass a char* to a function that expects a const char*
[04:14:08] <jmkasunich> the function is simply promising not to change whatever you pass it
[04:14:12] <SWPLinux> right
[04:14:22] <SWPLinux> I don't remember if c++ will warn you about that though
[04:14:30] <jmkasunich> its when you attempt to pass a const char* to a function that doesn't promise not to change it that you get a warning
[04:14:31] <SWPLinux> (it shouldn't, but then again ...)
[04:14:43] <jmkasunich> in this case, its C that is complaining
[04:14:48] <SWPLinux> heh - cool! ;)
[04:15:03] <jmkasunich> (I turned on the write-strings warning)
[04:15:39] <jmkasunich> I think I'm gonna fix hal_lib.c and hal.h to use const on things that the functions don't change
[04:16:42] <SWPLinux> fixing these up is easy - I've got the first 15 or so errors done (in 3 of the libnml files)
[04:16:59] <SWPLinux> I'll finish up all the libnml ones and commit that at once
[04:17:07] <SWPLinux> err - at one time ...
[04:42:15] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/hal/ (hal.h hal_lib.c hal_priv.h): add const to char pointer arguments in function prototypes if the function doesn't modify the arguement - eliminates about 400 warnings
[04:57:51] <SWPLinux> cradek: when you say that "this way lies madness" - are you saying that you think const_casts are the wrong thing to do, just that they're a waste of time, or something else?
[04:58:15] <jmkasunich> casts seem like a bad thing
[04:58:34] <jmkasunich> in fact, a very very bad thing
[04:58:43] <SWPLinux> I can make overloaded versions of functions, and if gcc is smart enough it'll use the same code for both versions
[04:58:51] <jmkasunich> don't go there
[04:59:02] <jmkasunich> I thought you were fixing declarations
[04:59:18] <SWPLinux> well, rcs_print_error(const_cast< char *>("Error String\n"), ...) is annoying to see, but correct code
[04:59:39] <jmkasunich> for example, if we had "void foo ( char *name)", and called it as foo("somename"), that would make a warning
[04:59:46] <SWPLinux> well, most of the stuff in libnml ends up being these rcs_print* calls
[05:00:05] <SWPLinux> yes
[05:00:05] <jmkasunich> changing it to "foo (const char *name)" fixes things and improves, not hurts, typechecking
[05:00:56] <jmkasunich> and one change at the function prototype (.h file) plus one change where the function is implemented, fixes _all_ calls to that function
[05:01:16] <SWPLinux> yep - that's the ideal fix
[05:01:29] <SWPLinux> I did attempt that (though I may have missed the .hh file - hmmm)
[05:01:38] <jmkasunich> thats what I did for hal,h and friends, doing rtapi.h now
[05:01:48] <SWPLinux> ok - I'll look at that again
[05:01:56] <SWPLinux> stupid errors do make for more work ;)
[05:06:43] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/rtapi/ (8 files): add const to char pointers to reduce warnings
[05:09:51] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/hal/user_comps/devices/hal_joystick.c: fix warning
[05:09:55] <cradek> SWPLinux: I'll try to summarize my feelings, but don't mistake me for an expert
[05:10:09] <SWPLinux> ok :)
[05:10:56] <cradek> const correctness is a lot of work, and as it spreads through the layers you will find places where it's not possible (like external libs)
[05:11:01] <cradek> it's a lot of work for no gain
[05:11:23] <cradek> it leads to cast droppings that are ugly and have to be maintained
[05:11:39] <cradek> it causes gratuitious incompatibilities with the older branches that we like to backport fixes to
[05:12:10] <SWPLinux> ah, so worse than a waste of time, because it increases maintenance and decreases backward "compatibility"
[05:12:16] <cradek> yes
[05:12:29] <cradek> and this is all triggered by a warning that nobody intended to even show up
[05:12:47] <SWPLinux> ok - and the simpler fixes in the categories jmkasunich mentioned (fixing function declarations) - how about that?
[05:12:50] <jmkasunich> I think there is one class of these warnings that we can and should fix
[05:13:16] <jmkasunich> new_pin(char* name) that doesn't actually modify name can and should be changed to new_pin(const char* name)
[05:13:33] <jmkasunich> change it in the .h and the .c, and you are done
[05:13:44] <cradek> why
[05:13:58] <jmkasunich> why not?
[05:14:01] <cradek> what does that give you, except failed patches when you backport real fixes
[05:14:12] <SWPLinux> it eliminates warnings from bad compilers, and it's more correct code
[05:14:22] <cradek> no the question when you change working code is definitely 'why'
[05:14:23] <SWPLinux> only if you fix theose declarations
[05:14:55] <SWPLinux> well, it's like the reasons why we discourage "indent"
[05:15:04] <SWPLinux> you can't see the real changes in the whitespace fixes
[05:15:08] <cradek> well it's no big deal, that will add only a little trouble later
[05:15:21] <SWPLinux> similarly, if you're actually looking for warnings and there are 2000 of these, it makes it hard to see the others
[05:15:33] <cradek> well that's right - it does screw with diffs.
[05:15:39] <SWPLinux> (yes - this is supposed to be a hidden warning)
[05:15:44] <cradek> like: what's different between trunk and X branch?
[05:15:55] <jmkasunich> the "2000 warnings means you ignore them all" problem is what I want to avoid, and the answer is probably to turn off that warning
[05:16:00] <cradek> oh, a hundred prototypes. wonder if any of them matter?
[05:16:49] <SWPLinux> ok, so no code changes should ever be made, because it makes it hard to keep track of the differences?
[05:17:03] <jmkasunich> SWPLinux: thats silly
[05:17:07] <SWPLinux> of course it is
[05:17:18] <cradek> well, you're being silly, but I do believe that no changes that don't matter should ever be made
[05:17:21] <jmkasunich> I would argue that the correct prototypes have real value
[05:17:49] <jmkasunich> if a function isn't supposed to modify an arg, and you declare it as const, then any accidental modification of that arg inside the function will be caught (error, not warning)
[05:18:01] <cradek> I have no emotional investment in this - but you asked what I thought
[05:18:06] <cradek> SWPLinux: ^
[05:18:10] <SWPLinux> sure - I appreciate the answer
[05:18:22] <SWPLinux> I didn't mean to sound snotty there
[05:18:50] <SWPLinux> it just seems that correctness of code, even fixing warnings, is a positive step
[05:19:21] <jmkasunich> SWPLinux: in general I agree, but adding a cast to prevent a warning is definitely something I would NOT do
[05:19:30] <jmkasunich> the cast can mask a real typing problem
[05:19:49] <SWPLinux> sure - I was starting to get an inkling that I was doing something wrong when hit the third or fourth file with 100 rcs_print_* calls ;)
[05:20:15] <jmkasunich> IMO, we should turn the warning on for a little while, find the most blatent issues, mostly prototypes, and fix the prototypes, NOT the calls
[05:20:25] <SWPLinux> no, in C++ a const_cast<> won't do anything but make something into a const - it can't change type (I think)
[05:20:32] <cradek> (IANA C++ programmer)
[05:21:11] <jmkasunich> SWPLinux: are you saying that C++ bitches when you pass a regular char * to a function expecting a const char *?
[05:21:17] <SWPLinux> the general C++ mantra is that casting is evil, so they made the words for it very long and the syntax very annoying
[05:21:24] <SWPLinux> yes, it does
[05:21:31] <SWPLinux> err - no, wait
[05:21:33] <jmkasunich> thats fucked
[05:22:02] <SWPLinux> a string literal is a const char *
[05:22:03] <jmkasunich> it should bitch when you pass a const char * to something that expects a regular char *, because that something my try to modify it
[05:22:08] <SWPLinux> exactly
[05:22:21] <SWPLinux> thinko'ed that first one
[05:22:25] <jmkasunich> the answer there is not to pass string literals to functions that will modify them
[05:22:31] <SWPLinux> sure
[05:22:37] <jmkasunich> and to properly declare functions that will NOT modify them
[05:22:48] <jmkasunich> don't change the calls, change the prototype
[05:22:50] <SWPLinux> right - that's what I'm doing now
[05:22:59] <jmkasunich> so why does that need casts?
[05:23:10] <SWPLinux> it doesn't - that was the old me :)
[05:23:13] <jmkasunich> oh, ok
[05:23:20] <SWPLinux> I was just pointing out that const_cast is pretty safe in c++
[05:23:37] <SWPLinux> it only makes a pointer const, it can't change type AFAIK
[05:23:45] <SWPLinux> s/pointer/variable/
[05:24:00] <jmkasunich> well, since C has no such thing, I didn't know it existed
[05:24:07] <SWPLinux> right
[05:24:23] <jmkasunich> any C fix done where the calls are being made is dangerous
[05:24:48] <jmkasunich> so I want to fix prototypes where we can, then turn off the warning to supress the ones we can't
[05:24:49] <SWPLinux> like I said - they made casting very very ugly in C++: dynamic_cast, static_cast, const_cast, reinterpret_cast ... all long names and with an annoying almost-function-like syntax
[05:24:53] <SWPLinux> yep
[05:29:50] <cradek> I'm glad our project has both "care about code correctness under the covers" types (you) and "gleefully hacks in one-line bugfixes without touching anything else" types (me) - whatever you decide is fine
[05:30:56] <jmkasunich> I just resisted the urge to fix the prototype of a function that is called from only one place
[05:31:02] <cradek> the me-types add to disorder over time and would probably eventually have an unusable code base
[05:31:20] <SWPLinux> yay!
[05:31:26] <jmkasunich> but functions that are called from 100 places means that adding one "const" fixes 100 warnings
[05:31:36] <SWPLinux> heh - I often have an unreadable codebase after 6 months or so
[05:31:53] <SWPLinux> and that's without any changes
[05:31:54] <jmkasunich> unreadabel codebase = emc1
[05:31:58] <SWPLinux> heh
[05:32:10] <SWPLinux> and anything APL
[05:32:27] <cradek> all code that's part of an actual project that's in use by users probably tends toward suck
[05:33:14] <cradek> (spending all your time concentrating only on internal beauty only means you have no users)
[05:33:53] <SWPLinux> well - I'm the kind of guy that makes sure there are no warnings or errors when I compile (code or PCB design rules)
[05:34:28] <SWPLinux> I found out early on that 100 warnings (a) probably mean my code is dumb and (b) make it very hard to notice when there are new ones
[05:34:37] <jmkasunich> cradek: I have a theory that hardware guys are more fastidious, because turnaround time for board mistakes is much longer than turnaround time for code mistakes
[05:35:15] <jmkasunich> as SWP mentioned - PCB design rule checks with bogus warnings really piss me off
[05:35:38] <jmkasunich> because one legit but missed warning can cost me a month - buy board, build, test, find problem, go back and fix, etc
[05:36:16] <SWPLinux> yep. when you know you're working against a problem with the tools (which we are at the moment), then a big red note saying why you turned something off is OK, otherwise, it's a big no-no in my book
[05:37:39] <jmkasunich> I did some grepping and such - found all warnings of the form "passing argument 1 of ‘ShowMessageBox’ discards qualifiers from pointer target type"
[05:37:49] <jmkasunich> and determined how many times each occurs
[05:38:13] <jmkasunich> those with large counts are candidates for fixes, assuming the functions are ours
[05:38:33] <SWPLinux> about how many uniques are there?
[05:38:33] <jmkasunich> print_rcs_error_new seems to be the highest - 60
[05:38:42] <SWPLinux> ok, that's the file I'm in right now
[05:39:02] <jmkasunich> 49 unique
[05:39:19] <SWPLinux> it eventually boils down to rcs_fputs, which can't use const char* because the string pointer is passed to various list manipulation functions
[05:39:30] <jmkasunich> probably about half are called either once or twice, and the diff mess probably outweighs the warning improvement
[05:39:56] <jmkasunich> 71 warning: passing argument 2 of ‘PyObject_SetAttrString’ discards qualifiers from pointer target type
[05:39:56] <jmkasunich> 78 warning: passing argument 2 of ‘PyArg_ParseTuple’ discards qualifiers from pointer target type
[05:40:04] <jmkasunich> these two are the highest
[05:40:59] <jmkasunich> in axis - I'll not touch that
[05:41:06] <jmkasunich> jepler can look at it tomorrow if he wants
[05:45:34] <jmkasunich> fixing one function in classicladder fixes 107 warnings - it has three char * args, and most calls have all three as constant strings
[05:45:47] <SWPLinux> cool
[05:53:01] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/hal/classicladder/ (classicladder_gtk.c classicladder_gtk.h): add const qualifier to char pointers in function prototypes and declarations
[05:53:16] <SWPLinux> hmmm. would you mind looking at libnml/os_intf/_sem.c line 119?
[05:53:43] <jmkasunich> "ugh"
[05:53:57] <SWPLinux> and the longer comments above
[05:54:13] <SWPLinux> now, I just ran cvs diff on that file, and it says there are no changes
[05:54:20] <SWPLinux> but I now get this error:
[05:54:48] <SWPLinux> libnml/os_intf/_sem.c: In function ‘rcs_sem_open’:
[05:54:50] <SWPLinux> libnml/os_intf/_sem.c:119: warning: cast from pointer to integer of different size
[05:55:14] <jmkasunich> there is key_t defined?
[05:55:20] <jmkasunich> where, not there
[05:55:37] <jmkasunich> that cast is almost certainly the issue
[05:55:53] <SWPLinux> I'm not sure where it's defined - I can find it
[05:56:00] <SWPLinux> hmmm - one sec
[05:56:11] <jmkasunich> it probably isn't the same length as a char pointer
[05:56:17] <SWPLinux> ah - ok
[05:56:29] <SWPLinux> that error does occur for me in the "clean" log I made
[05:56:36] <SWPLinux> it's not in acemi's log, so I thought it was new
[05:56:48] <SWPLinux> this is a 64-bit system, so that's why I get the warning
[05:57:03] <jmkasunich> ah - yet another reason why that cast is an abortion
[05:57:18] <SWPLinux> well, that's plain from the comments as well ;)
[05:58:30] <jmkasunich> key needs to be some integer, right?
[05:58:33] <SWPLinux> this kind of line causes a warning: char *ctime_ret = "";
[05:58:38] <SWPLinux> yes, I think so
[05:58:44] <jmkasunich> hopefully unique as long as name is unique
[05:58:50] <SWPLinux> I don't want to change that at the moment, because that's an actual code change
[05:58:58] <SWPLinux> it could cause other issues
[05:59:06] <SWPLinux> and it's only a 64-bit problem at the moment
[05:59:09] <jmkasunich> true
[05:59:11] <SWPLinux> (I think)
[05:59:17] <jmkasunich> error or warning?
[05:59:26] <SWPLinux> warning
[05:59:36] <jmkasunich> ok, lets not sweat it
[05:59:54] <SWPLinux> you're talking about the key thing in _sem.c, right?
[05:59:59] <jmkasunich> yes
[06:00:05] <SWPLinux> ok - just making sure
[06:00:13] <jmkasunich> id
[06:00:21] <jmkasunich> I'd probably code up a crude hash
[06:00:25] <SWPLinux> yeah - that should og oon the list, but I don't want to mix cosmetic/compiler fixes with possible functional changes
[06:00:30] <jmkasunich> right
[06:00:43] <SWPLinux> s/og oon/go on/
[06:00:50] <SWPLinux> how the heck did I get og oon
[06:01:03] <jmkasunich> fingers faster than keys
[06:01:10] <SWPLinux> it's not type like a caveman day is it?
[06:02:46] <jmkasunich> hmm, the other "high yield" fix is things like char *commands[] = {"HELLO", "SET", "GET", "QUIT", "SHUTDOWN", "HELP", ""};
[06:03:02] <jmkasunich> one const eliminates 6 warnings there
[06:03:23] <SWPLinux> yep, as long as it doesn't require a lot of variables and/or functions to change
[06:12:39] <SWPLinux> cool - all the warnings from the libnml/ tree are now gone (except for that one in _sem.c)
[06:13:50] <jmkasunich> how many files did you have to touch?
[06:14:00] <SWPLinux> well, I'm trying to figure that out now ;)
[06:14:09] <SWPLinux> I had modified a few, then was able to change them back
[06:16:38] <jmkasunich> well, my checkout is down from 4400ish warnings to 3286
[06:16:59] <SWPLinux> nice. I noticed that the log file went from ~600k to ~400k
[06:17:02] <jmkasunich> I imagine your changes will knock that down quite a bit more
[06:17:31] <jmkasunich> what log file? you been updating after my commits?
[06:17:56] <SWPLinux> I just updated once - there were some warnings in hal-related files
[06:18:12] <SWPLinux> I make clean ; make > logfile to see where errors are
[06:18:16] <SWPLinux> err - warnings
[06:18:22] <jmkasunich> I've been doing that too
[06:18:29] <SWPLinux> and I saved the first one I had created
[06:18:33] <jmkasunich> cat log | grep warning | wc
[06:18:37] <jmkasunich> I have 4 iterations
[06:19:02] <SWPLinux> steve@Opteron:/Project/emc2/src$ cat newlog | grep -c warning
[06:19:04] <SWPLinux> 2909
[06:19:25] <jmkasunich> interesting - I have far more
[06:19:32] <SWPLinux> you don't have my changes
[06:19:37] <jmkasunich> yeah, duh
[06:19:58] <jmkasunich> I went from 4233 to 3817 to 3412 to 3286
[06:20:00] <SWPLinux> heh - getting there - just need to weed out the stupid crap
[06:20:05] <SWPLinux> nice
[06:20:11] <jmkasunich> hitting diminishing returns tho
[06:22:16] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/libnml/inifile/inifile.cc: Fix some obscure c++ warnings
[06:22:31] <SWPLinux> more coming - hold off a sec
[06:23:32] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/libnml/nml/nml.cc: Fix some obscure c++ warnings - this may be more ugly than the warnings
[06:24:56] <jmkasunich> unless that fixes a boatload of warnings in one fell swoop, it is ugly
[06:25:28] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/libnml/rcs/ (rcs_print.cc rcs_print.hh): Fix some obscure c++ warnings - make char * arguments const
[06:25:38] <SWPLinux> that should be it
[06:25:42] <SWPLinux> heh - just one ;)
[06:26:04] <SWPLinux> hmmm. I should revert that. it is a const string
[06:26:11] <SWPLinux> how does one do that?
[06:26:26] <jmkasunich> I'm not sure
[06:26:36] <jmkasunich> if its simple, I just undo it and commit again
[06:26:43] <SWPLinux> yeah, it's one line
[06:26:45] <jmkasunich> in the comment I say something like "revert previous"
[06:28:58] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/libnml/nml/nml.cc: Revert warning fix - the code was silly and incorrect
[06:31:29] <jmkasunich> 2241 warnings now
[06:31:43] <jmkasunich> I have some uncommitted changes... lemme commit those
[06:31:47] <SWPLinux> have you been fixing streamer / classicladder?
[06:32:00] <jmkasunich> I fixed a couple files in CL only
[06:32:09] <jmkasunich> give me a few minutes to check what I have here
[06:32:14] <SWPLinux> ok - I'll look at streamer
[06:33:39] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/emc/motion/ (command.c control.c motion.c): add const qualifiers to char pointers
[06:38:26] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/emc/rs274ngc/rs274ngc_errors.cc: add const qualifiers to char pointers
[06:38:27] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/emc/usr_intf/emcrsh.cc: add const qualifiers to char pointers
[06:39:00] <jmkasunich> ok, all my changes are committed
[06:40:09] <SWPLinux> ok - got a couple little ones in streamer and vcp now
[06:42:19] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/hal/user_comps/vcp/ (tokenizer.h tokenizer.c): More const qualifiers on function delcarations, to silence warnings
[06:42:23] <CIA-21> EMC: 03swpadnos 07TRUNK * 10emc2/src/hal/components/streamer_usr.c: More const qualifiers on function delcarations, to silence warnings
[06:43:53] <SWPLinux> oooh - only 1734 now
[06:46:34] <SWPLinux> hmmm. looks like I made VCP worse
[06:49:29] <jmkasunich> when in doubt, revert
[06:49:58] <SWPLinux> ah - more of the 64-bit problems
[06:50:12] <SWPLinux> not worse than my original build, only worse than acemi's build
[06:50:58] <SWPLinux> hmmm. are you on an RT build there?
[06:57:01] <SWPLinux> man, there's some silly stuff in CL
[06:57:12] <jmkasunich> sim
[06:57:30] <SWPLinux> arithm_eval has a global called ErrorDesc, and a void function called SyntaxError
[06:57:48] <SWPLinux> ErrorDesc is always set just before a call to SyntaxError(), and only just before those calls
[06:57:57] <SWPLinux> seems like a perfect place for an argument to the function
[06:59:10] <SWPLinux> ok - sim here too - just wondering why I'm getting 1734 warnings including these 50 or so from 64-bit issues, when you're getting 2241
[06:59:28] <jmkasunich> all your fixes committed?
[06:59:43] <jmkasunich> and -Wwrite-strings turned on in your makefile?
[06:59:58] <SWPLinux> yeah - otherwise I don't get any of these
[07:00:10] <jmkasunich> dunno
[07:00:21] <SWPLinux> everything is committed I think, the last two changes only killed 10 or so warnings
[07:01:04] <jmkasunich> different compiler versions maybe
[07:01:28] <SWPLinux> steve@Opteron:/Project/emc2/src$ gcc --version
[07:01:30] <SWPLinux> gcc (GCC) 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
[07:01:31] <SWPLinux> Copyright (C) 2006 Free Software Foundation, Inc.
[07:01:46] <jmkasunich> same
[07:02:02] <SWPLinux> ./configure --enable-simulator --enable-run-in-place ...
[07:02:24] <SWPLinux> then make clean ; make > log 2>&1
[07:02:53] <jmkasunich> ype
[07:02:55] <jmkasunich> yep
[07:03:27] <SWPLinux> actually, I use -j8, but I hope that doesn't matter ;)
[07:03:30] <jmkasunich> you sure everything is committed? (cvs diff)
[07:03:42] <SWPLinux> I'll check once this make finishes
[07:03:48] <SWPLinux> is cvs diff recursive?
[07:03:59] <jmkasunich> yes
[07:04:22] <jmkasunich> I just did another update - I didn't have your streamer or vcp changes yet
[07:04:33] <SWPLinux> hmmm - ok, 2071 now. I wonder why I had 1734
[07:05:17] <jmkasunich> doing a clean make now, I have some changes to halcmd and other stuff in that dir, if they build clean I'll commit them
[07:05:48] <SWPLinux> [01:42:20]<CIA-21>EMC: swpadnos TRUNK * emc2/src/hal/user_comps/vcp/ (tokenizer.h tokenizer.c): More const qualifiers on function delcarations, to silence warnings
[07:05:50] <SWPLinux> [01:42:24]EMC: swpadnos TRUNK * emc2/src/hal/components/streamer_usr.c: More const qualifiers on function delcarations, to silence warnings
[07:05:59] <SWPLinux> those are the vcp and streamer commits
[07:06:19] <jmkasunich> I have them now, I just hadn't done an update since you committed them
[07:06:24] <SWPLinux> ah
[07:07:48] <jmkasunich> 2014
[07:08:20] <SWPLinux> you're on 32-bit?
[07:08:24] <jmkasunich> yes
[07:08:37] <SWPLinux> ok, I think that explains the difference
[07:16:30] <SWPLinux> hmmm. I think I see an error in CL, but I'm not sure if it's the code or the function name
[07:17:09] <SWPLinux> int pow_int(int a,int b)
[07:17:10] <SWPLinux> {
[07:17:12] <SWPLinux> int x;
[07:17:14] <SWPLinux> for (x=1;x<=b;x++)
[07:17:15] <SWPLinux> a = a*a;
[07:17:17] <SWPLinux> return a;
[07:17:19] <SWPLinux> }
[07:17:27] <SWPLinux> that returns a^(2^b), not a^b as I'd expect from the name
[07:18:49] <jmkasunich> that does look wrong
[07:19:05] <fenn> a^(2*b)
[07:19:22] <SWPLinux> oh - could be that too ;)
[07:20:10] <SWPLinux> no, I think it is a^(2^b)
[07:20:56] <SWPLinux> pass 1 = a^2, pass 2 = (a^2)^2 = a^4, pass 3 = (a^4)^2 = a^8
[07:21:28] <SWPLinux> could be 2^(b-1)
[07:22:11] <fenn> no, you had it right the first time
[07:22:52] <SWPLinux> it's only used in one place, and I think I may go to bed instead of figuring out what the intent was
[07:31:33] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/hal/components/stepgen.c: add const qualifier to char pointers
[07:33:48] <jmkasunich> cd ..
[07:33:55] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/hal/utils/ (8 files): add const qualifier to char pointers
[07:40:24] <CIA-21> EMC: 03jmkasunich 07TRUNK * 10emc2/src/Makefile: turn off a warning that is supposed to be off by default but is on in certain gcc versions due to a bug
[07:40:36] <jmkasunich> there - that will deal with the rest of them
[07:41:41] <jmkasunich> * jmkasunich goes to bed
[13:58:06] <CIA-21> EMC: 03jepler 07TRUNK * 10emc2/docs/man/man3/ (10 files): reflect addition of const qualifiers to APIs that take char*
[15:20:39] <jepler> jmkasunich, SWPLinux: you guys have fun with const last night?
[15:20:50] <SWPadnos> heh - great fun
[15:22:18] <SWPadnos> there are actually other issues that those warnings cover up - mostly related to 64-bit builds
[15:22:45] <SWPadnos> (or so it seems, since I get more warnings than jmkasunich with my 64-bit cs. his 32-bit build)
[15:22:49] <SWPadnos> s/cs/vs/
[22:05:52] <Roguish_> jepler: does the 5axis.pivot-length in the .hal file make it to the 5axisgui python file when running?
[22:06:41] <Roguish_> there is a hard coded pivot_len in the 5axisgui file.
[22:06:47] <jepler> Roguish_: no. the pivot_len is hardcoded as you have seen
[22:07:06] <jepler> 5axiskins.pivot-length is for the realtime kinematics module only
[22:07:36] <Roguish_> ok, and the .hal file pivot-length is for the actual motion?
[22:07:50] <jepler> it would be possible to make a 5axisgui.pivot-length parameter, however. You'd replace the single Translate with a Translate(-150) and a HalTranslate...
[22:07:56] <jepler> right
[22:08:31] <Roguish_> and the pivot length is from the center of rotation of the B axis to the end of the spindle without tool?
[22:09:37] <jepler> I'm not sure about the details of the machine construction
[22:12:47] <Roguish_> in the 5axis gui model, the pivot_len variable is used in some cals in some of the 'construction'
[22:13:02] <Roguish_> calcs.
[22:13:31] <jepler> CylinderZ(pivot_len, 100, 0.0, 50),
[22:13:31] <jepler> Box(-100,-100,pivot_len, 100,100,pivot_len+50),
[22:13:31] <jepler> Box(-50,25,pivot_len+50, 50,100,pivot_len+150)
[22:13:38] <jepler> oh yeah -- these set the size of some of the elements
[22:13:51] <jepler> you can't currently change the size of these elements dynamically based on hal variables
[22:14:19] <Roguish_> can i set a variable based on the hal parameter value?
[22:14:39] <Roguish_> sort of round-about.
[22:15:47] <jepler> that code (e.g., pivot_len + 50) is evaluated only once when 5axisgui starts, before you're guaranteed to have a value on the pivot_len pen or parameter..
[22:16:43] <jepler> that's the distinction between e.g., Translate and HalTranslate -- HalTranslate is a Python class which looks at the named HAL pin every time it redraws, Translate translates by the same amount every time
[22:17:17] <jepler> so in theory you would write a class that is similar to CylinderZ, but which gets (some of) its parameters from HAL at each redraw instead of once at initialization
[22:18:02] <jepler> (in fact this specific class was needed in 5axisgui to show the tool cylinder; you can see its definition at the top of 5axisgui)
[22:18:16] <Roguish_> i think that is done now with the tool_length. it's passed thru from the .hal file to the gui file
[22:18:21] <Roguish_> yeah.
[22:19:25] <jepler> I believe you can do the same by subclassing Box to provide a 'def coords' -- it returns 6 values which give the corners of the box: x1, y1, z1, x2, y2, z2
[22:20:56] <Roguish_> now you're programming, and i don't really know all that. i've managed to wade thru the 5axisgui and make a new model (that works)
[22:22:47] <Roguish_> check this out: http://imagebin.org/13505
[22:23:22] <jepler> cute
[22:23:50] <Roguish_> the yellow is the Y, moves in and out, the green is the X, moves side to side.
[22:24:05] <alex_joni> do they move together?
[22:24:13] <alex_joni> :P
[22:24:44] <Roguish_> yes. they are correctly linked. as is the column with the C and B
[22:24:51] <alex_joni> jepler: one of these days we'll need to add some obj import for slightly more complex objects :)
[22:25:06] <jepler> alex_joni: I'm not against that
[22:25:27] <Roguish_> it took awhile. but i'm pretty good at beating things until they submit.
[22:25:57] <jepler> Roguish_: that's the very spirit of programming right there
[22:26:17] <alex_joni> jepler: well.. I hinted "we" :P
[22:26:19] <Roguish_> i used to do that with basic and fortran4
[22:27:07] <Roguish_> wrote and FEA code for senior project back at CalPoly in '79
[22:27:13] <alex_joni> I know a bit about obj.. since my last attempts with python :)
[22:27:20] <Roguish_> punched cards!!!!!!!!!!!!
[22:27:28] <Roguish_> don't drop the box
[22:28:41] <Roguish_> thanks. i'll leave it as is for a while. give me a rain check to ask more silly questions later. gotta work on the post to get real code out.