Yes,
CMac arrays are zero-based, one of the few things in
Multi-Edit that is.
They can only occur within a struct, and can use any basic data type except for strings and nested structs (unless you nest them using a version of the technique that follows, which will become truly Byzantine). Thus, to some extent, you might consider the struct as a necessary but annoying wrapper around the array (although the struct can also contain other data elements).
If you need to keep an array around as a global, you have to go through a bit more, and there's a couple of gotchas along the way. The following example shows one way to use the global
cum string
cum struct; you could also split the initialization out as a separate macro, or eliminate it altogether if you could guarantee the global would always have a legitimate value on entering the macro. It's generally better to CYA in situations like this, though. Note that the initialized array-in-a-struct is first created in the string form used to save it as a global using the
Str_To_Struct() kernel function;
always do it this way. This sample does nothing of import, and the particular values the array is initialized to have no special import; you'll initialize it the way you want for your own application. Use this sample as a template, though (in fact, create a template if you do this kind of thing often). First, at minimum, put the following into your source (
.s) file:
- Code: Select all
#define ARRAY_SIZE 100
struct tag_State { // persistent-state structure
int aArray[ARRAY_SIZE];
}
void mSampleMacro() {
struct tag_State S; // local temporary for persistent state
str sState = g_sState; // Str_To_Struct() requires a local string
if(sState == "") { // initialize the string if necessary
int iArray;
for(iArray = 0; iArray < ARRAY_SIZE; ++iArray)
S.aArray[iArray] = iArray;
Struct_To_Str(sState, S);
}
Str_To_Struct(S, sState); // otherwise, unpack it into a struct
// do your business with S.aArray[]
Struct_To_Str(sState, S); // repack the struct into a string
g_sState = sState; // and save it out as a global
}
Then put the following into your header (
.sh) file:
- Code: Select all
global {
str g_sState "@MT_State"; // state data that must be persistent between macro calls
}
Note that globals are not themselves variables, and so, can't be directly passed to a kernel function or macro that expects a variable; hence, the use of a local temporary variable.
And a final note: I kept this sample as lean as possible, since the idea isn't all that clear to begin with, but in production code we recommend that you always use at least the
TTRACE_ENTER() and
TTRACE_LEAVE() macros. It's a lot easier to put them in when you write the macros than to try and go back and plug lots of them in later on when you need to debug something.