-//
-// -------------------------------------------------------------------------------------------------
-// Invoke a macro
-// o parse, count and copy arguments
-// o push macro's string-stream
-// -------------------------------------------------------------------------------------------------
-//
-
-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);
-}