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[256];
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))
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 SPEC_CONST(newSym->etype)=1;
293 SPEC_STAT(newSym->etype)=1;
294 resolveIvalSym(newSym->ival);
296 // add it to the "XINIT (CODE)" segment
297 addSet(&xinit->syms, newSym);
300 if (IS_AGGREGATE (sym->type)) {
301 ival = initAggregates (sym, sym->ival, NULL);
303 if (getNelements(sym->type, sym->ival)>1) {
304 werror (W_EXCESS_INITIALIZERS, "scalar",
305 sym->name, sym->lineDef);
307 ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
308 decorateType (resolveSymbols (list2expr (sym->ival))));
310 codeOutFile = statsg->oFile;
313 // set ival's lineno to where the symbol was defined
314 setAstLineno (ival, lineno=sym->lineDef);
315 // check if this is not a constant expression
316 if (!constExprTree(ival)) {
317 werror (E_CONST_EXPECTED, "found expression");
318 // but try to do it anyway
321 eBBlockFromiCode (iCodeFromAst (ival));
328 /* if is has an absolute address then generate
329 an equate for this no need to allocate space */
330 if (SPEC_ABSA (sym->etype))
334 fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
336 if (TARGET_IS_XA51) {
339 } else if (map==bit || map==sfrbit) {
343 fprintf (map->oFile, "%s\t%s\t0x%04x\n",
345 SPEC_ADDR (sym->etype));
348 int size = getSize (sym->type);
350 werror(E_UNKNOWN_SIZE,sym->name);
354 fprintf (map->oFile, "==.\n");
356 if (IS_STATIC (sym->etype))
357 tfprintf (map->oFile, "!slabeldef\n", sym->rname);
359 tfprintf (map->oFile, "!labeldef\n", sym->rname);
360 tfprintf (map->oFile, "\t!ds\n",
361 (unsigned int) size & 0xffff);
366 /*-----------------------------------------------------------------*/
367 /* initPointer - pointer initialization code massaging */
368 /*-----------------------------------------------------------------*/
370 initPointer (initList * ilist, sym_link *toType)
373 ast *expr = list2expr (ilist);
378 /* try it the oldway first */
379 if ((val = constExprValue (expr, FALSE)))
382 /* ( ptr + constant ) */
383 if (IS_AST_OP (expr) &&
384 (expr->opval.op == '+' || expr->opval.op == '-') &&
385 IS_AST_SYM_VALUE (expr->left) &&
386 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
387 compareType(toType, expr->left->ftype) &&
388 IS_AST_LIT_VALUE (expr->right)) {
389 return valForCastAggr (expr->left, expr->left->ftype,
395 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
396 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
397 if (compareType(toType, expr->left->ftype)!=1) {
398 werror (W_INIT_WRONG);
399 printFromToType(expr->left->ftype, toType);
405 /* no then we have to do these cludgy checks */
406 /* pointers can be initialized with address of
407 a variable or address of an array element */
408 if (IS_AST_OP (expr) && expr->opval.op == '&') {
409 /* address of symbol */
410 if (IS_AST_SYM_VALUE (expr->left)) {
411 val = copyValue (AST_VALUE (expr->left));
412 val->type = newLink (DECLARATOR);
413 if (SPEC_SCLS (expr->left->etype) == S_CODE) {
414 DCL_TYPE (val->type) = CPOINTER;
415 DCL_PTR_CONST (val->type) = port->mem.code_ro;
417 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
418 DCL_TYPE (val->type) = FPOINTER;
419 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
420 DCL_TYPE (val->type) = PPOINTER;
421 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
422 DCL_TYPE (val->type) = IPOINTER;
423 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
424 DCL_TYPE (val->type) = EEPPOINTER;
426 DCL_TYPE (val->type) = POINTER;
427 val->type->next = expr->left->ftype;
428 val->etype = getSpec (val->type);
432 /* if address of indexed array */
433 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
434 return valForArray (expr->left);
436 /* if address of structure element then
438 if (IS_AST_OP (expr->left) &&
439 expr->left->opval.op == '.') {
440 return valForStructElem (expr->left->left,
445 (&some_struct)->element */
446 if (IS_AST_OP (expr->left) &&
447 expr->left->opval.op == PTR_OP &&
448 IS_ADDRESS_OF_OP (expr->left->left)) {
449 return valForStructElem (expr->left->left->left,
453 /* case 3. (((char *) &a) +/- constant) */
454 if (IS_AST_OP (expr) &&
455 (expr->opval.op == '+' || expr->opval.op == '-') &&
456 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
457 IS_AST_OP (expr->left->right) &&
458 expr->left->right->opval.op == '&' &&
459 IS_AST_LIT_VALUE (expr->right)) {
461 return valForCastAggr (expr->left->right->left,
462 expr->left->left->opval.lnk,
463 expr->right, expr->opval.op);
466 /* case 4. (char *)(array type) */
467 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
468 IS_ARRAY(expr->right->ftype)) {
470 val = copyValue (AST_VALUE (expr->right));
471 val->type = newLink (DECLARATOR);
472 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
473 DCL_TYPE (val->type) = CPOINTER;
474 DCL_PTR_CONST (val->type) = port->mem.code_ro;
476 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
477 DCL_TYPE (val->type) = FPOINTER;
478 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
479 DCL_TYPE (val->type) = PPOINTER;
480 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
481 DCL_TYPE (val->type) = IPOINTER;
482 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
483 DCL_TYPE (val->type) = EEPPOINTER;
485 DCL_TYPE (val->type) = POINTER;
486 val->type->next = expr->right->ftype->next;
487 val->etype = getSpec (val->type);
491 werror (E_INCOMPAT_PTYPES);
496 /*-----------------------------------------------------------------*/
497 /* printChar - formats and prints a characater string with DB */
498 /*-----------------------------------------------------------------*/
500 printChar (FILE * ofile, char *s, int plen)
503 int len = strlen (s);
508 while (len && pplen < plen)
511 while (i && *s && pplen < plen)
513 if (*s < ' ' || *s == '\"' || *s=='\\')
517 tfprintf (ofile, "\t!ascii\n", buf);
518 tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
533 tfprintf (ofile, "\t!ascii\n", buf);
542 tfprintf (ofile, "\t!db !constbyte\n", 0);
545 /*-----------------------------------------------------------------*/
546 /* return the generic pointer high byte for a given pointer type. */
547 /*-----------------------------------------------------------------*/
549 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
557 werror (E_CANNOT_USE_GENERIC_POINTER,
558 iname ? iname : "<null>",
559 oname ? oname : "<null>");
566 return GPTYPE_XSTACK;
568 fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
576 /*-----------------------------------------------------------------*/
577 /* printPointerType - generates ival for pointer type */
578 /*-----------------------------------------------------------------*/
580 _printPointerType (FILE * oFile, const char *name)
582 if (options.model == MODEL_FLAT24)
584 fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
588 fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
592 /*-----------------------------------------------------------------*/
593 /* printPointerType - generates ival for pointer type */
594 /*-----------------------------------------------------------------*/
596 printPointerType (FILE * oFile, const char *name)
598 _printPointerType (oFile, name);
599 fprintf (oFile, "\n");
602 /*-----------------------------------------------------------------*/
603 /* printGPointerType - generates ival for generic pointer type */
604 /*-----------------------------------------------------------------*/
606 printGPointerType (FILE * oFile, const char *iname, const char *oname,
607 const unsigned int type)
609 _printPointerType (oFile, iname);
610 fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
613 /*-----------------------------------------------------------------*/
614 /* printIvalType - generates ival for int/char */
615 /*-----------------------------------------------------------------*/
617 printIvalType (symbol *sym, sym_link * type, initList * ilist, FILE * oFile)
621 /* if initList is deep */
622 if (ilist->type == INIT_DEEP)
623 ilist = ilist->init.deep;
625 if (!(val = list2val (ilist))) {
626 // assuming a warning has been thrown
630 if (val->type != type) {
631 val = valCastLiteral(type, floatFromVal(val));
634 switch (getSize (type)) {
637 tfprintf (oFile, "\t!db !constbyte\n", 0);
639 tfprintf (oFile, "\t!dbs\n",
640 aopLiteral (val, 0));
644 if (port->use_dw_for_init)
645 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
647 fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
651 tfprintf (oFile, "\t!dw !constword\n", 0);
652 tfprintf (oFile, "\t!dw !constword\n", 0);
655 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
656 aopLiteral (val, 0), aopLiteral (val, 1),
657 aopLiteral (val, 2), aopLiteral (val, 3));
663 /*-----------------------------------------------------------------*/
664 /* printIvalBitFields - generate initializer for bitfields */
665 /*-----------------------------------------------------------------*/
666 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
670 initList *lilist = *ilist ;
671 unsigned long ival = 0;
677 val = list2val(lilist);
679 if (SPEC_BLEN(lsym->etype) > 8) {
680 size += ((SPEC_BLEN (lsym->etype) / 8) +
681 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
684 size = ((SPEC_BLEN (lsym->etype) / 8) +
685 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
687 i = (unsigned long)floatFromVal(val);
688 i <<= SPEC_BSTR (lsym->etype);
690 if (! ( lsym->next &&
691 (IS_BITFIELD(lsym->next->type)) &&
692 (SPEC_BSTR(lsym->next->etype)))) break;
694 lilist = lilist->next;
698 tfprintf (oFile, "\t!db !constbyte\n",ival);
702 tfprintf (oFile, "\t!dw !constword\n",ival);
705 tfprintf (oFile, "\t!db !constword,!constword\n",
706 (ival >> 8) & 0xffff, (ival & 0xffff));
713 /*-----------------------------------------------------------------*/
714 /* printIvalStruct - generates initial value for structures */
715 /*-----------------------------------------------------------------*/
717 printIvalStruct (symbol * sym, sym_link * type,
718 initList * ilist, FILE * oFile)
723 sflds = SPEC_STRUCT (type)->fields;
724 if (ilist->type != INIT_DEEP) {
725 werror (E_INIT_STRUCT, sym->name);
729 iloop = ilist->init.deep;
731 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
732 if (IS_BITFIELD(sflds->type)) {
733 printIvalBitFields(&sflds,&iloop,oFile);
735 printIval (sym, sflds->type, iloop, oFile);
739 werror (W_EXCESS_INITIALIZERS, "struct", sym->name, sym->lineDef);
744 /*-----------------------------------------------------------------*/
745 /* printIvalChar - generates initital value for character array */
746 /*-----------------------------------------------------------------*/
748 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
756 val = list2val (ilist);
757 /* if the value is a character string */
758 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
760 if (!DCL_ELEM (type))
761 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
763 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
765 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
767 tfprintf (oFile, "\t!db !constbyte\n", 0);
775 printChar (oFile, s, strlen (s) + 1);
779 /*-----------------------------------------------------------------*/
780 /* printIvalArray - generates code for array initialization */
781 /*-----------------------------------------------------------------*/
783 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
787 int lcnt = 0, size = 0;
790 /* take care of the special case */
791 /* array of characters can be init */
793 if (IS_CHAR (type->next)) {
794 if (!IS_LITERAL(list2val(ilist)->etype)) {
795 werror (E_CONST_EXPECTED);
798 if (printIvalChar (type,
799 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
800 oFile, SPEC_CVAL (sym->etype).v_char))
803 /* not the special case */
804 if (ilist->type != INIT_DEEP)
806 werror (E_INIT_STRUCT, sym->name);
810 iloop = ilist->init.deep;
811 lcnt = DCL_ELEM (type);
812 for (last_type = type->next;
813 last_type && IS_DECL(last_type) && DCL_ELEM (last_type);
814 last_type = last_type->next) {
815 lcnt *= DCL_ELEM (last_type);
821 printIval (sym, type->next, iloop, oFile);
822 iloop = (iloop ? iloop->next : NULL);
825 /* if not array limits given & we */
826 /* are out of initialisers then */
827 if (!DCL_ELEM (type) && !iloop)
830 /* no of elements given and we */
831 /* have generated for all of them */
833 /* if initializers left */
835 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
841 /* if we have not been given a size */
842 if (!DCL_ELEM (type))
843 DCL_ELEM (type) = size;
848 /*-----------------------------------------------------------------*/
849 /* printIvalFuncPtr - generate initial value for function pointers */
850 /*-----------------------------------------------------------------*/
852 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
857 val = list2val (ilist);
860 // an error has been thrown allready
864 if (IS_LITERAL(val->etype)) {
865 if (compareType(type,val->etype)==0) {
866 werror (E_INCOMPAT_TYPES);
867 printFromToType (val->type, type);
869 printIvalCharPtr (NULL, type, val, oFile);
873 /* check the types */
874 if ((dLvl = compareType (val->type, type->next)) <= 0)
876 tfprintf (oFile, "\t!dw !constword\n", 0);
880 /* now generate the name */
883 if (port->use_dw_for_init)
885 tfprintf (oFile, "\t!dws\n", val->name);
889 printPointerType (oFile, val->name);
892 else if (port->use_dw_for_init)
894 tfprintf (oFile, "\t!dws\n", val->sym->rname);
898 printPointerType (oFile, val->sym->rname);
904 /*-----------------------------------------------------------------*/
905 /* printIvalCharPtr - generates initial values for character pointers */
906 /*-----------------------------------------------------------------*/
908 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
912 /* PENDING: this is _very_ mcs51 specific, including a magic
914 It's also endin specific.
916 size = getSize (type);
918 if (val->name && strlen (val->name))
920 if (size == 1) /* This appears to be Z80 specific?? */
923 "\t!dbs\n", val->name);
925 else if (size == FPTRSIZE)
927 if (port->use_dw_for_init)
929 tfprintf (oFile, "\t!dws\n", val->name);
933 printPointerType (oFile, val->name);
936 else if (size == GPTRSIZE)
939 if (IS_PTR (val->type)) {
940 type = DCL_TYPE (val->type);
942 type = PTR_TYPE (SPEC_OCLS (val->etype));
944 if (val->sym && val->sym->isstrlit) {
945 // this is a literal string
948 printGPointerType (oFile, val->name, sym->name, type);
952 fprintf (stderr, "*** internal error: unknown size in "
953 "printIvalCharPtr.\n");
958 // these are literals assigned to pointers
962 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
965 if (port->use_dw_for_init)
966 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
968 tfprintf (oFile, "\t.byte %s,%s\n",
969 aopLiteral (val, 0), aopLiteral (val, 1));
972 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
973 // non-zero mcs51 generic pointer
974 werror (E_LITERAL_GENERIC);
976 fprintf (oFile, "\t.byte %s,%s,%s\n",
979 aopLiteral (val, 2));
982 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
983 // non-zero ds390 generic pointer
984 werror (E_LITERAL_GENERIC);
986 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
990 aopLiteral (val, 3));
997 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
998 addSet (&statsg->syms, val->sym);
1004 /*-----------------------------------------------------------------*/
1005 /* printIvalPtr - generates initial value for pointers */
1006 /*-----------------------------------------------------------------*/
1008 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1014 if (ilist->type == INIT_DEEP)
1015 ilist = ilist->init.deep;
1017 /* function pointer */
1018 if (IS_FUNC (type->next))
1020 printIvalFuncPtr (type, ilist, oFile);
1024 if (!(val = initPointer (ilist, type)))
1027 /* if character pointer */
1028 if (IS_CHAR (type->next))
1029 if (printIvalCharPtr (sym, type, val, oFile))
1032 /* check the type */
1033 if (compareType (type, val->type) == 0) {
1034 werror (W_INIT_WRONG);
1035 printFromToType (val->type, type);
1038 /* if val is literal */
1039 if (IS_LITERAL (val->etype))
1041 switch (getSize (type))
1044 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1047 if (port->use_dw_for_init)
1048 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1050 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1052 case 3: // how about '390??
1053 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1054 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1060 size = getSize (type);
1062 if (size == 1) /* Z80 specific?? */
1064 tfprintf (oFile, "\t!dbs\n", val->name);
1066 else if (size == FPTRSIZE)
1068 if (port->use_dw_for_init) {
1069 tfprintf (oFile, "\t!dws\n", val->name);
1071 printPointerType (oFile, val->name);
1074 else if (size == GPTRSIZE)
1076 printGPointerType (oFile, val->name, sym->name,
1077 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1078 PTR_TYPE (SPEC_OCLS (val->etype))));
1083 /*-----------------------------------------------------------------*/
1084 /* printIval - generates code for initial value */
1085 /*-----------------------------------------------------------------*/
1087 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1094 /* update line number for error msgs */
1095 lineno=sym->lineDef;
1097 /* if structure then */
1098 if (IS_STRUCT (type))
1100 printIvalStruct (sym, type, ilist, oFile);
1104 /* if this is an array */
1105 if (IS_ARRAY (type))
1107 printIvalArray (sym, type, ilist, oFile);
1111 // not an aggregate, ilist must be a node
1112 if (ilist->type!=INIT_NODE &&
1113 // or a 1-element list
1114 ilist->init.deep->next) {
1115 werror (W_EXCESS_INITIALIZERS, "scalar",
1116 sym->name, sym->lineDef);
1119 // and the type must match
1120 val=list2val(ilist);
1121 if (compareType(type, val->type)==0) {
1122 // special case for literal strings
1123 if (IS_ARRAY (val->type) && IS_CHAR (val->etype) &&
1124 // which are really code pointers
1125 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1128 werror (E_TYPE_MISMATCH, "assignment", " ");
1129 printFromToType(list2val(ilist)->type, type);
1133 /* if this is a pointer */
1136 printIvalPtr (sym, type, ilist, oFile);
1140 /* if type is SPECIFIER */
1143 printIvalType (sym, type, ilist, oFile);
1148 /*-----------------------------------------------------------------*/
1149 /* emitStaticSeg - emitcode for the static segment */
1150 /*-----------------------------------------------------------------*/
1152 emitStaticSeg (memmap * map, FILE * out)
1156 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1158 /* for all variables in this segment do */
1159 for (sym = setFirstItem (map->syms); sym;
1160 sym = setNextItem (map->syms))
1163 /* if it is "extern" then do nothing */
1164 if (IS_EXTERN (sym->etype))
1167 /* if it is not static add it to the public
1169 if (!IS_STATIC (sym->etype))
1171 addSetHead (&publics, sym);
1174 /* print extra debug info if required */
1175 if (options.debug) {
1179 if (IS_STATIC (sym->etype))
1180 fprintf (out, "F%s$", moduleName); /* scope is file */
1182 fprintf (out, "G$"); /* scope is global */
1185 /* symbol is local */
1186 fprintf (out, "L%s$",
1187 (sym->localof ? sym->localof->name : "-null-"));
1188 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1191 /* if it has an absolute address */
1192 if (SPEC_ABSA (sym->etype))
1195 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1197 fprintf (out, "%s\t=\t0x%04x\n",
1199 SPEC_ADDR (sym->etype));
1204 fprintf (out, " == .\n");
1206 /* if it has an initial value */
1209 fprintf (out, "%s:\n", sym->rname);
1211 resolveIvalSym (sym->ival);
1212 printIval (sym, sym->type, sym->ival, out);
1214 /* if sym is a simple string and sym->ival is a string,
1215 WE don't need it anymore */
1216 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1217 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1218 list2val(sym->ival)->sym->isstrlit) {
1219 freeStringSymbol(list2val(sym->ival)->sym);
1223 /* allocate space */
1224 int size = getSize (sym->type);
1227 werror(E_UNKNOWN_SIZE,sym->name);
1229 fprintf (out, "%s:\n", sym->rname);
1230 /* special case for character strings */
1231 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1232 SPEC_CVAL (sym->etype).v_char)
1234 SPEC_CVAL (sym->etype).v_char,
1235 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1237 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1243 /*-----------------------------------------------------------------*/
1244 /* emitMaps - emits the code for the data portion the code */
1245 /*-----------------------------------------------------------------*/
1250 /* no special considerations for the following
1251 data, idata & bit & xdata */
1252 emitRegularMap (data, TRUE, TRUE);
1253 emitRegularMap (idata, TRUE, TRUE);
1254 emitRegularMap (bit, TRUE, FALSE);
1255 emitRegularMap (xdata, TRUE, TRUE);
1256 if (port->genXINIT) {
1257 emitRegularMap (xidata, TRUE, TRUE);
1259 emitRegularMap (sfr, FALSE, FALSE);
1260 emitRegularMap (sfrbit, FALSE, FALSE);
1261 emitRegularMap (home, TRUE, FALSE);
1262 emitRegularMap (code, TRUE, FALSE);
1264 emitStaticSeg (statsg, code->oFile);
1265 if (port->genXINIT) {
1266 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1267 emitStaticSeg (xinit, code->oFile);
1272 /*-----------------------------------------------------------------*/
1273 /* flushStatics - flush all currently defined statics out to file */
1274 /* and delete. Temporary function */
1275 /*-----------------------------------------------------------------*/
1279 emitStaticSeg (statsg, codeOutFile);
1280 statsg->syms = NULL;
1283 /*-----------------------------------------------------------------*/
1284 /* createInterruptVect - creates the interrupt vector */
1285 /*-----------------------------------------------------------------*/
1287 createInterruptVect (FILE * vFile)
1290 mainf = newSymbol ("main", 0);
1293 /* only if the main function exists */
1294 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1296 if (!options.cc_only && !noAssemble && !options.c1mode)
1301 /* if the main is only a prototype ie. no body then do nothing */
1302 if (!IFFUNC_HASBODY(mainf->type))
1304 /* if ! compile only then main function should be present */
1305 if (!options.cc_only && !noAssemble)
1310 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1311 fprintf (vFile, "__interrupt_vect:\n");
1314 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1316 /* "generic" interrupt table header (if port doesn't specify one).
1317 * Look suspiciously like 8051 code to me...
1320 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1323 /* now for the other interrupts */
1324 for (; i < maxInterrupts; i++)
1327 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1329 fprintf (vFile, "\treti\n\t.ds\t7\n");
1336 ";--------------------------------------------------------\n"
1337 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1341 ";--------------------------------------------------------\n"};
1344 /*-----------------------------------------------------------------*/
1345 /* initialComments - puts in some initial comments */
1346 /*-----------------------------------------------------------------*/
1348 initialComments (FILE * afile)
1352 fprintf (afile, "%s", iComments1);
1353 fprintf (afile, "; Version " SDCC_VERSION_STR " %s\n", asctime (localtime (&t)));
1354 fprintf (afile, "%s", iComments2);
1357 /*-----------------------------------------------------------------*/
1358 /* printPublics - generates .global for publics */
1359 /*-----------------------------------------------------------------*/
1361 printPublics (FILE * afile)
1365 fprintf (afile, "%s", iComments2);
1366 fprintf (afile, "; Public variables in this module\n");
1367 fprintf (afile, "%s", iComments2);
1369 for (sym = setFirstItem (publics); sym;
1370 sym = setNextItem (publics))
1371 tfprintf (afile, "\t!global\n", sym->rname);
1374 /*-----------------------------------------------------------------*/
1375 /* printExterns - generates .global for externs */
1376 /*-----------------------------------------------------------------*/
1378 printExterns (FILE * afile)
1382 fprintf (afile, "%s", iComments2);
1383 fprintf (afile, "; Externals used\n");
1384 fprintf (afile, "%s", iComments2);
1386 for (sym = setFirstItem (externs); sym;
1387 sym = setNextItem (externs))
1388 tfprintf (afile, "\t!extern\n", sym->rname);
1391 /*-----------------------------------------------------------------*/
1392 /* emitOverlay - will emit code for the overlay stuff */
1393 /*-----------------------------------------------------------------*/
1395 emitOverlay (FILE * afile)
1399 if (!elementsInSet (ovrSetSets))
1400 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1402 /* for each of the sets in the overlay segment do */
1403 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1404 ovrset = setNextItem (ovrSetSets))
1409 if (elementsInSet (ovrset))
1411 /* output the area informtion */
1412 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1415 for (sym = setFirstItem (ovrset); sym;
1416 sym = setNextItem (ovrset))
1418 /* if extern then it is in the publics table: do nothing */
1419 if (IS_EXTERN (sym->etype))
1422 /* if allocation required check is needed
1423 then check if the symbol really requires
1424 allocation only for local variables */
1425 if (!IS_AGGREGATE (sym->type) &&
1426 !(sym->_isparm && !IS_REGPARM (sym->etype))
1427 && !sym->allocreq && sym->level)
1430 /* if global variable & not static or extern
1431 and addPublics allowed then add it to the public set */
1432 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1433 && !IS_STATIC (sym->etype))
1435 addSetHead (&publics, sym);
1438 /* if extern then do nothing or is a function
1440 if (IS_FUNC (sym->type))
1443 /* print extra debug info if required */
1448 if (IS_STATIC (sym->etype))
1449 fprintf (afile, "F%s$", moduleName); /* scope is file */
1451 fprintf (afile, "G$"); /* scope is global */
1454 /* symbol is local */
1455 fprintf (afile, "L%s$",
1456 (sym->localof ? sym->localof->name : "-null-"));
1457 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1460 /* if is has an absolute address then generate
1461 an equate for this no need to allocate space */
1462 if (SPEC_ABSA (sym->etype))
1466 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1468 fprintf (afile, "%s\t=\t0x%04x\n",
1470 SPEC_ADDR (sym->etype));
1473 int size = getSize(sym->type);
1476 werror(E_UNKNOWN_SIZE,sym->name);
1479 fprintf (afile, "==.\n");
1481 /* allocate space */
1482 tfprintf (afile, "!labeldef\n", sym->rname);
1483 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1491 /*-----------------------------------------------------------------*/
1492 /* spacesToUnderscores - replace spaces with underscores */
1493 /*-----------------------------------------------------------------*/
1495 spacesToUnderscores (char *dest, const char *src, size_t len)
1500 assert(dest != NULL);
1501 assert(src != NULL);
1505 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1506 *p++ = isspace(*src) ? '_' : *src;
1514 /*-----------------------------------------------------------------*/
1515 /* glue - the final glue that hold the whole thing together */
1516 /*-----------------------------------------------------------------*/
1522 FILE *ovrFile = tempfile ();
1523 char moduleBuf[PATH_MAX];
1525 addSetHead (&tmpfileSet, ovrFile);
1526 /* print the global struct definitions */
1530 vFile = tempfile ();
1531 /* PENDING: this isnt the best place but it will do */
1532 if (port->general.glue_up_main)
1534 /* create the interrupt vector table */
1535 createInterruptVect (vFile);
1538 addSetHead (&tmpfileSet, vFile);
1540 /* emit code for the all the variables declared */
1542 /* do the overlay segments */
1543 emitOverlay (ovrFile);
1545 outputDebugSymbols();
1547 /* now put it all together into the assembler file */
1548 /* create the assembler file name */
1550 /* -o option overrides default name? */
1551 if ((noAssemble || options.c1mode) && fullDstFileName)
1553 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1557 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1558 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1561 if (!(asmFile = fopen (scratchFileName, "w")))
1563 werror (E_FILE_OPEN_ERR, scratchFileName);
1567 /* initial comments */
1568 initialComments (asmFile);
1570 /* print module name */
1571 tfprintf (asmFile, "\t!module\n",
1572 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1573 tfprintf (asmFile, "\t!fileprelude\n");
1575 /* Let the port generate any global directives, etc. */
1576 if (port->genAssemblerPreamble)
1578 port->genAssemblerPreamble (asmFile);
1581 /* print the global variables in this module */
1582 printPublics (asmFile);
1583 if (port->assembler.externGlobal)
1584 printExterns (asmFile);
1586 /* copy the sfr segment */
1587 fprintf (asmFile, "%s", iComments2);
1588 fprintf (asmFile, "; special function registers\n");
1589 fprintf (asmFile, "%s", iComments2);
1590 copyFile (asmFile, sfr->oFile);
1592 /* copy the sbit segment */
1593 fprintf (asmFile, "%s", iComments2);
1594 fprintf (asmFile, "; special function bits \n");
1595 fprintf (asmFile, "%s", iComments2);
1596 copyFile (asmFile, sfrbit->oFile);
1598 /*JCF: Create the areas for the register banks*/
1599 if(port->general.glue_up_main &&
1600 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1602 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1604 fprintf (asmFile, "%s", iComments2);
1605 fprintf (asmFile, "; overlayable register banks \n");
1606 fprintf (asmFile, "%s", iComments2);
1608 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1609 if(RegBankUsed[1]||options.parms_in_bank1)
1610 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1612 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1614 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1618 /* copy the data segment */
1619 fprintf (asmFile, "%s", iComments2);
1620 fprintf (asmFile, "; internal ram data\n");
1621 fprintf (asmFile, "%s", iComments2);
1622 copyFile (asmFile, data->oFile);
1625 /* create the overlay segments */
1627 fprintf (asmFile, "%s", iComments2);
1628 fprintf (asmFile, "; overlayable items in internal ram \n");
1629 fprintf (asmFile, "%s", iComments2);
1630 copyFile (asmFile, ovrFile);
1633 /* create the stack segment MOF */
1634 if (mainf && IFFUNC_HASBODY(mainf->type))
1636 fprintf (asmFile, "%s", iComments2);
1637 fprintf (asmFile, "; Stack segment in internal ram \n");
1638 fprintf (asmFile, "%s", iComments2);
1639 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1640 "__start__stack:\n\t.ds\t1\n\n");
1643 /* create the idata segment */
1645 fprintf (asmFile, "%s", iComments2);
1646 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1647 fprintf (asmFile, "%s", iComments2);
1648 copyFile (asmFile, idata->oFile);
1651 /* copy the bit segment */
1652 fprintf (asmFile, "%s", iComments2);
1653 fprintf (asmFile, "; bit data\n");
1654 fprintf (asmFile, "%s", iComments2);
1655 copyFile (asmFile, bit->oFile);
1657 /* if external stack then reserve space of it */
1658 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1660 fprintf (asmFile, "%s", iComments2);
1661 fprintf (asmFile, "; external stack \n");
1662 fprintf (asmFile, "%s", iComments2);
1663 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1664 fprintf (asmFile, "\t.ds 256\n");
1668 /* copy xtern ram data */
1669 fprintf (asmFile, "%s", iComments2);
1670 fprintf (asmFile, "; external ram data\n");
1671 fprintf (asmFile, "%s", iComments2);
1672 copyFile (asmFile, xdata->oFile);
1674 /* copy xternal initialized ram data */
1675 fprintf (asmFile, "%s", iComments2);
1676 fprintf (asmFile, "; external initialized ram data\n");
1677 fprintf (asmFile, "%s", iComments2);
1678 copyFile (asmFile, xidata->oFile);
1680 /* copy the interrupt vector table */
1681 if (mainf && IFFUNC_HASBODY(mainf->type))
1683 fprintf (asmFile, "%s", iComments2);
1684 fprintf (asmFile, "; interrupt vector \n");
1685 fprintf (asmFile, "%s", iComments2);
1686 copyFile (asmFile, vFile);
1689 /* copy global & static initialisations */
1690 fprintf (asmFile, "%s", iComments2);
1691 fprintf (asmFile, "; global & static initialisations\n");
1692 fprintf (asmFile, "%s", iComments2);
1694 /* Everywhere we generate a reference to the static_name area,
1695 * (which is currently only here), we immediately follow it with a
1696 * definition of the post_static_name area. This guarantees that
1697 * the post_static_name area will immediately follow the static_name
1700 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1701 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1702 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1704 if (mainf && IFFUNC_HASBODY(mainf->type))
1706 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1707 /* if external stack is specified then the
1708 higher order byte of the xdatalocation is
1709 going into P2 and the lower order going into
1711 if (options.useXstack)
1713 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1714 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1715 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1716 (unsigned int) options.xdata_loc & 0xff);
1719 // This should probably be a port option, but I'm being lazy.
1720 // on the 400, the firmware boot loader gives us a valid stack
1721 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1722 if (!TARGET_IS_DS400)
1724 /* initialise the stack pointer. JCF: aslink takes care of the location */
1725 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1728 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1729 fprintf (asmFile, "\tmov\ta,dpl\n");
1730 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1731 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1732 fprintf (asmFile, "__sdcc_init_data:\n");
1734 // if the port can copy the XINIT segment to XISEG
1735 if (port->genXINIT) {
1736 port->genXINIT(asmFile);
1740 copyFile (asmFile, statsg->oFile);
1742 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1744 /* This code is generated in the post-static area.
1745 * This area is guaranteed to follow the static area
1746 * by the ugly shucking and jiving about 20 lines ago.
1748 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1749 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1755 "%s", iComments2, iComments2);
1756 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1757 copyFile (asmFile, home->oFile);
1759 /* copy over code */
1760 fprintf (asmFile, "%s", iComments2);
1761 fprintf (asmFile, "; code\n");
1762 fprintf (asmFile, "%s", iComments2);
1763 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1764 if (mainf && IFFUNC_HASBODY(mainf->type))
1767 /* entry point @ start of CSEG */
1768 fprintf (asmFile, "__sdcc_program_startup:\n");
1770 /* put in the call to main */
1771 fprintf (asmFile, "\tlcall\t_main\n");
1772 if (options.mainreturn)
1775 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1776 fprintf (asmFile, "\tret\n");
1782 fprintf (asmFile, ";\treturn from main will lock up\n");
1783 fprintf (asmFile, "\tsjmp .\n");
1786 copyFile (asmFile, code->oFile);
1788 if (port->genAssemblerEnd) {
1789 port->genAssemblerEnd(asmFile);
1797 /** Creates a temporary file with unoque file name
1799 - TMP, TEMP, TMPDIR env. varibles
1800 - if Un*x system: /usr/tmp and /tmp
1801 - root directory using mkstemp() if avaliable
1802 - default location using tempnam()
1805 tempfileandname(char *fname, size_t len)
1807 #define TEMPLATE "sdccXXXXXX"
1808 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1810 const char *tmpdir = NULL;
1813 if ((tmpdir = getenv ("TMP")) == NULL)
1814 if ((tmpdir = getenv ("TEMP")) == NULL)
1815 tmpdir = getenv ("TMPDIR");
1819 /* try with /usr/tmp and /tmp on Un*x systems */
1820 struct stat statbuf;
1822 if (tmpdir == NULL) {
1823 if (stat("/usr/tmp", &statbuf) != -1)
1824 tmpdir = "/usr/tmp";
1825 else if (stat("/tmp", &statbuf) != -1)
1833 char fnamebuf[PATH_MAX];
1836 if (fname == NULL || len == 0) {
1838 len = sizeof fnamebuf;
1842 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1844 assert(name_len < len);
1845 if (!(name_len < len)) /* in NDEBUG is defined */
1846 return -1; /* buffer too small, temporary file can not be created */
1848 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1851 name_len = TEMPLATE_LEN;
1853 assert(name_len < len);
1854 if (!(name_len < len)) /* in NDEBUG is defined */
1855 return -1; /* buffer too small, temporary file can not be created */
1857 strcpy(fname, TEMPLATE);
1860 fd = mkstemp(fname);
1864 char *name = tempnam(tmpdir, "sdcc");
1867 perror("Can't create temporary file name");
1871 assert(strlen(name) < len);
1872 if (!(strlen(name) < len)) /* in NDEBUG is defined */
1873 return -1; /* buffer too small, temporary file can not be created */
1875 strcpy(fname, name);
1877 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
1879 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
1885 perror("Can't create temporary file");
1893 /** Create a temporary file name
1899 static char fnamebuf[PATH_MAX];
1901 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1902 fprintf(stderr, "Can't create temporary file name!");
1913 /** Create a temporary file and add it to tmpfileNameSet,
1914 so that it is removed explicitly by rm_tmpfiles()
1915 or implicitly at program extit.
1923 char fnamebuf[PATH_MAX];
1925 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1926 fprintf(stderr, "Can't create temporary file!");
1930 tmp = Safe_strdup(fnamebuf);
1932 addSetHead(&tmpfileNameSet, tmp);
1934 if ((fp = fdopen(fd, "w+b")) == NULL) {
1935 perror("Can't create temporary file!");