What is the meaning of ATS_EXTERN_PREFIX? - ats

For instance, I saw the following line in ATSLIB:
#define ATS_EXTERN_PREFIX "atslib_"
What is the meaning of ATS_EXTERN_PREFIX? what is its purpose?

If we have #define ATS_EXTERN_PREFIX "FOO_" and extern fun bar (...): ... = "mac#%", then the external name of bar becomes ${ATS_EXTERN_PREFIX}bar, i.e. FOO_bar.
Essentially, the '%' in the declaration is being replaced with the value of ATS_EXTERN_PREFIX.

Related

Batch building the same code multiple times with different values for a variable in Visual Studio

I need to build my code with a variable MyVar. I need to build it eg. 10 times but for each time, MyVar would be different, eg.
First build:
static unsigned char MyVar[] = "ABC";
Second build:
static unsigned char MyVar[] = "XYZ";
Is there an option to do this in a batch style? Eg. the command line? I just don't want to change MyVar manually, press "build", rename the built file etc.
Thanks a lot
PS: I'm not a professional coder, this could be bad practice. At the same time I'd just like to get the job done and don't want to change the code too much.
PPS: Already looked into several things (property sheets, custom macros, per-/post build actions, environment variables) but didn't find anything suitable.
Here is a sample C++ program utilizing a macro named MY_MACRO that you'll set in the CL environment variable using the /D option, before invoking MSBuild:
#include <iostream>
#include <string>
#ifndef MY_MACRO
#define MY_MACRO "unknown"
#endif
std::string greeting(const std::string& their_name)
{
static constexpr char my_name[] = MY_MACRO;
return "Hello, " + their_name + ", nice to meet you!\nMy name is " + my_name + '.';
}
int main()
{
std::cout << "Please enter your name: ";
std::string their_name;
std::cin >> their_name;
std::cout << greeting(their_name) << '\n';
}
As described in the docs mentioned above, when dealing with environment variables, you'll use the number sign (#) instead of the equal sign (=) to define a preprocessor constant with an explicit value. Also, the double-quotes (") need to be escaped (like \") when defining a string constant via command line.
To sum it up, here is a sample PowerShell script to build and collect ten different executables, each of which will be using a different string literal for the value of MY_MACRO, selected from a list of names, in a loop (note that in the script, \" needs to be expressed as \`" using a backtick before double-quotes, so that PowerShell will interpret literally those double-quotes inside a double-quoted string):
$MSBuildExe = 'C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe'
$MSBuildCmdLineArgs = #('MySolution.sln', '/property:Configuration=Release;Platform=x64', '/target:Rebuild', '/maxCpuCount')
New-Item -Force -ItemType Directory -Name 'CollectedExecutables'
$Names = #('Anni', 'Frida', 'Kadi', 'Mari', 'Piia', 'Pille', 'Piret', 'Reet', 'Siret', 'Triinu')
foreach ($MyNameString in $Names)
{
$env:CL = "/DMY_MACRO#\`"$MyNameString\`""
& $MSBuildExe $MSBuildCmdLineArgs "/property:TargetName=executable_named_$MyNameString"
Copy-Item -LiteralPath "x64\Release\executable_named_${MyNameString}.exe" -Destination 'CollectedExecutables'
}
In this script, I'm assuming you're using Visual Studio 2022; otherwise just change the value of $MSBuildExe to the appropriate path. Also, I'm assuming you want to build a Release (not Debug) configuration of your C++ project, and that you want to build for the x64 platform. If not, change those strings in the script accordingly. And of course, put the actual name of your C++ solution file (instead of MySolution.sln) into the first element of the MSBuild command-line arguments array in the script.

Append a string to a variable (function name) in #define MACRO [duplicate]

I have the following code:
#define MY_MACRO(PARAM) int PARAM_int; double PARAM_double; [subsequent instructions]
Unfortunately, it does not work, meaning that PARAM is not replaced inside the variables names. Is this solvable some way?
PARAM_int is considered to be a single token, that is distinct from PARAM. You can concatenate tokens in a macro definition with ##:
#define MY_MACRO(PARAM) int PARAM ## _int; double PARAM ## _double;
Now, PARAM will expand to whatever you invoke the macro with, and then the resulting token will be pasted together with _int and _double.

How can I use C-style macros with C++11-style constructor calls?

I've found what seems to be an incompatibility between using C-style macros and using the new unified list-initialization form introduced in C++11, but it seems incredible that this sort of thing would be absolutely impossible to write, so I assume I'm missing something.
Here's the issue: curly brackets seem to be ignored when the preprocessor looks to find a macros arguments. A call like MACR(Range{2,4}) is misinterpreted as having two arguments, Range{2 and 4. In the following code, it's all good (well, poor style, but it works) until the marked line:
#include <iostream>
using namespace std;
struct Range { int st, fn; };
ostream& operator << (ostream& out, const Range& r)
{ return out << "(" << r.st << "," << r.fn << ")"; }
#define COUT(X) (cout << (X) << endl)
int main()
{
COUT(3);
Range r {3,5};
COUT(r);
COUT(Range{3,5}); //this line won't compile
}
It gives the following error message:
badmacro.cpp:16:18: error: macro "COUT" passed 2 arguments, but takes just 1
COUT(Range{3,5});
^
compilation terminated due to -Wfatal-errors.
Especially when working with older libraries, it's sometimes unavoidable to use macro calls; surely we're not supposed to forgo the new syntax in those cases? Is there an official workaround for this?
If you need to pass an expression to an existing macro, and an expression contains unshielded commas, just enclose the whole expression in parentheses.
COUT((Range{3,5}));
Ugly? Yes, but that's what happens when you are using macros. Don't do that.
If it's not an expression and can't take extra parentheses, then you simply can't use that macro.
If you are writing a macro, which you shouldn't, sometimes you can write a variadic macro (if your compiler supports that):
#define COUT(...) cout << (__VA_ARGS__) << endl;
Preprocessor macros are just fancy text replacements prior to compiling. When calling a macro, the preprocessor does very little parsing of the parameter list. There is some logic to differentiate between commas inside of nested parenthesis versus outside, so it knows which commas belong to the parameter list of the macro itself versus commas for the parameter list of a nested function call. For example:
macro(param1, param2, func(param1, param2) )
The parameters are interpreted as
param1
param2
func(param1, param2)
Rather than
param1
param2
func(param1
param2)
In your case, your comma is not inside of nested parenthesis, so the preprocessor ends up splitting the parameter list Range{3,5} into two parameter values
Range{3
5}
Hence the error because your macro only accepts one parameter. The preprocessor does not have any context information to know that Range{3,5} should be treated as one parameter value. It just sees the comma and splits on it.
So, to solve your problem, try adding an extra pair of parenthesis:
COUT((Range{3,5}));
The preprocessor should then interpret one parameter value:
(Range{3,5})
Which will create the following statement for the compiler to consume:
(cout << ((Range{3,5})) << endl);

How to make a syntax manipulator?

Firstly, sorry for the question, I know I've heard something that could help, but I just can't remember.
Basically I would like to create my own syntax for a programming language. For example this code:
WRITE OUT 'Hello World!'
NEW LINE
would turn into this Java code:
System.out.print("Hello World!");
System.out.println();
How could I achieve this? Is there a method?
Olá.
There are techniques and proper algorithms to do that.
Search for "compiler techniques" and "Interpreter pattern".
An initial approach could be a basic pattern interpreter.
Assuming simple sentences and only one sentence per line, you could read the input file line by line and search for defined patterns (regular expressions).
The patterns describe the structure of the commands in your invented language.
If you get a match then you do the translation.
In particular, we use the regex.h library in c to perform the regular expression search.
Of course regex is also available in java.
Ex. NEW LINE match the pattern " *NEW +LINE *"
The * means that the preceding character occurs 0 or more times.
The + means that the preceding character occurs 1 or more times.
Thus, this pattern can match the command " NEW LINE " with arbitrary spaces between the words.
Ex. WRITE OUT 'Hello World!' match the pattern "WRITE OUT '([[:print:]]*)'"
or if you want to allow spaces " *WRITE +OUT +'([[:print:]]*)' *"
[[:print:]] means: match one printable character (ex. 'a' or 'Z' or '0' or '+')
Thus, [[:print:]]* match a sequence of 0, 1 or more printable characters
If a line of your input file matched the pattern of some command then you can do the translation, but in most cases you will need to retrieve some information before,
ex. the arbitrary text after WRITE OUT. Thats why you need to put parenthesis around [[:print:]]*. That will indicate to the function that perform the search that you want retrieve that particular part of your pattern.
A nice coincidence is that I recently assisted a friend with an college project similar to the problem you want to solve: a translator from c to basic. I reused that code to make an example for you.
I tested the code and it works.
It can translate:
WRITE OUT 'some text'
WRITE OUT variable
NEW LINE
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
#include <string.h>
#define STR_SHORT 100
#define MATCHES_SIZE 10
/**************************************************************
Returns the string of a match
**************************************************************/
char * GetExp(char *Source, char *Destination, regmatch_t Matches) {
//Source The string that was searched
//Destination Will contains the matched string
//Matches One element of the vector passed to regexec
int Length = Matches.rm_eo - Matches.rm_so;
strncpy(Destination, Source+Matches.rm_so, Length);
Destination[Length]=0;
return Destination;
}
/**************************************************************
MAIN
**************************************************************/
int main(int argc, char *argv[]) {
//Usage
if (argc==1) {
printf("Usage:\n");
printf("interpreter source_file\n");
printf("\n");
printf("Implements a very basic interpreter\n");
return 0;
}
//Open the source file
FILE *SourceFile;
if ( (SourceFile=fopen(argv[1], "r"))==NULL )
return 1;
//This variable is used to get the strings that matched the pattern
//Matches[0] -> the whole string being searched
//Matches[1] -> first parenthetical
//Matches[2] -> second parenthetical
regmatch_t Matches[MATCHES_SIZE];
char MatchedStr[STR_SHORT];
//Regular expression for NEW LINE
regex_t Regex_NewLine;
regcomp(&Regex_NewLine, " *NEW +LINE *", REG_EXTENDED);
//Regular expression for WRITE OUT 'some text'
regex_t Regex_WriteOutStr;
regcomp(&Regex_WriteOutStr, " *WRITE +OUT +'([[:print:]]*)' *", REG_EXTENDED);
//Regular expresion for WRITE OUT variable
regex_t Regex_WriteOutVar;
regcomp(&Regex_WriteOutVar, " *WRITE +OUT +([_[:alpha:]][[:alnum:]]*) *", REG_EXTENDED);
//Regular expression for an empty line'
regex_t Regex_EmptyLine;
regcomp(&Regex_EmptyLine, "^([[:space:]]+)$", REG_EXTENDED);
//Now we read the file line by line
char Buffer[STR_SHORT];
while( fgets(Buffer, STR_SHORT, SourceFile)!=NULL ) {
//printf("%s", Buffer);
//Shorcut for an empty line
if ( regexec(&Regex_EmptyLine, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
printf("\n");
continue;
}
//NEW LINE
if ( regexec(&Regex_NewLine, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
printf("System.out.println();\n");
continue;
}
//WRITE OUT 'some text'
if ( regexec(&Regex_WriteOutStr, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
printf("System.out.print(\"%s\");\n", GetExp(Buffer, MatchedStr, Matches[1]));
continue;
}
//WRITE OUT variable
//Assumes variable is a string variable
if ( regexec(&Regex_WriteOutVar, Buffer, MATCHES_SIZE, Matches, 0)==0 ) {
printf("System.out.print(\"%%s\", %s);\n", GetExp(Buffer, MatchedStr, Matches[1]));
continue;
}
//Unknown command
printf("Unknown command: %s", Buffer);
}
return 0;
}
Proper solution for this question requires the following steps:
Parse the original syntax code and create a syntax tree.
That is commonly done with tools like ANTLR.
Go through the syntax tree and either convert it to Java code, or to a Java syntax tree.
Both of those steps have their own complexity, so it would be better to ask separate questions about specific issues you encounter while implementing them.
Strictly speaking you can skip step 2 and generate Java directly when parsing, but unless your language is very simple renaming of Java concepts, you wouldn't be able to do that easily.

XCode: preprocessor concatenation broken?

We have a piece of cross-platform code that uses wide strings. All our string constants are wide strings and we need to use CFSTR() on some of them. We use these macros to get rid of L from wide strings:
// strip leading L"..." from wide string macros
// expand macro, e.g. turn WIDE_STRING (#define WIDE_STRING L"...") into L"..."
# define WIDE2NARROW(WideMacro) REMOVE_L(WideMacro)
// L"..." -> REM_L"..."
# define REMOVE_L(WideString) REM_##WideString
// REM_L"..." -> "..."
# define REM_L
This works on both Windows and Linux. Not on Mac – we get the following error:
“error: pasting "REM_" and "L"qm"" does not give a valid preprocessing token”
Mac example:
#define TRANSLATIONS_DIR_BASE_NAME L"Translations"
#define TRANSLATIONS_FILE_NAME_EXTENSION L"qm"
CFURLRef appUrlRef = CFBundleCopyResourceURL( CFBundleGetMainBundle()
, macTranslationFileName
, CFSTR(WIDE2NARROW(TRANSLATIONS_FILE_NAME_EXTENSION))
, CFSTR(WIDE2NARROW(TRANSLATIONS_DIR_BASE_NAME))
);
Any ideas?
During tokenization, which happens before the preprocessor language, string literals are processed. So the L"qm" is converted to a wide string literal. Which means you are trying to token paste with a string literal(and not the letter L), which C99 forbids.

Resources