]> Shamusworld >> Repos - rmac/blobdiff - macro.c
Fix for "*" getting bad section attributes, reported by A. Seed.
[rmac] / macro.c
diff --git a/macro.c b/macro.c
index 6c67bb628b6887bdc6f5381c38e96bec0cfabbb0..5aaa842a52d78d75c4808d676b384a54d5e1d914 100644 (file)
--- 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; nargs<imacro->im_nargs; ++nargs)
+               for(nargs=0; nargs<imacro->im_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);
-}