X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=macro.c;h=5aaa842a52d78d75c4808d676b384a54d5e1d914;hp=6c67bb628b6887bdc6f5381c38e96bec0cfabbb0;hb=d0c28c349ddfb8393568037f68bddbe8979ce0df;hpb=d16b8ea0ee65b2ad901ca6b0624c07e6e4930cc4 diff --git a/macro.c b/macro.c index 6c67bb6..5aaa842 100644 --- a/macro.c +++ b/macro.c @@ -3,7 +3,7 @@ // MACRO.C - Macro Definition and Invocation // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986 -// Source Utilised with the Kind Permission of Landon Dyer +// Source utilised with the kind permission of Landon Dyer // #include "macro.h" @@ -16,6 +16,7 @@ #include "symbol.h" #include "token.h" + LONG curuniq; // Current macro's unique number //TOKEN ** argp; // Free spot in argptrs[] int macnum; // Unique number for macro definition @@ -33,26 +34,31 @@ static int rptlevel; // .rept nesting level // -// Initialize Macro Processor +// Initialize macro processor // -void init_macro(void) +void InitMacro(void) { macuniq = 0; macnum = 1; // argp = NULL; argp = 0; - ib_macro(); } // -// Exit from a Macro; +// Exit from a macro; // -- pop any intervening include files and repeat blocks; // -- restore argument stack; // -- pop the macro. // -int exitmac(void) +int ExitMacro(void) { +#warning !!! Bad macro exiting !!! +/* +This is a problem. Currently, the argument logic just keeps the current +arguments and doesn't save anything if a new macro is called in the middle +of another (nested macros). Need to fix that somehow. +*/ // Pop intervening include files and .rept blocks while (cur_inobj != NULL && cur_inobj->in_type != SRC_IMACRO) fpop(); @@ -68,17 +74,19 @@ int exitmac(void) IMACRO * imacro = cur_inobj->inobj.imacro; curuniq = imacro->im_olduniq; - /*TOKEN ** p = */argp--; +// /*TOKEN ** p = */argp--; // argp = (TOKEN **)*argp; + DEBUG printf("ExitMacro: argp: %d -> ", argp); + argp -= imacro->im_nargs; + DEBUG printf("%d (nargs = %d)\n", argp, imacro->im_nargs); fpop(); - mjump_align = 0; return 0; } // -// Add a Formal Argument to a Macro Definition +// Add a formal argument to a macro definition // int defmac2(char * argname) { @@ -325,7 +333,7 @@ int lncatch(int (* lnfunc)(), char * dirlist) for(;;) { - if (tokln() == TKEOF) + if (TokenizeLine() == TKEOF) { errors("encountered end-of-file looking for '%s'", dirlist); fatal("cannot continue"); @@ -342,19 +350,11 @@ int lncatch(int (* lnfunc)(), char * dirlist) if ((tok[2] == ':' || tok[2] == DCOLON)) { if (tok[3] == SYMBOL) // label: symbol -#if 0 - p = (char *)tok[4]; -#else p = string[tok[4]]; -#endif } else { -#if 0 - p = (char *)tok[1]; // symbol -#else p = string[tok[1]]; // Symbol -#endif } } @@ -435,20 +435,20 @@ int InvokeMacro(SYM * mac, WORD siz) int dry_run; WORD arg_siz = 0; // TOKEN ** argptr = NULL; -//Doesn't need to be global! (or does it???) - argp = 0; - - if ((!strcmp(mac->sname, "mjump") || !strcmp(mac->sname, "mpad")) && !in_main) - { - error("macro cannot be used outside of .gpumain"); - return ERROR; - } +//Doesn't need to be global! (or does it???--it does) +// argp = 0; + DEBUG printf("InvokeMacro: argp: %d -> ", argp); INOBJ * inobj = a_inobj(SRC_IMACRO); // Alloc and init IMACRO IMACRO * imacro = inobj->inobj.imacro; imacro->im_siz = siz; WORD nargs = 0; TOKEN * beg_tok = tok; // 'tok' comes from token.c + TOKEN * startOfArg; + TOKEN * dest; + int stringNum = 0; + int argumentNum = 0; + int i; for(dry_run=1; ; dry_run--) { @@ -457,11 +457,14 @@ int InvokeMacro(SYM * mac, WORD siz) if (dry_run) nargs++; else + { #if 0 *argptr++ = p; #else argPtrs[argp++] = p; + startOfArg = p; #endif + } // Keep going while tok isn't pointing at a comma or EOL while (*tok != ',' && *tok != EOL) @@ -474,6 +477,7 @@ int InvokeMacro(SYM * mac, WORD siz) { case CONST: case SYMBOL: +//Shamus: Possible bug. ACONST has 2 tokens after it, not just 1 case ACONST: if (dry_run) { @@ -481,7 +485,9 @@ int InvokeMacro(SYM * mac, WORD siz) tok++; } else + { *p++ = *tok++; + } // FALLTHROUGH (picks up the arg after a CONST, SYMBOL or ACONST) default: if (dry_run) @@ -490,7 +496,9 @@ int InvokeMacro(SYM * mac, WORD siz) tok++; } else + { *p++ = *tok++; + } break; } @@ -505,6 +513,31 @@ int InvokeMacro(SYM * mac, WORD siz) // If we hit the comma instead of an EOL, skip over it if (*tok == ',') tok++; + + // Do our QnD token grabbing (this will be redone once we get all + // the data structures fixed as this is a really dirty hack) + if (!dry_run) + { + dest = imacro->argument[argumentNum].token; + stringNum = 0; + + do + { + // Remap strings to point the IMACRO internal token storage + if (*startOfArg == SYMBOL || *startOfArg == STRING) + { + *dest++ = *startOfArg++; + imacro->argument[argumentNum].string[stringNum] = strdup(string[*startOfArg++]); + *dest++ = stringNum++; + } + else + *dest++ = *startOfArg++; + } + while (*startOfArg != EOL); + + *dest = *startOfArg; // Copy EOL... + argumentNum++; + } } // Allocate space for argument ptrs and so on and then go back and @@ -512,25 +545,39 @@ int InvokeMacro(SYM * mac, WORD siz) 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); // p = (TOKEN *)malloc(arg_siz + sizeof(TOKEN)); -// This construct is meant to deal with nested macros, so the simple minded way -// we deal with them now won't work. :-/ Have to think about how to fix. +/* +Shamus: +This construct is meant to deal with nested macros, so the simple minded way +we deal with them now won't work. :-/ Have to think about how to fix. +What we could do is simply move the argp with each call, and move it back by +the number of arguments in the macro that's ending. That would solve the +problem nicely. +[Which we do now. But that uncovered another problem: the token strings are all +stale by the time a nested macro gets to the end. But they're supposed to be +symbols, which means if we put symbol references into the argument token +streams, we can alleviate this problem.] +*/ #if 0 argptr = (TOKEN **)malloc((nargs + 1) * sizeof(LONG)); *argptr++ = (TOKEN *)argp; argp = argptr; #else + // We don't need to do anything here since we already advance argp + // when parsing the arguments. +// argp += nargs; #endif } else break; } + DEBUG printf("%d\n", argp); + // Setup imacro: - // o #arguments; + // o # arguments; // o -> macro symbol; // o -> macro definition string list; // o save 'curuniq', to be restored when the macro pops; @@ -541,63 +588,21 @@ int InvokeMacro(SYM * mac, WORD siz) imacro->im_nextln = mac->lineList; imacro->im_olduniq = curuniq; curuniq = macuniq++; + imacro->argBase = argp - nargs; // Shamus: keep track of argument base DEBUG { printf("nargs=%d\n", nargs); - for(nargs=0; nargsim_nargs; ++nargs) + for(nargs=0; nargsim_nargs; nargs++) { printf("arg%d=", nargs); // dumptok(argp[imacro->im_nargs - nargs - 1]); - dumptok(argPtrs[imacro->im_nargs - nargs - 1]); +// dumptok(argPtrs[imacro->im_nargs - nargs - 1]); + dumptok(argPtrs[(argp - imacro->im_nargs) + nargs]); } } return OK; } - -// -// Setup inbuilt macros -// -void ib_macro(void) -{ - curmac = NewSymbol("mjump", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); - defmac2("jreg"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" nop", -1); - defmac1(" movei #\\addr,\\jreg", -1); - defmac1(" jump \\cc,(\\jreg)", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = NewSymbol("mjr", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("cc"); - defmac2("addr"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" jr \\cc,\\addr", -1); - defmac1(" nop", -1); - defmac1(" nop", -1); - - curmac = NewSymbol("mpad", MACRO, 0); - curmac->svalue = 0; - curmac->sattr = (WORD)(macnum++); - argno = 0; - defmac2("size"); -// curmln = NULL; - curmac->lineList = NULL; - defmac1(" .rept (\\size/2)", -1); - defmac1(" nop", -1); - defmac1(" .endr", -1); -}