1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
38 symbol *interrupts[INTNO_MAX+1];
40 void printIval (symbol *, sym_link *, initList *, FILE *);
41 set *publics = NULL; /* public variables */
42 set *externs = NULL; /* Varibles that are declared as extern */
44 /* TODO: this should be configurable (DS803C90 uses more than 6) */
45 unsigned maxInterrupts = 6;
48 set *pipeSet = NULL; /* set of pipes */
49 set *tmpfileSet = NULL; /* set of tmp file created by the compiler */
50 set *tmpfileNameSet = NULL; /* All are unlinked at close. */
52 /*-----------------------------------------------------------------*/
53 /* closePipes - closes all pipes created by the compiler */
54 /*-----------------------------------------------------------------*/
55 DEFSETFUNC (closePipes)
68 /*-----------------------------------------------------------------*/
69 /* closeTmpFiles - closes all tmp files created by the compiler */
70 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
71 /*-----------------------------------------------------------------*/
72 DEFSETFUNC (closeTmpFiles)
85 /*-----------------------------------------------------------------*/
86 /* rmTmpFiles - unlinks all tmp files created by the compiler */
87 /* because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
88 /*-----------------------------------------------------------------*/
89 DEFSETFUNC (rmTmpFiles)
103 /*-----------------------------------------------------------------*/
104 /* rm_tmpfiles - close and remove temporary files and delete sets */
105 /*-----------------------------------------------------------------*/
109 /* close temporary files */
110 applyToSet (pipeSet, closePipes);
111 /* close temporary files */
112 deleteSet (&pipeSet);
114 applyToSet (tmpfileSet, closeTmpFiles);
115 /* remove temporary files */
116 applyToSet (tmpfileNameSet, rmTmpFiles);
117 /* delete temorary file sets */
118 deleteSet (&tmpfileSet);
119 deleteSet (&tmpfileNameSet);
122 /*-----------------------------------------------------------------*/
123 /* copyFile - copies source file to destination file */
124 /*-----------------------------------------------------------------*/
126 copyFile (FILE * dest, FILE * src)
132 if ((ch = fgetc (src)) != EOF)
137 aopLiteralLong (value * val, int offset, int size)
146 // assuming we have been warned before
150 /* if it is a float then it gets tricky */
151 /* otherwise it is fairly simple */
152 if (!IS_FLOAT (val->type)) {
153 unsigned long v = (unsigned long) floatFromVal (val);
158 tsprintf (buffer, sizeof(buffer),
159 "!immedbyte", (unsigned int) v & 0xff);
162 tsprintf (buffer, sizeof(buffer),
163 "!immedword", (unsigned int) v & 0xffff);
166 /* Hmm. Too big for now. */
169 return Safe_strdup (buffer);
172 /* PENDING: For now size must be 1 */
175 /* it is type float */
176 fl.f = (float) floatFromVal (val);
177 #ifdef WORDS_BIGENDIAN
178 tsprintf (buffer, sizeof(buffer),
179 "!immedbyte", fl.c[3 - offset]);
181 tsprintf (buffer, sizeof(buffer),
182 "!immedbyte", fl.c[offset]);
184 return Safe_strdup (buffer);
187 /*-----------------------------------------------------------------*/
188 /* aopLiteral - string from a literal value */
189 /*-----------------------------------------------------------------*/
191 aopLiteral (value * val, int offset)
193 return aopLiteralLong (val, offset, 1);
196 /*-----------------------------------------------------------------*/
197 /* emitRegularMap - emit code for maps with no special cases */
198 /*-----------------------------------------------------------------*/
200 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
210 /* PENDING: special case here - should remove */
211 if (!strcmp (map->sname, CODE_NAME))
212 tfprintf (map->oFile, "\t!areacode\n", map->sname);
213 else if (!strcmp (map->sname, DATA_NAME))
214 tfprintf (map->oFile, "\t!areadata\n", map->sname);
215 else if (!strcmp (map->sname, HOME_NAME))
216 tfprintf (map->oFile, "\t!areahome\n", map->sname);
218 tfprintf (map->oFile, "\t!area\n", map->sname);
221 for (sym = setFirstItem (map->syms); sym;
222 sym = setNextItem (map->syms))
226 /* if extern then add it into the extern list */
227 if (IS_EXTERN (sym->etype))
229 addSetHead (&externs, sym);
233 /* if allocation required check is needed
234 then check if the symbol really requires
235 allocation only for local variables */
237 if (arFlag && !IS_AGGREGATE (sym->type) &&
238 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
239 !sym->allocreq && sym->level)
242 /* for bitvar locals and parameters */
243 if (!arFlag && !sym->allocreq && sym->level
244 && !SPEC_ABSA (sym->etype)) {
248 /* if global variable & not static or extern
249 and addPublics allowed then add it to the public set */
250 if ((sym->level == 0 ||
251 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
253 !IS_STATIC (sym->etype) &&
254 (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
256 addSetHead (&publics, sym);
259 /* if extern then do nothing or is a function
261 if (IS_FUNC (sym->type) && !(sym->isitmp))
264 /* print extra debug info if required */
267 if (!sym->level) /* global */
269 if (IS_STATIC (sym->etype))
270 fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
272 fprintf (map->oFile, "G$"); /* scope is global */
276 /* symbol is local */
277 fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
279 fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
282 /* if it has an initial value then do it only if
283 it is a global variable */
284 if (sym->ival && sym->level == 0) {
285 if (SPEC_OCLS(sym->etype)==xidata) {
286 /* create a new "XINIT (CODE)" symbol, that will be emitted later
288 newSym=copySymbol (sym);
289 SPEC_OCLS(newSym->etype)=xinit;
290 SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
291 SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
292 if (IS_SPEC (newSym->type))
293 SPEC_CONST (newSym->type) = 1;
295 DCL_PTR_CONST (newSym->type) = 1;
296 SPEC_STAT(newSym->etype)=1;
297 resolveIvalSym(newSym->ival);
299 // add it to the "XINIT (CODE)" segment
300 addSet(&xinit->syms, newSym);
303 if (IS_AGGREGATE (sym->type)) {
304 ival = initAggregates (sym, sym->ival, NULL);
306 if (getNelements(sym->type, sym->ival)>1) {
307 werrorfl (filename, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
310 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
311 decorateType (resolveSymbols (list2expr (sym->ival))));
313 codeOutFile = statsg->oFile;
316 // set ival's lineno to where the symbol was defined
317 setAstLineno (ival, lineno=sym->lineDef);
318 // check if this is not a constant expression
319 if (!constExprTree(ival)) {
320 werror (E_CONST_EXPECTED, "found expression");
321 // but try to do it anyway
324 if (!astErrors(ival))
325 eBBlockFromiCode (iCodeFromAst (ival));
332 /* if is has an absolute address then generate
333 an equate for this no need to allocate space */
334 if (SPEC_ABSA (sym->etype))
338 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
340 if (TARGET_IS_XA51) {
343 } else if (map==bit || map==sfrbit) {
347 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
349 SPEC_ADDR (sym->etype));
352 int size = getSize (sym->type);
354 werrorfl (filename, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
358 fprintf (map->oFile, "==.\n");
360 if (IS_STATIC (sym->etype))
361 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
363 tfprintf (map->oFile, "!labeldef\n", sym->rname);
364 tfprintf (map->oFile, "\t!ds\n",
365 (unsigned int) size & 0xffff);
370 /*-----------------------------------------------------------------*/
371 /* initPointer - pointer initialization code massaging */
372 /*-----------------------------------------------------------------*/
374 initPointer (initList * ilist, sym_link *toType)
377 ast *expr = list2expr (ilist);
382 /* try it the oldway first */
383 if ((val = constExprValue (expr, FALSE)))
386 /* ( ptr + constant ) */
387 if (IS_AST_OP (expr) &&
388 (expr->opval.op == '+' || expr->opval.op == '-') &&
389 IS_AST_SYM_VALUE (expr->left) &&
390 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
391 compareType(toType, expr->left->ftype) &&
392 IS_AST_LIT_VALUE (expr->right)) {
393 return valForCastAggr (expr->left, expr->left->ftype,
399 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
400 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
401 if (compareType(toType, expr->left->ftype)!=1) {
402 werror (W_INIT_WRONG);
403 printFromToType(expr->left->ftype, toType);
409 /* no then we have to do these cludgy checks */
410 /* pointers can be initialized with address of
411 a variable or address of an array element */
412 if (IS_AST_OP (expr) && expr->opval.op == '&') {
413 /* address of symbol */
414 if (IS_AST_SYM_VALUE (expr->left)) {
415 val = copyValue (AST_VALUE (expr->left));
416 val->type = newLink (DECLARATOR);
417 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
418 DCL_TYPE (val->type) = CPOINTER;
419 DCL_PTR_CONST (val->type) = port->mem.code_ro;
421 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
422 DCL_TYPE (val->type) = FPOINTER;
423 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
424 DCL_TYPE (val->type) = PPOINTER;
425 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
426 DCL_TYPE (val->type) = IPOINTER;
427 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
428 DCL_TYPE (val->type) = EEPPOINTER;
430 DCL_TYPE (val->type) = POINTER;
431 val->type->next = expr->left->ftype;
432 val->etype = getSpec (val->type);
436 /* if address of indexed array */
437 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
438 return valForArray (expr->left);
440 /* if address of structure element then
442 if (IS_AST_OP (expr->left) &&
443 expr->left->opval.op == '.') {
444 return valForStructElem (expr->left->left,
449 (&some_struct)->element */
450 if (IS_AST_OP (expr->left) &&
451 expr->left->opval.op == PTR_OP &&
452 IS_ADDRESS_OF_OP (expr->left->left)) {
453 return valForStructElem (expr->left->left->left,
457 /* case 3. (((char *) &a) +/- constant) */
458 if (IS_AST_OP (expr) &&
459 (expr->opval.op == '+' || expr->opval.op == '-') &&
460 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
461 IS_AST_OP (expr->left->right) &&
462 expr->left->right->opval.op == '&' &&
463 IS_AST_LIT_VALUE (expr->right)) {
465 return valForCastAggr (expr->left->right->left,
466 expr->left->left->opval.lnk,
467 expr->right, expr->opval.op);
470 /* case 4. (char *)(array type) */
471 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
472 IS_ARRAY(expr->right->ftype)) {
474 val = copyValue (AST_VALUE (expr->right));
475 val->type = newLink (DECLARATOR);
476 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
477 DCL_TYPE (val->type) = CPOINTER;
478 DCL_PTR_CONST (val->type) = port->mem.code_ro;
480 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
481 DCL_TYPE (val->type) = FPOINTER;
482 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
483 DCL_TYPE (val->type) = PPOINTER;
484 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
485 DCL_TYPE (val->type) = IPOINTER;
486 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
487 DCL_TYPE (val->type) = EEPPOINTER;
489 DCL_TYPE (val->type) = POINTER;
490 val->type->next = expr->right->ftype->next;
491 val->etype = getSpec (val->type);
496 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
498 werror (E_INCOMPAT_PTYPES);
503 /*-----------------------------------------------------------------*/
504 /* printChar - formats and prints a characater string with DB */
505 /*-----------------------------------------------------------------*/
507 printChar (FILE * ofile, char *s, int plen)
510 int len = strlen (s);
515 while (len && pplen < plen)
518 while (i && pplen < plen)
520 if (*s < ' ' || *s == '\"' || *s=='\\')
524 tfprintf (ofile, "\t!ascii\n", buf);
525 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
540 tfprintf (ofile, "\t!ascii\n", buf);
551 /*-----------------------------------------------------------------*/
552 /* return the generic pointer high byte for a given pointer type. */
553 /*-----------------------------------------------------------------*/
555 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
563 werror (E_CANNOT_USE_GENERIC_POINTER,
564 iname ? iname : "<null>",
565 oname ? oname : "<null>");
572 return GPTYPE_XSTACK;
574 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
582 /*-----------------------------------------------------------------*/
583 /* printPointerType - generates ival for pointer type */
584 /*-----------------------------------------------------------------*/
586 _printPointerType (FILE * oFile, const char *name)
588 if (options.model == MODEL_FLAT24)
590 if (port->little_endian)
591 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
593 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
597 if (port->little_endian)
598 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
600 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
604 /*-----------------------------------------------------------------*/
605 /* printPointerType - generates ival for pointer type */
606 /*-----------------------------------------------------------------*/
608 printPointerType (FILE * oFile, const char *name)
610 _printPointerType (oFile, name);
611 fprintf (oFile, "\n");
614 /*-----------------------------------------------------------------*/
615 /* printGPointerType - generates ival for generic pointer type */
616 /*-----------------------------------------------------------------*/
618 printGPointerType (FILE * oFile, const char *iname, const char *oname,
619 const unsigned int type)
621 _printPointerType (oFile, iname);
622 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
625 /*-----------------------------------------------------------------*/
626 /* printIvalType - generates ival for int/char */
627 /*-----------------------------------------------------------------*/
629 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
633 /* if initList is deep */
634 if (ilist->type == INIT_DEEP)
635 ilist = ilist->init.deep;
637 if (!(val = list2val (ilist))) {
638 // assuming a warning has been thrown
642 if (val->type != type) {
643 val = valCastLiteral(type, floatFromVal(val));
646 switch (getSize (type)) {
649 tfprintf (oFile, "\t!db !constbyte\n", 0);
651 tfprintf (oFile, "\t!dbs\n",
652 aopLiteral (val, 0));
656 if (port->use_dw_for_init)
657 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
658 else if (port->little_endian)
659 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
661 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
665 tfprintf (oFile, "\t!dw !constword\n", 0);
666 tfprintf (oFile, "\t!dw !constword\n", 0);
668 else if (port->little_endian) {
669 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
670 aopLiteral (val, 0), aopLiteral (val, 1),
671 aopLiteral (val, 2), aopLiteral (val, 3));
674 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
675 aopLiteral (val, 3), aopLiteral (val, 2),
676 aopLiteral (val, 1), aopLiteral (val, 0));
682 /*-----------------------------------------------------------------*/
683 /* printIvalBitFields - generate initializer for bitfields */
684 /*-----------------------------------------------------------------*/
685 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
689 initList *lilist = *ilist ;
690 unsigned long ival = 0;
696 val = list2val(lilist);
698 if (SPEC_BLEN(lsym->etype) > 8) {
699 size += ((SPEC_BLEN (lsym->etype) / 8) +
700 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
703 size = ((SPEC_BLEN (lsym->etype) / 8) +
704 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
706 i = (unsigned long)floatFromVal(val);
707 i <<= SPEC_BSTR (lsym->etype);
709 if (! ( lsym->next &&
710 (IS_BITFIELD(lsym->next->type)) &&
711 (SPEC_BSTR(lsym->next->etype)))) break;
713 lilist = lilist->next;
717 tfprintf (oFile, "\t!db !constbyte\n",ival);
721 tfprintf (oFile, "\t!dw !constword\n",ival);
723 case 4: /* EEP: why is this db and not dw? */
724 tfprintf (oFile, "\t!db !constword,!constword\n",
725 (ival >> 8) & 0xffff, (ival & 0xffff));
732 /*-----------------------------------------------------------------*/
733 /* printIvalStruct - generates initial value for structures */
734 /*-----------------------------------------------------------------*/
736 printIvalStruct (symbol * sym, sym_link * type,
737 initList * ilist, FILE * oFile)
742 sflds = SPEC_STRUCT (type)->fields;
743 if (ilist->type != INIT_DEEP) {
744 werrorfl (filename, sym->lineDef, E_INIT_STRUCT, sym->name);
748 iloop = ilist->init.deep;
750 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
751 if (IS_BITFIELD(sflds->type)) {
752 printIvalBitFields(&sflds,&iloop,oFile);
754 printIval (sym, sflds->type, iloop, oFile);
758 werrorfl (filename, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
763 /*-----------------------------------------------------------------*/
764 /* printIvalChar - generates initital value for character array */
765 /*-----------------------------------------------------------------*/
767 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
774 val = list2val (ilist);
775 /* if the value is a character string */
776 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
778 if (!DCL_ELEM (type))
779 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
781 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
789 printChar (oFile, s, strlen (s) + 1);
793 /*-----------------------------------------------------------------*/
794 /* printIvalArray - generates code for array initialization */
795 /*-----------------------------------------------------------------*/
797 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
803 /* take care of the special case */
804 /* array of characters can be init */
806 if (IS_CHAR (type->next)) {
807 if (!IS_LITERAL(list2val(ilist)->etype)) {
808 werrorfl (filename, ilist->lineno, E_CONST_EXPECTED);
811 if (printIvalChar (type,
812 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
813 oFile, SPEC_CVAL (sym->etype).v_char))
816 /* not the special case */
817 if (ilist->type != INIT_DEEP)
819 werrorfl (filename, ilist->lineno, E_INIT_STRUCT, sym->name);
823 for (iloop=ilist->init.deep; iloop; iloop=iloop->next)
825 printIval (sym, type->next, iloop, oFile);
827 if (++size > DCL_ELEM(type)) {
828 werrorfl (filename, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
833 if (DCL_ELEM(type)) {
834 // pad with zeros if needed
835 if (size<DCL_ELEM(type)) {
836 size = (DCL_ELEM(type) - size) * getSize(type->next);
838 tfprintf (oFile, "\t!db !constbyte\n", 0);
842 // we have not been given a size, but we now know it
843 DCL_ELEM (type) = size;
849 /*-----------------------------------------------------------------*/
850 /* printIvalFuncPtr - generate initial value for function pointers */
851 /*-----------------------------------------------------------------*/
853 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
858 val = list2val (ilist);
861 // an error has been thrown allready
865 if (IS_LITERAL(val->etype)) {
866 if (compareType(type,val->etype)==0) {
867 werrorfl (filename, ilist->lineno, E_INCOMPAT_TYPES);
868 printFromToType (val->type, type);
870 printIvalCharPtr (NULL, type, val, oFile);
874 /* check the types */
875 if ((dLvl = compareType (val->type, type->next)) <= 0)
877 tfprintf (oFile, "\t!dw !constword\n", 0);
881 /* now generate the name */
884 if (port->use_dw_for_init)
886 tfprintf (oFile, "\t!dws\n", val->name);
890 printPointerType (oFile, val->name);
893 else if (port->use_dw_for_init)
895 tfprintf (oFile, "\t!dws\n", val->sym->rname);
899 printPointerType (oFile, val->sym->rname);
905 /*-----------------------------------------------------------------*/
906 /* printIvalCharPtr - generates initial values for character pointers */
907 /*-----------------------------------------------------------------*/
909 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
913 /* PENDING: this is _very_ mcs51 specific, including a magic
915 It's also endin specific.
917 size = getSize (type);
919 if (val->name && strlen (val->name))
921 if (size == 1) /* This appears to be Z80 specific?? */
924 "\t!dbs\n", val->name);
926 else if (size == FPTRSIZE)
928 if (port->use_dw_for_init)
930 tfprintf (oFile, "\t!dws\n", val->name);
934 printPointerType (oFile, val->name);
937 else if (size == GPTRSIZE)
940 if (IS_PTR (val->type)) {
941 type = DCL_TYPE (val->type);
943 type = PTR_TYPE (SPEC_OCLS (val->etype));
945 if (val->sym && val->sym->isstrlit) {
946 // this is a literal string
949 printGPointerType (oFile, val->name, sym->name, type);
953 fprintf (stderr, "*** internal error: unknown size in "
954 "printIvalCharPtr.\n");
959 // these are literals assigned to pointers
963 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
966 if (port->use_dw_for_init)
967 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
968 else if (port->little_endian)
969 tfprintf (oFile, "\t.byte %s,%s\n",
970 aopLiteral (val, 0), aopLiteral (val, 1));
972 tfprintf (oFile, "\t.byte %s,%s\n",
973 aopLiteral (val, 1), aopLiteral (val, 0));
976 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
977 // non-zero mcs51 generic pointer
978 werrorfl (filename, sym->lineDef, E_LITERAL_GENERIC);
980 if (port->little_endian) {
981 fprintf (oFile, "\t.byte %s,%s,%s\n",
984 aopLiteral (val, 2));
986 fprintf (oFile, "\t.byte %s,%s,%s\n",
989 aopLiteral (val, 0));
993 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
994 // non-zero ds390 generic pointer
995 werrorfl (filename, sym->lineDef, E_LITERAL_GENERIC);
997 if (port->little_endian) {
998 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1000 aopLiteral (val, 1),
1001 aopLiteral (val, 2),
1002 aopLiteral (val, 3));
1004 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1005 aopLiteral (val, 3),
1006 aopLiteral (val, 2),
1007 aopLiteral (val, 1),
1008 aopLiteral (val, 0));
1016 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1017 addSet (&statsg->syms, val->sym);
1023 /*-----------------------------------------------------------------*/
1024 /* printIvalPtr - generates initial value for pointers */
1025 /*-----------------------------------------------------------------*/
1027 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1033 if (ilist->type == INIT_DEEP)
1034 ilist = ilist->init.deep;
1036 /* function pointer */
1037 if (IS_FUNC (type->next))
1039 printIvalFuncPtr (type, ilist, oFile);
1043 if (!(val = initPointer (ilist, type)))
1046 /* if character pointer */
1047 if (IS_CHAR (type->next))
1048 if (printIvalCharPtr (sym, type, val, oFile))
1051 /* check the type */
1052 if (compareType (type, val->type) == 0) {
1053 werrorfl (filename, ilist->lineno, W_INIT_WRONG);
1054 printFromToType (val->type, type);
1057 /* if val is literal */
1058 if (IS_LITERAL (val->etype))
1060 switch (getSize (type))
1063 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1066 if (port->use_dw_for_init)
1067 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1068 else if (port->little_endian)
1069 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1071 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1073 case 3: // how about '390??
1074 if (port->little_endian)
1076 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1077 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1081 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1082 aopLiteral (val, 1), aopLiteral (val, 0), GPTYPE_CODE);
1089 size = getSize (type);
1091 if (size == 1) /* Z80 specific?? */
1093 tfprintf (oFile, "\t!dbs\n", val->name);
1095 else if (size == FPTRSIZE)
1097 if (port->use_dw_for_init) {
1098 tfprintf (oFile, "\t!dws\n", val->name);
1100 printPointerType (oFile, val->name);
1103 else if (size == GPTRSIZE)
1105 printGPointerType (oFile, val->name, sym->name,
1106 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1107 PTR_TYPE (SPEC_OCLS (val->etype))));
1112 /*-----------------------------------------------------------------*/
1113 /* printIval - generates code for initial value */
1114 /*-----------------------------------------------------------------*/
1116 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1123 /* if structure then */
1124 if (IS_STRUCT (type))
1126 printIvalStruct (sym, type, ilist, oFile);
1130 /* if this is an array */
1131 if (IS_ARRAY (type))
1133 printIvalArray (sym, type, ilist, oFile);
1137 // not an aggregate, ilist must be a node
1138 if (ilist->type!=INIT_NODE) {
1139 // or a 1-element list
1140 if (ilist->init.deep->next) {
1141 werrorfl (filename, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1144 ilist=ilist->init.deep;
1148 // and the type must match
1149 itype=ilist->init.node->ftype;
1151 if (compareType(type, itype)==0) {
1152 // special case for literal strings
1153 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1154 // which are really code pointers
1155 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1158 werrorfl (filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1159 printFromToType(itype, type);
1163 /* if this is a pointer */
1166 printIvalPtr (sym, type, ilist, oFile);
1170 /* if type is SPECIFIER */
1173 printIvalType (sym, type, ilist, oFile);
1178 /*-----------------------------------------------------------------*/
1179 /* emitStaticSeg - emitcode for the static segment */
1180 /*-----------------------------------------------------------------*/
1182 emitStaticSeg (memmap * map, FILE * out)
1186 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1188 /* for all variables in this segment do */
1189 for (sym = setFirstItem (map->syms); sym;
1190 sym = setNextItem (map->syms))
1193 /* if it is "extern" then do nothing */
1194 if (IS_EXTERN (sym->etype))
1197 /* if it is not static add it to the public
1199 if (!IS_STATIC (sym->etype))
1201 addSetHead (&publics, sym);
1204 /* print extra debug info if required */
1205 if (options.debug) {
1209 if (IS_STATIC (sym->etype))
1210 fprintf (out, "F%s$", moduleName); /* scope is file */
1212 fprintf (out, "G$"); /* scope is global */
1215 /* symbol is local */
1216 fprintf (out, "L%s$",
1217 (sym->localof ? sym->localof->name : "-null-"));
1218 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1221 /* if it has an absolute address */
1222 if (SPEC_ABSA (sym->etype))
1225 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1227 fprintf (out, "%s\t=\t0x%04x\n",
1229 SPEC_ADDR (sym->etype));
1234 fprintf (out, " == .\n");
1236 /* if it has an initial value */
1239 fprintf (out, "%s:\n", sym->rname);
1241 resolveIvalSym (sym->ival);
1242 printIval (sym, sym->type, sym->ival, out);
1244 /* if sym is a simple string and sym->ival is a string,
1245 WE don't need it anymore */
1246 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1247 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1248 list2val(sym->ival)->sym->isstrlit) {
1249 freeStringSymbol(list2val(sym->ival)->sym);
1253 /* allocate space */
1254 int size = getSize (sym->type);
1257 werrorfl (filename, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1259 fprintf (out, "%s:\n", sym->rname);
1260 /* special case for character strings */
1261 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1262 SPEC_CVAL (sym->etype).v_char)
1264 SPEC_CVAL (sym->etype).v_char,
1267 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1273 /*-----------------------------------------------------------------*/
1274 /* emitMaps - emits the code for the data portion the code */
1275 /*-----------------------------------------------------------------*/
1280 /* no special considerations for the following
1281 data, idata & bit & xdata */
1282 emitRegularMap (data, TRUE, TRUE);
1283 emitRegularMap (idata, TRUE, TRUE);
1284 emitRegularMap (bit, TRUE, FALSE);
1285 emitRegularMap (xdata, TRUE, TRUE);
1286 if (port->genXINIT) {
1287 emitRegularMap (xidata, TRUE, TRUE);
1289 emitRegularMap (sfr, FALSE, FALSE);
1290 emitRegularMap (sfrbit, FALSE, FALSE);
1291 emitRegularMap (home, TRUE, FALSE);
1292 emitRegularMap (code, TRUE, FALSE);
1294 emitStaticSeg (statsg, code->oFile);
1295 if (port->genXINIT) {
1296 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1297 emitStaticSeg (xinit, code->oFile);
1302 /*-----------------------------------------------------------------*/
1303 /* flushStatics - flush all currently defined statics out to file */
1304 /* and delete. Temporary function */
1305 /*-----------------------------------------------------------------*/
1309 emitStaticSeg (statsg, codeOutFile);
1310 statsg->syms = NULL;
1313 /*-----------------------------------------------------------------*/
1314 /* createInterruptVect - creates the interrupt vector */
1315 /*-----------------------------------------------------------------*/
1317 createInterruptVect (FILE * vFile)
1320 mainf = newSymbol ("main", 0);
1323 /* only if the main function exists */
1324 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1326 if (!options.cc_only && !noAssemble && !options.c1mode)
1331 /* if the main is only a prototype ie. no body then do nothing */
1332 if (!IFFUNC_HASBODY(mainf->type))
1334 /* if ! compile only then main function should be present */
1335 if (!options.cc_only && !noAssemble)
1340 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1341 fprintf (vFile, "__interrupt_vect:\n");
1344 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1346 /* "generic" interrupt table header (if port doesn't specify one).
1347 * Look suspiciously like 8051 code to me...
1350 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1353 /* now for the other interrupts */
1354 for (; i < maxInterrupts; i++)
1357 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1359 fprintf (vFile, "\treti\n\t.ds\t7\n");
1366 ";--------------------------------------------------------\n"
1367 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1371 ";--------------------------------------------------------\n"};
1374 /*-----------------------------------------------------------------*/
1375 /* initialComments - puts in some initial comments */
1376 /*-----------------------------------------------------------------*/
1378 initialComments (FILE * afile)
1382 fprintf (afile, "%s", iComments1);
1383 fprintf (afile, "; Version " SDCC_VERSION_STR " %s\n", asctime (localtime (&t)));
1384 fprintf (afile, "%s", iComments2);
1387 /*-----------------------------------------------------------------*/
1388 /* printPublics - generates .global for publics */
1389 /*-----------------------------------------------------------------*/
1391 printPublics (FILE * afile)
1395 fprintf (afile, "%s", iComments2);
1396 fprintf (afile, "; Public variables in this module\n");
1397 fprintf (afile, "%s", iComments2);
1399 for (sym = setFirstItem (publics); sym;
1400 sym = setNextItem (publics))
1401 tfprintf (afile, "\t!global\n", sym->rname);
1404 /*-----------------------------------------------------------------*/
1405 /* printExterns - generates .global for externs */
1406 /*-----------------------------------------------------------------*/
1408 printExterns (FILE * afile)
1412 fprintf (afile, "%s", iComments2);
1413 fprintf (afile, "; Externals used\n");
1414 fprintf (afile, "%s", iComments2);
1416 for (sym = setFirstItem (externs); sym;
1417 sym = setNextItem (externs))
1418 tfprintf (afile, "\t!extern\n", sym->rname);
1421 /*-----------------------------------------------------------------*/
1422 /* emitOverlay - will emit code for the overlay stuff */
1423 /*-----------------------------------------------------------------*/
1425 emitOverlay (FILE * afile)
1429 if (!elementsInSet (ovrSetSets))
1430 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1432 /* for each of the sets in the overlay segment do */
1433 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1434 ovrset = setNextItem (ovrSetSets))
1439 if (elementsInSet (ovrset))
1441 /* output the area informtion */
1442 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1445 for (sym = setFirstItem (ovrset); sym;
1446 sym = setNextItem (ovrset))
1448 /* if extern then it is in the publics table: do nothing */
1449 if (IS_EXTERN (sym->etype))
1452 /* if allocation required check is needed
1453 then check if the symbol really requires
1454 allocation only for local variables */
1455 if (!IS_AGGREGATE (sym->type) &&
1456 !(sym->_isparm && !IS_REGPARM (sym->etype))
1457 && !sym->allocreq && sym->level)
1460 /* if global variable & not static or extern
1461 and addPublics allowed then add it to the public set */
1462 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1463 && !IS_STATIC (sym->etype))
1465 addSetHead (&publics, sym);
1468 /* if extern then do nothing or is a function
1470 if (IS_FUNC (sym->type))
1473 /* print extra debug info if required */
1478 if (IS_STATIC (sym->etype))
1479 fprintf (afile, "F%s$", moduleName); /* scope is file */
1481 fprintf (afile, "G$"); /* scope is global */
1484 /* symbol is local */
1485 fprintf (afile, "L%s$",
1486 (sym->localof ? sym->localof->name : "-null-"));
1487 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1490 /* if is has an absolute address then generate
1491 an equate for this no need to allocate space */
1492 if (SPEC_ABSA (sym->etype))
1496 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1498 fprintf (afile, "%s\t=\t0x%04x\n",
1500 SPEC_ADDR (sym->etype));
1503 int size = getSize(sym->type);
1506 werrorfl (filename, sym->lineDef, E_UNKNOWN_SIZE);
1509 fprintf (afile, "==.\n");
1511 /* allocate space */
1512 tfprintf (afile, "!labeldef\n", sym->rname);
1513 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1521 /*-----------------------------------------------------------------*/
1522 /* spacesToUnderscores - replace spaces with underscores */
1523 /*-----------------------------------------------------------------*/
1525 spacesToUnderscores (char *dest, const char *src, size_t len)
1530 assert(dest != NULL);
1531 assert(src != NULL);
1535 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1536 *p++ = isspace(*src) ? '_' : *src;
1544 /*-----------------------------------------------------------------*/
1545 /* glue - the final glue that hold the whole thing together */
1546 /*-----------------------------------------------------------------*/
1552 FILE *ovrFile = tempfile ();
1553 char moduleBuf[PATH_MAX];
1556 if(port->general.glue_up_main &&
1557 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1559 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1566 addSetHead (&tmpfileSet, ovrFile);
1567 /* print the global struct definitions */
1571 vFile = tempfile ();
1572 /* PENDING: this isnt the best place but it will do */
1573 if (port->general.glue_up_main)
1575 /* create the interrupt vector table */
1576 createInterruptVect (vFile);
1579 addSetHead (&tmpfileSet, vFile);
1581 /* emit code for the all the variables declared */
1583 /* do the overlay segments */
1584 emitOverlay (ovrFile);
1586 outputDebugSymbols();
1588 /* now put it all together into the assembler file */
1589 /* create the assembler file name */
1591 /* -o option overrides default name? */
1592 if ((noAssemble || options.c1mode) && fullDstFileName)
1594 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1598 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1599 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1602 if (!(asmFile = fopen (scratchFileName, "w")))
1604 werror (E_FILE_OPEN_ERR, scratchFileName);
1608 /* initial comments */
1609 initialComments (asmFile);
1611 /* print module name */
1612 tfprintf (asmFile, "\t!module\n",
1613 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1616 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1618 switch(options.model)
1620 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1621 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1622 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1623 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1624 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1625 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1628 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1629 if(options.useXstack) fprintf (asmFile, " --xstack");
1630 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1631 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1632 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1633 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1634 fprintf (asmFile, "\n");
1636 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 )
1638 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1641 tfprintf (asmFile, "\t!fileprelude\n");
1643 /* Let the port generate any global directives, etc. */
1644 if (port->genAssemblerPreamble)
1646 port->genAssemblerPreamble (asmFile);
1649 /* print the global variables in this module */
1650 printPublics (asmFile);
1651 if (port->assembler.externGlobal)
1652 printExterns (asmFile);
1655 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1657 /* copy the sfr segment */
1658 fprintf (asmFile, "%s", iComments2);
1659 fprintf (asmFile, "; special function registers\n");
1660 fprintf (asmFile, "%s", iComments2);
1661 copyFile (asmFile, sfr->oFile);
1666 /* copy the sbit segment */
1667 fprintf (asmFile, "%s", iComments2);
1668 fprintf (asmFile, "; special function bits \n");
1669 fprintf (asmFile, "%s", iComments2);
1670 copyFile (asmFile, sfrbit->oFile);
1672 /*JCF: Create the areas for the register banks*/
1673 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1675 fprintf (asmFile, "%s", iComments2);
1676 fprintf (asmFile, "; overlayable register banks \n");
1677 fprintf (asmFile, "%s", iComments2);
1679 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1680 if(RegBankUsed[1]||options.parms_in_bank1)
1681 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1683 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1685 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1689 /* copy the data segment */
1690 fprintf (asmFile, "%s", iComments2);
1691 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1692 fprintf (asmFile, "%s", iComments2);
1693 copyFile (asmFile, data->oFile);
1696 /* create the overlay segments */
1698 fprintf (asmFile, "%s", iComments2);
1699 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1700 fprintf (asmFile, "%s", iComments2);
1701 copyFile (asmFile, ovrFile);
1704 /* create the stack segment MOF */
1705 if (mainf && IFFUNC_HASBODY(mainf->type))
1707 fprintf (asmFile, "%s", iComments2);
1708 fprintf (asmFile, "; Stack segment in internal ram \n");
1709 fprintf (asmFile, "%s", iComments2);
1710 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1711 "__start__stack:\n\t.ds\t1\n\n");
1714 /* create the idata segment */
1715 if ( (idata) && (mcs51_like) ) {
1716 fprintf (asmFile, "%s", iComments2);
1717 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1718 fprintf (asmFile, "%s", iComments2);
1719 copyFile (asmFile, idata->oFile);
1722 /* copy the bit segment */
1724 fprintf (asmFile, "%s", iComments2);
1725 fprintf (asmFile, "; bit data\n");
1726 fprintf (asmFile, "%s", iComments2);
1727 copyFile (asmFile, bit->oFile);
1730 /* if external stack then reserve space of it */
1731 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1733 fprintf (asmFile, "%s", iComments2);
1734 fprintf (asmFile, "; external stack \n");
1735 fprintf (asmFile, "%s", iComments2);
1736 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1737 fprintf (asmFile, "\t.ds 256\n");
1741 /* copy xtern ram data */
1743 fprintf (asmFile, "%s", iComments2);
1744 fprintf (asmFile, "; external ram data\n");
1745 fprintf (asmFile, "%s", iComments2);
1746 copyFile (asmFile, xdata->oFile);
1749 /* copy xternal initialized ram data */
1750 fprintf (asmFile, "%s", iComments2);
1751 fprintf (asmFile, "; external initialized ram data\n");
1752 fprintf (asmFile, "%s", iComments2);
1753 copyFile (asmFile, xidata->oFile);
1755 /* If the port wants to generate any extra areas, let it do so. */
1756 if (port->extraAreas.genExtraAreaDeclaration)
1758 port->extraAreas.genExtraAreaDeclaration(asmFile,
1759 mainf && IFFUNC_HASBODY(mainf->type));
1762 /* copy the interrupt vector table */
1763 if (mainf && IFFUNC_HASBODY(mainf->type))
1765 fprintf (asmFile, "%s", iComments2);
1766 fprintf (asmFile, "; interrupt vector \n");
1767 fprintf (asmFile, "%s", iComments2);
1768 copyFile (asmFile, vFile);
1771 /* copy global & static initialisations */
1772 fprintf (asmFile, "%s", iComments2);
1773 fprintf (asmFile, "; global & static initialisations\n");
1774 fprintf (asmFile, "%s", iComments2);
1776 /* Everywhere we generate a reference to the static_name area,
1777 * (which is currently only here), we immediately follow it with a
1778 * definition of the post_static_name area. This guarantees that
1779 * the post_static_name area will immediately follow the static_name
1782 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1783 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1784 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1786 if (mainf && IFFUNC_HASBODY(mainf->type))
1788 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1789 /* if external stack is specified then the
1790 higher order byte of the xdatalocation is
1791 going into P2 and the lower order going into
1793 if (options.useXstack)
1795 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1796 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1797 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1798 (unsigned int) options.xdata_loc & 0xff);
1801 // This should probably be a port option, but I'm being lazy.
1802 // on the 400, the firmware boot loader gives us a valid stack
1803 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1804 if (!TARGET_IS_DS400)
1806 /* initialise the stack pointer. JCF: aslink takes care of the location */
1807 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1810 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1811 fprintf (asmFile, "\tmov\ta,dpl\n");
1812 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1813 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1814 fprintf (asmFile, "__sdcc_init_data:\n");
1816 // if the port can copy the XINIT segment to XISEG
1817 if (port->genXINIT) {
1818 port->genXINIT(asmFile);
1822 copyFile (asmFile, statsg->oFile);
1824 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1826 /* This code is generated in the post-static area.
1827 * This area is guaranteed to follow the static area
1828 * by the ugly shucking and jiving about 20 lines ago.
1830 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1831 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1837 "%s", iComments2, iComments2);
1838 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1839 copyFile (asmFile, home->oFile);
1841 /* copy over code */
1842 fprintf (asmFile, "%s", iComments2);
1843 fprintf (asmFile, "; code\n");
1844 fprintf (asmFile, "%s", iComments2);
1845 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1846 if (mainf && IFFUNC_HASBODY(mainf->type))
1849 /* entry point @ start of CSEG */
1850 fprintf (asmFile, "__sdcc_program_startup:\n");
1852 /* put in the call to main */
1853 fprintf (asmFile, "\tlcall\t_main\n");
1854 if (options.mainreturn)
1857 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1858 fprintf (asmFile, "\tret\n");
1864 fprintf (asmFile, ";\treturn from main will lock up\n");
1865 fprintf (asmFile, "\tsjmp .\n");
1868 copyFile (asmFile, code->oFile);
1870 if (port->genAssemblerEnd) {
1871 port->genAssemblerEnd(asmFile);
1879 /** Creates a temporary file with unoque file name
1881 - TMP, TEMP, TMPDIR env. varibles
1882 - if Un*x system: /usr/tmp and /tmp
1883 - root directory using mkstemp() if avaliable
1884 - default location using tempnam()
1887 tempfileandname(char *fname, size_t len)
1889 #define TEMPLATE "sdccXXXXXX"
1890 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1892 const char *tmpdir = NULL;
1895 if ((tmpdir = getenv ("TMP")) == NULL)
1896 if ((tmpdir = getenv ("TEMP")) == NULL)
1897 tmpdir = getenv ("TMPDIR");
1901 static int warning_emitted;
1906 if (!warning_emitted)
1908 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1909 warning_emitted = 1;
1915 /* try with /usr/tmp and /tmp on Un*x systems */
1916 struct stat statbuf;
1918 if (tmpdir == NULL) {
1919 if (stat("/usr/tmp", &statbuf) != -1)
1920 tmpdir = "/usr/tmp";
1921 else if (stat("/tmp", &statbuf) != -1)
1929 char fnamebuf[PATH_MAX];
1932 if (fname == NULL || len == 0) {
1934 len = sizeof fnamebuf;
1938 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1940 assert(name_len < len);
1941 if (!(name_len < len)) /* in NDEBUG is defined */
1942 return -1; /* buffer too small, temporary file can not be created */
1944 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1947 name_len = TEMPLATE_LEN;
1949 assert(name_len < len);
1950 if (!(name_len < len)) /* in NDEBUG is defined */
1951 return -1; /* buffer too small, temporary file can not be created */
1953 strcpy(fname, TEMPLATE);
1956 fd = mkstemp(fname);
1960 char *name = tempnam(tmpdir, "sdcc");
1963 perror("Can't create temporary file name");
1967 assert(strlen(name) < len);
1968 if (!(strlen(name) < len)) /* in NDEBUG is defined */
1969 return -1; /* buffer too small, temporary file can not be created */
1971 strcpy(fname, name);
1973 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
1975 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
1981 perror("Can't create temporary file");
1989 /** Create a temporary file name
1995 static char fnamebuf[PATH_MAX];
1997 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1998 fprintf(stderr, "Can't create temporary file name!");
2009 /** Create a temporary file and add it to tmpfileNameSet,
2010 so that it is removed explicitly by rm_tmpfiles()
2011 or implicitly at program extit.
2019 char fnamebuf[PATH_MAX];
2021 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2022 fprintf(stderr, "Can't create temporary file!");
2026 tmp = Safe_strdup(fnamebuf);
2028 addSetHead(&tmpfileNameSet, tmp);
2030 if ((fp = fdopen(fd, "w+b")) == NULL) {
2031 perror("Can't create temporary file!");