BookmarkSubscribeRSS Feed
CurlerBob
Fluorite | Level 6

So I was asked to look at a program that was using some macros but they are getting funny results.  It looks like some funny business going on with the original programmer so please bear with the story.

 

There was a process in place where a SAS program was run in EG.  When the program was submitted, 14 prompts were presented for the user to enter.  This was a pain.  A new programmer suggested that these prompts could be populated via a file instead and wrote some code to fill the 14 global variables from a file rather than from the prompts.  The program that the person doing the work runs originally only contained three lines of codes.  One option statement to set the location of the compiled macros and two statements that call the compiled macros.  The new code contains a file read in, a _null_ data step that creates the global variables, and the exact same three lines of code from the original program.

 

Here is where it starts to get weird.  When executing the two sets of code everything is the same except that in the new code one of the global variables gets blanked out.  Originally I thought we had a read in problem or that the symput wasn't working correctly.  However, I ran the pieces through and the blanked out global variable is populated until the second compiled macro is called.  After the macro finishes, the global variable is blanked out.  So I thought "ah-ha", I'll just look at the log and see what is going on.  I set option mprint and run the code.  Guess what?  I don't see any of the submitted statements from the compiled code in the log.  The only determination I can make is that the guy who wrote the code has an option nomprint as the very first line.  Because it is a compiled macro and we don't have access to the source code.  The guy who wrote the original thinks the new code is "less secure" and doesn't want the process to change.  He already sabotaged the new process twice but the new guy was able to get around those issues (with my help for one of them which is how I got involved).

 

That got me to thinking that the two programs were calling from different libraries.  I traced that back and no, the same macros are called in both programs.  That means that the same set of code is giving two different results.  The only difference is in the prompting.  What I can't figure out is how the macro knows if the global variables are populated from a file or a prompt.  Any thoughts or ideas on further analysis?

 

Using SAS EG 7.12 (I think) and SAS 9.4 if you think it matters.

11 REPLIES 11
ballardw
Super User

A key part of your story:

 Because it is a compiled macro and we don't have access to the source code.

 

Is the reason you don't have access to the code that it no longer exists or was it contract work and your contract didn't specify access to the completed code?

 

This sounds like it may be a scope issue where your global variable name is used as a local variable at some level but wasn't declared local and hence is overwriting the value at some point.

 

Did you by any chance try the MPRINTNEST option when you were using MPRINT? How about SYMBOLGEN and MLOGIC (this last may be helpful if only certain values are misbehaving).

 

 

 

 

 

 

CurlerBob
Fluorite | Level 6

The person I'm working with doesn't have access because the other employee is being stuborn.  Personally, if I was in this situation the other guy would be getting chewed out from his boss right now.  I think it's crazy that two programmers can't work together but there's some kind of politics going on that I'm not really privy to.  Neither of them are really SAS programmers, they code primarily in C#.

 

I didn't try MPRINTNEST or SYMBOLGEN or MLOGIC.  I figured I'd get the same reslut as with MPRINT.  We'll try it today and see what happens.

Kurt_Bremser
Super User

@CurlerBob wrote:

....... they code primarily in C#.

 


I've always thought that working in a MS environment is dangerous to one's mental health. Your experience seems to confirm this.

CurlerBob
Fluorite | Level 6

I generally avoid anyone who refers to themselves as "in IT" simply to protect my sanity Smiley Happy  That normally goes double for any object oriented programmer.  Those guys just think weird with their containers and jars Smiley Tongue  Like they're making strawberry jam or something.

Patrick
Opal | Level 21

@CurlerBob

There are severeral facets to what you describe here.

 

To answer your immediate question:

1. Make sure that you always create a new SAS session (reconnect to server) so that you don't have "left overs" from previous runs like global macro variables already created.

2. If you can't access the macro code then create the global macro variables EXACTLY the same than what the prompts generate.

- The prompts will also create macro variables and you'll get in the SAS log the %let statements.

- Just thinking that there might be something in the macro which for example blanks out the macro variable if characters aren't quoted like a prompt generated value passing would do (i.e. for a single quote).

 

MPRINT not returning anything:

Setting NOMPRINT in the compiled macro is only one option. One can also compile a macro with the SECURE option and such a macro won't allow you to access anything.

As you know where the macro store resides: You can use PROC CATALOG to at least access some metadata information of the macros (i.e. if compiled secure).

Ideally macros get compiled with the SOURCE option so it never happens that there is a compiled macro which needs investigation or change and no one can access the source code anymore and fix and recompile the macro.

 

And last but not least:

What's going on that people aren't working together? That's in my mind the primary problem to be solved. "coding fights" can only end up in messy and costly solultions.

CurlerBob
Fluorite | Level 6

I checked the prompts in a couple of ways.  However, the dev sent me a screenshot that shows an extra parameter in the prompt manager window that isn't being used in the program.  I'm wondering if this might be it.  It is also possible that he is scanning for additional user created global variables and using that as a trigger.  If I run the program so that the prompts populate the glogal variables and I compare that to the global variables created fromt he file, they look identical.  I was checking for some odd stuff like trailing or leading spaces but nothing popped out.  It's possible that there might be some imbedded command characters or something that doesn't dispaly as a text character but I don't want to go through the work of seaching for that kind of thing unless I think that is what is really going on.

 

I'll try the PROC CATALOG and see what it returns.

 

I know!  It's crazy!  I've never encountered anything like this in my nearly two decades of SAS programming!  I've seen a lot of really terrible code that creates problems like you wouldn't believe.  I've seen variable names like BigJoe and LittleJoe to represent a birthdate and street address (I'm still puzzled over how the guy was ever able to know what was going on in his programs).  I've seen people store number sas text just to convert it back to a number to do calculations, and then convert it back to text!  But I have never seen anything whare I thought someone was intentionally sabotaging a project just to "prove" he was right.  That kind of thing wouldn't fly in my department and I'm not certain what the politics are that this doesn't go right to the bosses to straighten out.  I've given my advice in that area but that's all I can really do.

Kurt_Bremser
Super User

When you're confronted with a kludge like this, there's only one really good solution:

Rewrite the macros from scratch, according to specifications. Without the source code, you'll never know what's really happening in there.

Hey, that code could send your data to Bjelarus!

Astounding
PROC Star

If you hired the first contractor, you own the source code.  Even if the macros are compiled, that contractor should produce the source code or risk not getting paid.

Reeza
Super User

@Astounding wrote:

If you hired the first contractor, you own the source code.  Even if the macros are compiled, that contractor should produce the source code or risk not getting paid.


That depends on the contract, in my org it's often still the contractor who owns the code. And this screws us over regularly Smiley Frustrated

Tom
Super User Tom
Super User

A couple of things to try.

1) Turn on the options in EG that allow you to see the code that it generates in the SAS log. Then run using the prompts and copy the %LET statements that EG generated.  Then submit those instead of using the prompts and see if you can reproduce the results.  Perhpas there is some minor difference in how the values are created or some variable you forgot to create.

 

2) So if that works then check the new "read from file" program and make sure it is making the same macro variables with the same values and that it is not by mistake making them as LOCAL macro variables that disappear before the compiled macro runs.

CurlerBob
Fluorite | Level 6

That is a really good idea.  I totally forgot about scope.  It is possible that some sort of local variables are produced that are creating adverse behavior.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 11 replies
  • 1371 views
  • 1 like
  • 7 in conversation