Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I need help with a compile error

Status
Not open for further replies.

BugZap13

Programmer
Dec 2, 2013
30
US
I am getting a compile error which has me confused. The following are the errors from the compile and stored to the .err file associated with the program. Note the datanames m.12 which does not match the lines in the program. What is odd is that the number portion corresponds to the field number of the underlying cursor.
Code:
STORE lnP_FIT_Amt TO m.12
Error in line 390: Command contains unrecognized phrase/keyword.
m.12 = lnP_FIT_Amt
Error in line 391: Unrecognized command verb.
m.13= lnP_FICA_Amt
Error in line 392: Unrecognized command verb.
m.14 = lnP_SIT_Amt
Error in line 393: Unrecognized command verb.
m.25   = lcP_State
Error in line 413: Unrecognized command verb.
m.28  = lcP_Gender
Error in line 416: Unrecognized command verb.

Here are the associated lines in the program. The m.g_ prefixed names are from a cursor where I have done a "SCATTER MEMVAR MEMO BLANK". I am assigning values to the memory variables in preparation of doing a APPEND BLANK and GATHER MEMVAR MEMO a bit later.
Code:
      STORE lnP_FIT_Amt TO m.g_fit_amt
      m.g_fit_amt = lnP_FIT_Amt
      m.g_fica_amt= lnP_FICA_Amt
      m.g_sit_amt = lnP_SIT_Amt
      m.g_oth_amt = lnP_Oth_Amt

The cursor was created from an actual table as shown below.
Code:
PROCEDURE CreateCursor
LOCAL laGMS, lnIxMax
DIMENSION laGMS[1]
*
SELECT 0
USE GMS NOUPDATE
lnIxMax = AFIELDS(laGMS, 'GMS')
USE
CREATE CURSOR gms FROM ARRAY laGMS
RETURN

So what or why has the compiler interpreted the m.g_ prefixed datanames and substituted m.12 for the dataname? In the debugger I can watch the m.g_fit_amt for instance and see its value after the SCATTER.

TIA, Mark
 
Is there a #define in use, with

#define g_fit_amt 12?

That's the only thing that would explain this. VFP is not case sensitive, by the way, so #define G_FIT_AMT 12 would also affect the compiler to substitute g_fit_amt with 12.

Edit: Using such a construct I can reproduce exactly that compilation error.

Such a definition can be included directly or indirectly, because a header file can also have #include and so in the end you could even have a .h file that has such a definition and is not part of the pjx, so even code references search doesn't find that.

But in the usual case a Code References search should be your first try to find where this definition comes from, maybe there's a comment explaining it. or you find other code, in which such a constant makes sense, i.e. where 12 instead of g_fit_amt is working. Because this definition was made with some intent. It just turns out this was no good idea, obviously.

Chriss
 
You hit the nail on the head. That is exactly what was happening. Good catch. Should have realized it was a pre compile directive that was causing the grief.

Thanx
 
One way to detect such and also completely other problems early and not just when building an EXE is to set the IDE option "compile before saving"

It has pros and cons, too, In case you have a compile problem you might not be able to save your changes until you identify problems and as you see it can be tricky to understand where a problem comes from. But then, when you make the change you also know what you changed and that narrows down the problem, usually. And one thing I also do, if compilation at saving fails is to at least save changed code as a comment

Chriss
 
A minor point:

In statements similar to the following:

[tt]STORE lnP_FIT_Amt TO m.12
m.g_fit_amt = lnP_FIT_Amt[/tt]

many developers will frown on the use of[tt] m.[/tt] This is not an error, but it is redundant to use[tt] m.[/tt] with a variable that is the target of an assignment.

Probably not worth worrying about in this case, but worth keeping in mind.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, right.

But to make your point, you should probably edit the 12 to a valid variable name.

Chriss
 
Bugzap, the point about a #DEFINE ruining the code was (and is) much more important, that's why I didn't explicitly address the aspect Mike now addressed: You put all your mdot in unnecessary places, they won't hurt anyway, but it points out several possible misunderstandings.

So let's talk about your code snippet:
Code:
STORE lnP_FIT_Amt TO m.g_fit_amt
      m.g_fit_amt = lnP_FIT_Amt
      m.g_fica_amt= lnP_FICA_Amt
      m.g_sit_amt = lnP_SIT_Amt
      m.g_oth_amt = lnP_Oth_Amt

1. Putting the mdot prefixes where they are could mean you have the complete inverse understanding of the actual meaning.
2. You could also explicitly meant field names where you didn't use mdot in your code, which means it's okay that way, but could also work exactly the same without any mdots.
3. In case of 2) you might have feared the target variable names have to be mdot prefixed to not accidentally write to fields which a following GATHER should do. Well, you can't set a field with STORE, nor can an x=y assignment ever assign anything to a field called x. For assigning to field you need REPLACE or UPDATE, there is no shortcut possible that assigns to the fields, not even just to the current workareas current record.

I assume you're not living by naming conventions standard the VFP help proposes anyway. And so I wouldn't refactor code to start using these naming conventions, as that could cause cascading effects without much profit. So, if you asked me to straighten this code, aside from not using constants with the same names as variables or fields, the most important thing to straighten here is either use STORE throughout all assignments or use the normal assignment throughout.

The way you use mdot whre they are not necessary but explicitly mean variables has one advantage for us, now: It points out all the g_ prefixed names are variables. And knowing that I could point out these names are not conventional. That would easily be explained by them being generated from SCATTER MEMVAR, though. Which means this knowledge implicitly passed to us is quite useless anyway. It doesn't tell us whether mdots should be used on the opposite side.

I actually assume all the names prefixed ln are field names, too, though they don't match the other field names with g_ prefix. They could mean variable names, which would require mdot prefix. But then your code actually could want to make use of the ambiguity of names not prefixed with mdots, so this could be intentional.

Which means, there are scenarios where the ambiguity of field vs variable name can be used, which in short means MEMVAR scattering could cause both wanted or unwanted side effects by name collisions and to decide that, you'd need to look at all code in the context, not just the excerpts you only show us.

And that finally means I can't tell you whether there lurks another problem or not.

Chriss
 
I wonder why you even have defined field names as constants. Maybe to address array elements of AFIELDS almost in the way PHP has for associative array elements addressed by a name key. Or for FIELD(n)?

Well, as you see this name collision is causing trouble, but you could of course use constant names with a prefix FN_ for field number, for example.

Or did the constants exist first, for something else and you defined a table storing related data with the same name fields? Then a field name change would of course be needed, again with a prefix as the best way to avoid a name collision.

Chriss
 
Thank you Chris and Mike for your suggestions. The name collision was caused by a poor naming convention on my part. The all caps G_ prefixed names are from #DEFINE statements that correspond to columns in a spreadsheet used as input (example shown below). Unfortunately, the spreadsheet format changes when the vendor changes releases of their software. To make things easier when that occurs, I just change the #DEFINE statements to the new spreadsheet format and do not have to go searching through a bunch of code and change column numbers.

Code:
#DEFINE G_PROJ_WORK                    1 
#DEFINE G_PERIOD_END_DATE              2    
...
#DEFINE G_DEDUCT_CODE001               83   
#DEFINE G_AMOUNT001                    84

Through the years this code has been maintained to death. I had to scan the spreadsheet and fix a number of columns that changed formats such as character dates to actual date cells, ZIP changing from character to numeric, etc. After scanning and fixing all the anomalies I then scan the spreadsheet again and actually process the data. The spreadsheet again changed format and so this go round I elected to use an updatable cursor to hold the values after the first scan. I accidentally named a few fields in the cursor the same as the #DEFINE name. As my original post showed the pre compiler substituted the field name with the #DEFINE value as it should have. It should have dawned on me when I copied the offending line to the command window and it worked without an error and only failed after the code was compiled. Unfortunately, my rust from not using FoxPro often is showing.

Again thanx for spotting the error and the commentary.
 
Ah, thanks for explaining the source of those defines.

BugZap13 said:
It should have dawned on me when I copied the offending line to the command window and it worked without an error and only failed after the code was compiled.

There's a hint in ther, if you exclude those defines from that code, a cursor with these names can be addressed. But I assume you need these constants in that code, explicitly for Excel addressing. Then obviously changing the cursor field names is the thing to do.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top