Fixed a character pointer bug
[fw/sdcc] / src / SDCCglue.c
index 22db18f9080f7104ded458951d28190f6eab27f9..ab215efc917517b23a2c83596e8f347c54742e72 100644 (file)
@@ -23,6 +23,7 @@
 -------------------------------------------------------------------------*/
 
 #include "common.h"
+#include "asm.h"
 #include <time.h>
 
 symbol *interrupts[256];
@@ -30,12 +31,15 @@ symbol *interrupts[256];
 void printIval (symbol *, link *, initList *, FILE *);
 extern int noAlloc;
 set *publics = NULL;           /* public variables */
+
+/* TODO: this should be configurable (DS803C90 uses more than 6) */
 int maxInterrupts = 6;
 extern int maxRegBank ;
 symbol *mainf;
 extern char *VersionString;
 extern FILE *codeOutFile;
 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
+set *tmpfileNameSet = NULL; /* All are unlinked at close. */
 /*-----------------------------------------------------------------*/
 /* closeTmpFiles - closes all tmp files created by the compiler    */
 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
@@ -50,6 +54,21 @@ DEFSETFUNC(closeTmpFiles)
     return 0;
 }
 
+/*-----------------------------------------------------------------*/
+/* rmTmpFiles - closes all tmp files created by the compiler    */
+/*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(rmTmpFiles)
+{
+    char *name = item;
+
+    if (name) {
+       unlink(name);
+       free(name);
+    }
+    return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /* copyFile - copies source file to destination file               */
 /*-----------------------------------------------------------------*/
@@ -63,10 +82,7 @@ void copyFile (FILE * dest, FILE * src)
            fputc (ch, dest);
 }
 
-/*-----------------------------------------------------------------*/
-/* aopLiteral - string from a literal value                        */
-/*-----------------------------------------------------------------*/
-char *aopLiteral (value *val, int offset)
+char *aopLiteralLong(value *val, int offset, int size)
 {
     char *rs;
     union {
@@ -80,11 +96,24 @@ char *aopLiteral (value *val, int offset)
         unsigned long v = floatFromVal(val);
 
         v >>= (offset * 8);
-        sprintf(buffer,"#0x%02x",((char) v) & 0xff);
+       switch (size) {
+       case 1:
+           sprintf(buffer,"#0x%02x", (unsigned int)v & 0xff);
+           break;
+       case 2:
+           sprintf(buffer,"#0x%04x", (unsigned int)v & 0xffff);
+           break;
+       default:
+           /* Hmm.  Too big for now. */
+           assert(0);
+       }
         ALLOC_ATOMIC(rs,strlen(buffer)+1);
         return strcpy (rs,buffer);
     }
 
+    /* PENDING: For now size must be 1 */
+    assert(size == 1);
+
     /* it is type float */
     fl.f = (float) floatFromVal(val);
 #ifdef _BIG_ENDIAN    
@@ -96,6 +125,14 @@ char *aopLiteral (value *val, int offset)
     return strcpy (rs,buffer);
 }
 
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value                        */
+/*-----------------------------------------------------------------*/
+char *aopLiteral (value *val, int offset)
+{
+    return aopLiteralLong(val, offset, 1);
+}
+
 /*-----------------------------------------------------------------*/
 /* emitRegularMap - emit code for maps with no special cases       */
 /*-----------------------------------------------------------------*/
@@ -104,7 +141,7 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
     symbol *sym;
     
     if (addPublics)
-       fprintf (map->oFile, "\t.area\t%s\n", map->sname);
+       asm_printf(map->oFile, asm_port->area, map->sname);
     
     /* print the area name */
     for (sym = setFirstItem (map->syms); sym;
@@ -136,7 +173,7 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
            continue;
        
        /* print extra debug info if required */
-       if (options.debug || sym->level == 0) {
+       if ((options.debug || sym->level == 0) && !options.nodebug) {
 
            cdbSymbol(sym,cdbFile,FALSE,FALSE);
 
@@ -154,7 +191,7 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
        /* if is has an absolute address then generate
           an equate for this no need to allocate space */
        if (SPEC_ABSA (sym->etype)) {
-           if (options.debug || sym->level == 0)
+           if ((options.debug || sym->level == 0) && !options.nodebug)
                fprintf (map->oFile," == 0x%04x\n",SPEC_ADDR (sym->etype));         
 
            fprintf (map->oFile, "%s\t=\t0x%04x\n",
@@ -163,10 +200,10 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
        }
        else {
            /* allocate space */
-           if (options.debug || sym->level == 0)
+           if ((options.debug || sym->level == 0) && !options.nodebug)
                fprintf(map->oFile,"==.\n");
-           fprintf (map->oFile, "%s:\n", sym->rname);
-           fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+           asm_printf(map->oFile, asm_port->label, sym->rname);
+           asm_printf(map->oFile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
        }
        
        /* if it has a initial value then do it only if
@@ -212,7 +249,7 @@ value *initPointer (initList *ilist)
            val->type = newLink();
            if (SPEC_SCLS(expr->left->etype) == S_CODE) {
                DCL_TYPE(val->type) = CPOINTER ;
-               DCL_PTR_CONST(val->type) = 1;
+               DCL_PTR_CONST(val->type) = port->mem.code_ro;
            }
            else
                if (SPEC_SCLS(expr->left->etype) == S_XDATA)
@@ -224,7 +261,10 @@ value *initPointer (initList *ilist)
                        if (SPEC_SCLS(expr->left->etype) == S_IDATA)
                            DCL_TYPE(val->type) = IPOINTER ;
                        else
-                           DCL_TYPE(val->type) = POINTER ;
+                           if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
+                               DCL_TYPE(val->type) = EEPPOINTER ;
+                           else
+                               DCL_TYPE(val->type) = POINTER ;
            val->type->next = expr->left->ftype;
            val->etype = getSpec(val->type);
            return val;
@@ -265,9 +305,41 @@ void printChar (FILE * ofile, char *s, int plen)
     int i;
     int len = strlen (s);
     int pplen = 0;
-    
-    while (len && pplen < plen) {
+    char buf[100];
+    char *p = buf;
 
+    while (len && pplen < plen) {
+       while (i && *s && pplen < plen) {
+           if (*s < ' ' || *s == '\"') {
+               *p = '\0';
+               if (p != buf) 
+                   asm_printf(ofile, asm_port->ascii, buf);
+               asm_printf(ofile, asm_port->db, *s);
+               p = buf;
+           }
+           else {
+               *p = *s;
+               p++;
+           }
+           s++;
+           pplen++;
+           i--;
+       }
+       if (p != buf) {
+           *p = '\0';
+           asm_printf(ofile, asm_port->ascii, buf);
+       }
+       
+       if (len > 60)
+           len -= 60;
+       else
+           len = 0;
+    }
+    asm_printf(ofile, asm_port->db, 0);
+#if 0
+    if (pplen < plen)
+       fprintf(ofile,"\t.byte\t0\n");
+       
        fprintf (ofile, "\t.ascii /");
        i = 60;
        while (i && *s && pplen < plen) {
@@ -288,6 +360,7 @@ void printChar (FILE * ofile, char *s, int plen)
     }
     if (pplen < plen)
        fprintf(ofile,"\t.byte\t0\n");
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -312,13 +385,8 @@ void printIvalType (link * type, initList * ilist, FILE * oFile)
        break;
 
     case 2:
-       if (!val)
-           fprintf (oFile, "\t.word 0\n");
-       else
-           fprintf (oFile, "\t.byte %s,%s\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1));
-       break;
-
+    fprintf(oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
+break;
     case 4:
        if (!val)
            fprintf (oFile, "\t.word 0,0\n");
@@ -481,21 +549,49 @@ int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
 {
     int size = 0;
     
+    /* PENDING: this is _very_ mcs51 specific, including a magic
+       number... 
+       It's also endin specific.
+    */
     size = getSize (type);
-    
-    if (size == 1)
-       fprintf(oFile,
-            "\t.byte %s", val->name) ;
-    else
-       fprintf (oFile,
-                "\t.byte %s,(%s >> 8)",
-                val->name, val->name);
-   
-    if (size > 2)
-       fprintf (oFile, ",#0x02\n");
-    else
-       fprintf (oFile, "\n");
-    
+
+    if (val->name && strlen(val->name)) {
+       switch (size) {
+       case 1:
+           fprintf(oFile,
+                   "\t.byte %s\n", val->name) ;
+           break;
+       case 2:
+           fprintf(oFile, "\t.word %s\n", val->name);
+           break;
+           /* PENDING: probably just 3 */
+       default:
+           /* PENDING: 0x02 or 0x%02x, CDATA? */
+           fprintf (oFile,
+                    "\t.byte %s,(%s >> 8),#0x02\n",
+                    val->name, val->name);
+       }
+    }
+    else {
+       switch (size) {
+       case 1:
+           fprintf(oFile, "\t.byte %s\n", aopLiteral(val, 0));
+           break;
+       case 2:
+           fprintf(oFile, "\t.word %s\n", 
+                   aopLiteralLong(val, 0, 2));
+           break;
+       case 3:
+           /* PENDING: 0x02 or 0x%02x, CDATA? */
+           fprintf(oFile, "\t.byte %s,%s,0x02\n",
+                   aopLiteral (val, 0), aopLiteral (val, 1));
+           break;
+       default:
+           assert(0);
+       }
+    }
+
+
     if (val->sym && val->sym->isstrlit)
        addSet (&statsg->syms, val->sym);
     
@@ -538,9 +634,7 @@ void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
            fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
            break;
        case 2:
-           fprintf (oFile, "\t.byte %s,%s\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1));
-           
+           fprintf (oFile, "\t.word %s\n", aopLiteralLong(val, 0, 2));
            break;
        case 3:
            fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
@@ -622,7 +716,7 @@ void emitStaticSeg (memmap * map)
            addSetHead (&publics, sym);
 
        /* print extra debug info if required */
-       if (options.debug || sym->level == 0) {
+       if ((options.debug || sym->level == 0) && !options.nodebug) {
 
            cdbSymbol(sym,cdbFile,FALSE,FALSE);
 
@@ -641,7 +735,7 @@ void emitStaticSeg (memmap * map)
        
        /* if it has an absolute address */
        if (SPEC_ABSA (sym->etype)) {
-           if (options.debug || sym->level == 0)
+           if ((options.debug || sym->level == 0) && !options.nodebug)
                fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
 
            fprintf (code->oFile, "%s\t=\t0x%04x\n",
@@ -649,7 +743,7 @@ void emitStaticSeg (memmap * map)
                     SPEC_ADDR (sym->etype));
        }
        else {
-           if (options.debug || sym->level == 0)
+           if ((options.debug || sym->level == 0) && !options.nodebug)
                fprintf(code->oFile," == .\n"); 
 
            /* if it has an initial value */
@@ -669,8 +763,8 @@ void emitStaticSeg (memmap * map)
                    printChar (code->oFile,
                               SPEC_CVAL (sym->etype).v_char,
                               strlen(SPEC_CVAL (sym->etype).v_char)+1);
-               else
-                   fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
+               else 
+                   asm_printf(code->oFile, asm_port->ds, (unsigned int)getSize (sym->type)& 0xffff);
            }
        }
     }
@@ -719,16 +813,25 @@ void createInterruptVect (FILE * vFile)
     
     fprintf (vFile, "\t.area\t%s\n", CODE_NAME);
     fprintf (vFile, "__interrupt_vect:\n");
+
     
-    fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
+    if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
+    {
+        /* "generic" interrupt table header (if port doesn't specify one).
+         *
+         * Look suspiciously like 8051 code to me...
+         */
     
+       fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
     
-    /* now for the other interrupts */
-    for (; i < maxInterrupts; i++) {
-       if (interrupts[i])
-           fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
-       else
-           fprintf (vFile, "\treti\n\t.ds\t7\n");
+    
+       /* now for the other interrupts */
+       for (; i < maxInterrupts; i++) {
+               if (interrupts[i])
+                       fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
+               else
+                       fprintf (vFile, "\treti\n\t.ds\t7\n");
+       }
     }
 }
 
@@ -767,7 +870,7 @@ void printPublics (FILE * afile)
     
     for (sym = setFirstItem (publics); sym;
         sym = setNextItem (publics))
-       fprintf (afile, "\t.globl %s\n", sym->rname);
+       asm_printf(afile, asm_port->global, sym->rname);
 }
 
 /*-----------------------------------------------------------------*/
@@ -823,7 +926,7 @@ static void emitOverlay(FILE *afile)
                continue;
 
            /* print extra debug info if required */
-           if (options.debug || sym->level == 0) {
+           if ((options.debug || sym->level == 0) && !options.nodebug) {
                
                cdbSymbol(sym,cdbFile,FALSE,FALSE);
                
@@ -844,7 +947,7 @@ static void emitOverlay(FILE *afile)
               an equate for this no need to allocate space */
            if (SPEC_ABSA (sym->etype)) {
                
-               if (options.debug || sym->level == 0)
+               if ((options.debug || sym->level == 0) && !options.nodebug)
                    fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));          
 
                fprintf (afile, "%s\t=\t0x%04x\n",
@@ -852,12 +955,12 @@ static void emitOverlay(FILE *afile)
                         SPEC_ADDR (sym->etype));
            }
            else {
-               if (options.debug || sym->level == 0)
+               if ((options.debug || sym->level == 0) && !options.nodebug)
                    fprintf(afile,"==.\n");
        
                /* allocate space */
-               fprintf (afile, "%s:\n", sym->rname);
-               fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
+               asm_printf(afile, asm_port->label, sym->rname);
+               asm_printf(afile, asm_port->ds, (unsigned int)getSize (sym->type) & 0xffff);
            }
            
        }
@@ -871,15 +974,20 @@ void glue ()
 {
     FILE *vFile;
     FILE *asmFile;
-    FILE *ovrFile = tmpfile();
+    FILE *ovrFile = tempfile();
     
     addSetHead(&tmpfileSet,ovrFile);
     /* print the global struct definitions */
     if (options.debug)
        cdbStructBlock (0,cdbFile);
 
-    /* create the interrupt vector table */
-    createInterruptVect ((vFile = tmpfile ()));
+    vFile = tempfile();
+    /* PENDING: this isnt the best place but it will do */
+    if (port->general.glue_up_main) {
+       /* create the interrupt vector table */
+       createInterruptVect (vFile);
+    }
+
     addSetHead(&tmpfileSet,vFile);
     
     /* emit code for the all the variables declared */
@@ -889,8 +997,15 @@ void glue ()
 
     /* now put it all together into the assembler file */
     /* create the assembler file name */
-    sprintf (buffer, srcFileName);
-    strcat (buffer, ".asm");
+    
+    if (!options.c1mode) {
+       sprintf (buffer, srcFileName);
+       strcat (buffer, ".asm");
+    }
+    else {
+       strcpy(buffer, options.out_name);
+    }
+
     if (!(asmFile = fopen (buffer, "w"))) {
        werror (E_FILE_OPEN_ERR, buffer);
        exit (1);
@@ -900,11 +1015,16 @@ void glue ()
     initialComments (asmFile);
     
     /* print module name */
-    fprintf (asmFile, "\t.module %s\n", moduleName);
+    asm_printf(asmFile, asm_port->module, moduleName);
+    
+    /* Let the port generate any global directives, etc. */
+    if (port->genAssemblerPreamble)
+    {
+       port->genAssemblerPreamble(asmFile);
+    }
     
     /* print the global variables in this module */
     printPublics (asmFile);
-
     
     /* copy the sfr segment */
     fprintf (asmFile, "%s", iComments2);
@@ -980,7 +1100,17 @@ void glue ()
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; global & static initialisations\n");
     fprintf (asmFile, "%s", iComments2);
+    
+    /* Everywhere we generate a reference to the static_name area, 
+     * (which is currently only here), we immediately follow it with a 
+     * definition of the post_static_name area. This guarantees that
+     * the post_static_name area will immediately follow the static_name
+     * area.
+     */
     fprintf (asmFile, "\t.area %s\n", port->mem.static_name); /* MOF */
+    fprintf (asmFile, "\t.area %s\n", port->mem.post_static_name);
+    fprintf (asmFile, "\t.area %s\n", port->mem.static_name);
+    
     if (mainf && mainf->fbody) {
        fprintf (asmFile,"__sdcc_gsinit_startup:\n");
        /* if external stack is specified then the
@@ -1013,7 +1143,17 @@ void glue ()
        
     }
     copyFile (asmFile, statsg->oFile);
-    
+
+    if (port->general.glue_up_main && mainf && mainf->fbody)
+    {
+        /* This code is generated in the post-static area.
+         * This area is guaranteed to follow the static area
+         * by the ugly shucking and jiving about 20 lines ago.
+         */
+       fprintf(asmFile, "\t.area %s\n", port->mem.post_static_name);
+       fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
+    }
+       
     /* copy over code */
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; code\n");
@@ -1041,4 +1181,31 @@ void glue ()
     
     fclose (asmFile);
     applyToSet(tmpfileSet,closeTmpFiles);
+    applyToSet(tmpfileNameSet, rmTmpFiles);
+}
+
+/** Creates a temporary file a'la tmpfile which avoids the bugs
+    in cygwin wrt c:\tmp.
+    Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
+*/
+FILE *tempfile(void)
+{
+    const char *tmpdir = NULL;
+    if (getenv("TMP"))
+       tmpdir = getenv("TMP");
+    else if (getenv("TEMP"))
+       tmpdir = getenv("TEMP");
+    else if (getenv("TMPDIR"))
+       tmpdir = getenv("TMPDIR");
+    if (tmpdir) {
+       char *name = tempnam(tmpdir, "sdcc");
+       if (name) {
+           FILE *fp = fopen(name, "w+b");
+           if (fp)
+               addSetHead(&tmpfileNameSet, name);
+           return fp;
+       }
+       return NULL;
+    }
+    return tmpfile();
 }