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,
789 /* take care of the special case */
790 /* array of characters can be init */
792 if (IS_CHAR (type->next)) {
793 if (!IS_LITERAL(list2val(ilist)->etype)) {
794 werror (E_CONST_EXPECTED);
797 if (printIvalChar (type,
798 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
799 oFile, SPEC_CVAL (sym->etype).v_char))
802 /* not the special case */
803 if (ilist->type != INIT_DEEP)
805 werror (E_INIT_STRUCT, sym->name);
809 for (iloop=ilist->init.deep; iloop; iloop=iloop->next)
811 printIval (sym, type->next, iloop, oFile);
813 if (++size > DCL_ELEM(type)) {
814 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
819 if (DCL_ELEM(type)) {
820 // pad with zeros if needed
821 if (size<DCL_ELEM(type)) {
822 size = (DCL_ELEM(type) - size) * getSize(type->next);
824 tfprintf (oFile, "\t!db !constbyte\n", 0);
828 // we have not been given a size, but we now know it
829 DCL_ELEM (type) = size;
835 /*-----------------------------------------------------------------*/
836 /* printIvalFuncPtr - generate initial value for function pointers */
837 /*-----------------------------------------------------------------*/
839 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
844 val = list2val (ilist);
847 // an error has been thrown allready
851 if (IS_LITERAL(val->etype)) {
852 if (compareType(type,val->etype)==0) {
853 werror (E_INCOMPAT_TYPES);
854 printFromToType (val->type, type);
856 printIvalCharPtr (NULL, type, val, oFile);
860 /* check the types */
861 if ((dLvl = compareType (val->type, type->next)) <= 0)
863 tfprintf (oFile, "\t!dw !constword\n", 0);
867 /* now generate the name */
870 if (port->use_dw_for_init)
872 tfprintf (oFile, "\t!dws\n", val->name);
876 printPointerType (oFile, val->name);
879 else if (port->use_dw_for_init)
881 tfprintf (oFile, "\t!dws\n", val->sym->rname);
885 printPointerType (oFile, val->sym->rname);
891 /*-----------------------------------------------------------------*/
892 /* printIvalCharPtr - generates initial values for character pointers */
893 /*-----------------------------------------------------------------*/
895 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
899 /* PENDING: this is _very_ mcs51 specific, including a magic
901 It's also endin specific.
903 size = getSize (type);
905 if (val->name && strlen (val->name))
907 if (size == 1) /* This appears to be Z80 specific?? */
910 "\t!dbs\n", val->name);
912 else if (size == FPTRSIZE)
914 if (port->use_dw_for_init)
916 tfprintf (oFile, "\t!dws\n", val->name);
920 printPointerType (oFile, val->name);
923 else if (size == GPTRSIZE)
926 if (IS_PTR (val->type)) {
927 type = DCL_TYPE (val->type);
929 type = PTR_TYPE (SPEC_OCLS (val->etype));
931 if (val->sym && val->sym->isstrlit) {
932 // this is a literal string
935 printGPointerType (oFile, val->name, sym->name, type);
939 fprintf (stderr, "*** internal error: unknown size in "
940 "printIvalCharPtr.\n");
945 // these are literals assigned to pointers
949 tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
952 if (port->use_dw_for_init)
953 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
955 tfprintf (oFile, "\t.byte %s,%s\n",
956 aopLiteral (val, 0), aopLiteral (val, 1));
959 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
960 // non-zero mcs51 generic pointer
961 werror (E_LITERAL_GENERIC);
963 fprintf (oFile, "\t.byte %s,%s,%s\n",
966 aopLiteral (val, 2));
969 if (IS_GENPTR(type) && floatFromVal(val)!=0) {
970 // non-zero ds390 generic pointer
971 werror (E_LITERAL_GENERIC);
973 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
977 aopLiteral (val, 3));
984 if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
985 addSet (&statsg->syms, val->sym);
991 /*-----------------------------------------------------------------*/
992 /* printIvalPtr - generates initial value for pointers */
993 /*-----------------------------------------------------------------*/
995 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1001 if (ilist->type == INIT_DEEP)
1002 ilist = ilist->init.deep;
1004 /* function pointer */
1005 if (IS_FUNC (type->next))
1007 printIvalFuncPtr (type, ilist, oFile);
1011 if (!(val = initPointer (ilist, type)))
1014 /* if character pointer */
1015 if (IS_CHAR (type->next))
1016 if (printIvalCharPtr (sym, type, val, oFile))
1019 /* check the type */
1020 if (compareType (type, val->type) == 0) {
1021 werror (W_INIT_WRONG);
1022 printFromToType (val->type, type);
1025 /* if val is literal */
1026 if (IS_LITERAL (val->etype))
1028 switch (getSize (type))
1031 tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
1034 if (port->use_dw_for_init)
1035 tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
1037 tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1039 case 3: // how about '390??
1040 fprintf (oFile, "\t.byte %s,%s,#0x%d\n",
1041 aopLiteral (val, 0), aopLiteral (val, 1), GPTYPE_CODE);
1047 size = getSize (type);
1049 if (size == 1) /* Z80 specific?? */
1051 tfprintf (oFile, "\t!dbs\n", val->name);
1053 else if (size == FPTRSIZE)
1055 if (port->use_dw_for_init) {
1056 tfprintf (oFile, "\t!dws\n", val->name);
1058 printPointerType (oFile, val->name);
1061 else if (size == GPTRSIZE)
1063 printGPointerType (oFile, val->name, sym->name,
1064 (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1065 PTR_TYPE (SPEC_OCLS (val->etype))));
1070 /*-----------------------------------------------------------------*/
1071 /* printIval - generates code for initial value */
1072 /*-----------------------------------------------------------------*/
1074 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
1081 /* update line number for error msgs */
1082 lineno=sym->lineDef;
1084 /* if structure then */
1085 if (IS_STRUCT (type))
1087 printIvalStruct (sym, type, ilist, oFile);
1091 /* if this is an array */
1092 if (IS_ARRAY (type))
1094 printIvalArray (sym, type, ilist, oFile);
1098 // not an aggregate, ilist must be a node
1099 if (ilist->type!=INIT_NODE) {
1100 // or a 1-element list
1101 if (ilist->init.deep->next) {
1102 werror (W_EXCESS_INITIALIZERS, "scalar",
1103 sym->name, sym->lineDef);
1105 ilist=ilist->init.deep;
1109 // and the type must match
1110 itype=ilist->init.node->ftype;
1112 if (compareType(type, itype)==0) {
1113 // special case for literal strings
1114 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1115 // which are really code pointers
1116 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1119 werror (E_TYPE_MISMATCH, "assignment", " ");
1120 printFromToType(itype, type);
1124 /* if this is a pointer */
1127 printIvalPtr (sym, type, ilist, oFile);
1131 /* if type is SPECIFIER */
1134 printIvalType (sym, type, ilist, oFile);
1139 /*-----------------------------------------------------------------*/
1140 /* emitStaticSeg - emitcode for the static segment */
1141 /*-----------------------------------------------------------------*/
1143 emitStaticSeg (memmap * map, FILE * out)
1147 /* fprintf(out, "\t.area\t%s\n", map->sname); */
1149 /* for all variables in this segment do */
1150 for (sym = setFirstItem (map->syms); sym;
1151 sym = setNextItem (map->syms))
1154 /* if it is "extern" then do nothing */
1155 if (IS_EXTERN (sym->etype))
1158 /* if it is not static add it to the public
1160 if (!IS_STATIC (sym->etype))
1162 addSetHead (&publics, sym);
1165 /* print extra debug info if required */
1166 if (options.debug) {
1170 if (IS_STATIC (sym->etype))
1171 fprintf (out, "F%s$", moduleName); /* scope is file */
1173 fprintf (out, "G$"); /* scope is global */
1176 /* symbol is local */
1177 fprintf (out, "L%s$",
1178 (sym->localof ? sym->localof->name : "-null-"));
1179 fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
1182 /* if it has an absolute address */
1183 if (SPEC_ABSA (sym->etype))
1186 fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1188 fprintf (out, "%s\t=\t0x%04x\n",
1190 SPEC_ADDR (sym->etype));
1195 fprintf (out, " == .\n");
1197 /* if it has an initial value */
1200 fprintf (out, "%s:\n", sym->rname);
1202 resolveIvalSym (sym->ival);
1203 printIval (sym, sym->type, sym->ival, out);
1205 /* if sym is a simple string and sym->ival is a string,
1206 WE don't need it anymore */
1207 if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1208 IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1209 list2val(sym->ival)->sym->isstrlit) {
1210 freeStringSymbol(list2val(sym->ival)->sym);
1214 /* allocate space */
1215 int size = getSize (sym->type);
1218 werror(E_UNKNOWN_SIZE,sym->name);
1220 fprintf (out, "%s:\n", sym->rname);
1221 /* special case for character strings */
1222 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1223 SPEC_CVAL (sym->etype).v_char)
1225 SPEC_CVAL (sym->etype).v_char,
1226 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1228 tfprintf (out, "\t!ds\n", (unsigned int) size & 0xffff);
1234 /*-----------------------------------------------------------------*/
1235 /* emitMaps - emits the code for the data portion the code */
1236 /*-----------------------------------------------------------------*/
1241 /* no special considerations for the following
1242 data, idata & bit & xdata */
1243 emitRegularMap (data, TRUE, TRUE);
1244 emitRegularMap (idata, TRUE, TRUE);
1245 emitRegularMap (bit, TRUE, FALSE);
1246 emitRegularMap (xdata, TRUE, TRUE);
1247 if (port->genXINIT) {
1248 emitRegularMap (xidata, TRUE, TRUE);
1250 emitRegularMap (sfr, FALSE, FALSE);
1251 emitRegularMap (sfrbit, FALSE, FALSE);
1252 emitRegularMap (home, TRUE, FALSE);
1253 emitRegularMap (code, TRUE, FALSE);
1255 emitStaticSeg (statsg, code->oFile);
1256 if (port->genXINIT) {
1257 tfprintf (code->oFile, "\t!area\n", xinit->sname);
1258 emitStaticSeg (xinit, code->oFile);
1263 /*-----------------------------------------------------------------*/
1264 /* flushStatics - flush all currently defined statics out to file */
1265 /* and delete. Temporary function */
1266 /*-----------------------------------------------------------------*/
1270 emitStaticSeg (statsg, codeOutFile);
1271 statsg->syms = NULL;
1274 /*-----------------------------------------------------------------*/
1275 /* createInterruptVect - creates the interrupt vector */
1276 /*-----------------------------------------------------------------*/
1278 createInterruptVect (FILE * vFile)
1281 mainf = newSymbol ("main", 0);
1284 /* only if the main function exists */
1285 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1287 if (!options.cc_only && !noAssemble && !options.c1mode)
1292 /* if the main is only a prototype ie. no body then do nothing */
1293 if (!IFFUNC_HASBODY(mainf->type))
1295 /* if ! compile only then main function should be present */
1296 if (!options.cc_only && !noAssemble)
1301 tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1302 fprintf (vFile, "__interrupt_vect:\n");
1305 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1307 /* "generic" interrupt table header (if port doesn't specify one).
1308 * Look suspiciously like 8051 code to me...
1311 fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1314 /* now for the other interrupts */
1315 for (; i < maxInterrupts; i++)
1318 fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1320 fprintf (vFile, "\treti\n\t.ds\t7\n");
1327 ";--------------------------------------------------------\n"
1328 "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1332 ";--------------------------------------------------------\n"};
1335 /*-----------------------------------------------------------------*/
1336 /* initialComments - puts in some initial comments */
1337 /*-----------------------------------------------------------------*/
1339 initialComments (FILE * afile)
1343 fprintf (afile, "%s", iComments1);
1344 fprintf (afile, "; Version " SDCC_VERSION_STR " %s\n", asctime (localtime (&t)));
1345 fprintf (afile, "%s", iComments2);
1348 /*-----------------------------------------------------------------*/
1349 /* printPublics - generates .global for publics */
1350 /*-----------------------------------------------------------------*/
1352 printPublics (FILE * afile)
1356 fprintf (afile, "%s", iComments2);
1357 fprintf (afile, "; Public variables in this module\n");
1358 fprintf (afile, "%s", iComments2);
1360 for (sym = setFirstItem (publics); sym;
1361 sym = setNextItem (publics))
1362 tfprintf (afile, "\t!global\n", sym->rname);
1365 /*-----------------------------------------------------------------*/
1366 /* printExterns - generates .global for externs */
1367 /*-----------------------------------------------------------------*/
1369 printExterns (FILE * afile)
1373 fprintf (afile, "%s", iComments2);
1374 fprintf (afile, "; Externals used\n");
1375 fprintf (afile, "%s", iComments2);
1377 for (sym = setFirstItem (externs); sym;
1378 sym = setNextItem (externs))
1379 tfprintf (afile, "\t!extern\n", sym->rname);
1382 /*-----------------------------------------------------------------*/
1383 /* emitOverlay - will emit code for the overlay stuff */
1384 /*-----------------------------------------------------------------*/
1386 emitOverlay (FILE * afile)
1390 if (!elementsInSet (ovrSetSets))
1391 tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1393 /* for each of the sets in the overlay segment do */
1394 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1395 ovrset = setNextItem (ovrSetSets))
1400 if (elementsInSet (ovrset))
1402 /* output the area informtion */
1403 fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1406 for (sym = setFirstItem (ovrset); sym;
1407 sym = setNextItem (ovrset))
1409 /* if extern then it is in the publics table: do nothing */
1410 if (IS_EXTERN (sym->etype))
1413 /* if allocation required check is needed
1414 then check if the symbol really requires
1415 allocation only for local variables */
1416 if (!IS_AGGREGATE (sym->type) &&
1417 !(sym->_isparm && !IS_REGPARM (sym->etype))
1418 && !sym->allocreq && sym->level)
1421 /* if global variable & not static or extern
1422 and addPublics allowed then add it to the public set */
1423 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1424 && !IS_STATIC (sym->etype))
1426 addSetHead (&publics, sym);
1429 /* if extern then do nothing or is a function
1431 if (IS_FUNC (sym->type))
1434 /* print extra debug info if required */
1439 if (IS_STATIC (sym->etype))
1440 fprintf (afile, "F%s$", moduleName); /* scope is file */
1442 fprintf (afile, "G$"); /* scope is global */
1445 /* symbol is local */
1446 fprintf (afile, "L%s$",
1447 (sym->localof ? sym->localof->name : "-null-"));
1448 fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1451 /* if is has an absolute address then generate
1452 an equate for this no need to allocate space */
1453 if (SPEC_ABSA (sym->etype))
1457 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1459 fprintf (afile, "%s\t=\t0x%04x\n",
1461 SPEC_ADDR (sym->etype));
1464 int size = getSize(sym->type);
1467 werror(E_UNKNOWN_SIZE,sym->name);
1470 fprintf (afile, "==.\n");
1472 /* allocate space */
1473 tfprintf (afile, "!labeldef\n", sym->rname);
1474 tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1482 /*-----------------------------------------------------------------*/
1483 /* spacesToUnderscores - replace spaces with underscores */
1484 /*-----------------------------------------------------------------*/
1486 spacesToUnderscores (char *dest, const char *src, size_t len)
1491 assert(dest != NULL);
1492 assert(src != NULL);
1496 for (p = dest, i = 0; *src != '\0' && i < len; ++src, ++i) {
1497 *p++ = isspace(*src) ? '_' : *src;
1505 /*-----------------------------------------------------------------*/
1506 /* glue - the final glue that hold the whole thing together */
1507 /*-----------------------------------------------------------------*/
1513 FILE *ovrFile = tempfile ();
1514 char moduleBuf[PATH_MAX];
1517 if(port->general.glue_up_main &&
1518 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400))
1520 mcs51_like=1; /*So it has bits, sfr, sbits, data, idata, etc...*/
1527 addSetHead (&tmpfileSet, ovrFile);
1528 /* print the global struct definitions */
1532 vFile = tempfile ();
1533 /* PENDING: this isnt the best place but it will do */
1534 if (port->general.glue_up_main)
1536 /* create the interrupt vector table */
1537 createInterruptVect (vFile);
1540 addSetHead (&tmpfileSet, vFile);
1542 /* emit code for the all the variables declared */
1544 /* do the overlay segments */
1545 emitOverlay (ovrFile);
1547 outputDebugSymbols();
1549 /* now put it all together into the assembler file */
1550 /* create the assembler file name */
1552 /* -o option overrides default name? */
1553 if ((noAssemble || options.c1mode) && fullDstFileName)
1555 strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1559 strncpyz (scratchFileName, dstFileName, PATH_MAX);
1560 strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1563 if (!(asmFile = fopen (scratchFileName, "w")))
1565 werror (E_FILE_OPEN_ERR, scratchFileName);
1569 /* initial comments */
1570 initialComments (asmFile);
1572 /* print module name */
1573 tfprintf (asmFile, "\t!module\n",
1574 spacesToUnderscores (moduleBuf, moduleName, sizeof moduleBuf));
1575 tfprintf (asmFile, "\t!fileprelude\n");
1577 /* Let the port generate any global directives, etc. */
1578 if (port->genAssemblerPreamble)
1580 port->genAssemblerPreamble (asmFile);
1583 /* print the global variables in this module */
1584 printPublics (asmFile);
1585 if (port->assembler.externGlobal)
1586 printExterns (asmFile);
1590 /* copy the sfr segment */
1591 fprintf (asmFile, "%s", iComments2);
1592 fprintf (asmFile, "; special function registers\n");
1593 fprintf (asmFile, "%s", iComments2);
1594 copyFile (asmFile, sfr->oFile);
1596 /* copy the sbit segment */
1597 fprintf (asmFile, "%s", iComments2);
1598 fprintf (asmFile, "; special function bits \n");
1599 fprintf (asmFile, "%s", iComments2);
1600 copyFile (asmFile, sfrbit->oFile);
1602 /*JCF: Create the areas for the register banks*/
1603 if(RegBankUsed[0]||RegBankUsed[1]||RegBankUsed[2]||RegBankUsed[3])
1605 fprintf (asmFile, "%s", iComments2);
1606 fprintf (asmFile, "; overlayable register banks \n");
1607 fprintf (asmFile, "%s", iComments2);
1609 fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1610 if(RegBankUsed[1]||options.parms_in_bank1)
1611 fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1613 fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1615 fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1619 /* copy the data segment */
1620 fprintf (asmFile, "%s", iComments2);
1621 fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1622 fprintf (asmFile, "%s", iComments2);
1623 copyFile (asmFile, data->oFile);
1626 /* create the overlay segments */
1628 fprintf (asmFile, "%s", iComments2);
1629 fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1630 fprintf (asmFile, "%s", iComments2);
1631 copyFile (asmFile, ovrFile);
1634 /* create the stack segment MOF */
1635 if (mainf && IFFUNC_HASBODY(mainf->type))
1637 fprintf (asmFile, "%s", iComments2);
1638 fprintf (asmFile, "; Stack segment in internal ram \n");
1639 fprintf (asmFile, "%s", iComments2);
1640 fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1641 "__start__stack:\n\t.ds\t1\n\n");
1644 /* create the idata segment */
1645 if ( (idata) && (mcs51_like) ) {
1646 fprintf (asmFile, "%s", iComments2);
1647 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1648 fprintf (asmFile, "%s", iComments2);
1649 copyFile (asmFile, idata->oFile);
1652 /* copy the bit segment */
1654 fprintf (asmFile, "%s", iComments2);
1655 fprintf (asmFile, "; bit data\n");
1656 fprintf (asmFile, "%s", iComments2);
1657 copyFile (asmFile, bit->oFile);
1660 /* if external stack then reserve space of it */
1661 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack)
1663 fprintf (asmFile, "%s", iComments2);
1664 fprintf (asmFile, "; external stack \n");
1665 fprintf (asmFile, "%s", iComments2);
1666 fprintf (asmFile, "\t.area XSEG (XDATA)\n"); /* MOF */
1667 fprintf (asmFile, "\t.ds 256\n");
1671 /* copy xtern ram data */
1673 fprintf (asmFile, "%s", iComments2);
1674 fprintf (asmFile, "; external ram data\n");
1675 fprintf (asmFile, "%s", iComments2);
1676 copyFile (asmFile, xdata->oFile);
1679 /* copy xternal initialized ram data */
1680 fprintf (asmFile, "%s", iComments2);
1681 fprintf (asmFile, "; external initialized ram data\n");
1682 fprintf (asmFile, "%s", iComments2);
1683 copyFile (asmFile, xidata->oFile);
1685 /* If the port wants to generate any extra areas, let it do so. */
1686 if (port->extraAreas.genExtraAreaDeclaration)
1688 port->extraAreas.genExtraAreaDeclaration(asmFile,
1689 mainf && IFFUNC_HASBODY(mainf->type));
1692 /* copy the interrupt vector table */
1693 if (mainf && IFFUNC_HASBODY(mainf->type))
1695 fprintf (asmFile, "%s", iComments2);
1696 fprintf (asmFile, "; interrupt vector \n");
1697 fprintf (asmFile, "%s", iComments2);
1698 copyFile (asmFile, vFile);
1701 /* copy global & static initialisations */
1702 fprintf (asmFile, "%s", iComments2);
1703 fprintf (asmFile, "; global & static initialisations\n");
1704 fprintf (asmFile, "%s", iComments2);
1706 /* Everywhere we generate a reference to the static_name area,
1707 * (which is currently only here), we immediately follow it with a
1708 * definition of the post_static_name area. This guarantees that
1709 * the post_static_name area will immediately follow the static_name
1712 tfprintf (asmFile, "\t!area\n", port->mem.static_name); /* MOF */
1713 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1714 tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1716 if (mainf && IFFUNC_HASBODY(mainf->type))
1718 fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1719 /* if external stack is specified then the
1720 higher order byte of the xdatalocation is
1721 going into P2 and the lower order going into
1723 if (options.useXstack)
1725 fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1726 (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1727 fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1728 (unsigned int) options.xdata_loc & 0xff);
1731 // This should probably be a port option, but I'm being lazy.
1732 // on the 400, the firmware boot loader gives us a valid stack
1733 // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1734 if (!TARGET_IS_DS400)
1736 /* initialise the stack pointer. JCF: aslink takes care of the location */
1737 fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
1740 fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1741 fprintf (asmFile, "\tmov\ta,dpl\n");
1742 fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1743 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1744 fprintf (asmFile, "__sdcc_init_data:\n");
1746 // if the port can copy the XINIT segment to XISEG
1747 if (port->genXINIT) {
1748 port->genXINIT(asmFile);
1752 copyFile (asmFile, statsg->oFile);
1754 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type))
1756 /* This code is generated in the post-static area.
1757 * This area is guaranteed to follow the static area
1758 * by the ugly shucking and jiving about 20 lines ago.
1760 tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1761 fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1767 "%s", iComments2, iComments2);
1768 tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1769 copyFile (asmFile, home->oFile);
1771 /* copy over code */
1772 fprintf (asmFile, "%s", iComments2);
1773 fprintf (asmFile, "; code\n");
1774 fprintf (asmFile, "%s", iComments2);
1775 tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1776 if (mainf && IFFUNC_HASBODY(mainf->type))
1779 /* entry point @ start of CSEG */
1780 fprintf (asmFile, "__sdcc_program_startup:\n");
1782 /* put in the call to main */
1783 fprintf (asmFile, "\tlcall\t_main\n");
1784 if (options.mainreturn)
1787 fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1788 fprintf (asmFile, "\tret\n");
1794 fprintf (asmFile, ";\treturn from main will lock up\n");
1795 fprintf (asmFile, "\tsjmp .\n");
1798 copyFile (asmFile, code->oFile);
1800 if (port->genAssemblerEnd) {
1801 port->genAssemblerEnd(asmFile);
1809 /** Creates a temporary file with unoque file name
1811 - TMP, TEMP, TMPDIR env. varibles
1812 - if Un*x system: /usr/tmp and /tmp
1813 - root directory using mkstemp() if avaliable
1814 - default location using tempnam()
1817 tempfileandname(char *fname, size_t len)
1819 #define TEMPLATE "sdccXXXXXX"
1820 #define TEMPLATE_LEN ((sizeof TEMPLATE) - 1)
1822 const char *tmpdir = NULL;
1825 if ((tmpdir = getenv ("TMP")) == NULL)
1826 if ((tmpdir = getenv ("TEMP")) == NULL)
1827 tmpdir = getenv ("TMPDIR");
1831 static int warning_emitted;
1836 if (!warning_emitted)
1838 fprintf (stderr, "TMP not defined in environment, using %s for temporary files\n.", tmpdir);
1839 warning_emitted = 1;
1845 /* try with /usr/tmp and /tmp on Un*x systems */
1846 struct stat statbuf;
1848 if (tmpdir == NULL) {
1849 if (stat("/usr/tmp", &statbuf) != -1)
1850 tmpdir = "/usr/tmp";
1851 else if (stat("/tmp", &statbuf) != -1)
1859 char fnamebuf[PATH_MAX];
1862 if (fname == NULL || len == 0) {
1864 len = sizeof fnamebuf;
1868 name_len = strlen(tmpdir) + 1 + TEMPLATE_LEN;
1870 assert(name_len < len);
1871 if (!(name_len < len)) /* in NDEBUG is defined */
1872 return -1; /* buffer too small, temporary file can not be created */
1874 sprintf(fname, "%s" DIR_SEPARATOR_STRING TEMPLATE, tmpdir);
1877 name_len = TEMPLATE_LEN;
1879 assert(name_len < len);
1880 if (!(name_len < len)) /* in NDEBUG is defined */
1881 return -1; /* buffer too small, temporary file can not be created */
1883 strcpy(fname, TEMPLATE);
1886 fd = mkstemp(fname);
1890 char *name = tempnam(tmpdir, "sdcc");
1893 perror("Can't create temporary file name");
1897 assert(strlen(name) < len);
1898 if (!(strlen(name) < len)) /* in NDEBUG is defined */
1899 return -1; /* buffer too small, temporary file can not be created */
1901 strcpy(fname, name);
1903 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
1905 fd = open(name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
1911 perror("Can't create temporary file");
1919 /** Create a temporary file name
1925 static char fnamebuf[PATH_MAX];
1927 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1928 fprintf(stderr, "Can't create temporary file name!");
1939 /** Create a temporary file and add it to tmpfileNameSet,
1940 so that it is removed explicitly by rm_tmpfiles()
1941 or implicitly at program extit.
1949 char fnamebuf[PATH_MAX];
1951 if ((fd = tempfileandname(fnamebuf, sizeof fnamebuf)) == -1) {
1952 fprintf(stderr, "Can't create temporary file!");
1956 tmp = Safe_strdup(fnamebuf);
1958 addSetHead(&tmpfileNameSet, tmp);
1960 if ((fp = fdopen(fd, "w+b")) == NULL) {
1961 perror("Can't create temporary file!");