-
-int invokemac(SYM *mac, WORD siz) {
- TOKEN *p = NULL;
- IMACRO *imacro;
- INOBJ *inobj;
- int dry_run;
- WORD nargs;
- WORD arg_siz = 0;
- TOKEN **argptr = NULL;
- TOKEN *beg_tok;
-
- if((!strcmp(mac->sname, "mjump") || !strcmp(mac->sname, "mpad")) && !in_main) {
- error("macro cannot be used outside of .gpumain");
- return(ERROR);
- }
-
- inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO
- imacro = inobj->inobj.imacro;
- imacro->im_siz = siz;
- nargs = 0;
- beg_tok = tok;
-
- for(dry_run = 1;; --dry_run) {
- for(tok = beg_tok; *tok != EOL;) {
- if(dry_run) ++nargs;
- else *argptr++ = p;
-
- while(*tok != ',' && *tok != EOL) {
- if(*tok == '\\' && tok[1] != EOL) ++tok;
- switch((int)*tok) {
- case CONST:
- case SYMBOL:
- case ACONST:
- if(dry_run) arg_siz += sizeof(TOKEN), ++tok;
- else *p++ = *tok++;
- // FALLTHROUGH
- default:
- if(dry_run) arg_siz += sizeof(TOKEN), ++tok;
- else *p++ = *tok++;
- break;
- }
- }
-
- if(dry_run) arg_siz += sizeof(TOKEN);
- else *p++ = EOL;
-
- if(*tok == ',') ++tok;
- }
-
- // Allocate space for argument ptrs and so on and then go back and construct the arg frame
- if(dry_run) {
- if(nargs != 0) p = (TOKEN *)malloc((LONG)(arg_siz + 1));
- argptr = (TOKEN **)malloc((LONG)((nargs + 1) * sizeof(LONG)));
- *argptr++ = (TOKEN *)argp;
- argp = argptr;
- } else
- break;
- }
-
-
- // 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_nextln = (LONG *)mac->svalue;
- imacro->im_olduniq = curuniq;
- curuniq = ++macuniq;
-
- DEBUG {
- printf("nargs=%d\n", nargs);
- for(nargs = 0; nargs < imacro->im_nargs; ++nargs) {
- printf("arg%d=", nargs);
- dumptok(argp[imacro->im_nargs - nargs - 1]);
- }
- }
-
- return(OK);
+int invokemac(SYM * mac, WORD siz)
+{
+ TOKEN * p = NULL;
+ IMACRO * imacro;
+ INOBJ * inobj;
+ int dry_run;
+ WORD nargs;
+ WORD arg_siz = 0;
+ TOKEN ** argptr = NULL;
+ TOKEN * beg_tok;
+
+ if ((!strcmp(mac->sname, "mjump") || !strcmp(mac->sname, "mpad")) && !in_main)
+ {
+ error("macro cannot be used outside of .gpumain");
+ return ERROR;
+ }
+
+ inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO
+ imacro = inobj->inobj.imacro;
+ imacro->im_siz = siz;
+ nargs = 0;
+ beg_tok = tok; // 'tok' comes from token.c
+
+ for(dry_run=1;; --dry_run)
+ {
+ for(tok=beg_tok; *tok!=EOL;)
+ {
+ if (dry_run)
+ nargs++;
+ else
+ *argptr++ = p;
+
+ // Keep going while tok isn't pointing at a comma or EOL
+ while (*tok != ',' && *tok != EOL)
+ {
+ // Skip over backslash character, unless it's followed by an EOL
+ if (*tok == '\\' && tok[1] != EOL)
+ tok++;
+
+ switch (*tok)
+ {
+ case CONST:
+ case SYMBOL:
+ case ACONST:
+ if (dry_run)
+ {
+ arg_siz += sizeof(TOKEN);
+ tok++;
+ }
+ else
+ *p++ = *tok++;
+ // FALLTHROUGH (picks up the arg after a CONST, SYMBOL or ACONST)
+ default:
+ if (dry_run)
+ {
+ arg_siz += sizeof(TOKEN);
+ tok++;
+ }
+ else
+ *p++ = *tok++;
+
+ break;
+ }
+ }
+
+ // We hit the comma or EOL, so count/stuff it
+ if (dry_run)
+ arg_siz += sizeof(TOKEN);
+ else
+ *p++ = EOL;
+
+ // If we hit the comma instead of an EOL, skip over it
+ if (*tok == ',')
+ tok++;
+ }
+
+ // Allocate space for argument ptrs and so on and then go back and
+ // construct the arg frame
+ if (dry_run)
+ {
+ if (nargs != 0)
+//Barfing here with memory corruption in glibc. TOKEN is defined as LONG, which is uint32_t
+// p = (TOKEN *)malloc(arg_siz + 1);
+ p = (TOKEN *)malloc(arg_siz + sizeof(TOKEN));
+
+ argptr = (TOKEN **)malloc((nargs + 1) * sizeof(LONG));
+ *argptr++ = (TOKEN *)argp;
+ argp = argptr;
+ }
+ else
+ break;
+ }
+
+ // 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_nextln = (TOKEN *)mac->svalue;
+ imacro->im_olduniq = curuniq;
+ curuniq = macuniq++;
+/*IMACRO {
+ IMACRO * im_link; // Pointer to ancient IMACROs
+ LONG * im_nextln; // Next line to include
+ WORD im_nargs; // # of arguments supplied on invocation
+ WORD im_siz; // Size suffix supplied on invocation
+ LONG im_olduniq; // Old value of 'macuniq'
+ SYM * im_macro; // Pointer to macro we're in
+ char im_lnbuf[LNSIZ]; // Line buffer
+};*/
+
+ DEBUG
+ {
+ printf("nargs=%d\n", nargs);
+
+ for(nargs=0; nargs<imacro->im_nargs; ++nargs)
+ {
+ printf("arg%d=", nargs);
+ dumptok(argp[imacro->im_nargs - nargs - 1]);
+ }
+ }
+
+ return OK;