X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCglue.c;h=199a7c06594809094ea04fea22bd10ae527f3e39;hb=195ee3f3ee25ce2c5f2a59fbd2779c4cb80527c3;hp=7f8f3d70a4d0ad1581b794b374db04df8af23c30;hpb=38f3cafde54cd354fce784c6996ae83702412cda;p=fw%2Fsdcc diff --git a/src/SDCCglue.c b/src/SDCCglue.c index 7f8f3d70..199a7c06 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -26,24 +26,43 @@ #include "asm.h" #include #include "newalloc.h" +#include +#include -#if !defined(__BORLANDC__) && !defined(_MSC_VER) +#ifdef _WIN32 +#include +#else #include #endif -symbol *interrupts[256]; +symbol *interrupts[INTNO_MAX+1]; void printIval (symbol *, sym_link *, initList *, FILE *); -set *publics = NULL; /* public variables */ -set *externs = NULL; /* Varibles that are declared as extern */ +set *publics = NULL; /* public variables */ +set *externs = NULL; /* Variables that are declared as extern */ -/* TODO: this should be configurable (DS803C90 uses more than 6) */ -unsigned maxInterrupts = 6; +unsigned maxInterrupts = 0; int allocInfo = 1; symbol *mainf; -extern char *VersionString; -set *tmpfileSet = NULL; /* set of tmp file created by the compiler */ -set *tmpfileNameSet = NULL; /* All are unlinked at close. */ +set *pipeSet = NULL; /* set of pipes */ +set *tmpfileSet = NULL; /* set of tmp file created by the compiler */ +set *tmpfileNameSet = NULL; /* All are unlinked at close. */ + +/*-----------------------------------------------------------------*/ +/* closePipes - closes all pipes created by the compiler */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC (closePipes) +{ + FILE *pfile = item; + int ret; + + if (pfile) { + ret = pclose (pfile); + assert(ret != -1); + } + + return 0; +} /*-----------------------------------------------------------------*/ /* closeTmpFiles - closes all tmp files created by the compiler */ @@ -52,29 +71,53 @@ set *tmpfileNameSet = NULL; /* All are unlinked at close. */ DEFSETFUNC (closeTmpFiles) { FILE *tfile = item; + int ret; - if (tfile) - fclose (tfile); + if (tfile) { + ret = fclose (tfile); + assert(ret == 0); + } return 0; } /*-----------------------------------------------------------------*/ -/* rmTmpFiles - closes all tmp files created by the compiler */ +/* rmTmpFiles - unlinks all tmp files created by the compiler */ /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */ /*-----------------------------------------------------------------*/ DEFSETFUNC (rmTmpFiles) { char *name = item; + int ret; - if (name) - { - unlink (name); + if (name) { + ret = unlink (name); + assert(ret == 0); Safe_free (name); - } + } + return 0; } +/*-----------------------------------------------------------------*/ +/* rm_tmpfiles - close and remove temporary files and delete sets */ +/*-----------------------------------------------------------------*/ +void +rm_tmpfiles (void) +{ + /* close temporary files */ + applyToSet (pipeSet, closePipes); + /* close temporary files */ + deleteSet (&pipeSet); + + applyToSet (tmpfileSet, closeTmpFiles); + /* remove temporary files */ + applyToSet (tmpfileNameSet, rmTmpFiles); + /* delete temorary file sets */ + deleteSet (&tmpfileSet); + deleteSet (&tmpfileNameSet); +} + /*-----------------------------------------------------------------*/ /* copyFile - copies source file to destination file */ /*-----------------------------------------------------------------*/ @@ -92,51 +135,52 @@ copyFile (FILE * dest, FILE * src) char * aopLiteralLong (value * val, int offset, int size) { - char *rs; - union { - float f; - unsigned char c[4]; - } - fl; - - if (!val) { - // assuming we have been warned before - val=constVal("0"); - } - - /* if it is a float then it gets tricky */ - /* otherwise it is fairly simple */ - if (!IS_FLOAT (val->type)) { - unsigned long v = (unsigned long) floatFromVal (val); - - v >>= (offset * 8); - 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); - } - rs = Safe_calloc (1, 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 - tsprintf (buffer, "!immedbyte", fl.c[3 - offset]); + union { + float f; + unsigned char c[4]; + } + fl; + + if (!val) { + // assuming we have been warned before + val=constVal("0"); + } + + /* if it is a float then it gets tricky */ + /* otherwise it is fairly simple */ + if (!IS_FLOAT (val->type)) { + unsigned long v = (unsigned long) floatFromVal (val); + + v >>= (offset * 8); + switch (size) { + case 1: + tsprintf (buffer, sizeof(buffer), + "!immedbyte", (unsigned int) v & 0xff); + break; + case 2: + tsprintf (buffer, sizeof(buffer), + "!immedword", (unsigned int) v & 0xffff); + break; + default: + /* Hmm. Too big for now. */ + assert (0); + } + return Safe_strdup (buffer); + } + + /* PENDING: For now size must be 1 */ + assert (size == 1); + + /* it is type float */ + fl.f = (float) floatFromVal (val); +#ifdef WORDS_BIGENDIAN + tsprintf (buffer, sizeof(buffer), + "!immedbyte", fl.c[3 - offset]); #else - tsprintf (buffer, "!immedbyte", fl.c[offset]); + tsprintf (buffer, sizeof(buffer), + "!immedbyte", fl.c[offset]); #endif - rs = Safe_calloc (1, strlen (buffer) + 1); - return strcpy (rs, buffer); + return Safe_strdup (buffer); } /*-----------------------------------------------------------------*/ @@ -145,7 +189,7 @@ aopLiteralLong (value * val, int offset, int size) char * aopLiteral (value * val, int offset) { - return aopLiteralLong (val, offset, 1); + return aopLiteralLong (val, offset, 1); } /*-----------------------------------------------------------------*/ @@ -154,21 +198,23 @@ aopLiteral (value * val, int offset) static void emitRegularMap (memmap * map, bool addPublics, bool arFlag) { - symbol *sym, *symIval; + symbol *sym; ast *ival = NULL; - memmap *segment; + + if (!map) + return; if (addPublics) { /* PENDING: special case here - should remove */ if (!strcmp (map->sname, CODE_NAME)) - tfprintf (map->oFile, "\t!areacode\n", map->sname); + tfprintf (map->oFile, "\t!areacode\n", map->sname); else if (!strcmp (map->sname, DATA_NAME)) - tfprintf (map->oFile, "\t!areadata\n", map->sname); + tfprintf (map->oFile, "\t!areadata\n", map->sname); else if (!strcmp (map->sname, HOME_NAME)) - tfprintf (map->oFile, "\t!areahome\n", map->sname); + tfprintf (map->oFile, "\t!areahome\n", map->sname); else - tfprintf (map->oFile, "\t!area\n", map->sname); + tfprintf (map->oFile, "\t!area\n", map->sname); } for (sym = setFirstItem (map->syms); sym; @@ -176,152 +222,159 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag) { symbol *newSym=NULL; - /* if extern then add it into the extern list */ if (IS_EXTERN (sym->etype)) - { + { addSetHead (&externs, sym); - continue; - } + continue; + } /* if allocation required check is needed then check if the symbol really requires allocation only for local variables */ if (arFlag && !IS_AGGREGATE (sym->type) && - !(sym->_isparm && !IS_REGPARM (sym->etype)) && - !sym->allocreq && sym->level) - continue; + !(sym->_isparm && !IS_REGPARM (sym->etype)) && + !sym->allocreq && sym->level) + continue; /* for bitvar locals and parameters */ if (!arFlag && !sym->allocreq && sym->level - && !SPEC_ABSA (sym->etype)) { - continue; + && !SPEC_ABSA (sym->etype)) { + continue; } /* if global variable & not static or extern and addPublics allowed then add it to the public set */ if ((sym->level == 0 || - (sym->_isparm && !IS_REGPARM (sym->etype))) && - addPublics && - !IS_STATIC (sym->etype) && + (sym->_isparm && !IS_REGPARM (sym->etype))) && + addPublics && + !IS_STATIC (sym->etype) && (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1)) - { - addSetHead (&publics, sym); - } + { + addSetHead (&publics, sym); + } /* if extern then do nothing or is a function then do nothing */ - if (IS_FUNC (sym->type)) - continue; + if (IS_FUNC (sym->type) && !(sym->isitmp)) + continue; /* print extra debug info if required */ - if (options.debug) { - cdbSymbol (sym, cdbFile, FALSE, FALSE); - if (!sym->level) /* global */ - if (IS_STATIC (sym->etype)) - fprintf (map->oFile, "F%s$", moduleName); /* scope is file */ - else - fprintf (map->oFile, "G$"); /* scope is global */ - else - /* symbol is local */ - fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-")); - fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block); - } + if (options.debug) + { + if (!sym->level) /* global */ + { + if (IS_STATIC (sym->etype)) + fprintf (map->oFile, "F%s$", moduleName); /* scope is file */ + else + fprintf (map->oFile, "G$"); /* scope is global */ + } + else + { + /* symbol is local */ + fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-")); + } + fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block); + } /* if it has an initial value then do it only if it is a global variable */ if (sym->ival && sym->level == 0) { - if (SPEC_OCLS(sym->etype)==xidata) { - // create a new "XINIT (CODE)" symbol, that will be emitted later - newSym=copySymbol (sym); - SPEC_OCLS(newSym->etype)=xinit; - sprintf (newSym->name, "_xinit_%s", sym->name); - sprintf (newSym->rname,"_xinit_%s", sym->rname); - SPEC_CONST(newSym->etype)=1; - //SPEC_STAT(newSym->etype)=1; - addSym (SymbolTab, newSym, newSym->name, 0, 0, 1); - - // add it to the "XINIT (CODE)" segment - addSet(&xinit->syms, newSym); - - //fprintf (stderr, "moved %s from xdata to xidata\n", sym->rname); - - } else { - if (IS_AGGREGATE (sym->type)) { - ival = initAggregates (sym, sym->ival, NULL); - } else { - if (getNelements(sym->type, sym->ival)>1) { - werror (W_EXCESS_INITIALIZERS, "scalar", - sym->name, sym->lineDef); - } - ival = newNode ('=', newAst_VALUE (symbolVal (sym)), - decorateType (resolveSymbols (list2expr (sym->ival)))); - } - codeOutFile = statsg->oFile; - - if (ival) { - // set ival's lineno to where the symbol was defined - lineno=ival->lineno=sym->lineDef; -#if 0 - // check if this is a constant expression - if (constExprTree(ival->right)) { - allocInfo = 0; -#endif - eBBlockFromiCode (iCodeFromAst (ival)); - allocInfo = 1; -#if 0 - } else { - werror (E_CONST_EXPECTED, "found expression"); - } -#endif - } - } - - /* if the ival is a symbol assigned to an aggregate, - (bug #458099 -> #462479) - we don't need it anymore, so delete it from its segment */ - if (sym->ival->type == INIT_NODE && - IS_AST_SYM_VALUE(sym->ival->init.node) && - IS_AGGREGATE (sym->type) ) { - symIval=AST_SYMBOL(sym->ival->init.node); - segment = SPEC_OCLS (symIval->etype); - deleteSetItem (&segment->syms, symIval); - } - - sym->ival = NULL; + if (SPEC_OCLS(sym->etype)==xidata) { + /* create a new "XINIT (CODE)" symbol, that will be emitted later + in the static seg */ + newSym=copySymbol (sym); + SPEC_OCLS(newSym->etype)=xinit; + SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name); + SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname); + if (IS_SPEC (newSym->type)) + SPEC_CONST (newSym->type) = 1; + else + DCL_PTR_CONST (newSym->type) = 1; + SPEC_STAT(newSym->etype)=1; + resolveIvalSym(newSym->ival, newSym->type); + + // add it to the "XINIT (CODE)" segment + addSet(&xinit->syms, newSym); + + if (!SPEC_ABSA (sym->etype)) + { + FILE *tmpFile = tempfile (); + addSetHead (&tmpfileSet, tmpFile); + // before allocation we must parse the sym->ival tree + // but without actually generating initialization code + noAlloc++; + resolveIvalSym (sym->ival, sym->type); + printIval (sym, sym->type, sym->ival, tmpFile); + noAlloc--; + } + + sym->ival=NULL; + } else { + if (IS_AGGREGATE (sym->type)) { + ival = initAggregates (sym, sym->ival, NULL); + } else { + if (getNelements(sym->type, sym->ival)>1) { + werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", + sym->name); + } + ival = newNode ('=', newAst_VALUE (symbolVal (sym)), + decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE)); + } + codeOutFile = statsg->oFile; + + if (ival) { + // set ival's lineno to where the symbol was defined + setAstLineno (ival, lineno=sym->lineDef); + // check if this is not a constant expression + if (!constExprTree(ival)) { + werror (E_CONST_EXPECTED, "found expression"); + // but try to do it anyway + } + allocInfo = 0; + if (!astErrors(ival)) + eBBlockFromiCode (iCodeFromAst (ival)); + allocInfo = 1; + } + } + sym->ival = NULL; } - /* if is has an absolute address then generate + /* if it has an absolute address then generate an equate for this no need to allocate space */ if (SPEC_ABSA (sym->etype)) - { - if (options.debug) { - fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype)); - } - fprintf (map->oFile, "%s\t=\t0x%04x\n", - sym->rname, - SPEC_ADDR (sym->etype)); - } + { + char *equ="="; + if (options.debug) { + fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype)); + } + if (TARGET_IS_XA51) { + if (map==sfr) { + equ="sfr"; + } else if (map==bit || map==sfrbit) { + equ="bit"; + } + } + fprintf (map->oFile, "%s\t%s\t0x%04x\n", + sym->rname, equ, + SPEC_ADDR (sym->etype)); + } else { - if (newSym) { - // this has been moved to another segment - } else { - int size = getSize (sym->type); - if (size==0) { - werror(E_UNKNOWN_SIZE,sym->name); - } - /* allocate space */ - if (options.debug) { - fprintf (map->oFile, "==.\n"); - } - 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) size & 0xffff); - } + int size = getAllocSize (sym->type); + if (size==0) { + werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name); + } + /* allocate space */ + if (options.debug) { + fprintf (map->oFile, "==.\n"); + } + 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) size & 0xffff); } } } @@ -330,107 +383,138 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag) /* initPointer - pointer initialization code massaging */ /*-----------------------------------------------------------------*/ value * -initPointer (initList * ilist) +initPointer (initList * ilist, sym_link *toType) { - value *val; - ast *expr = list2expr (ilist); - - if (!expr) - goto wrong; - - /* try it the oldway first */ - if ((val = constExprValue (expr, FALSE))) - return val; - - /* no then we have to do these cludgy checks */ - /* pointers can be initialized with address of - a variable or address of an array element */ - if (IS_AST_OP (expr) && expr->opval.op == '&') { - /* address of symbol */ - if (IS_AST_SYM_VALUE (expr->left)) { - val = copyValue (AST_VALUE (expr->left)); - val->type = newLink (); - if (SPEC_SCLS (expr->left->etype) == S_CODE) { - DCL_TYPE (val->type) = CPOINTER; - DCL_PTR_CONST (val->type) = port->mem.code_ro; - } - else if (SPEC_SCLS (expr->left->etype) == S_XDATA) - DCL_TYPE (val->type) = FPOINTER; - else if (SPEC_SCLS (expr->left->etype) == S_XSTACK) - DCL_TYPE (val->type) = PPOINTER; - else if (SPEC_SCLS (expr->left->etype) == S_IDATA) - DCL_TYPE (val->type) = IPOINTER; - else 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; - } - - /* if address of indexed array */ - if (IS_AST_OP (expr->left) && expr->left->opval.op == '[') - return valForArray (expr->left); - - /* if address of structure element then - case 1. a.b ; */ - if (IS_AST_OP (expr->left) && - expr->left->opval.op == '.') { - return valForStructElem (expr->left->left, - expr->left->right); - } - - /* case 2. (&a)->b ; - (&some_struct)->element */ - if (IS_AST_OP (expr->left) && - expr->left->opval.op == PTR_OP && - IS_ADDRESS_OF_OP (expr->left->left)) - return valForStructElem (expr->left->left->left, - 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); - - } - - /* case 4. (char *)(array type) */ - if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) && - IS_ARRAY(expr->right->ftype)) { - - val = copyValue (AST_VALUE (expr->right)); - val->type = newLink (); - if (SPEC_SCLS (expr->right->etype) == S_CODE) { - DCL_TYPE (val->type) = CPOINTER; - DCL_PTR_CONST (val->type) = port->mem.code_ro; - } - else if (SPEC_SCLS (expr->right->etype) == S_XDATA) - DCL_TYPE (val->type) = FPOINTER; - else if (SPEC_SCLS (expr->right->etype) == S_XSTACK) - DCL_TYPE (val->type) = PPOINTER; - else if (SPEC_SCLS (expr->right->etype) == S_IDATA) - DCL_TYPE (val->type) = IPOINTER; - else if (SPEC_SCLS (expr->right->etype) == S_EEPROM) - DCL_TYPE (val->type) = EEPPOINTER; - else - DCL_TYPE (val->type) = POINTER; - val->type->next = expr->right->ftype->next; - val->etype = getSpec (val->type); - return val; - } + value *val; + ast *expr; + + if (!ilist) { + return valCastLiteral(toType, 0.0); + } + + expr = list2expr (ilist); + + if (!expr) + goto wrong; + + /* try it the old way first */ + if ((val = constExprValue (expr, FALSE))) + return val; + + /* ( ptr + constant ) */ + if (IS_AST_OP (expr) && + (expr->opval.op == '+' || expr->opval.op == '-') && + IS_AST_SYM_VALUE (expr->left) && + (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) && + compareType(toType, expr->left->ftype) && + IS_AST_LIT_VALUE (expr->right)) { + return valForCastAggr (expr->left, expr->left->ftype, + expr->right, + expr->opval.op); + } + + /* (char *)&a */ + if (IS_AST_OP(expr) && expr->opval.op==CAST && + IS_AST_OP(expr->right) && expr->right->opval.op=='&') { + if (compareType(toType, expr->left->ftype)!=1) { + werror (W_INIT_WRONG); + printFromToType(expr->left->ftype, toType); + } + // skip the cast ??? + expr=expr->right; + } + + /* no then we have to do these cludgy checks */ + /* pointers can be initialized with address of + a variable or address of an array element */ + if (IS_AST_OP (expr) && expr->opval.op == '&') { + /* address of symbol */ + if (IS_AST_SYM_VALUE (expr->left)) { + val = copyValue (AST_VALUE (expr->left)); + val->type = newLink (DECLARATOR); + if (SPEC_SCLS (expr->left->etype) == S_CODE) { + DCL_TYPE (val->type) = CPOINTER; + DCL_PTR_CONST (val->type) = port->mem.code_ro; + } + else if (SPEC_SCLS (expr->left->etype) == S_XDATA) + DCL_TYPE (val->type) = FPOINTER; + else if (SPEC_SCLS (expr->left->etype) == S_XSTACK) + DCL_TYPE (val->type) = PPOINTER; + else if (SPEC_SCLS (expr->left->etype) == S_IDATA) + DCL_TYPE (val->type) = IPOINTER; + else 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; + } + + /* if address of indexed array */ + if (IS_AST_OP (expr->left) && expr->left->opval.op == '[') + return valForArray (expr->left); + + /* if address of structure element then + case 1. a.b ; */ + if (IS_AST_OP (expr->left) && + expr->left->opval.op == '.') { + return valForStructElem (expr->left->left, + expr->left->right); + } + + /* case 2. (&a)->b ; + (&some_struct)->element */ + if (IS_AST_OP (expr->left) && + expr->left->opval.op == PTR_OP && + IS_ADDRESS_OF_OP (expr->left->left)) { + return valForStructElem (expr->left->left->left, + 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); + + } + /* case 4. (char *)(array type) */ + if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) && + IS_ARRAY(expr->right->ftype)) { + + val = copyValue (AST_VALUE (expr->right)); + val->type = newLink (DECLARATOR); + if (SPEC_SCLS (expr->right->etype) == S_CODE) { + DCL_TYPE (val->type) = CPOINTER; + DCL_PTR_CONST (val->type) = port->mem.code_ro; + } + else if (SPEC_SCLS (expr->right->etype) == S_XDATA) + DCL_TYPE (val->type) = FPOINTER; + else if (SPEC_SCLS (expr->right->etype) == S_XSTACK) + DCL_TYPE (val->type) = PPOINTER; + else if (SPEC_SCLS (expr->right->etype) == S_IDATA) + DCL_TYPE (val->type) = IPOINTER; + else if (SPEC_SCLS (expr->right->etype) == S_EEPROM) + DCL_TYPE (val->type) = EEPPOINTER; + else + DCL_TYPE (val->type) = POINTER; + val->type->next = expr->right->ftype->next; + val->etype = getSpec (val->type); + return val; + } wrong: - werror (W_INIT_WRONG); - return NULL; + if (expr) + werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES); + else + werror (E_INCOMPAT_PTYPES); + return NULL; } @@ -441,7 +525,7 @@ void printChar (FILE * ofile, char *s, int plen) { int i; - int len = strlen (s); + int len = plen; int pplen = 0; char buf[100]; char *p = buf; @@ -449,38 +533,42 @@ printChar (FILE * ofile, char *s, int plen) while (len && pplen < plen) { i = 60; - while (i && *s && pplen < plen) - { - if (*s < ' ' || *s == '\"' || *s=='\\') - { - *p = '\0'; - if (p != buf) - tfprintf (ofile, "\t!ascii\n", buf); - tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s); - p = buf; - } - else - { - *p = *s; - p++; - } - s++; - pplen++; - i--; - } + while (i && pplen < plen) + { + if (*s < ' ' || *s == '\"' || *s=='\\') + { + *p = '\0'; + if (p != buf) + tfprintf (ofile, "\t!ascii\n", buf); + tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s); + p = buf; + } + else + { + *p = *s; + p++; + } + s++; + pplen++; + i--; + } if (p != buf) - { - *p = '\0'; - tfprintf (ofile, "\t!ascii\n", buf); - p = buf; - } + { + *p = '\0'; + tfprintf (ofile, "\t!ascii\n", buf); + p = buf; + } if (len > 60) - len -= 60; + len -= 60; else - len = 0; + len = 0; + } + while (pplen < plen) + { + tfprintf (ofile, "\t!db !constbyte\n", 0); + pplen++; } - tfprintf (ofile, "\t!db !constbyte\n", 0); } /*-----------------------------------------------------------------*/ @@ -493,23 +581,21 @@ pointerTypeToGPByte (const int p_type, const char *iname, const char *oname) { case IPOINTER: case POINTER: - return 0; + return GPTYPE_NEAR; case GPOINTER: - /* hack - if we get a generic pointer, we just assume - * it's an FPOINTER (i.e. in XDATA space). - */ - werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname); + werror (E_CANNOT_USE_GENERIC_POINTER, + iname ? iname : "", + oname ? oname : ""); exit (1); - // fall through case FPOINTER: - return 1; + return GPTYPE_FAR; case CPOINTER: - return 2; + return GPTYPE_CODE; case PPOINTER: - return 3; + return GPTYPE_XSTACK; default: fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n", - p_type); + p_type); break; } return -1; @@ -522,14 +608,19 @@ pointerTypeToGPByte (const int p_type, const char *iname, const char *oname) void _printPointerType (FILE * oFile, const char *name) { - /* if (TARGET_IS_DS390) */ if (options.model == MODEL_FLAT24) { - fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name); + if (port->little_endian) + fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name); + else + fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name); } else { - fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name); + if (port->little_endian) + fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name); + else + fprintf (oFile, "\t.byte (%s >> 8),%s", name, name); } } @@ -548,7 +639,7 @@ printPointerType (FILE * oFile, const char *name) /*-----------------------------------------------------------------*/ void printGPointerType (FILE * oFile, const char *iname, const char *oname, - const unsigned int type) + const unsigned int type) { _printPointerType (oFile, iname); fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname)); @@ -560,52 +651,55 @@ printGPointerType (FILE * oFile, const char *iname, const char *oname, void printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile) { - value *val; - - /* if initList is deep */ - if (ilist->type == INIT_DEEP) - ilist = ilist->init.deep; - - if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) { - werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef); - } - - if (!(val = list2val (ilist))) { - // assuming a warning has been thrown - val=constVal("0"); - } - - if (val->type != type) { - val = valCastLiteral(type, floatFromVal(val)); - } - - switch (getSize (type)) { - case 1: - if (!val) - tfprintf (oFile, "\t!db !constbyte\n", 0); - else - 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, 2)); - else - fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1)); - break; - case 4: - 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; - } + value *val; + + /* if initList is deep */ + if (ilist && (ilist->type == INIT_DEEP)) + ilist = ilist->init.deep; + + if (!(val = list2val (ilist))) { + // assuming a warning has been thrown + val=constVal("0"); + } + + if (val->type != type) { + val = valCastLiteral(type, floatFromVal(val)); + } + + switch (getSize (type)) { + case 1: + if (!val) + tfprintf (oFile, "\t!db !constbyte\n", 0); + else + 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, 2)); + else if (port->little_endian) + fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1)); + else + fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0)); + break; + case 4: + if (!val) { + tfprintf (oFile, "\t!dw !constword\n", 0); + tfprintf (oFile, "\t!dw !constword\n", 0); + } + else if (port->little_endian) { + fprintf (oFile, "\t.byte %s,%s,%s,%s\n", + aopLiteral (val, 0), aopLiteral (val, 1), + aopLiteral (val, 2), aopLiteral (val, 3)); + } + else { + fprintf (oFile, "\t.byte %s,%s,%s,%s\n", + aopLiteral (val, 3), aopLiteral (val, 2), + aopLiteral (val, 1), aopLiteral (val, 0)); + } + break; + } } /*-----------------------------------------------------------------*/ @@ -613,49 +707,49 @@ printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile) /*-----------------------------------------------------------------*/ void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile) { - value *val ; - symbol *lsym = *sym; - initList *lilist = *ilist ; - unsigned long ival = 0; - int size =0; - - - do { - unsigned long i; - val = list2val(lilist); - if (size) { - if (SPEC_BLEN(lsym->etype) > 8) { - size += ((SPEC_BLEN (lsym->etype) / 8) + - (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0)); - } - } else { - size = ((SPEC_BLEN (lsym->etype) / 8) + - (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0)); - } - i = (unsigned long)floatFromVal(val); - i <<= SPEC_BSTR (lsym->etype); - ival |= i; - if (! ( lsym->next && - (IS_BITFIELD(lsym->next->type)) && - (SPEC_BSTR(lsym->next->etype)))) break; - lsym = lsym->next; - lilist = lilist->next; - } while (1); - switch (size) { - case 1: - tfprintf (oFile, "\t!db !constbyte\n",ival); - break; - - case 2: - tfprintf (oFile, "\t!dw !constword\n",ival); - break; - case 4: - tfprintf (oFile, "\t!db !constword,!constword\n", - (ival >> 8) & 0xffff, (ival & 0xffff)); - break; - } - *sym = lsym; - *ilist = lilist; + value *val ; + symbol *lsym = *sym; + initList *lilist = *ilist ; + unsigned long ival = 0; + int size =0; + + + do { + unsigned long i; + val = list2val(lilist); + if (size) { + if (SPEC_BLEN(lsym->etype) > 8) { + size += ((SPEC_BLEN (lsym->etype) / 8) + + (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0)); + } + } else { + size = ((SPEC_BLEN (lsym->etype) / 8) + + (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0)); + } + i = (unsigned long)floatFromVal(val); + i <<= SPEC_BSTR (lsym->etype); + ival |= i; + if (! ( lsym->next && + (IS_BITFIELD(lsym->next->type)) && + (SPEC_BSTR(lsym->next->etype)))) break; + lsym = lsym->next; + lilist = lilist->next; + } while (1); + switch (size) { + case 1: + tfprintf (oFile, "\t!db !constbyte\n",ival); + break; + + case 2: + tfprintf (oFile, "\t!dw !constword\n",ival); + break; + case 4: /* EEP: why is this db and not dw? */ + tfprintf (oFile, "\t!db !constword,!constword\n", + (ival >> 8) & 0xffff, (ival & 0xffff)); + break; + } + *sym = lsym; + *ilist = lilist; } /*-----------------------------------------------------------------*/ @@ -663,30 +757,33 @@ void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile) /*-----------------------------------------------------------------*/ void printIvalStruct (symbol * sym, sym_link * type, - initList * ilist, FILE * oFile) + initList * ilist, FILE * oFile) { - symbol *sflds; - initList *iloop; - - sflds = SPEC_STRUCT (type)->fields; - if (ilist->type != INIT_DEEP) { - werror (E_INIT_STRUCT, sym->name); - return; - } - - iloop = ilist->init.deep; - - for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) { - if (IS_BITFIELD(sflds->type)) { - printIvalBitFields(&sflds,&iloop,oFile); - } else { - printIval (sym, sflds->type, iloop, oFile); - } - } - if (iloop) { - werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef); - } - return; + symbol *sflds; + initList *iloop = NULL; + + sflds = SPEC_STRUCT (type)->fields; + + if (ilist) { + if (ilist->type != INIT_DEEP) { + werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name); + return; + } + + iloop = ilist->init.deep; + } + + for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) { + if (IS_BITFIELD(sflds->type)) { + printIvalBitFields(&sflds,&iloop,oFile); + } else { + printIval (sym, sflds->type, iloop, oFile); + } + } + if (iloop) { + werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name); + } + return; } /*-----------------------------------------------------------------*/ @@ -696,7 +793,6 @@ int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s) { value *val; - int remain; if (!s) { @@ -704,20 +800,16 @@ printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s) val = list2val (ilist); /* if the value is a character string */ if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) - { - if (!DCL_ELEM (type)) - DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1; - - printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type)); + { + if (!DCL_ELEM (type)) + DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1; - if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) - while (remain--) - tfprintf (oFile, "\t!db !constbyte\n", 0); + printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type)); - return 1; - } + return 1; + } else - return 0; + return 0; } else printChar (oFile, s, strlen (s) + 1); @@ -727,58 +819,54 @@ printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s) /*-----------------------------------------------------------------*/ /* printIvalArray - generates code for array initialization */ /*-----------------------------------------------------------------*/ -void +void printIvalArray (symbol * sym, sym_link * type, initList * ilist, - FILE * oFile) + FILE * oFile) { initList *iloop; - int lcnt = 0, size = 0; - - /* take care of the special case */ - /* array of characters can be init */ - /* by a string */ - if (IS_CHAR (type->next)) - if (printIvalChar (type, - (ilist->type == INIT_DEEP ? ilist->init.deep : ilist), - oFile, SPEC_CVAL (sym->etype).v_char)) - return; - - /* not the special case */ - if (ilist->type != INIT_DEEP) - { - werror (E_INIT_STRUCT, sym->name); + unsigned int size = 0; + + if (ilist) { + /* take care of the special case */ + /* array of characters can be init */ + /* by a string */ + if (IS_CHAR (type->next)) { + if (!IS_LITERAL(list2val(ilist)->etype)) { + werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED); + return; + } + if (printIvalChar (type, + (ilist->type == INIT_DEEP ? ilist->init.deep : ilist), + oFile, SPEC_CVAL (sym->etype).v_char)) + return; + } + /* not the special case */ + if (ilist->type != INIT_DEEP) { + werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name); return; } - iloop = ilist->init.deep; - lcnt = DCL_ELEM (type); - - for (;;) - { - size++; + for (iloop=ilist->init.deep; iloop; iloop=iloop->next) { + if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) { + werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name); + break; + } printIval (sym, type->next, iloop, oFile); - iloop = (iloop ? iloop->next : NULL); - - - /* if not array limits given & we */ - /* are out of initialisers then */ - if (!DCL_ELEM (type) && !iloop) - break; - - /* no of elements given and we */ - /* have generated for all of them */ - if (!--lcnt) { - /* if initializers left */ - if (iloop) { - werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef); - } - break; + } + } + + if (DCL_ELEM(type)) { + // pad with zeros if needed + if (sizenext); + while (size--) { + tfprintf (oFile, "\t!db !constbyte\n", 0); } } - - /* if we have not been given a size */ - if (!DCL_ELEM (type)) + } else { + // we have not been given a size, but we now know it DCL_ELEM (type) = size; + } return; } @@ -792,7 +880,25 @@ printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile) value *val; int dLvl = 0; - val = list2val (ilist); + if (ilist) + val = list2val (ilist); + else + val = valCastLiteral(type, 0.0); + + if (!val) { + // an error has been thrown already + val=constVal("0"); + } + + if (IS_LITERAL(val->etype)) { + if (compareType(type, val->etype) == 0) { + werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES); + printFromToType (val->type, type); + } + printIvalCharPtr (NULL, type, val, oFile); + return; + } + /* check the types */ if ((dLvl = compareType (val->type, type->next)) <= 0) { @@ -804,13 +910,13 @@ printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile) if (!val->sym) { if (port->use_dw_for_init) - { - tfprintf (oFile, "\t!dws\n", val->name); - } + { + tfprintf (oFile, "\t!dws\n", val->name); + } else - { - printPointerType (oFile, val->name); - } + { + printPointerType (oFile, val->name); + } } else if (port->use_dw_for_init) { @@ -840,81 +946,99 @@ printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile) if (val->name && strlen (val->name)) { - if (size == 1) /* This appears to be Z80 specific?? */ - { - tfprintf (oFile, - "\t!dbs\n", 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); - } - } + { + if (port->use_dw_for_init) + { + tfprintf (oFile, "\t!dws\n", val->name); + } + else + { + printPointerType (oFile, val->name); + } + } else if (size == GPTRSIZE) - { - int type; - if (IS_PTR (val->type)) { - type = DCL_TYPE (val->type); - } else { - type = PTR_TYPE (SPEC_OCLS (val->etype)); - } - if (val->sym && val->sym->isstrlit) { - // this is a literal string - type=CPOINTER; - } - printGPointerType (oFile, val->name, sym->name, type); - } + { + int type; + if (IS_PTR (val->type)) { + type = DCL_TYPE (val->type); + } else { + type = PTR_TYPE (SPEC_OCLS (val->etype)); + } + if (val->sym && val->sym->isstrlit) { + // this is a literal string + type=CPOINTER; + } + printGPointerType (oFile, val->name, sym->name, type); + } else - { - fprintf (stderr, "*** internal error: unknown size in " - "printIvalCharPtr.\n"); - } + { + fprintf (stderr, "*** internal error: unknown size in " + "printIvalCharPtr.\n"); + } } else { // these are literals assigned to 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: - // mcs51 generic pointer - if (floatFromVal(val)!=0) { - werror (E_LITERAL_GENERIC); - } - fprintf (oFile, "\t.byte %s,%s,%s\n", - aopLiteral (val, 0), - aopLiteral (val, 1), - aopLiteral (val, 2)); - break; - case 4: - // ds390 generic pointer - if (floatFromVal(val)!=0) { - werror (E_LITERAL_GENERIC); - } - fprintf (oFile, "\t.byte %s,%s,%s,%s\n", - aopLiteral (val, 0), - aopLiteral (val, 1), - aopLiteral (val, 2), - aopLiteral (val, 3)); - break; - default: - assert (0); - } + { + 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 if (port->little_endian) + tfprintf (oFile, "\t.byte %s,%s\n", + aopLiteral (val, 0), aopLiteral (val, 1)); + else + tfprintf (oFile, "\t.byte %s,%s\n", + aopLiteral (val, 1), aopLiteral (val, 0)); + break; + case 3: + if (IS_GENPTR(type) && floatFromVal(val)!=0) { + // non-zero mcs51 generic pointer + werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC); + } + if (port->little_endian) { + fprintf (oFile, "\t.byte %s,%s,%s\n", + aopLiteral (val, 0), + aopLiteral (val, 1), + aopLiteral (val, 2)); + } else { + fprintf (oFile, "\t.byte %s,%s,%s\n", + aopLiteral (val, 2), + aopLiteral (val, 1), + aopLiteral (val, 0)); + } + break; + case 4: + if (IS_GENPTR(type) && floatFromVal(val)!=0) { + // non-zero ds390 generic pointer + werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC); + } + if (port->little_endian) { + fprintf (oFile, "\t.byte %s,%s,%s,%s\n", + aopLiteral (val, 0), + aopLiteral (val, 1), + aopLiteral (val, 2), + aopLiteral (val, 3)); + } else { + fprintf (oFile, "\t.byte %s,%s,%s,%s\n", + aopLiteral (val, 3), + aopLiteral (val, 2), + aopLiteral (val, 1), + aopLiteral (val, 0)); + } + break; + default: + assert (0); + } } if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) { @@ -934,7 +1058,7 @@ printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) int size; /* if deep then */ - if (ilist->type == INIT_DEEP) + if (ilist && (ilist->type == INIT_DEEP)) ilist = ilist->init.deep; /* function pointer */ @@ -944,7 +1068,7 @@ printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) return; } - if (!(val = initPointer (ilist))) + if (!(val = initPointer (ilist, type))) return; /* if character pointer */ @@ -953,50 +1077,69 @@ printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) return; /* check the type */ - if (compareType (type, val->type) == 0) - werror (W_INIT_WRONG); + if (compareType (type, val->type) == 0) { + werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG); + printFromToType (val->type, type); + } /* if val is literal */ if (IS_LITERAL (val->etype)) { switch (getSize (type)) - { - case 1: - tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff); - break; - case 2: - 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,#0x02\n", - aopLiteral (val, 0), aopLiteral (val, 1)); - } + { + case 1: + tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff); + break; + case 2: + if (port->use_dw_for_init) + tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2)); + else if (port->little_endian) + tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1)); + else + tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0)); + break; + case 3: // how about '390?? + fprintf (oFile, "; generic printIvalPtr\n"); + if (port->little_endian) + { + fprintf (oFile, "\t.byte %s,%s", + aopLiteral (val, 0), aopLiteral (val, 1)); + } + else + { + fprintf (oFile, "\t.byte %s,%s", + aopLiteral (val, 1), aopLiteral (val, 0)); + } + if (IS_GENPTR (val->type)) + fprintf (oFile, ",%s\n", aopLiteral (val, 2)); + else if (IS_PTR (val->type)) + fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL)); + else + fprintf (oFile, ",%s\n", aopLiteral (val, 2)); + } return; } size = getSize (type); - if (size == 1) /* Z80 specific?? */ + if (size == 1) /* 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); + tfprintf (oFile, "\t!dws\n", val->name); } else { - printPointerType (oFile, val->name); + printPointerType (oFile, val->name); } } else if (size == GPTRSIZE) { printGPointerType (oFile, val->name, sym->name, - (IS_PTR (val->type) ? DCL_TYPE (val->type) : - PTR_TYPE (SPEC_OCLS (val->etype)))); + (IS_PTR (val->type) ? DCL_TYPE (val->type) : + PTR_TYPE (SPEC_OCLS (val->etype)))); } return; } @@ -1007,9 +1150,8 @@ printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) { - if (!ilist) - return; - + sym_link *itype; + /* if structure then */ if (IS_STRUCT (type)) { @@ -1017,17 +1159,46 @@ printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile) return; } - /* if this is a pointer */ - if (IS_PTR (type)) + /* if this is an array */ + if (IS_ARRAY (type)) { - printIvalPtr (sym, type, ilist, oFile); + printIvalArray (sym, type, ilist, oFile); return; } - /* if this is an array */ - if (IS_ARRAY (type)) + if (ilist) { - printIvalArray (sym, type, ilist, oFile); + // not an aggregate, ilist must be a node + if (ilist->type!=INIT_NODE) { + // or a 1-element list + if (ilist->init.deep->next) { + werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", + sym->name); + } else { + ilist=ilist->init.deep; + } + } + + // and the type must match + itype=ilist->init.node->ftype; + + if (compareType(type, itype)==0) { + // special case for literal strings + if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) && + // which are really code pointers + IS_PTR(type) && DCL_TYPE(type)==CPOINTER) { + // no sweat + } else { + werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " "); + printFromToType(itype, type); + } + } + } + + /* if this is a pointer */ + if (IS_PTR (type)) + { + printIvalPtr (sym, type, ilist, oFile); return; } @@ -1056,7 +1227,7 @@ emitStaticSeg (memmap * map, FILE * out) /* if it is "extern" then do nothing */ if (IS_EXTERN (sym->etype)) - continue; + continue; /* if it is not static add it to the public table */ @@ -1067,63 +1238,70 @@ emitStaticSeg (memmap * map, FILE * out) /* print extra debug info if required */ if (options.debug) { - cdbSymbol (sym, cdbFile, FALSE, FALSE); - if (!sym->level) - { /* global */ - if (IS_STATIC (sym->etype)) - fprintf (out, "F%s$", moduleName); /* scope is file */ - else - fprintf (out, "G$"); /* scope is global */ - } - else - /* symbol is local */ - fprintf (out, "L%s$", - (sym->localof ? sym->localof->name : "-null-")); - fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block); + + if (!sym->level) + { /* global */ + if (IS_STATIC (sym->etype)) + fprintf (out, "F%s$", moduleName); /* scope is file */ + else + fprintf (out, "G$"); /* scope is global */ + } + else + /* symbol is local */ + fprintf (out, "L%s$", + (sym->localof ? sym->localof->name : "-null-")); + 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) - fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype)); - - fprintf (out, "%s\t=\t0x%04x\n", - sym->rname, - SPEC_ADDR (sym->etype)); - } + { + if (options.debug) + fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype)); + + fprintf (out, "%s\t=\t0x%04x\n", + sym->rname, + SPEC_ADDR (sym->etype)); + } else - { - if (options.debug) - fprintf (out, " == .\n"); - - /* if it has an initial value */ - if (sym->ival) - { - fprintf (out, "%s:\n", sym->rname); - noAlloc++; - resolveIvalSym (sym->ival); - printIval (sym, sym->type, sym->ival, out); - noAlloc--; - } - else { - /* allocate space */ - int size = getSize (sym->type); - - if (size==0) { - werror(E_UNKNOWN_SIZE,sym->name); - } - 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 (out, - SPEC_CVAL (sym->etype).v_char, - strlen (SPEC_CVAL (sym->etype).v_char) + 1); - else - tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff); - } - } + { + if (options.debug) + fprintf (out, " == .\n"); + + /* if it has an initial value */ + if (sym->ival) + { + fprintf (out, "%s:\n", sym->rname); + noAlloc++; + resolveIvalSym (sym->ival, sym->type); + printIval (sym, sym->type, sym->ival, out); + noAlloc--; + /* if sym is a simple string and sym->ival is a string, + WE don't need it anymore */ + if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) && + IS_AST_SYM_VALUE(list2expr(sym->ival)) && + list2val(sym->ival)->sym->isstrlit) { + freeStringSymbol(list2val(sym->ival)->sym); + } + } + else { + /* allocate space */ + int size = getSize (sym->type); + + if (size==0) { + werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name); + } + 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 (out, + SPEC_CVAL (sym->etype).v_char, + size); + else + tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff); + } + } } } @@ -1131,26 +1309,33 @@ emitStaticSeg (memmap * map, FILE * out) /* emitMaps - emits the code for the data portion the code */ /*-----------------------------------------------------------------*/ void -emitMaps () +emitMaps (void) { + int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */ + /* ports but let's be conservative - EEP */ + inInitMode++; /* no special considerations for the following data, idata & bit & xdata */ emitRegularMap (data, TRUE, TRUE); emitRegularMap (idata, TRUE, TRUE); - emitRegularMap (bit, TRUE, FALSE); + emitRegularMap (bit, TRUE, TRUE); + emitRegularMap (pdata, TRUE, TRUE); emitRegularMap (xdata, TRUE, TRUE); if (port->genXINIT) { emitRegularMap (xidata, TRUE, TRUE); } - emitRegularMap (sfr, FALSE, FALSE); - emitRegularMap (sfrbit, FALSE, FALSE); + emitRegularMap (sfr, publicsfr, FALSE); + emitRegularMap (sfrbit, publicsfr, FALSE); emitRegularMap (home, TRUE, FALSE); emitRegularMap (code, TRUE, FALSE); + if (options.const_seg) { + tfprintf (code->oFile, "\t!area\n", options.const_seg); + } emitStaticSeg (statsg, code->oFile); if (port->genXINIT) { - fprintf (code->oFile, "\t.area\t%s\n", xinit->sname); + tfprintf (code->oFile, "\t!area\n", xinit->sname); emitStaticSeg (xinit, code->oFile); } inInitMode--; @@ -1173,15 +1358,14 @@ flushStatics (void) void createInterruptVect (FILE * vFile) { - unsigned i = 0; mainf = newSymbol ("main", 0); mainf->block = 0; /* only if the main function exists */ if (!(mainf = findSymWithLevel (SymbolTab, mainf))) { - if (!options.cc_only && !noAssemble) - werror (E_NO_MAIN); + if (!options.cc_only && !noAssemble && !options.c1mode) + werror (E_NO_MAIN); return; } @@ -1190,31 +1374,18 @@ createInterruptVect (FILE * vFile) { /* if ! compile only then main function should be present */ if (!options.cc_only && !noAssemble) - werror (E_NO_MAIN); + werror (E_NO_MAIN); return; } - tfprintf (vFile, "\t!areacode\n", CODE_NAME); + tfprintf (vFile, "\t!areacode\n", HOME_NAME); fprintf (vFile, "__interrupt_vect:\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"); - } + /* There's no such thing as a "generic" interrupt table header. */ + wassert(0); } } @@ -1237,7 +1408,8 @@ initialComments (FILE * afile) time_t t; time (&t); fprintf (afile, "%s", iComments1); - fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t))); + fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber(), __DATE__); + fprintf (afile, "; This file generated %s", asctime (localtime (&t))); fprintf (afile, "%s", iComments2); } @@ -1294,115 +1466,139 @@ emitOverlay (FILE * afile) symbol *sym; if (elementsInSet (ovrset)) - { -#if 0 - /* this dummy area is used to fool the assembler - otherwise the assembler will append each of these - declarations into one chunk and will not overlay - sad but true */ - fprintf (afile, "\t.area _DUMMY\n"); -#else - /* not anymore since asmain.c:1.13 */ -#endif - /* output the area informtion */ - fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */ - } + { + /* output the area informtion */ + fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */ + } for (sym = setFirstItem (ovrset); sym; - sym = setNextItem (ovrset)) - { - - /* if extern then add it to the publics tabledo nothing */ - if (IS_EXTERN (sym->etype)) - continue; - - /* if allocation required check is needed - then check if the symbol really requires - allocation only for local variables */ - if (!IS_AGGREGATE (sym->type) && - !(sym->_isparm && !IS_REGPARM (sym->etype)) - && !sym->allocreq && sym->level) - continue; - - /* if global variable & not static or extern - and addPublics allowed then add it to the public set */ - if ((sym->_isparm && !IS_REGPARM (sym->etype)) - && !IS_STATIC (sym->etype)) + sym = setNextItem (ovrset)) + { + /* if extern then it is in the publics table: do nothing */ + if (IS_EXTERN (sym->etype)) + continue; + + /* if allocation required check is needed + then check if the symbol really requires + allocation only for local variables */ + if (!IS_AGGREGATE (sym->type) && + !(sym->_isparm && !IS_REGPARM (sym->etype)) + && !sym->allocreq && sym->level) + continue; + + /* if global variable & not static or extern + and addPublics allowed then add it to the public set */ + if ((sym->_isparm && !IS_REGPARM (sym->etype)) + && !IS_STATIC (sym->etype)) { addSetHead (&publics, sym); } - /* if extern then do nothing or is a function - then do nothing */ - if (IS_FUNC (sym->type)) - continue; - - /* print extra debug info if required */ - if (options.debug) - { - cdbSymbol (sym, cdbFile, FALSE, FALSE); - - if (!sym->level) - { /* global */ - if (IS_STATIC (sym->etype)) - fprintf (afile, "F%s$", moduleName); /* scope is file */ - else - fprintf (afile, "G$"); /* scope is global */ - } - else - /* symbol is local */ - fprintf (afile, "L%s$", - (sym->localof ? sym->localof->name : "-null-")); - fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block); - } - - /* 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) - fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype)); - - fprintf (afile, "%s\t=\t0x%04x\n", - sym->rname, - SPEC_ADDR (sym->etype)); - } - else { - int size = getSize(sym->type); - - if (size==0) { - werror(E_UNKNOWN_SIZE,sym->name); - } - if (options.debug) - fprintf (afile, "==.\n"); - - /* allocate space */ - tfprintf (afile, "!labeldef\n", sym->rname); - tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff); - } - - } + /* if extern then do nothing or is a function + then do nothing */ + if (IS_FUNC (sym->type)) + continue; + + /* print extra debug info if required */ + if (options.debug) + { + if (!sym->level) + { /* global */ + if (IS_STATIC (sym->etype)) + fprintf (afile, "F%s$", moduleName); /* scope is file */ + else + fprintf (afile, "G$"); /* scope is global */ + } + else + /* symbol is local */ + fprintf (afile, "L%s$", + (sym->localof ? sym->localof->name : "-null-")); + fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block); + } + + /* 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) + fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype)); + + fprintf (afile, "%s\t=\t0x%04x\n", + sym->rname, + SPEC_ADDR (sym->etype)); + } + else { + int size = getSize(sym->type); + + if (size==0) { + werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE); + } + if (options.debug) + fprintf (afile, "==.\n"); + + /* allocate space */ + tfprintf (afile, "!labeldef\n", sym->rname); + tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff); + } + + } } } + +/*-----------------------------------------------------------------*/ +/* spacesToUnderscores - replace spaces with underscores */ +/*-----------------------------------------------------------------*/ +static char * +spacesToUnderscores (char *dest, const char *src, size_t len) +{ + unsigned int i; + char *p; + + assert(dest != NULL); + assert(src != NULL); + assert(len > 0); + + --len; + for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) { + *p++ = isspace((unsigned char)*src) ? '_' : *src; + } + *p = '\0'; + + return dest; +} + + /*-----------------------------------------------------------------*/ /* glue - the final glue that hold the whole thing together */ /*-----------------------------------------------------------------*/ void -glue () +glue (void) { FILE *vFile; FILE *asmFile; FILE *ovrFile = tempfile (); + char moduleBuf[PATH_MAX]; + int mcs51_like; + + if(port->general.glue_up_main && + (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400)) + { + mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/ + } + else + { + mcs51_like=0; + } addSetHead (&tmpfileSet, ovrFile); /* print the global struct definitions */ if (options.debug) - cdbStructBlock (0, cdbFile); + cdbStructBlock (0); vFile = tempfile (); - /* PENDING: this isnt the best place but it will do */ + /* PENDING: this isn't the best place but it will do */ if (port->general.glue_up_main) { /* create the interrupt vector table */ @@ -1416,17 +1612,20 @@ glue () /* do the overlay segments */ emitOverlay (ovrFile); + outputDebugSymbols(); + /* now put it all together into the assembler file */ /* create the assembler file name */ - if (!options.c1mode) + /* -o option overrides default name? */ + if ((noAssemble || options.c1mode) && fullDstFileName) { - sprintf (scratchFileName, srcFileName); - strcat (scratchFileName, port->assembler.file_ext); + strncpyz (scratchFileName, fullDstFileName, PATH_MAX); } else { - strcpy (scratchFileName, options.out_name); + strncpyz (scratchFileName, dstFileName, PATH_MAX); + strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX); } if (!(asmFile = fopen (scratchFileName, "w"))) @@ -1439,7 +1638,35 @@ glue () initialComments (asmFile); /* print module name */ - tfprintf (asmFile, "\t!module\n", moduleName); + tfprintf (asmFile, "\t!module\n", + spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf)); + if(mcs51_like) + { + fprintf (asmFile, "\t.optsdcc -m%s", port->target); + + switch(options.model) + { + case MODEL_SMALL: fprintf (asmFile, " --model-small"); break; + case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break; + case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break; + case MODEL_LARGE: fprintf (asmFile, " --model-large"); break; + case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break; + case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break; + default: break; + } + /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/ + if(options.useXstack) fprintf (asmFile, " --xstack"); + /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/ + /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/ + if(options.noRegParams) fprintf (asmFile, " --no-reg-params"); + if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1"); + fprintf (asmFile, "\n"); + } + else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08) + { + fprintf (asmFile, "\t.optsdcc -m%s\n", port->target); + } + tfprintf (asmFile, "\t!fileprelude\n"); /* Let the port generate any global directives, etc. */ @@ -1453,30 +1680,71 @@ glue () if (port->assembler.externGlobal) printExterns (asmFile); - /* copy the sfr segment */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; special function registers\n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, sfr->oFile); - - /* copy the sbit segment */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; special function bits \n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, sfrbit->oFile); + if(( mcs51_like ) + ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */ + { + /* copy the sfr segment */ + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; special function registers\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, sfr->oFile); + } + + if(mcs51_like) + { + /* copy the sbit segment */ + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; special function bits\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, sfrbit->oFile); + + /*JCF: Create the areas for the register banks*/ + if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3]) + { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; overlayable register banks\n"); + fprintf (asmFile, "%s", iComments2); + if(RegBankUsed[0]) + fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n"); + if(RegBankUsed[1]||options.parms_in_bank1) + fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n"); + if(RegBankUsed[2]) + fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n"); + if(RegBankUsed[3]) + fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n"); + } + if(BitBankUsed) + { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; overlayable bit register bank\n"); + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n"); + fprintf (asmFile, "bits:\n\t.ds 1\n"); + fprintf (asmFile, "\tb0 = bits[0]\n"); + fprintf (asmFile, "\tb1 = bits[1]\n"); + fprintf (asmFile, "\tb2 = bits[2]\n"); + fprintf (asmFile, "\tb3 = bits[3]\n"); + fprintf (asmFile, "\tb4 = bits[4]\n"); + fprintf (asmFile, "\tb5 = bits[5]\n"); + fprintf (asmFile, "\tb6 = bits[6]\n"); + fprintf (asmFile, "\tb7 = bits[7]\n"); + } + } /* copy the data segment */ fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; internal ram data\n"); + fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":""); fprintf (asmFile, "%s", iComments2); copyFile (asmFile, data->oFile); /* create the overlay segments */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; overlayable items in internal ram \n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, ovrFile); + if (overlay) { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":""); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, ovrFile); + } /* create the stack segment MOF */ if (mainf && IFFUNC_HASBODY(mainf->type)) @@ -1485,44 +1753,65 @@ glue () fprintf (asmFile, "; Stack segment in internal ram \n"); fprintf (asmFile, "%s", iComments2); fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n" - "__start__stack:\n\t.ds\t1\n\n"); + "__start__stack:\n\t.ds\t1\n\n"); } /* create the idata segment */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; indirectly addressable internal ram data\n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, idata->oFile); + if ( (idata) && (mcs51_like) ) { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; indirectly addressable internal ram data\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, idata->oFile); + } /* copy the bit segment */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; bit data\n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, bit->oFile); + if (mcs51_like) { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; bit data\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, bit->oFile); + } - /* if external stack then reserve space of it */ + /* copy paged external ram data */ + if (mcs51_like) + { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; paged external ram data\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, pdata->oFile); + } + + /* if external stack then reserve space for it */ if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack) { fprintf (asmFile, "%s", iComments2); fprintf (asmFile, "; external stack \n"); fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */ - fprintf (asmFile, "\t.ds 256\n"); + fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n" + "__start__xstack:\n\t.ds\t1\n\n"); } + /* copy external ram data */ + if (mcs51_like) { + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; external ram data\n"); + fprintf (asmFile, "%s", iComments2); + copyFile (asmFile, xdata->oFile); + } - /* copy xtern ram data */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; external ram data\n"); - fprintf (asmFile, "%s", iComments2); - copyFile (asmFile, xdata->oFile); - - /* copy xternal initialized ram data */ + /* copy external initialized ram data */ fprintf (asmFile, "%s", iComments2); fprintf (asmFile, "; external initialized ram data\n"); fprintf (asmFile, "%s", iComments2); copyFile (asmFile, xidata->oFile); + /* If the port wants to generate any extra areas, let it do so. */ + if (port->extraAreas.genExtraAreaDeclaration) + { + port->extraAreas.genExtraAreaDeclaration(asmFile, + mainf && IFFUNC_HASBODY(mainf->type)); + } + /* copy the interrupt vector table */ if (mainf && IFFUNC_HASBODY(mainf->type)) { @@ -1543,46 +1832,53 @@ glue () * 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.home_name); + 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 && IFFUNC_HASBODY(mainf->type)) { - fprintf (asmFile, "__sdcc_gsinit_startup:\n"); - /* if external stack is specified then the - higher order byte of the xdatalocation is - going into P2 and the lower order going into - spx */ - if (options.useXstack) - { - fprintf (asmFile, "\tmov\tP2,#0x%02x\n", - (((unsigned int) options.xdata_loc) >> 8) & 0xff); - fprintf (asmFile, "\tmov\t_spx,#0x%02x\n", - (unsigned int) options.xdata_loc & 0xff); - } - - /* initialise the stack pointer */ - /* if the user specified a value then use it */ - if (options.stack_loc) - fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc & 0xff); - else - /* no: we have to compute it */ - if (!options.stackOnData && maxRegBank <= 3) - fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1); + if (port->genInitStartup) + { + port->genInitStartup(asmFile); + } else - fprintf (asmFile, "\tmov\tsp,#__start__stack\n"); /* MOF */ + { + fprintf (asmFile, "__sdcc_gsinit_startup:\n"); + /* if external stack is specified then the + higher order byte of the xdatalocation is + going into P2 and the lower order going into + spx */ + if (options.useXstack) + { + fprintf (asmFile, "\tmov\tP2,#0x%02x\n", + (((unsigned int) options.xdata_loc) >> 8) & 0xff); + fprintf (asmFile, "\tmov\t_spx,#0x%02x\n", + (unsigned int) options.xdata_loc & 0xff); + } - fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n"); - fprintf (asmFile, "\tmov\ta,dpl\n"); - fprintf (asmFile, "\tjz\t__sdcc_init_data\n"); - fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n"); - fprintf (asmFile, "__sdcc_init_data:\n"); + // This should probably be a port option, but I'm being lazy. + // on the 400, the firmware boot loader gives us a valid stack + // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code) + if (!TARGET_IS_DS400) + { + /* initialise the stack pointer. JCF: aslink takes care of the location */ + fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */ + } - // if the port can copy the XINIT segment to XISEG - if (port->genXINIT) { - port->genXINIT(asmFile); - } + fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n"); + fprintf (asmFile, "\tmov\ta,dpl\n"); + fprintf (asmFile, "\tjz\t__sdcc_init_data\n"); + fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n"); + fprintf (asmFile, "__sdcc_init_data:\n"); + + // if the port can copy the XINIT segment to XISEG + if (port->genXINIT) + { + port->genXINIT(asmFile); + } + } } copyFile (asmFile, statsg->oFile); @@ -1598,115 +1894,202 @@ glue () } fprintf (asmFile, - "%s" - "; Home\n" - "%s", iComments2, iComments2); + "%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); - tfprintf (asmFile, "\t!areacode\n", CODE_NAME); if (mainf && IFFUNC_HASBODY(mainf->type)) { - /* entry point @ start of CSEG */ + /* entry point @ start of HOME */ fprintf (asmFile, "__sdcc_program_startup:\n"); - /* put in the call to main */ - fprintf (asmFile, "\tlcall\t_main\n"); + /* put in jump or call to main */ if (options.mainreturn) - { - - fprintf (asmFile, ";\treturn from main ; will return to caller\n"); - fprintf (asmFile, "\tret\n"); - - } + { + fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */ + fprintf (asmFile, ";\treturn from main will return to caller\n"); + } else - { - - fprintf (asmFile, ";\treturn from main will lock up\n"); - fprintf (asmFile, "\tsjmp .\n"); - } + { + fprintf (asmFile, "\tlcall\t_main\n"); + fprintf (asmFile, ";\treturn from main will lock up\n"); + fprintf (asmFile, "\tsjmp .\n"); + } } + /* copy over code */ + fprintf (asmFile, "%s", iComments2); + fprintf (asmFile, "; code\n"); + fprintf (asmFile, "%s", iComments2); + tfprintf (asmFile, "\t!areacode\n", options.code_seg); copyFile (asmFile, code->oFile); if (port->genAssemblerEnd) { port->genAssemblerEnd(asmFile); } fclose (asmFile); - applyToSet (tmpfileSet, closeTmpFiles); - applyToSet (tmpfileNameSet, rmTmpFiles); -} -#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER) -void -rm_tmpfiles (void) -{ - applyToSet (tmpfileSet, closeTmpFiles); - applyToSet (tmpfileNameSet, rmTmpFiles); + rm_tmpfiles (); } -#endif -/** Creates a temporary file name a'la tmpnam which avoids the bugs - in cygwin wrt c:\tmp. - Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile(). + +/** Creates a temporary file with unique file name + Scans, in order: + - TMP, TEMP, TMPDIR env. variables + - if Un*x system: /usr/tmp and /tmp + - root directory using mkstemp() if available + - default location using tempnam() */ -char * -tempfilename (void) +static int +tempfileandname(char *fname, size_t len) { -#if !defined(_MSC_VER) +#define TEMPLATE "sdccXXXXXX" +#define TEMPLATE_LEN ((sizeof TEMPLATE) - 1) + 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) - { - return name; - } + int fd; + + if ((tmpdir = getenv ("TMP")) == NULL) + if ((tmpdir = getenv ("TEMP")) == NULL) + tmpdir = getenv ("TMPDIR"); + +#if defined(_WIN32) + { + static int warning_emitted; + + if (tmpdir == NULL) + { + tmpdir = "c:\\"; + if (!warning_emitted) + { + fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir); + warning_emitted = 1; + } + } + } +#else + { + /* try with /usr/tmp and /tmp on Un*x systems */ + struct stat statbuf; + + if (tmpdir == NULL) { + if (stat("/usr/tmp", &statbuf) != -1) + tmpdir = "/usr/tmp"; + else if (stat("/tmp", &statbuf) != -1) + tmpdir = "/tmp"; + } + } +#endif + +#ifdef HAVE_MKSTEMP + { + char fnamebuf[PATH_MAX]; + size_t name_len; + + if (fname == NULL || len == 0) { + fname = fnamebuf; + len = sizeof fnamebuf; + } + + if (tmpdir) { + name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN; + + assert(name_len < len); + if (!(name_len < len)) /* in NDEBUG is defined */ + return -1; /* buffer too small, temporary file can not be created */ + + sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir); + } + else { + name_len = TEMPLATE_LEN; + + assert(name_len < len); + if (!(name_len < len)) /* in NDEBUG is defined */ + return -1; /* buffer too small, temporary file can not be created */ + + strcpy(fname, TEMPLATE); + } + + fd = mkstemp(fname); + } +#else + { + char *name = tempnam(tmpdir, "sdcc"); + + if (name == NULL) { + perror("Can't create temporary file name"); + exit(1); } + + assert(strlen(name) < len); + if (!(strlen(name) < len)) /* in NDEBUG is defined */ + return -1; /* buffer too small, temporary file can not be created */ + + strcpy(fname, name); +#ifdef _WIN32 + fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE); +#else + fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); #endif - return tmpnam (NULL); + } +#endif + + if (fd == -1) { + perror("Can't create temporary file"); + exit(1); + } + + return fd; } -/** 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(). + +/** Create a temporary file name */ -FILE * -tempfile (void) +char * +tempfilename(void) { -#if !defined(_MSC_VER) - 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 = Safe_strdup( tempnam (tmpdir, "sdcc")); - if (name) - { - FILE *fp = fopen (name, "w+b"); - if (fp) - { - addSetHead (&tmpfileNameSet, name); - } - return fp; - } - return NULL; - } -#endif - return tmpfile (); + int fd; + static char fnamebuf[PATH_MAX]; + + if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) { + fprintf(stderr, "Can't create temporary file name!"); + exit(1); + } + + fd = close(fd); + assert(fd != -1); + + return fnamebuf; } + +/** Create a temporary file and add it to tmpfileNameSet, + so that it is removed explicitly by rm_tmpfiles() + or implicitly at program extit. +*/ +FILE * +tempfile(void) +{ + int fd; + char *tmp; + FILE *fp; + char fnamebuf[PATH_MAX]; + + if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) { + fprintf(stderr, "Can't create temporary file!"); + exit(1); + } + + tmp = Safe_strdup(fnamebuf); + if (tmp) + addSetHead(&tmpfileNameSet, tmp); + + if ((fp = fdopen(fd, "w+b")) == NULL) { + perror("Can't create temporary file!"); + exit(1); + } + + return fp; +}