erbo@lime.ucsb.edu (Eric J. Bowersox) (07/16/89)
Sorry if these bugs have appeared in this newsgroup before, but _I_ cer- tainly haven't seen them. At my workplace, I am currently engaged in what amounts to almost a complete rewrite of a system for expense tracking that I had written some time earlier in dBASE III Plus. The new version is being written in dBASE IV, and uses many of the neat features of that system (like pulldown menus and .MDX files), but in the process, I have run into some very frustrating system bugs. Here are a couple I haven't heard mentioned. BUG #1: The Case of the Missing Procedure (or: Son of Line Eater? :-) ) If you have a .PRG file with more than about 8 procedures in it, and you try to call the last procedure in that file, dBASE won't find it, and will hand you a "File does not exist" error. WORKAROUND: Easy. Just place a dummy procedure at the very end of each file that might have a large number of procedures in it, like: PROCEDURE Blort *** Never call Blort! RETURN Unfortunately, this bug also affects generated report and label forms, since the code generator generates dBASE code, and that code has quite a few procedures in it, the last one of which (Reset) is affected by this bug. There are two things you can do with this: edit the .FRG/.LBG files directly to insert the aforementioned dummy procedure (which you have to then do every time you re-generate the report), or (if you have the Developer's Edition) edit the templates to include that procedure at the end. Since we do have the "Gold" edition, I chose the latter course, and it works fine. (Postscript: I looked at one of the .DBO files under Norton Utilities, and it seems that, at the end of the file, they have some sort of jump table showing where all the procedures are; the last procedure was missing from this table. So, apparently, the compiler is just forgetting to stick that last entry in. Or am I off base here?) BUG #2: PLAYing Loop-the-Loop with MACROs At one point in my application, I wanted to send a certain number of down- arrow keys to the keyboard, but that number might vary at certain times (it was to position the light-bar of a POPUP menu on a certain item). So, I used the Tools/Macros (or something like that) menu in the Control Center to define a macro consisting of one down arrow key, called DOWNARROW. Now, with that macro suitably loaded in my program, you would think the right thing to do would be: I = 1 DO WHILE I <= NDOWNS && the number of down arrows I want PLAY MACRO DOWNARROW I = I + 1 ENDDO Right? WRONG! Apparently, on the second iteration of this loop, dBASE stopped my program with an error about "recursive macros" or somesuch (I don't remember the exact error message, but it was very irritating). My guess is it doesn't like to see the same PLAY MACRO twice in a row. WORKAROUND: In this case, it wasn't so bad; I just had to remember my binary. I defined three more macros consisting of two, four, and eight down arrow keys, called DOWN2, DOWN4, and DOWN8 respectively. Now my code looked like this: I = NDOWNS IF I >= 8 PLAY MACRO DOWN8 I = I - 8 ENDIF IF I >= 4 PLAY MACRO DOWN4 I = I - 4 ENDIF IF I >= 2 PLAY MACRO DOWN2 I = I - 2 ENDIF IF I >= 1 PLAY MACRO DOWNARROW I = I - 1 ENDIF Of course, this means you can't play more than 15 down arrows this way, but since I didn't even need _that_ many maximum, I let it go. Besides, this method is extendable if necessary. Even better, though, would have been an "ACTIVATE POPUP name BAR number" syntax, similar to "ACTIVATE MENU name PAD pad_name." Now, the obligatory disclaimer: I am not an Ashton-Tate affiliate in any way, shape, or form, except as YAPSWDBIV (yet another programmer struggling with dBASE IV), and I sincerely feel that, as long as I can keep hacking around the difficulties, the advantages of the new system greatly outweigh the disadvantages, and I will definitely be interested when A-T ships their v.1.1. So, no flames from the A-T-bashers, please! Hope someone, somewhere, can use this :-) :-) :-). | Disclaimer: This posting is definitive. Reality may have got it wrong. | | * Eric J. Bowersox (ERBO) * LIVE! from Isla Vista, California! | | erbo@cornu.ucsb.edu ...!{ucbvax,ucsd}!ucsbcsl!cornu!erbo | | If wishes were DRAMs, I don't think we would worry about the Japanese. -me |
awd@dbase.UUCP (Alastair Dallas) (07/19/89)
In article <2071@hub.UUCP>, erbo@lime.ucsb.edu (Eric J. Bowersox) writes: > > BUG #1: The Case of the Missing Procedure (or: Son of Line Eater? :-) ) > > If you have a .PRG file with more than about 8 procedures in it, and you > try to call the last procedure in that file, dBASE won't find it, and will > hand you a "File does not exist" error. I couldn't get this to fail. I created a 150-line prg containing 14 simple, but not empty procedures. The main proc just called the others, and the last one was never ignored. Is it possible your code is unusual enough that the nesting on RETURN statements looks okay to you but looks different to dBASE? (That's fairly unlikely, though--the keyword PROCEDURE automatically ends the preceding procedure and the compiler would complain then about missing control structures like ENDIFs.) Can you send me a simple failing test case? > BUG #2: PLAYing Loop-the-Loop with MACROs > This is out of my area; the fellow I would ask about MACRO questions had a small accident this morning and wound up in the hospital, so I can't help you. It sounds like you're playing a game we play here a lot--let's figure out what the software is _supposed_ to do by trial and error. Sometimes subsystems are not very clearly defined (documentation and spec writers are not programmers, and, to be fair, vice versa). Looks like you figured out what we intended the hard way. I'm glad the workaround wasn't too difficult for you. Thanks for presenting such clear cases. I think the people on comp.databases who don't hit 'N' when the subject line says 'dBASE' appreciate hearing about any bugs or unexpected features (:-). I'll try to investigate any reports of bugs, and although I'll probably shy away from saying "That's a bug!" (unless I know it will be fixed in v1.1), I may explain why some behavior might be considered meritorious in such a way that you can read between the lines. :-) /alastair/
awd@dbase.UUCP (Alastair Dallas) (07/19/89)
In article <167@dbase.UUCP>, awd@dbase.UUCP (Alastair Dallas) writes: > In article <2071@hub.UUCP>, erbo@lime.ucsb.edu (Eric J. Bowersox) writes: > > > > BUG #1: The Case of the Missing Procedure (or: Son of Line Eater? :-) ) > > > > If you have a .PRG file with more than about 8 procedures in it, and you > > try to call the last procedure in that file, dBASE won't find it, and will > > hand you a "File does not exist" error. > > ...Is it possible your code is unusual enough that the > nesting on RETURN statements looks okay to you but looks different to dBASE? > (That's fairly unlikely, though... The software designer here who is actually responsible for procedures had a better explanation. He points out that dBASE III PLUS (and IV to be compatible) will allow duplicate procedure names and that only the first procedure encountered will then be "found." Procedure names are case- insensitive and silently truncate (I think) at some limit (approx. 10), thus MyProcedureName and MYPROCEDURENAME2 are identical; the compiler generates no warning about this (maybe it should). Hope it helps. /alastair/
erbo@mango.ucsb.edu (Eric J. Bowersox) (07/20/89)
In article <167@dbase.UUCP> awd@dbase.UUCP (Alastair Dallas) writes: :In article <2071@hub.UUCP>, erbo@lime.ucsb.edu (Eric J. Bowersox) writes: :> BUG #1: The Case of the Missing Procedure (or: Son of Line Eater? :-) ) :I couldn't get this to fail. I created a 150-line prg containing 14 simple, :but not empty procedures. The main proc just called the others, and the last :one was never ignored. After seeing this message for the first time, I ran back to my machine at work (a true-blue IBM PC-XT with 20Mb hard disk -- slow! :-( ) and tried to duplicate the problem. Here's what I came up with: *** DBFail.prg *** A failing test case that demonstrates the procedure bug. *************************************** *** *** Set up error logging. *** set talk off set space off set alternate to "dbfail.run" set alternate on on error ? "Error ",error()," at ",program(),"-",lineno(),": ",message() *** *** Test procedure calls. *** ? "Now starting the procedure call test..." do test1 do test2 do test3 do test4 do test5 do test6 do test7 do test8 do test9 do test10 *** *** Finish up. *** ? "End of DBFAIL.PRG" set alternate off close alternate return *** The test procedures, ten in number. procedure test1 ? "Procedure TEST1 called!" return [The remaining procedures omitted for brevity, but they're just like the first one] *** EOF: DBFail.prg Well, after compiling this with "compile dbfail" and getting no errors (I know you don't need to do that, since dBASE will do it for you, but I just wanted to make sure :-) ), I ran the program and got the following results in DBFAIL.RUN: Now starting the procedure call test... Procedure TEST1 called! Procedure TEST2 called! Procedure TEST3 called! Procedure TEST4 called! Procedure TEST5 called! Procedure TEST6 called! Procedure TEST7 called! Procedure TEST8 called! Procedure TEST9 called! Error 1 at DBFAIL- 25: File does not exist End of DBFAIL.PRG A-ha! You think! Well, I thought of something else, and rebooted my machine, selecting "local boot" instead of "network boot." (Oops! Forgot to mention, my machine is a workstation on a LAN, but dBASE IV was installed single-user on my own hard disk.) Cranking up dBASE IV, recompiling DBFAIL.PRG, and running it again produced the following: Now starting the procedure call test... Procedure TEST1 called! Procedure TEST2 called! Procedure TEST3 called! Procedure TEST4 called! Procedure TEST5 called! Procedure TEST6 called! Procedure TEST7 called! Procedure TEST8 called! Procedure TEST9 called! Procedure TEST10 called! End of DBFAIL.PRG Checking both .DBO files out with LIST (the program LIST.COM, not dBASE's LIST command :-) ) in hex dump mode revealed, sure enough, the one compiled with the LAN on was missing the last entry in its "jump table" (for procedure TEST10), but the one compiled with the machine booted locally had it in its correct place. Logically, though, both files should have been identical whether the LAN was present or not. I am afraid I am totally at a loss to explain this, but I have a sneaking suspicion that Alastair is probably right. (sigh) :Thanks for presenting such clear cases. I think the people on comp.databases :who don't hit 'N' when the subject line says 'dBASE' appreciate hearing :about any bugs or unexpected features (:-). You're welcome. Actually, I tune in _just_ to find out anything new I can about dBASE...as my paycheck depends on it, this is understandable :-). I think it's probably worth it in the end, though. | Disclaimer: This posting is definitive. Reality may have got it wrong. | | * Eric J. Bowersox (ERBO) * LIVE! from Isla Vista, California! | | erbo@cornu.ucsb.edu ...!{ucbvax,ucsd}!ucsbcsl!cornu!erbo | | If wishes were DRAMs, I don't think we would worry about the Japanese. -me |
dukel@dbase.UUCP (Duke Luper) (07/20/89)
In article <2071@hub.UUCP>, erbo@lime.ucsb.edu (Eric J. Bowersox) writes: > Sorry if these bugs have appeared in this newsgroup before, but _I_ cer- > tainly haven't seen them. > > At my workplace, I am currently engaged in what amounts to almost a complete > rewrite of a system for expense tracking that I had written some time > earlier in dBASE III Plus. The new version is being written in dBASE IV, > and uses many of the neat features of that system (like pulldown menus and > .MDX files), but in the process, I have run into some very frustrating > system bugs. Here are a couple I haven't heard mentioned. > > BUG #1: The Case of the Missing Procedure (or: Son of Line Eater? :-) ) > > If you have a .PRG file with more than about 8 procedures in it, and you > try to call the last procedure in that file, dBASE won't find it, and will > hand you a "File does not exist" error. > > WORKAROUND: Easy. Just place a dummy procedure at the very end of each > file that might have a large number of procedures in it, like: > > PROCEDURE Blort > *** Never call Blort! > RETURN > > Unfortunately, this bug also affects generated report and label forms, > since the code generator generates dBASE code, and that code has quite a > few procedures in it, the last one of which (Reset) is affected by this bug. > There are two things you can do with this: edit the .FRG/.LBG files directly > to insert the aforementioned dummy procedure (which you have to then do every > time you re-generate the report), or (if you have the Developer's Edition) > edit the templates to include that procedure at the end. Since we do have > the "Gold" edition, I chose the latter course, and it works fine. > > (Postscript: I looked at one of the .DBO files under Norton Utilities, and > it seems that, at the end of the file, they have some sort of jump table > showing where all the procedures are; the last procedure was missing from > this table. So, apparently, the compiler is just forgetting to stick that > last entry in. Or am I off base here?) > Attempt to find BUG1: Now, I'm not doubting that this happened to you. I just wanted to try it for myself and report to you my findings. I ran the following program: * DUKE.PRG do 1 do 2 do 3 do 4 do 5 do 6 do 7 do 8 do 9 do 10 do 11 do 12 do 13 do 14 do 15 do 16 do 17 do 18 do 19 do 20 return proc 1 ? "this is proc 1" return proc 2 ? "this is proc 2" return . . . proc 20 ? "this is proc 20" return * EOF: duke.prg Here is the output: this is test 1 this is test 2 this is test 3 this is test 4 this is test 5 this is test 6 this is test 7 this is test 8 this is test 9 this is test 10 . . this is test 19 this is test 20 Unfortunately, I couldn't reproduce it. I also tried SET PROC TO DUKE and removed all of the DO's and the first RETURN from DUKE.PRG and placed them in TEST.PRG and ran TEST.PRG. The output was the same. I am running dBASE 1.0 on a Novell network (SFT Netware 286 V2.12) on a Compaq 386/16 with a HICARD. > BUG #2: PLAYing Loop-the-Loop with MACROs > > At one point in my application, I wanted to send a certain number of down- > arrow keys to the keyboard, but that number might vary at certain times (it > was to position the light-bar of a POPUP menu on a certain item). So, I > used the Tools/Macros (or something like that) menu in the Control Center to > define a macro consisting of one down arrow key, called DOWNARROW. Now, with > that macro suitably loaded in my program, you would think the right thing to do would be: > > I = 1 > DO WHILE I <= NDOWNS && the number of down arrows I want > PLAY MACRO DOWNARROW > I = I + 1 > ENDDO > > Right? WRONG! Apparently, on the second iteration of this loop, dBASE stopped > my program with an error about "recursive macros" or somesuch(I don't remember > the exact error message, but it was very irritating). My guess is it doesn't > like to see the same PLAY MACRO twice in a row. I tried this test case on 1.0 multi-user version on Novell too and could not reproduce the bug (unfortunately): restore macros from test.key && contains DOWNARROW as you described use testdb1 i = 1 ndowns = 10 do while i <= ndowns play macro downarrow i = i+1 enddo browse return Since successive PLAY MACRO statements load on a LIFO basis (refer to the language reference manual page 2-196), then we would suspect to see the BROWSE screen and the cursor move down to the 11th record (which it did without a problem). I BELIEVE YOU that it happened to you, but my environment was apparently not set up in a manner to catch the bug. > > WORKAROUND: In this case, it wasn't so bad; I just had to remember my binary. > I defined three more macros consisting of two, four, and eight down arrow > keys, called DOWN2, DOWN4, and DOWN8 respectively. Now my code looked like > this: > > I = NDOWNS > IF I >= 8 > PLAY MACRO DOWN8 > I = I - 8 > ENDIF > IF I >= 4 > PLAY MACRO DOWN4 > I = I - 4 > ENDIF > IF I >= 2 > PLAY MACRO DOWN2 > I = I - 2 > ENDIF > IF I >= 1 > PLAY MACRO DOWNARROW > I = I - 1 > ENDIF > > Of course, this means you can't play more than 15 down arrows this way, but > since I didn't even need _that_ many maximum, I let it go. Besides, this > method is extendable if necessary. Even better, though, would have been > an "ACTIVATE POPUP name BAR number" syntax, similar to "ACTIVATE MENU name > PAD pad_name." > > Now, the obligatory disclaimer: I am not an Ashton-Tate affiliate in any > way, shape, or form, except as YAPSWDBIV (yet another programmer struggling > with dBASE IV), and I sincerely feel that, as long as I can keep hacking > around the difficulties, the advantages of the new system greatly outweigh > the disadvantages, and I will definitely be interested when A-T ships their > v.1.1. So, no flames from the A-T-bashers, please! > > Hope someone, somewhere, can use this :-) :-) :-). > > | Disclaimer: This posting is definitive. Reality may have got it wrong. | > | * Eric J. Bowersox (ERBO) * LIVE! from Isla Vista, California! | > | erbo@cornu.ucsb.edu ...!{ucbvax,ucsd}!ucsbcsl!cornu!erbo | > | If wishes were DRAMs, I don't think we would worry about the Japanese. -me | Good luck Eric. Sorry I couldn't have been of more help. If I could have reproduced it, I would have checked our tracking system here at AT and entered a bug report. Duke Luper Consultant to Ashton-Tate I don't think I have to disclaim anything I've said but just in case, they are my views and not Ashton-Tate's. After all, what are Ashton-Tate's views?