Default for optional string option in .ado program - stata

I wrote a .ado program that generates a new variable. I would like to have a
default suffix appended to the new variable, but allow a user-specified
suffix. That is, by default append _tr to the original variable's name, but
allow a user-specified suffix, say _tr1pct.
Is this possible with syntax?
My syntax line is as follows.
syntax varlist [if] [in] ///
[, Byvar(varlist) Tail(real 1) ///
Suffix(string) noRelabel]
And the suffix is applied later in the program as follows.
clonevar `x'_`suffix' = `x' ///
if `thisuse' & inrange(`pct', `tail', 100 - `tail')
I tried Suffix(string tr) and Suffix(string "tr"), but these are syntax
errors. I guess I can't have a default argument to an option (and I can't find
anything about defaults for string options, in any case).
Is there a way to give local macro suffix a default?

Yes. You can declare Suffix(string) as an option and then after syntax go
if "`suffix'" == "" local suffix "_tr"
If the user didn't specify an argument, the local macro suffix will be empty and you define what it should be. That's a default.
I don't know a reason why syntax does not allow this, but I take this to be the standard procedure given that it does not.

Related

G++ Unused Label Warning for Preprocessor Macro

I'm working through compiler warnings in a project, attempting to clean up the code, and one warning/error that has confused me is an unused-label warning for the following code.
STATE(initialize)
It says that the "initialize" label is defined but not used. STATE is a #define macro that is as follows:
#define STATE(x) x: __TRACE__("enter", #x);
And the __TRACE__ macro is as follows:
#define __TRACE__(y,x) dbg.printf(DebugIO::debug2,"FSM:" y "(" x ")\n");
Note, I did not write this code, and am just working through a project attempting to correct as many warnings as possible. But from what I can tell, the initialize label is passed to __TRACE__ where it's used as an argument for a printf() call.
So, why is it not used? Does the compiler not look at preprocessor directives for variable usage?
How would I correct this?
from what I can tell, the initialize label is passed to __TRACE__ where it's used as an argument for a printf() call.
No, it is not, actually. The x parameter of STATE() is not the same as the x parameter of __TRACE__().
In the statement STATE(initialize), the x parameter is initialize, so x: becomes simply initialize: (the label in question), but #x stringifies the input value of x as "initialize" in this case, so STATE(initialize) expands to this:
initialize: __TRACE__("enter", "initialize");
And then, in the __TRACE__ macro, the y parameter is "enter" and the x parameter is "initialize", so __TRACE__("enter", "initialize") expands to this:
dbg.printf(DebugIO::debug2,"FSM:" "enter" "(" "initialize" ")\n");
And lastly, string literals that are separated by only whitespace are merged together by the compiler, so the final code for STATE(initialize) looks like this:
initialize: dbg.printf(DebugIO::debug2,"FSM:enter(initialize)\n");;
And since there is no goto or other statement that references the initialize label, that is why you get a warning about it.
How would I correct this?
Unless there is an actual goto initialize statement in the code somewhere, I would just get rid of the label altogether:
#define STATE(x) __TRACE__("enter", #x);
The very reason for the warning is the fact that
x: TRACE...
introduces the label to be used with goto. It bears to reason that there is no goto to initialize state (it looks like we are looking at FSM implementation).
There is probably no way to remove this warning without re-working the framework (for example, adding a special state macro which does not define a label for states you never get into), but one can also just silence this particular warning for the project.
Note that __attribute__((unused)) can be used on a label.
Converting the macro argument to a string doesn't count as "using" the label that happens to have the same name (remember that labels are a separate namespace from variables anyway, let alone macro arguments).
Using the (GCC extension) unary && operator to take the address of the label might also suppress the warning, but as a rule you should avoid anything that looks like a dynamic goto unless you really know what you're doing. So prefer the attribute version.
Note also that __TRACE__ is a reserved name since it contains 2 underscores next to each other.

error while setting default macro parameters SAS 9.2

I am trying to set default variables for my macro parameters. I found this example on a site:
%macro myprint (var1, var2=t);
PROC PRINT data = &var1..&var2;
Run;
%mend myprint;
/* Macro Call */
%myprint (store,)
But when i try to run it I get ERROR: More positional parameters found than defined.
I am using SAS 9.2. Is there something different I have to do?
There are two kinds of parameters in SAS Macros: Positional parameters and named parameters. It is possible to mix them, although generally speaking a bad idea.
Named parameters are like your var2=t. They must be specified explicitly by name in the call. This is actually a 'best practice' much of the time; it ensures you have the right parameters defined (how easy is it to forget the order of the parameters in a macro?).
Named parameters can be used in any order, and can be left out (whether or not they have a default value). For example,
%macro myprint(var1=,var2=t);
...
%mend;
That would set a default for var2, but not for var1; it still must either be provided, or it will evaluate to a blank (which may be okay or may not be).
Positional parameters are exactly what they sound like: parameters defined by the location in the macro definition. They must be provided in order (of course) and if they are left out they default to blank. They cannot be provided a default value. Positional parameters must precede named parameters - ie, you could not have done
%macro myprint(var2=t,var1);
as that would confuse things too much.
So in your case, if you want to keep the 1 named 1 positional, just remove that extra ',' when you don't provide var2.

A previously defined constant, given as macro argument, is considered as string literal

Let's say I have defined a macro which does this
#define MY_MACRO(NAME) \
std::string get##NAME() const \
{ \
return doSomething(#NAME); \
}
Where doSomething method signature will be something like this
std::string doSomething(const std::string& parameter);
This works pretty well when the NAME macro parameter has no dashes in it.
For example :
#define MY_MACRO(thisIsA_test) // Works
But, when I have a dash in my string (this can happen) it won't work because dashes are not allowed in method names
#define MY_MACRO(thisIsA-test) // does NOT WORK
I have tried to work it around this way
#define thisIsAtest "thisIsA-test"
#define MY_MACRO(thisIsAtest)
Everything compiles just fine and I have the getthisIsAtest method generated but unfortunately the macro is not resolved and "thisIsAtest" is kept as string literal.
In other words the doSomething parameter string value will be "thisIsAtest" whereas I was expecting "thisIsA-test".
To expand the macro argument, just use an indirection macro.
#define stringize_literal( x ) # x
#define stringize_expanded( x ) stringize_literal( x )
Your use-case:
return doSomething( stringize_expanded( NAME ) );
Now the method will be named with name of the macro, and the function will be called with the contents of the macro. Somewhat questionable in terms of organization, but there you have it.
Why it works:
By default, macro arguments are expanded before being substituted. So if you pass thisIsAtest to parameter NAME, the macro expansion will replace NAME with "thisIsA-test". The pre-expansion step does not apply when you use a preprocessor operator # or ## though.
In your original code, one use of NAME is subject to ## and the other is subject to # so the macro definition of thisIsAtest never gets used. I just introduced a macro stringize_expanded which introduces an artificial use of NAME (via x) which is not subject to an operator.
This is the idiomatic way to use # and ##, since the expansion is desired more often than the literal macro name. You do happen to want the default behavior for ## in this case, but it could be considered a case of poor encapsulation (as the name of an interface is used to produce output), if you wanted to apply real programming principles to the problem.
There's nothing to work around.
As you have said yourself, dashes are not valid in function names.
So, do not use them.

What is the difference between Informatica parameters?

What is the difference between $myvar and $$myvar parameters in Informatica PowerCenter?
Actually $ means internal Parameter/Variable (such as $DBConnection prefix or $PMSessionLogDir) whereas $$ are used for user-defined parameters or variables (which could be defined at mapping or workflow/worklet level).
You can declare and use variables and parameters starting with $$
You can override and use pre-defined parameters starting with $PM* (i.e. $PMSessionLogDir, $PMWorkflowLogCount)
You can use without declaration parameters following predefined templates (i.e. $InputFile, $DBConnection, etc.).
I hope this all make more sense to you.
Regards,
--
YM
$ means Session Parameter/Session Variable
$$ means Mapping Parameter/Mapping Variable

How to define a pattern in macro in C++?

I have a file having too many section like
[Section]
[Section.Ia32]
[Section.x64].... so more
so, I need to define single macro to when parsing the file we can get the section using one macro. currently I am trying like,
#define APattern = "(^(\\s)*\\[Section(\\.\\w+)*\\])";
it's compile succesfully... but it is not working.
For e.g
CString a = Section;
a.compareNoCase(APattern);
it is not working..
thanks
I think the syntax in your define is incorrect. In c++ a
define
is without
"=",
rather like
#define SQR(a) (a * a).
So in your define an argument is missing as well. Do not use the
";"
at the end of the line.
And for second, you are passing the result as an argument to the function
a.compareNoCase(),
which might be incorrect in meaning of which type is returned by your define.
With #define everything you have after the name is just pasted. So for yuor example the result will be:
CString a = Section;
a.compareNoCase( = "(^(\\s)*\\[Section(\\.\\w+)*\\])"; );
You can see for yourself it is invalid syntax. For correct definition you an go backwards:
a.compareNoCase( "(^(\\s)*\\[Section(\\.\\w+)*\\])" );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-->
#define APattern "(^(\\s)*\\[Section(\\.\\w+)*\\])"
I think you have 2 problems, the first one, regarding C macro syntax, rightly addressed by fiscblog answer (+1), the other is that seems you are actually expecting a regular expression match, that is over CString capabilities. See for instance this answer to get regular expressions matching working in Visual C++
To be true, I would address the problem using sscanf, more or less like
#define ASection(In, Section) (sscanf(In, " [Section(%^[)])", Section) == 1)