DEFSTRUCT newbie question
#20320
31 Oct 13 11:40 AM
|
Joined: Sep 2002
Posts: 5,471
Frank
OP
Member
|
OP
Member
Joined: Sep 2002
Posts: 5,471 |
Due to some recent "plodding" i am looking at converting some legacy MAPS to structures. I was hoping to basically replace the MAP1 with DEFSTRUCT and still reference the variables as usual. This doesnt seem to be this straight forward. Do i have to first read the record into a separate instant then reference it with the name.var syntax?
i.e. the old record is MAP1 CHG$ MAP2 CHG'STAT,S,1 MAP2 CHG'PAT,B,3 ...
New: DEFSTRUCT CHG$ MAP2 CHG'STAT,S,1 MAP2 CHG'PAT,B,3
But if I read #FCN,CHG$ then try to reference the MAP2 level vars it doesnt work.. in fact it actually crashes the program.
I realize this may be over-simplifying this but i am not going to be able to change all the legacy mapped names in the bazillions of line of code if that is going to be a requirement.
Thanks.
|
|
|
Re: DEFSTRUCT newbie question
#20321
31 Oct 13 01:05 PM
|
Joined: Nov 2006
Posts: 2,223
Stephen Funkhouser
Member
|
Member
Joined: Nov 2006
Posts: 2,223 |
1. I'd remove the CHG' prefix from the MAP statement inside the DEFSTRUCT. 2. You'll have to create an instance of the DEFSTRUCT. If these are global includes then you could acheive this by putting the following where old map was defined. Notice the MAP1 instance of CHG$ inside the conditional compilation statement. ++IFNDEF CHG_STRUCT
DEFSTRCT CHG_STRUCT
MAP2 STAT,S,1
MAP2 PAT,B,3
ENDSTRUCT
MAP1 CHG'REC,CHG_STRUCT
++ENDIF Then you need to do a global find/replace of CHG' with CHG'REC. and then CHG$ CHG'REC. The order of the find/replace is important. That'll change references from CHG'STAT to CHG'REC.STAT You can use a windows program called grepWin to perform find/replace on lots of files in a directory. That'll just require Samba access to your linux source directory.
Stephen Funkhouser Diversified Data Solutions
|
|
|
Re: DEFSTRUCT newbie question
#20322
31 Oct 13 01:21 PM
|
Joined: Sep 2002
Posts: 5,471
Frank
OP
Member
|
OP
Member
Joined: Sep 2002
Posts: 5,471 |
Hey Stephen - thanks for the reply and advice. I understand now what i need to do. Unfortunately now is not a great time for us to do this makeover. (is it ever??!). There are limited time to make necessary govt changes and release the project early enough for tech support to install and train... and i don't have the luxury if you will to take on this upgrade... but i can see doing this with new records and backing that into some of the older legacy programs.
Thanks again.
|
|
|
Re: DEFSTRUCT newbie question
#20323
31 Oct 13 01:21 PM
|
Joined: Jun 2001
Posts: 11,794
Jack McGregor
Member
|
Member
Joined: Jun 2001
Posts: 11,794 |
The DEFSTRUCT (even though it contains MAP statements) does not actually allocate any variables, so you can't access them directly. (Perhaps the compiler should be more strict in detecting such an attempt). Instead, DEFSTRUCT merely defines a structure/layout, which you can then instantiate via another MAP statement, i.e. DEFSTRUCT ST_CHG
MAP2 STAT,S,1
MAP2 PAT,B,3
...
ENDSTRUCT
...
! allocate an instance of the structure...
MAP1 CHG,ST_CHG
...
READ #FCN, CHG
PRINT CHG.STAT
PRINT CHG.PAT
... The name of the structure is arbitrary (but must be unique); I like to put "ST_" in front of them just for clarity, but it isn't necessary. When I allocated the instance of the structure, using the MAP1 CHG, I could have also used any variable name, but not with a trailing $. (The trailing $ is confusing anyway, since $ is supposed to indicate a string, but in your case, CHG$ is not a string but an X variable. It's impossible though with structure variables, due to the fact that it would require a $ in the middle of the structure's member variable names, i.e. CHG$.STAT, which the compiler will simply not tolerate.) To clarify what the MAP1 CHG,ST_CHG does, it effectively generates the following MAP statements: MAP1 CHG
MAP2 CHG.STAT,S,1
MAP2 CHG.PAT,B,3
.. As you can see, all of the member variables automatically get the structure's instantiated name (CHG) prepended to the member name, with a dot in the middle. (This syntax is similar to what you may see in some other languages.) The benefit here is that you can make multiple copies of the structure without any global replace operations, i.e. MAP1 CHG2,ST_CHG
MAP1 CHG3,ST_CHG
etc.
...
CHG2.PAT = CHG3.PAT But as for converting your existing code, indeed you will need to do a lot of global replacements. That might not be too horrible though, since in the above case, you could probably just use the VUE >GLOBAL command to replace CHG' with CHG. . (You'll also have to eliminate the existing MAPs defining the CHG record and replace them with the single MAP1 CHG, ST_CHG. I would strongly recommend at the same time, if you haven't already done so, to convert to using /M to enforce the mapping of all variables (so the compiler can help you locate variables you messed up or missed in the conversion). Note that if you have a lot of unmapped variables now, you can compile with /L to generate an LSX listing which contains a section for the auto-mapped variables which you can then just ++include into your program to map them all in one fell swoop (although giving them a review first would certainly be advised). As they say, no pain, no gain. But it's really a very small amount of pain for a substantially larger gain in terms of the ease of maintaining, debugging, and generally moving forward with your code.
|
|
|
Re: DEFSTRUCT newbie question
#20324
31 Oct 13 01:22 PM
|
Joined: Jun 2001
Posts: 11,794
Jack McGregor
Member
|
Member
Joined: Jun 2001
Posts: 11,794 |
Oops, I guess Stephen beat me to it!
|
|
|
Re: DEFSTRUCT newbie question
#20325
31 Oct 13 01:27 PM
|
Joined: Sep 2002
Posts: 5,471
Frank
OP
Member
|
OP
Member
Joined: Sep 2002
Posts: 5,471 |
Thanks Jack - crossed posts! I get it.. but i am in enough "pain" with what has to get done!! we have a very short time span and i am literally worried that this will add time to the overall project that we cannot afford... not to say its not worth it in the end but in this case, i think i am going to have to push this to the next upgrade.
I do appreciate the education and recommendation and will work the new structures into the next wave of new programs.
|
|
|
Re: DEFSTRUCT newbie question
#20326
31 Oct 13 02:36 PM
|
Joined: Sep 2003
Posts: 4,158
Steve - Caliq
Member
|
Member
Joined: Sep 2003
Posts: 4,158 |
In mean time are you using functions ? Find they help speed up development as well as what Jack said about Structures: "maintaining, debugging, and generally moving forward with your code"
|
|
|
Re: DEFSTRUCT newbie question
#20327
31 Oct 13 03:24 PM
|
Joined: Sep 2002
Posts: 5,471
Frank
OP
Member
|
OP
Member
Joined: Sep 2002
Posts: 5,471 |
yes thanks! changing over to structures however is going to be like ripping the transmission out of a vw bus
|
|
|
Re: DEFSTRUCT newbie question
#20328
31 Oct 13 03:36 PM
|
Joined: Nov 2006
Posts: 2,223
Stephen Funkhouser
Member
|
Member
Joined: Nov 2006
Posts: 2,223 |
I think its more like putting a Continously Variable Transmission in the VW! Makes life much smoother.
I actually, currently maintain an old map structure, and a defstruct for a lot files. This makes writing functions that need an instance of structure easier, but doesn't require modifying all programs to use the structure. This is a nice middle ground, you just have to make sure to keep the original map and defstruct in sync. Then you can later rip out the original map statement.
Stephen Funkhouser Diversified Data Solutions
|
|
|
Re: DEFSTRUCT newbie question
#20329
31 Oct 13 03:44 PM
|
Joined: Jun 2001
Posts: 11,794
Jack McGregor
Member
|
Member
Joined: Jun 2001
Posts: 11,794 |
Note that it doesn't require an all-at-once-or-nothing approach. You could follow an incremental plan something like this:
1. For one or more existing xxxxxx.map files that you currently have, create a .def file containing the structure def(s) corresponding to the mapped record(s). If the .map files have other variables that you need besides the record structure, create a new version of the .map file (perhaps .mp2) which just removes the existing record map statements (replaced with a single MAP1 referencing the structure) but retains the other map statements that you want to keep. 2. Now, while you're working on a program, if you have an extra 2 minutes, replace the existing ++include xxxxxx.map with the .def (and .mp2 if applicable), and do the global replace(s) that were described above. A quick /M compile will help you verify that you did it correctly.
Obviously this works best if the references to the record variables aren't scattered all over a bunch of include files. If that's the case, then it might be more productive to try to reduce that problem first (using functions and parameter passing to eliminate all the direct references to file variables), before upgrading to structures.
That is actually similar to what I've been doing myself with legacy code, a little bit at a time.
I guess this is basically what Stephen just said, although I would caution that if you have two versions (the structure and traditional map) of a record variable in a program, you must be careful not to read into one and then reference the other. (Of course you could reduce that problem by immediately copying one to the other just after any READ operation, but it might still expose the possibility of one piece of code updating the CHG'xxx variable in the traditional copy, and some other piece of code updating the CHG.xxx variable in the new copy, with one being lost when you WRITE. But again, if you have updates to record variables scattered all around like that, you should probably focus on cleaning that up first.)
|
|
|
Re: DEFSTRUCT newbie question
#20330
01 Nov 13 09:03 AM
|
Joined: Jun 2001
Posts: 713
Steven Shatz
Member
|
Member
Joined: Jun 2001
Posts: 713 |
Thanks for starting this topic, Frank. There are some great ideas here. I love functions, but haven't yet switched to structures. With the suggestions here, it seems very doable. Thank you, Jack. Thank you, Stephen.
|
|
|
|
|