+int InvokeMacro(SYM * mac, WORD siz)
+{
+ DEBUG { printf("InvokeMacro: arguments="); DumpTokens(tok.u32); }
+
+ INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO
+ IMACRO * imacro = inobj->inobj.imacro;
+ uint16_t nargs = 0;
+
+ // Chop up the arguments, if any (tok comes from token.c, which at this
+ // point points at the macro argument token stream)
+ if (*tok.u32 != EOL)
+ {
+ // Parse out the arguments and set them up correctly
+ TOKEN * p = imacro->argument[nargs].token;
+ int stringNum = 0;
+
+ while (*tok.u32 != EOL)
+ {
+ if (*tok.u32 == ACONST)
+ {
+ for(int i=0; i<3; i++)
+ *p++ = *tok.u32++;
+ }
+ else if (*tok.u32 == CONST) // Constants are 64-bits
+ {
+ *p++ = *tok.u32++; // Token
+ uint64_t *p64 = (uint64_t *)p;
+ uint64_t *tok64 = (uint64_t *)tok.u32;
+ *p64++ = *tok64++;
+ tok.u32 = (TOKEN *)tok64;
+ p = (uint32_t *)p64;
+ }
+ else if ((*tok.u32 == STRING) || (*tok.u32 == SYMBOL))
+ {
+ *p++ = *tok.u32++;
+ imacro->argument[nargs].string[stringNum] = strdup(string[*tok.u32++]);
+ *p++ = stringNum++;
+ }
+ else if (*tok.u32 == ',')
+ {
+ // Comma delimiter was found, so set up for next argument
+ *p++ = EOL;
+ tok.u32++;
+ stringNum = 0;
+ nargs++;
+ p = imacro->argument[nargs].token;
+ }
+ else
+ {
+ *p++ = *tok.u32++;
+ }
+ }
+
+ // Make sure to stuff the final EOL (otherwise, it will be skipped)
+ *p++ = EOL;
+ nargs++;
+ }
+
+ // Setup IMACRO:
+ // o # arguments;
+ // o -> macro symbol;
+ // o -> macro definition string list;
+ // o save 'curuniq', to be restored when the macro pops;
+ // o bump `macuniq' counter and set 'curuniq' to it;
+ imacro->im_nargs = nargs;
+ imacro->im_macro = mac;
+ imacro->im_siz = siz;
+ imacro->im_nextln = mac->lineList;
+ imacro->im_olduniq = curuniq;
+ curuniq = macuniq++;
+
+ DEBUG
+ {
+ printf("# args = %d\n", nargs);
+
+ for(uint16_t i=0; i<nargs; i++)
+ {
+ printf("arg%d=", i);
+ DumpTokens(imacro->argument[i].token);
+ }
+ }
+
+ return OK;
+}