Get Borland C++ build working yet again
[fw/sdcc] / src / SDCCglue.c
index 131a958fb176ae8a76f249a9e053c853a6b212e4..477ad3b51ce3b2316a5d7ad13bbffc0fa3580435 100644 (file)
 -------------------------------------------------------------------------*/
 
 #include "common.h"
+#include "asm.h"
 #include <time.h>
 
+#ifndef __BORLANDC__
+// This is a bit messy because we define link ourself
+#define link NoLiNk
+#include <unistd.h>
+#undef link
+#else
+// No unistd.h in Borland C++
+#endif
+
 symbol *interrupts[256];
-/*extern char *aopLiteral (value *, int);*//* drdani Jan 30 2000 */
+
 void printIval (symbol *, link *, initList *, FILE *);
-extern int noAlloc;
 set *publics = NULL;           /* public variables */
+set *externs = NULL;           /* Varibles that are declared as extern */
 
 /* TODO: this should be configurable (DS803C90 uses more than 6) */
 int maxInterrupts = 6;
-extern int maxRegBank ;
+int allocInfo = 1;
 symbol *mainf;
-extern char *VersionString;
-extern FILE *codeOutFile;
+char *VersionString;
 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 */
@@ -52,6 +63,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               */
 /*-----------------------------------------------------------------*/
@@ -65,10 +91,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 {
@@ -82,22 +105,43 @@ 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:
+           tsprintf(buffer, "!immedbyte", (unsigned int)v & 0xff);
+           break;
+       case 2:
+           tsprintf(buffer, "!immedword", (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    
-    sprintf(buffer,"#0x%02x",fl.c[3-offset]);
+#ifdef _BIG_ENDIAN
+    tsprintf(buffer, "!immedbyte", fl.c[3-offset]);
 #else
-    sprintf(buffer,"#0x%02x",fl.c[offset]);
+    tsprintf(buffer, "!immedbyte", fl.c[offset]);
 #endif
     ALLOC_ATOMIC(rs,strlen(buffer)+1);
     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       */
 /*-----------------------------------------------------------------*/
@@ -105,16 +149,27 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
 {
     symbol *sym;
     
-    if (addPublics)
-       fprintf (map->oFile, "\t.area\t%s\n", map->sname);
+    if (addPublics) {
+       /* PENDING: special case here - should remove */
+       if (!strcmp(map->sname, CODE_NAME))
+           tfprintf(map->oFile, "\t!areacode\n", map->sname);
+       else if (!strcmp(map->sname, DATA_NAME)) 
+           tfprintf(map->oFile, "\t!areadata\n", map->sname);
+       else if (!strcmp(map->sname, HOME_NAME)) 
+           tfprintf(map->oFile, "\t!areahome\n", map->sname);
+       else
+           tfprintf(map->oFile, "\t!area\n", map->sname);
+    }
     
     /* print the area name */
     for (sym = setFirstItem (map->syms); sym;
         sym = setNextItem (map->syms))  {
        
-       /* if extern then do nothing */
-       if (IS_EXTERN (sym->etype))
+       /* if extern then add it into the extern list */
+       if (IS_EXTERN (sym->etype)) {
+           addSetHead (&externs, sym);
            continue;
+       }
        
        /* if allocation required check is needed
           then check if the symbol really requires
@@ -129,8 +184,10 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
        if ((sym->level == 0 || 
             (sym->_isparm && !IS_REGPARM(sym->etype))) &&
            addPublics &&
-           !IS_STATIC (sym->etype))
+           !IS_STATIC (sym->etype) &&
+           (sym->used || sym->fbody)) {
            addSetHead (&publics, sym);
+       }
        
        /* if extern then do nothing or is a function 
           then do nothing */
@@ -138,7 +195,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);
 
@@ -156,7 +213,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",
@@ -165,13 +222,16 @@ 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);
+           if (IS_STATIC(sym->etype))
+               tfprintf(map->oFile, "!slabeldef\n", sym->rname);
+           else
+               tfprintf(map->oFile, "!labeldef\n", sym->rname);
+           tfprintf(map->oFile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
        }
        
-       /* if it has a initial value then do it only if
+       /* if it has an initial value then do it only if
           it is a global variable */
        if (sym->ival && sym->level == 0) {
            ast *ival = NULL;
@@ -182,13 +242,14 @@ static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
                ival = newNode ('=', newAst (EX_VALUE, symbolVal (sym)),
                                decorateType (resolveSymbols (list2expr (sym->ival))));
            codeOutFile = statsg->oFile;
+           allocInfo = 0;
            eBBlockFromiCode (iCodeFromAst (ival));
+           allocInfo = 1;
            sym->ival = NULL;
        }
     }
 }
 
-
 /*-----------------------------------------------------------------*/
 /* initPointer - pointer initialization code massaging             */
 /*-----------------------------------------------------------------*/
@@ -214,7 +275,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)
@@ -226,7 +287,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;
@@ -250,7 +314,21 @@ value *initPointer (initList *ilist)
            expr->left->opval.op == PTR_OP &&
            IS_ADDRESS_OF_OP(expr->left->left))
                return valForStructElem(expr->left->left->left,
-                                       expr->left->right);     
+                                       expr->left->right);
+
+    }
+    /* case 3. (((char *) &a) +/- constant) */
+    if (IS_AST_OP(expr) && 
+       (expr->opval.op == '+' || expr->opval.op == '-') &&
+       IS_AST_OP(expr->left) && expr->left->opval.op == CAST &&
+       IS_AST_OP(expr->left->right) && 
+       expr->left->right->opval.op == '&' &&
+       IS_AST_LIT_VALUE(expr->right)) {
+       
+       return valForCastAggr(expr->left->right->left,
+                             expr->left->left->opval.lnk,
+                             expr->right,expr->opval.op);
+       
     }
 
  wrong:    
@@ -267,29 +345,102 @@ 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;
 
-       fprintf (ofile, "\t.ascii /");
+    while (len && pplen < plen) {
        i = 60;
        while (i && *s && pplen < plen) {
-           if (*s < ' ' || *s == '/') {               
-               fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
+           if (*s < ' ' || *s == '\"') {
+               *p = '\0';
+               if (p != buf) 
+                   tfprintf(ofile, "\t!ascii\n", buf);
+               tfprintf(ofile, "\t!db !constbyte\n", *s);
+               p = buf;
            }
-           else 
-               fprintf (ofile, "%c", *s++);
+           else {
+               *p = *s;
+               p++;
+           }
+           s++;
            pplen++;
            i--;
        }
-       fprintf (ofile, "/\n");
+       if (p != buf) {
+           *p = '\0';
+           tfprintf(ofile, "\t!ascii\n", buf);
+           p = buf;
+       }
        
        if (len > 60)
            len -= 60;
        else
            len = 0;
     }
-    if (pplen < plen)
-       fprintf(ofile,"\t.byte\t0\n");
+    tfprintf(ofile, "\t!db !constbyte\n", 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* return the generic pointer high byte for a given pointer type.  */
+/*-----------------------------------------------------------------*/
+int pointerTypeToGPByte(const int p_type)
+{
+    switch (p_type) 
+    {
+           case IPOINTER:
+           case POINTER:
+               return 0;
+           case GPOINTER:
+               /* hack - if we get a generic pointer, we just assume
+                * it's an FPOINTER (i.e. in XDATA space).
+                */
+           case FPOINTER:
+               return 1;
+           case CPOINTER:
+               return 2;
+           case PPOINTER:
+               return 3;
+           default:
+               fprintf(stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
+                       p_type);
+               break;
+    }
+    return -1;
+}
+    
+    
+/*-----------------------------------------------------------------*/
+/* printPointerType - generates ival for pointer type              */
+/*-----------------------------------------------------------------*/
+void _printPointerType(FILE *oFile, const char *name)
+{
+    if (IS_DS390_PORT)
+    {
+       fprintf(oFile, "\t.byte %s,(%s >> 8),(%s >> 16)",name,name,name);
+    }
+    else
+    {
+       fprintf(oFile, "\t.byte %s,(%s >> 8)",name,name);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* printPointerType - generates ival for pointer type              */
+/*-----------------------------------------------------------------*/
+void printPointerType(FILE *oFile, const char *name)
+{
+    _printPointerType(oFile, name);
+    fprintf(oFile, "\n");
+}
+
+/*-----------------------------------------------------------------*/
+/* printGPointerType - generates ival for generic pointer type     */
+/*-----------------------------------------------------------------*/
+void printGPointerType(FILE *oFile, const char *name, 
+                     const unsigned int type)
+{
+    _printPointerType(oFile,name);
+    fprintf(oFile, ",#0x%02x\n", pointerTypeToGPByte(type)); 
 }
 
 /*-----------------------------------------------------------------*/
@@ -307,31 +458,30 @@ void printIvalType (link * type, initList * ilist, FILE * oFile)
     switch (getSize (type)) {
     case 1:
        if (!val)
-           fprintf (oFile, "\t.byte 0\n");
+           tfprintf(oFile, "\t!db !constbyte\n", 0);
        else
-           fprintf (oFile, "\t.byte %s\n",
+           tfprintf(oFile, "\t!dbs\n",
                     aopLiteral (val, 0));
        break;
 
     case 2:
-       if (!val)
-           fprintf (oFile, "\t.word 0\n");
+       if (port->use_dw_for_init)
+           tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
        else
-           fprintf (oFile, "\t.byte %s,%s\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1));
+           fprintf(oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
        break;
-
     case 4:
-       if (!val)
-           fprintf (oFile, "\t.word 0,0\n");
-       else
+       if (!val) {
+           tfprintf (oFile, "\t!dw !constword\n", 0);
+           tfprintf (oFile, "\t!dw !constword\n", 0);
+       }
+       else {
            fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
                     aopLiteral (val, 0), aopLiteral (val, 1),
                     aopLiteral (val, 2), aopLiteral (val, 3));
+       }
        break;
     }
-    
-    return;
 }
 
 /*-----------------------------------------------------------------*/
@@ -381,7 +531,7 @@ int printIvalChar (link * type, initList * ilist, FILE * oFile, char *s)
            
            if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
                while (remain--)
-                   fprintf (oFile, "\t.byte 0\n");
+                   tfprintf (oFile, "\t!db !constbyte\n", 0);
            
            return 1;
        }
@@ -455,23 +605,30 @@ void printIvalFuncPtr (link * type, initList * ilist, FILE * oFile)
     val = list2val (ilist);
     /* check the types   */
     if ((dLvl = checkType (val->type, type->next)) <= 0) {
-       
-       fprintf (oFile, "\t.word 0\n");
+       tfprintf(oFile, "\t!dw !constword\n", 0);
        return;
     }
     
     /* now generate the name */
     if (!val->sym) {
-       if (IS_LITERAL (val->etype))
-           fprintf (oFile, "\t.byte %s,%s\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1));
-       else
-           fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
-                    val->name, val->name);
+        if (port->use_dw_for_init)
+       {
+           tfprintf(oFile, "\t!dws\n", val->name);
+       }
+       else  
+       {
+           printPointerType(oFile, val->name);
+       }
     }
-    else 
-       fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
-                val->sym->rname, val->sym->rname);
+    else
+       if (port->use_dw_for_init)
+       {
+           tfprintf(oFile, "\t!dws\n", val->sym->rname);
+       }
+       else
+       {
+           printPointerType(oFile, val->sym->rname);
+       }
     
     return;
 }
@@ -483,21 +640,66 @@ 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)) {
+       if (size == 1) /* This appears to be Z80 specific?? */
+       {
+           tfprintf(oFile,
+                   "\t!dbs\n", val->name);
+       }
+       else if (size == FPTRSIZE)
+       {
+           if (port->use_dw_for_init)
+           {
+               tfprintf(oFile, "\t!dws\n", val->name);
+           }
+           else
+           {
+               printPointerType(oFile, val->name);
+           }
+       }
+       else  if (size == GPTRSIZE)
+       {
+           /* PENDING: 0x02 or 0x%02x, CDATA? */
+           printGPointerType(oFile, val->name, 
+                             (IS_PTR(val->type) ? DCL_TYPE(val->type) :
+                             PTR_TYPE(SPEC_OCLS(val->etype))));
+       }
+       else
+       {
+           fprintf(stderr, "*** internal error: unknown size in "
+                           "printIvalCharPtr.\n");
+       }
+    }
+    else {
+       /* What is this case? Are these pointers? */
+       switch (size) {
+       case 1:
+           tfprintf(oFile, "\t!dbs\n", aopLiteral(val, 0));
+           break;
+       case 2:
+           if (port->use_dw_for_init)
+               tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, size));
+           else 
+               tfprintf(oFile, "\t.byte %s,%s\n", 
+                        aopLiteral(val, 0),aopLiteral(val, 1));
+           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);
     
@@ -510,6 +712,7 @@ int printIvalCharPtr (symbol * sym, link * type, value * val, FILE * oFile)
 void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
 {
     value *val;
+    int size;
     
     /* if deep then   */
     if (ilist->type == INIT_DEEP)
@@ -537,32 +740,37 @@ void printIvalPtr (symbol * sym, link * type, initList * ilist, FILE * oFile)
     if (IS_LITERAL (val->etype)) {
        switch (getSize (type)) {
        case 1:
-           fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
+           tfprintf(oFile, "\t!db !constbyte\n", (unsigned int)floatFromVal(val) & 0xff);
            break;
        case 2:
-           fprintf (oFile, "\t.byte %s,%s\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1));
-           
+           if (port->use_dw_for_init)
+               tfprintf(oFile, "\t!dws\n", aopLiteralLong(val, 0, 2));
+           else
+               tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral(val, 0),aopLiteral(val, 1));
            break;
        case 3:
-           fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
-                    aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
+           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
+                    aopLiteral (val, 0), aopLiteral (val, 1));
        }
        return;
     }
     
     
-    switch (getSize (type)) {
-    case 1:
-       fprintf (oFile, "\t.byte %s\n", val->name);
-       break;
-    case 2:
-       fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
-       break;
-       
-    case 3:
-       fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
-                val->name, val->name, DCL_TYPE(val->type));
+    size = getSize (type);
+    
+    if (size == 1)  /* Z80 specific?? */
+    {
+       tfprintf (oFile, "\t!dbs\n", val->name);
+    }
+    else if (size == FPTRSIZE)
+    {
+       tfprintf (oFile, "\t!dws\n", val->name);
+    }
+    else if (size == GPTRSIZE)
+    {
+       printGPointerType(oFile, val->name, 
+                     (IS_PTR(val->type) ? DCL_TYPE(val->type) :
+                     PTR_TYPE(SPEC_OCLS(val->etype))));
     }
     return;
 }
@@ -603,13 +811,14 @@ void printIval (symbol * sym, link * type, initList * ilist, FILE * oFile)
 /*-----------------------------------------------------------------*/
 /* emitStaticSeg - emitcode for the static segment                 */
 /*-----------------------------------------------------------------*/
-void emitStaticSeg (memmap * map)
+void emitStaticSeg(memmap * map, FILE *out)
 {
     symbol *sym;
     
     /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
-    
-    
+    if (!out)
+       out = code->oFile;
+
     /* for all variables in this segment do */
     for (sym = setFirstItem (map->syms); sym;
         sym = setNextItem (map->syms)) {
@@ -624,55 +833,55 @@ 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);
 
            if (!sym->level) { /* global */
                if (IS_STATIC(sym->etype))
-                   fprintf(code->oFile,"F%s$",moduleName); /* scope is file */
+                   fprintf(out,"F%s$",moduleName); /* scope is file */
                else
-                   fprintf(code->oFile,"G$"); /* scope is global */
+                   fprintf(out,"G$"); /* scope is global */
            }
            else
                /* symbol is local */
-               fprintf(code->oFile,"L%s$",
+               fprintf(out,"L%s$",
                        (sym->localof ? sym->localof->name : "-null-"));
-           fprintf(code->oFile,"%s$%d$%d",sym->name,sym->level,sym->block);
+           fprintf(out,"%s$%d$%d",sym->name,sym->level,sym->block);
        }
        
        /* if it has an absolute address */
        if (SPEC_ABSA (sym->etype)) {
-           if (options.debug || sym->level == 0)
-               fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
+           if ((options.debug || sym->level == 0) && !options.nodebug)
+               fprintf(out," == 0x%04x\n", SPEC_ADDR (sym->etype));
 
-           fprintf (code->oFile, "%s\t=\t0x%04x\n",
+           fprintf (out, "%s\t=\t0x%04x\n",
                     sym->rname,
                     SPEC_ADDR (sym->etype));
        }
        else {
-           if (options.debug || sym->level == 0)
-               fprintf(code->oFile," == .\n"); 
+           if ((options.debug || sym->level == 0) && !options.nodebug)
+               fprintf(out," == .\n"); 
 
            /* if it has an initial value */
            if (sym->ival) {
-               fprintf (code->oFile, "%s:\n", sym->rname);
+               fprintf (out, "%s:\n", sym->rname);
                noAlloc++;
                resolveIvalSym (sym->ival);
-               printIval (sym, sym->type, sym->ival, code->oFile);
+               printIval (sym, sym->type, sym->ival, out);
                noAlloc--;
            }
            else {
                /* allocate space */
-               fprintf (code->oFile, "%s:\n", sym->rname);
+               fprintf (out, "%s:\n", sym->rname);
                /* special case for character strings */
                if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
                    SPEC_CVAL (sym->etype).v_char)
-                   printChar (code->oFile,
+                   printChar (out,
                               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 
+                   tfprintf(out, "\t!ds\n", (unsigned int)getSize (sym->type)& 0xffff);
            }
        }
     }
@@ -691,8 +900,20 @@ void emitMaps ()
     emitRegularMap (xdata, TRUE,TRUE);
     emitRegularMap (sfr, FALSE,FALSE);
     emitRegularMap (sfrbit, FALSE,FALSE);
+    emitRegularMap (home, TRUE,FALSE);
     emitRegularMap (code, TRUE,FALSE);
-    emitStaticSeg (statsg);
+
+    emitStaticSeg (statsg, code->oFile);
+}
+
+/*-----------------------------------------------------------------*/
+/* flushStatics - flush all currently defined statics out to file  */
+/*  and delete.  Temporary function                                */
+/*-----------------------------------------------------------------*/
+void flushStatics(void)
+{
+    emitStaticSeg(statsg, codeOutFile);
+    statsg->syms = NULL;
 }
 
 /*-----------------------------------------------------------------*/
@@ -719,7 +940,7 @@ void createInterruptVect (FILE * vFile)
        return;
     }
     
-    fprintf (vFile, "\t.area\t%s\n", CODE_NAME);
+    tfprintf(vFile, "\t!areacode\n", CODE_NAME);
     fprintf (vFile, "__interrupt_vect:\n");
 
     
@@ -773,12 +994,28 @@ void printPublics (FILE * afile)
     symbol *sym;
     
     fprintf (afile, "%s", iComments2);
-    fprintf (afile, "; publics variables in this module\n");
+    fprintf (afile, "; Public variables in this module\n");
     fprintf (afile, "%s", iComments2);
     
     for (sym = setFirstItem (publics); sym;
         sym = setNextItem (publics))
-       fprintf (afile, "\t.globl %s\n", sym->rname);
+       tfprintf(afile, "\t!global\n", sym->rname);
+}
+
+/*-----------------------------------------------------------------*/
+/* printExterns - generates .global for externs                    */
+/*-----------------------------------------------------------------*/
+void printExterns (FILE * afile)
+{
+    symbol *sym;
+    
+    fprintf (afile, "%s", iComments2);
+    fprintf (afile, "; Externals used\n");
+    fprintf (afile, "%s", iComments2);
+    
+    for (sym = setFirstItem (externs); sym;
+        sym = setNextItem (externs))
+       tfprintf(afile, "\t!global\n", sym->rname);
 }
 
 /*-----------------------------------------------------------------*/
@@ -789,7 +1026,7 @@ static void emitOverlay(FILE *afile)
     set *ovrset;
     
     if (!elementsInSet(ovrSetSets))
-       fprintf(afile,"\t.area\t%s\n", port->mem.overlay_name);
+       tfprintf(afile,"\t!area\n", port->mem.overlay_name);
 
     /* for each of the sets in the overlay segment do */
     for (ovrset = setFirstItem(ovrSetSets); ovrset;
@@ -809,8 +1046,8 @@ static void emitOverlay(FILE *afile)
        
        for (sym = setFirstItem(ovrset); sym;
             sym = setNextItem(ovrset)) {
-       
-           /* if extern then do nothing */
+
+           /* if extern then add it to the publics tabledo nothing */
            if (IS_EXTERN (sym->etype))
                continue;
            
@@ -834,7 +1071,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);
                
@@ -855,7 +1092,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",
@@ -863,12 +1100,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);
+               tfprintf(afile, "!labeldef\n", sym->rname);
+               tfprintf(afile, "\t!ds\n", (unsigned int)getSize (sym->type) & 0xffff);
            }
            
        }
@@ -882,15 +1119,20 @@ void glue ()
 {
     FILE *vFile;
     FILE *asmFile;
-    FILE *ovrFile = tmpfile();
+    FILE *ovrFile = tempfile();
     
     addSetHead(&tmpfileSet,ovrFile);
     /* print the global struct definitions */
-    if (options.debug)
+    if (options.debug && !options.nodebug)
        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 */
@@ -900,8 +1142,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);
@@ -911,8 +1160,9 @@ void glue ()
     initialComments (asmFile);
     
     /* print module name */
-    fprintf (asmFile, "\t.module %s\n", moduleName);
-    
+    tfprintf(asmFile, "\t!module\n", moduleName);
+    tfprintf(asmFile, "\t!fileprelude\n");
+
     /* Let the port generate any global directives, etc. */
     if (port->genAssemblerPreamble)
     {
@@ -921,8 +1171,9 @@ void glue ()
     
     /* print the global variables in this module */
     printPublics (asmFile);
+    if (port->assembler.externGlobal)
+       printExterns (asmFile);
 
-    
     /* copy the sfr segment */
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; special function registers\n");
@@ -952,7 +1203,7 @@ void glue ()
     if (mainf && mainf->fbody) {
        fprintf (asmFile, "%s", iComments2);
        fprintf (asmFile, "; Stack segment in internal ram \n");
-       fprintf (asmFile, "%s", iComments2);    
+       fprintf (asmFile, "%s", iComments2);
        fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
                 "__start__stack:\n\t.ds\t1\n\n");
     }
@@ -997,7 +1248,17 @@ void glue ()
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; global & static initialisations\n");
     fprintf (asmFile, "%s", iComments2);
-    fprintf (asmFile, "\t.area %s\n", port->mem.static_name); /* MOF */
+    
+    /* 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.
+     */
+    tfprintf(asmFile, "\t!area\n", port->mem.static_name); /* MOF */
+    tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
+    tfprintf(asmFile, "\t!area\n", port->mem.static_name);
+    
     if (mainf && mainf->fbody) {
        fprintf (asmFile,"__sdcc_gsinit_startup:\n");
        /* if external stack is specified then the
@@ -1030,12 +1291,29 @@ 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.
+         */
+       tfprintf(asmFile, "\t!area\n", port->mem.post_static_name);
+       fprintf (asmFile,"\tljmp\t__sdcc_program_startup\n");
+    }
+
+    fprintf (asmFile,
+            "%s"
+            "; Home\n"
+            "%s", iComments2, iComments2);
+    tfprintf(asmFile, "\t!areahome\n", HOME_NAME);
+    copyFile (asmFile, home->oFile);
+
     /* copy over code */
     fprintf (asmFile, "%s", iComments2);
     fprintf (asmFile, "; code\n");
     fprintf (asmFile, "%s", iComments2);
-    fprintf (asmFile, "\t.area %s\n", port->mem.code_name);
+    tfprintf(asmFile, "\t!areacode\n", CODE_NAME);
     if (mainf && mainf->fbody) {
        
        /* entry point @ start of CSEG */
@@ -1058,4 +1336,41 @@ 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();
+}
+
+char *gc_strdup(const char *s)
+{
+    char *ret;
+    ALLOC_ATOMIC(ret, strlen(s)+1);
+    strcpy(ret, s);
+    return ret;
 }