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, newSym->type);
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 (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
310 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
311 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK));
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 (sym->fileDef, 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 tfprintf (ofile, "\t!db !constbyte\n", 0);
556 /*-----------------------------------------------------------------*/
557 /* return the generic pointer high byte for a given pointer type. */
558 /*-----------------------------------------------------------------*/
560 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
568 werror (E_CANNOT_USE_GENERIC_POINTER,
569 iname ? iname : "<null>",
570 oname ? oname : "<null>");
577 return GPTYPE_XSTACK;
579 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
587 /*-----------------------------------------------------------------*/
588 /* printPointerType - generates ival for pointer type */
589 /*-----------------------------------------------------------------*/
591 _printPointerType (FILE * oFile, const char *name)
593 if (options.model == MODEL_FLAT24)
595 if (port->little_endian)
596 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
598 fprintf (oFile, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
602 if (port->little_endian)
603 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
605 fprintf (oFile, "\t.byte (%s >> 8),%s", name, name);
609 /*-----------------------------------------------------------------*/
610 /* printPointerType - generates ival for pointer type */
611 /*-----------------------------------------------------------------*/
613 printPointerType (FILE * oFile, const char *name)
615 _printPointerType (oFile, name);
616 fprintf (oFile, "\n");
619 /*-----------------------------------------------------------------*/
620 /* printGPointerType - generates ival for generic pointer type */
621 /*-----------------------------------------------------------------*/
623 printGPointerType (FILE * oFile, const char *iname, const char *oname,
624 const unsigned int type)
626 _printPointerType (oFile, iname);
627 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
630 /*-----------------------------------------------------------------*/
631 /* printIvalType - generates ival for int/char */
632 /*-----------------------------------------------------------------*/
634 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
638 /* if initList is deep */
639 if (ilist->type == INIT_DEEP)
640 ilist = ilist->init.deep;
642 if (!(val = list2val (ilist))) {
643 // assuming a warning has been thrown
647 if (val->type != type) {
648 val = valCastLiteral(type, floatFromVal(val));
651 switch (getSize (type)) {
654 tfprintf (oFile, "\t!db !constbyte\n", 0);
656 tfprintf (oFile, "\t!dbs\n",
657 aopLiteral (val, 0));
661 if (port->use_dw_for_init)
662 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
663 else if (port->little_endian)
664 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
666 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
670 tfprintf (oFile, "\t!dw !constword\n", 0);
671 tfprintf (oFile, "\t!dw !constword\n", 0);
673 else if (port->little_endian) {
674 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
675 aopLiteral (val, 0), aopLiteral (val, 1),
676 aopLiteral (val, 2), aopLiteral (val, 3));
679 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
680 aopLiteral (val, 3), aopLiteral (val, 2),
681 aopLiteral (val, 1), aopLiteral (val, 0));
687 /*-----------------------------------------------------------------*/
688 /* printIvalBitFields - generate initializer for bitfields */
689 /*-----------------------------------------------------------------*/
690 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
694 initList *lilist = *ilist ;
695 unsigned long ival = 0;
701 val = list2val(lilist);
703 if (SPEC_BLEN(lsym->etype) > 8) {
704 size += ((SPEC_BLEN (lsym->etype) / 8) +
705 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
708 size = ((SPEC_BLEN (lsym->etype) / 8) +
709 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
711 i = (unsigned long)floatFromVal(val);
712 i <<= SPEC_BSTR (lsym->etype);
714 if (! ( lsym->next &&
715 (IS_BITFIELD(lsym->next->type)) &&
716 (SPEC_BSTR(lsym->next->etype)))) break;
718 lilist = lilist->next;
722 tfprintf (oFile, "\t!db !constbyte\n",ival);
726 tfprintf (oFile, "\t!dw !constword\n",ival);
728 case 4: /* EEP: why is this db and not dw? */
729 tfprintf (oFile, "\t!db !constword,!constword\n",
730 (ival >> 8) & 0xffff, (ival & 0xffff));
737 /*-----------------------------------------------------------------*/
738 /* printIvalStruct - generates initial value for structures */
739 /*-----------------------------------------------------------------*/
741 printIvalStruct (symbol * sym, sym_link * type,
742 initList * ilist, FILE * oFile)
747 sflds = SPEC_STRUCT (type)->fields;
748 if (ilist->type != INIT_DEEP) {
749 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
753 iloop = ilist->init.deep;
755 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
756 if (IS_BITFIELD(sflds->type)) {
757 printIvalBitFields(&sflds,&iloop,oFile);
759 printIval (sym, sflds->type, iloop, oFile);
763 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
768 /*-----------------------------------------------------------------*/
769 /* printIvalChar - generates initital value for character array */
770 /*-----------------------------------------------------------------*/
772 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
779 val = list2val (ilist);
780 /* if the value is a character string */
781 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
783 if (!DCL_ELEM (type))
784 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
786 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
794 printChar (oFile, s, strlen (s) + 1);
798 /*-----------------------------------------------------------------*/
799 /* printIvalArray - generates code for array initialization */
800 /*-----------------------------------------------------------------*/
802 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
808 /* take care of the special case */
809 /* array of characters can be init */
811 if (IS_CHAR (type->next)) {
812 if (!IS_LITERAL(list2val(ilist)->etype)) {
813 werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
816 if (printIvalChar (type,
817 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
818 oFile, SPEC_CVAL (sym->etype).v_char))
821 /* not the special case */
822 if (ilist->type != INIT_DEEP)
824 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
828 for (iloop=ilist->init.deep; iloop; iloop=iloop->next)
830 printIval (sym, type->next, iloop, oFile);
832 if (++size > DCL_ELEM(type)) {
833 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
838 if (DCL_ELEM(type)) {
839 // pad with zeros if needed
840 if (size<DCL_ELEM(type)) {
841 size = (DCL_ELEM(type) - size) * getSize(type->next);
843 tfprintf (oFile, "\t!db !constbyte\n", 0);
847 // we have not been given a size, but we now know it
848 DCL_ELEM (type) = size;
854 /*-----------------------------------------------------------------*/
855 /* printIvalFuncPtr - generate initial value for function pointers */
856 /*-----------------------------------------------------------------*/
858 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
863 val = list2val (ilist);
866 // an error has been thrown allready
870 if (IS_LITERAL(val->etype)) {
871 if (compareType(type,val->etype)==0) {
872 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
873 printFromToType (val->type, type);
875 printIvalCharPtr (NULL, type, val, oFile);
879 /* check the types */
880 if ((dLvl = compareType (val->type, type->next)) <= 0)
882 tfprintf (oFile, "\t!dw !constword\n", 0);
886 /* now generate the name */
889 if (port->use_dw_for_init)
891 tfprintf (oFile, "\t!dws\n", val->name);
895 printPointerType (oFile, val->name);
898 else if (port->use_dw_for_init)
900 tfprintf (oFile, "\t!dws\n", val->sym->rname);
904 printPointerType (oFile, val->sym->rname);
910 /*-----------------------------------------------------------------*/
911 /* printIvalCharPtr - generates initial values for character pointers */
912 /*-----------------------------------------------------------------*/
914 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
918 /* PENDING: this is _very_ mcs51 specific, including a magic
920 It's also endin specific.
922 size = getSize (type);
924 if (val->name && strlen (val->name))
926 if (size == 1) /* This appears to be Z80 specific?? */
929 "\t!dbs\n", val->name);
931 else if (size == FPTRSIZE)
933 if (port->use_dw_for_init)
935 tfprintf (oFile, "\t!dws\n", val->name);
939 printPointerType (oFile, val->name);
942 else if (size == GPTRSIZE)
945 if (IS_PTR (val->type)) {
946 type = DCL_TYPE (val->type);
948 type = PTR_TYPE (SPEC_OCLS (val->etype));
950 if (val->sym && val->sym->isstrlit) {
951 // this is a literal string
954 printGPointerType (oFile, val->name, sym->name, type);
958 fprintf (stderr, "*** internal error: unknown size in "
959 "printIvalCharPtr.\n");
964 // these are literals assigned to pointers
968 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
971 if (port->use_dw_for_init)
972 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
973 else if (port->little_endian)
974 tfprintf (oFile, "\t.byte %s,%s\n",
975 aopLiteral (val, 0), aopLiteral (val, 1));
977 tfprintf (oFile, "\t.byte %s,%s\n",
978 aopLiteral (val, 1), aopLiteral (val, 0));
981 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
982 // non-zero mcs51 generic pointer
983 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
985 if (port->little_endian) {
986 fprintf (oFile, "\t.byte %s,%s,%s\n",
989 aopLiteral (val, 2));
991 fprintf (oFile, "\t.byte %s,%s,%s\n",
994 aopLiteral (val, 0));
998 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
999 // non-zero ds390 generic pointer
1000 werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1002 if (port->little_endian) {
1003 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1004 aopLiteral (val, 0),
1005 aopLiteral (val, 1),
1006 aopLiteral (val, 2),
1007 aopLiteral (val, 3));
1009 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
1010 aopLiteral (val, 3),
1011 aopLiteral (val, 2),
1012 aopLiteral (val, 1),
1013 aopLiteral (val, 0));
1021 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1022 addSet (&statsg->syms, val->sym);
1028 /*-----------------------------------------------------------------*/
1029 /* printIvalPtr - generates initial value for pointers */
1030 /*-----------------------------------------------------------------*/
1032 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1038 if (ilist->type == INIT_DEEP)
1039 ilist = ilist->init.deep;
1041 /* function pointer */
1042 if (IS_FUNC (type->next))
1044 printIvalFuncPtr (type, ilist, oFile);
1048 if (!(val = initPointer (ilist, type)))
1051 /* if character pointer */
1052 if (IS_CHAR (type->next))
1053 if (printIvalCharPtr (sym, type, val, oFile))
1056 /* check the type */
1057 if (compareType (type, val->type) == 0) {
1058 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1059 printFromToType (val->type, type);
1062 /* if val is literal */
1063 if (IS_LITERAL (val->etype))
1065 switch (getSize (type))
1068 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1071 if (port->use_dw_for_init)
1072 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1073 else if (port->little_endian)
1074 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1076 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1078 case 3: // how about '390??
1079 fprintf (oFile, "; generic printIvalPtr\n");
1080 if (port->little_endian)
1082 fprintf (oFile, "\t.byte %s,%s",
1083 aopLiteral (val, 0), aopLiteral (val, 1));
1087 fprintf (oFile, "\t.byte %s,%s",
1088 aopLiteral (val, 1), aopLiteral (val, 0));
1090 if (IS_GENPTR (val->type))
1091 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1092 else if (IS_PTR (val->type))
1093 fprintf (oFile, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1095 fprintf (oFile, ",%s\n", aopLiteral (val, 2));
1101 size = getSize (type);
1103 if (size == 1) /* Z80 specific?? */
1105 tfprintf (oFile, "\t!dbs\n", val->name);
1107 else if (size == FPTRSIZE)
1109 if (port->use_dw_for_init) {
1110 tfprintf (oFile, "\t!dws\n", val->name);
1112 printPointerType (oFile, val->name);
1115 else if (size == GPTRSIZE)
1117 printGPointerType (oFile, val->name, sym->name,
1118 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1119 PTR_TYPE (SPEC_OCLS (val->etype))));
1124 /*-----------------------------------------------------------------*/
1125 /* printIval - generates code for initial value */
1126 /*-----------------------------------------------------------------*/
1128 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1135 /* if structure then */
1136 if (IS_STRUCT (type))
1138 printIvalStruct (sym, type, ilist, oFile);
1142 /* if this is an array */
1143 if (IS_ARRAY (type))
1145 printIvalArray (sym, type, ilist, oFile);
1149 // not an aggregate, ilist must be a node
1150 if (ilist->type!=INIT_NODE) {
1151 // or a 1-element list
1152 if (ilist->init.deep->next) {
1153 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1156 ilist=ilist->init.deep;
1160 // and the type must match
1161 itype=ilist->init.node->ftype;
1163 if (compareType(type, itype)==0) {
1164 // special case for literal strings
1165 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1166 // which are really code pointers
1167 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1170 werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1171 printFromToType(itype, type);
1175 /* if this is a pointer */
1178 printIvalPtr (sym, type, ilist, oFile);
1182 /* if type is SPECIFIER */
1185 printIvalType (sym, type, ilist, oFile);
1190 /*-----------------------------------------------------------------*/
1191 /* emitStaticSeg - emitcode for the static segment */
1192 /*-----------------------------------------------------------------*/
1194 emitStaticSeg (memmap * map, FILE * out)
1198 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1200 /* for all variables in this segment do */
1201 for (sym = setFirstItem (map->syms); sym;
1202 sym = setNextItem (map->syms))
1205 /* if it is "extern" then do nothing */
1206 if (IS_EXTERN (sym->etype))
1209 /* if it is not static add it to the public
1211 if (!IS_STATIC (sym->etype))
1213 addSetHead (&publics, sym);
1216 /* print extra debug info if required */
1217 if (options.debug) {
1221 if (IS_STATIC (sym->etype))
1222 fprintf (out, "F%s$", moduleName); /* scope is file */
1224 fprintf (out, "G$"); /* scope is global */
1227 /* symbol is local */
1228 fprintf (out, "L%s$",
1229 (sym->localof ? sym->localof->name : "-null-"));
1230 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1233 /* if it has an absolute address */
1234 if (SPEC_ABSA (sym->etype))
1237 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1239 fprintf (out, "%s\t=\t0x%04x\n",
1241 SPEC_ADDR (sym->etype));
1246 fprintf (out, " == .\n");
1248 /* if it has an initial value */
1251 fprintf (out, "%s:\n", sym->rname);
1253 resolveIvalSym (sym->ival, sym->type);
1254 printIval (sym, sym->type, sym->ival, out);
1256 /* if sym is a simple string and sym->ival is a string,
1257 WE don't need it anymore */
1258 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1259 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1260 list2val(sym->ival)->sym->isstrlit) {
1261 freeStringSymbol(list2val(sym->ival)->sym);
1265 /* allocate space */
1266 int size = getSize (sym->type);
1269 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1271 fprintf (out, "%s:\n", sym->rname);
1272 /* special case for character strings */
1273 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1274 SPEC_CVAL (sym->etype).v_char)
1276 SPEC_CVAL (sym->etype).v_char,
1279 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1285 /*-----------------------------------------------------------------*/
1286 /* emitMaps - emits the code for the data portion the code */
1287 /*-----------------------------------------------------------------*/
1291 int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all */
1292 /* ports but let's be conservative - EEP */
1295 /* no special considerations for the following
1296 data, idata & bit & xdata */
1297 emitRegularMap (data, TRUE, TRUE);
1298 emitRegularMap (idata, TRUE, TRUE);
1299 emitRegularMap (bit, TRUE, FALSE);
1300 emitRegularMap (xdata, TRUE, TRUE);
1301 if (port->genXINIT) {
1302 emitRegularMap (xidata, TRUE, TRUE);
1304 emitRegularMap (sfr, publicsfr, FALSE);
1305 emitRegularMap (sfrbit, publicsfr, FALSE);
1306 emitRegularMap (home, TRUE, FALSE);
1307 emitRegularMap (code, TRUE, FALSE);
1309 emitStaticSeg (statsg, code->oFile);
1310 if (port->genXINIT) {
1311 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1312 emitStaticSeg (xinit, code->oFile);
1317 /*-----------------------------------------------------------------*/
1318 /* flushStatics - flush all currently defined statics out to file */
1319 /* and delete. Temporary function */
1320 /*-----------------------------------------------------------------*/
1324 emitStaticSeg (statsg, codeOutFile);
1325 statsg->syms = NULL;
1328 /*-----------------------------------------------------------------*/
1329 /* createInterruptVect - creates the interrupt vector */
1330 /*-----------------------------------------------------------------*/
1332 createInterruptVect (FILE * vFile)
1335 mainf = newSymbol ("main", 0);
1338 /* only if the main function exists */
1339 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1341 if (!options.cc_only && !noAssemble && !options.c1mode)
1346 /* if the main is only a prototype ie. no body then do nothing */
1347 if (!IFFUNC_HASBODY(mainf->type))
1349 /* if ! compile only then main function should be present */
1350 if (!options.cc_only && !noAssemble)
1355 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1356 fprintf (vFile, "__interrupt_vect:\n");
1359 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1361 /* "generic" interrupt table header (if port doesn't specify one).
1362 * Look suspiciously like 8051 code to me...
1365 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1367 /* now for the other interrupts */
1368 for (; i < maxInterrupts; i++)
1372 fprintf (vFile, "\tljmp\t%s\n", interrupts[i]->rname);
1373 if ( i != maxInterrupts - 1 )
1374 fprintf (vFile, "\t.ds\t5\n");
1378 fprintf (vFile, "\treti\n");
1379 if ( i != maxInterrupts - 1 )
1380 fprintf (vFile, "\t.ds\t7\n");
1388 ";--------------------------------------------------------\n"
1389 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1393 ";--------------------------------------------------------\n"};
1396 /*-----------------------------------------------------------------*/
1397 /* initialComments - puts in some initial comments */
1398 /*-----------------------------------------------------------------*/
1400 initialComments (FILE * afile)
1404 fprintf (afile, "%s", iComments1);
1405 fprintf (afile, "; Version " SDCC_VERSION_STR " (%s)\n", __DATE__);
1406 fprintf (afile, "; This file generated %s", asctime (localtime (&t)));
1407 fprintf (afile, "%s", iComments2);
1410 /*-----------------------------------------------------------------*/
1411 /* printPublics - generates .global for publics */
1412 /*-----------------------------------------------------------------*/
1414 printPublics (FILE * afile)
1418 fprintf (afile, "%s", iComments2);
1419 fprintf (afile, "; Public variables in this module\n");
1420 fprintf (afile, "%s", iComments2);
1422 for (sym = setFirstItem (publics); sym;
1423 sym = setNextItem (publics))
1424 tfprintf (afile, "\t!global\n", sym->rname);
1427 /*-----------------------------------------------------------------*/
1428 /* printExterns - generates .global for externs */
1429 /*-----------------------------------------------------------------*/
1431 printExterns (FILE * afile)
1435 fprintf (afile, "%s", iComments2);
1436 fprintf (afile, "; Externals used\n");
1437 fprintf (afile, "%s", iComments2);
1439 for (sym = setFirstItem (externs); sym;
1440 sym = setNextItem (externs))
1441 tfprintf (afile, "\t!extern\n", sym->rname);
1444 /*-----------------------------------------------------------------*/
1445 /* emitOverlay - will emit code for the overlay stuff */
1446 /*-----------------------------------------------------------------*/
1448 emitOverlay (FILE * afile)
1452 if (!elementsInSet (ovrSetSets))
1453 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1455 /* for each of the sets in the overlay segment do */
1456 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1457 ovrset = setNextItem (ovrSetSets))
1462 if (elementsInSet (ovrset))
1464 /* output the area informtion */
1465 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1468 for (sym = setFirstItem (ovrset); sym;
1469 sym = setNextItem (ovrset))
1471 /* if extern then it is in the publics table: do nothing */
1472 if (IS_EXTERN (sym->etype))
1475 /* if allocation required check is needed
1476 then check if the symbol really requires
1477 allocation only for local variables */
1478 if (!IS_AGGREGATE (sym->type) &&
1479 !(sym->_isparm && !IS_REGPARM (sym->etype))
1480 && !sym->allocreq && sym->level)
1483 /* if global variable & not static or extern
1484 and addPublics allowed then add it to the public set */
1485 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1486 && !IS_STATIC (sym->etype))
1488 addSetHead (&publics, sym);
1491 /* if extern then do nothing or is a function
1493 if (IS_FUNC (sym->type))
1496 /* print extra debug info if required */
1501 if (IS_STATIC (sym->etype))
1502 fprintf (afile, "F%s$", moduleName); /* scope is file */
1504 fprintf (afile, "G$"); /* scope is global */
1507 /* symbol is local */
1508 fprintf (afile, "L%s$",
1509 (sym->localof ? sym->localof->name : "-null-"));
1510 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1513 /* if is has an absolute address then generate
1514 an equate for this no need to allocate space */
1515 if (SPEC_ABSA (sym->etype))
1519 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1521 fprintf (afile, "%s\t=\t0x%04x\n",
1523 SPEC_ADDR (sym->etype));
1526 int size = getSize(sym->type);
1529 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1532 fprintf (afile, "==.\n");
1534 /* allocate space */
1535 tfprintf (afile, "!labeldef\n", sym->rname);
1536 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1544 /*-----------------------------------------------------------------*/
1545 /* spacesToUnderscores - replace spaces with underscores */
1546 /*-----------------------------------------------------------------*/
1548 spacesToUnderscores (char *dest, const char *src, size_t len)
1553 assert(dest != NULL);
1554 assert(src != NULL);
1558 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1559 *p++ = isspace(*src) ? '_' : *src;
1567 /*-----------------------------------------------------------------*/
1568 /* glue - the final glue that hold the whole thing together */
1569 /*-----------------------------------------------------------------*/
1575 FILE *ovrFile = tempfile ();
1576 char moduleBuf[PATH_MAX];
1579 if(port->general.glue_up_main &&
1580 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1582 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1589 addSetHead (&tmpfileSet, ovrFile);
1590 /* print the global struct definitions */
1594 vFile = tempfile ();
1595 /* PENDING: this isnt the best place but it will do */
1596 if (port->general.glue_up_main)
1598 /* create the interrupt vector table */
1599 createInterruptVect (vFile);
1602 addSetHead (&tmpfileSet, vFile);
1604 /* emit code for the all the variables declared */
1606 /* do the overlay segments */
1607 emitOverlay (ovrFile);
1609 outputDebugSymbols();
1611 /* now put it all together into the assembler file */
1612 /* create the assembler file name */
1614 /* -o option overrides default name? */
1615 if ((noAssemble || options.c1mode) && fullDstFileName)
1617 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1621 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1622 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1625 if (!(asmFile = fopen (scratchFileName, "w")))
1627 werror (E_FILE_OPEN_ERR, scratchFileName);
1631 /* initial comments */
1632 initialComments (asmFile);
1634 /* print module name */
1635 tfprintf (asmFile, "\t!module\n",
1636 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1639 fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1641 switch(options.model)
1643 case MODEL_SMALL: fprintf (asmFile, " --model-small"); break;
1644 case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1645 case MODEL_MEDIUM: fprintf (asmFile, " --model-medium"); break;
1646 case MODEL_LARGE: fprintf (asmFile, " --model-large"); break;
1647 case MODEL_FLAT24: fprintf (asmFile, " --model-flat24"); break;
1648 case MODEL_PAGE0: fprintf (asmFile, " --model-page0"); break;
1651 /*if(options.stackAuto) fprintf (asmFile, " --stack-auto");*/
1652 if(options.useXstack) fprintf (asmFile, " --xstack");
1653 /*if(options.intlong_rent) fprintf (asmFile, " --int-long-rent");*/
1654 /*if(options.float_rent) fprintf (asmFile, " --float-rent");*/
1655 if(options.noRegParams) fprintf (asmFile, " --no-reg-params");
1656 if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1657 fprintf (asmFile, "\n");
1659 else if(TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_HC08)
1661 fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1664 tfprintf (asmFile, "\t!fileprelude\n");
1666 /* Let the port generate any global directives, etc. */
1667 if (port->genAssemblerPreamble)
1669 port->genAssemblerPreamble (asmFile);
1672 /* print the global variables in this module */
1673 printPublics (asmFile);
1674 if (port->assembler.externGlobal)
1675 printExterns (asmFile);
1678 ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1680 /* copy the sfr segment */
1681 fprintf (asmFile, "%s", iComments2);
1682 fprintf (asmFile, "; special function registers\n");
1683 fprintf (asmFile, "%s", iComments2);
1684 copyFile (asmFile, sfr->oFile);
1689 /* copy the sbit segment */
1690 fprintf (asmFile, "%s", iComments2);
1691 fprintf (asmFile, "; special function bits \n");
1692 fprintf (asmFile, "%s", iComments2);
1693 copyFile (asmFile, sfrbit->oFile);
1695 /*JCF: Create the areas for the register banks*/
1696 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1698 fprintf (asmFile, "%s", iComments2);
1699 fprintf (asmFile, "; overlayable register banks \n");
1700 fprintf (asmFile, "%s", iComments2);
1702 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1703 if(RegBankUsed[1]||options.parms_in_bank1)
1704 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1706 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1708 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1712 /* copy the data segment */
1713 fprintf (asmFile, "%s", iComments2);
1714 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1715 fprintf (asmFile, "%s", iComments2);
1716 copyFile (asmFile, data->oFile);
1719 /* create the overlay segments */
1721 fprintf (asmFile, "%s", iComments2);
1722 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1723 fprintf (asmFile, "%s", iComments2);
1724 copyFile (asmFile, ovrFile);
1727 /* create the stack segment MOF */
1728 if (mainf && IFFUNC_HASBODY(mainf->type))
1730 fprintf (asmFile, "%s", iComments2);
1731 fprintf (asmFile, "; Stack segment in internal ram \n");
1732 fprintf (asmFile, "%s", iComments2);
1733 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1734 "__start__stack:\n\t.ds\t1\n\n");
1737 /* create the idata segment */
1738 if ( (idata) && (mcs51_like) ) {
1739 fprintf (asmFile, "%s", iComments2);
1740 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1741 fprintf (asmFile, "%s", iComments2);
1742 copyFile (asmFile, idata->oFile);
1745 /* copy the bit segment */
1747 fprintf (asmFile, "%s", iComments2);
1748 fprintf (asmFile, "; bit data\n");
1749 fprintf (asmFile, "%s", iComments2);
1750 copyFile (asmFile, bit->oFile);
1753 /* if external stack then reserve space of it */
1754 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1756 fprintf (asmFile, "%s", iComments2);
1757 fprintf (asmFile, "; external stack \n");
1758 fprintf (asmFile, "%s", iComments2);
1759 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1760 fprintf (asmFile, "\t.ds 256\n");
1764 /* copy xtern ram data */
1766 fprintf (asmFile, "%s", iComments2);
1767 fprintf (asmFile, "; external ram data\n");
1768 fprintf (asmFile, "%s", iComments2);
1769 copyFile (asmFile, xdata->oFile);
1772 /* copy xternal initialized ram data */
1773 fprintf (asmFile, "%s", iComments2);
1774 fprintf (asmFile, "; external initialized ram data\n");
1775 fprintf (asmFile, "%s", iComments2);
1776 copyFile (asmFile, xidata->oFile);
1778 /* If the port wants to generate any extra areas, let it do so. */
1779 if (port->extraAreas.genExtraAreaDeclaration)
1781 port->extraAreas.genExtraAreaDeclaration(asmFile,
1782 mainf && IFFUNC_HASBODY(mainf->type));
1785 /* copy the interrupt vector table */
1786 if (mainf && IFFUNC_HASBODY(mainf->type))
1788 fprintf (asmFile, "%s", iComments2);
1789 fprintf (asmFile, "; interrupt vector \n");
1790 fprintf (asmFile, "%s", iComments2);
1791 copyFile (asmFile, vFile);
1794 /* copy global & static initialisations */
1795 fprintf (asmFile, "%s", iComments2);
1796 fprintf (asmFile, "; global & static initialisations\n");
1797 fprintf (asmFile, "%s", iComments2);
1799 /* Everywhere we generate a reference to the static_name area,
1800 * (which is currently only here), we immediately follow it with a
1801 * definition of the post_static_name area. This guarantees that
1802 * the post_static_name area will immediately follow the static_name
1805 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1806 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1807 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1809 if (mainf && IFFUNC_HASBODY(mainf->type))
1811 if (port->genInitStartup)
1813 port->genInitStartup(asmFile);
1817 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1818 /* if external stack is specified then the
1819 higher order byte of the xdatalocation is
1820 going into P2 and the lower order going into
1822 if (options.useXstack)
1824 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1825 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1826 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1827 (unsigned int) options.xdata_loc & 0xff);
1830 // This should probably be a port option, but I'm being lazy.
1831 // on the 400, the firmware boot loader gives us a valid stack
1832 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1833 if (!TARGET_IS_DS400)
1835 /* initialise the stack pointer. JCF: aslink takes care of the location */
1836 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1839 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1840 fprintf (asmFile, "\tmov\ta,dpl\n");
1841 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1842 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1843 fprintf (asmFile, "__sdcc_init_data:\n");
1845 // if the port can copy the XINIT segment to XISEG
1848 port->genXINIT(asmFile);
1853 copyFile (asmFile, statsg->oFile);
1855 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1857 /* This code is generated in the post-static area.
1858 * This area is guaranteed to follow the static area
1859 * by the ugly shucking and jiving about 20 lines ago.
1861 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1862 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1868 "%s", iComments2, iComments2);
1869 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1870 copyFile (asmFile, home->oFile);
1872 /* copy over code */
1873 fprintf (asmFile, "%s", iComments2);
1874 fprintf (asmFile, "; code\n");
1875 fprintf (asmFile, "%s", iComments2);
1876 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1877 if (mainf && IFFUNC_HASBODY(mainf->type))
1880 /* entry point @ start of CSEG */
1881 fprintf (asmFile, "__sdcc_program_startup:\n");
1883 /* put in jump or call to main */
1884 if (options.mainreturn)
1886 fprintf (asmFile, "\tljmp\t_main\n"); /* needed? */
1887 fprintf (asmFile, ";\treturn from main will return to caller\n");
1891 fprintf (asmFile, "\tlcall\t_main\n");
1892 fprintf (asmFile, ";\treturn from main will lock up\n");
1893 fprintf (asmFile, "\tsjmp .\n");
1896 copyFile (asmFile, code->oFile);
1898 if (port->genAssemblerEnd) {
1899 port->genAssemblerEnd(asmFile);
1907 /** Creates a temporary file with unoque file name
1909 - TMP, TEMP, TMPDIR env. varibles
1910 - if Un*x system: /usr/tmp and /tmp
1911 - root directory using mkstemp() if avaliable
1912 - default location using tempnam()
1915 tempfileandname(char *fname, size_t len)
1917 #define TEMPLATE "sdccXXXXXX"
1918 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1920 const char *tmpdir = NULL;
1923 if ((tmpdir = getenv ("TMP")) == NULL)
1924 if ((tmpdir = getenv ("TEMP")) == NULL)
1925 tmpdir = getenv ("TMPDIR");
1929 static int warning_emitted;
1934 if (!warning_emitted)
1936 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1937 warning_emitted = 1;
1943 /* try with /usr/tmp and /tmp on Un*x systems */
1944 struct stat statbuf;
1946 if (tmpdir == NULL) {
1947 if (stat("/usr/tmp", &statbuf) != -1)
1948 tmpdir = "/usr/tmp";
1949 else if (stat("/tmp", &statbuf) != -1)
1957 char fnamebuf[PATH_MAX];
1960 if (fname == NULL || len == 0) {
1962 len = sizeof fnamebuf;
1966 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1968 assert(name_len < len);
1969 if (!(name_len < len)) /* in NDEBUG is defined */
1970 return -1; /* buffer too small, temporary file can not be created */
1972 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1975 name_len = TEMPLATE_LEN;
1977 assert(name_len < len);
1978 if (!(name_len < len)) /* in NDEBUG is defined */
1979 return -1; /* buffer too small, temporary file can not be created */
1981 strcpy(fname, TEMPLATE);
1984 fd = mkstemp(fname);
1988 char *name = tempnam(tmpdir, "sdcc");
1991 perror("Can't create temporary file name");
1995 assert(strlen(name) < len);
1996 if (!(strlen(name) < len)) /* in NDEBUG is defined */
1997 return -1; /* buffer too small, temporary file can not be created */
1999 strcpy(fname, name);
2001 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
2003 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
2009 perror("Can't create temporary file");
2017 /** Create a temporary file name
2023 static char fnamebuf[PATH_MAX];
2025 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2026 fprintf(stderr, "Can't create temporary file name!");
2037 /** Create a temporary file and add it to tmpfileNameSet,
2038 so that it is removed explicitly by rm_tmpfiles()
2039 or implicitly at program extit.
2047 char fnamebuf[PATH_MAX];
2049 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
2050 fprintf(stderr, "Can't create temporary file!");
2054 tmp = Safe_strdup(fnamebuf);
2056 addSetHead(&tmpfileNameSet, tmp);
2058 if ((fp = fdopen(fd, "w+b")) == NULL) {
2059 perror("Can't create temporary file!");