Fixed bitfield initialization in code space
[fw/sdcc] / src / SDCCglue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
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
9    later version.
10
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.
15
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.
19
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 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include "asm.h"
27 #include <time.h>
28 #include "newalloc.h"
29
30 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
31 #if 0                           /* This should no longer be necessary. */
32 // This is a bit messy because we define link ourself
33 #define link NoLiNk
34 #include <unistd.h>
35 #undef link
36 #else
37
38 #include <unistd.h>
39 #endif
40 #else
41 // No unistd.h in Borland C++
42 #endif
43
44 symbol *interrupts[256];
45
46 void printIval (symbol *, sym_link *, initList *, FILE *);
47 set *publics = NULL;            /* public variables */
48 set *externs = NULL;            /* Varibles that are declared as extern */
49
50 /* TODO: this should be configurable (DS803C90 uses more than 6) */
51 int maxInterrupts = 6;
52 int allocInfo = 1;
53 symbol *mainf;
54 extern char *VersionString;
55 set *tmpfileSet = NULL;         /* set of tmp file created by the compiler */
56 set *tmpfileNameSet = NULL;     /* All are unlinked at close. */
57
58 /*-----------------------------------------------------------------*/
59 /* closeTmpFiles - closes all tmp files created by the compiler    */
60 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
61 /*-----------------------------------------------------------------*/
62 DEFSETFUNC (closeTmpFiles)
63 {
64   FILE *tfile = item;
65
66   if (tfile)
67     fclose (tfile);
68
69   return 0;
70 }
71
72 /*-----------------------------------------------------------------*/
73 /* rmTmpFiles - closes all tmp files created by the compiler    */
74 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
75 /*-----------------------------------------------------------------*/
76 DEFSETFUNC (rmTmpFiles)
77 {
78   char *name = item;
79
80   if (name)
81     {
82       unlink (name);
83       free (name);
84     }
85   return 0;
86 }
87
88 /*-----------------------------------------------------------------*/
89 /* copyFile - copies source file to destination file               */
90 /*-----------------------------------------------------------------*/
91 void 
92 copyFile (FILE * dest, FILE * src)
93 {
94   int ch;
95
96   rewind (src);
97   while (!feof (src))
98     if ((ch = fgetc (src)) != EOF)
99       fputc (ch, dest);
100 }
101
102 char *
103 aopLiteralLong (value * val, int offset, int size)
104 {
105         char *rs;
106         union {
107                 float f;
108                 unsigned char c[4];
109         }
110         fl;
111
112         /* if it is a float then it gets tricky */
113         /* otherwise it is fairly simple */
114         if (!IS_FLOAT (val->type)) {
115                 unsigned long v = floatFromVal (val);
116
117                 v >>= (offset * 8);
118                 switch (size) {
119                 case 1:
120                         tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
121                         break;
122                 case 2:
123                         tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
124                         break;
125                 default:
126                         /* Hmm.  Too big for now. */
127                         assert (0);
128                 }
129                 rs = Safe_calloc (1, strlen (buffer) + 1);
130                 return strcpy (rs, buffer);
131         }
132
133         /* PENDING: For now size must be 1 */
134         assert (size == 1);
135
136         /* it is type float */
137         fl.f = (float) floatFromVal (val);
138 #ifdef _BIG_ENDIAN
139         tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
140 #else
141         tsprintf (buffer, "!immedbyte", fl.c[offset]);
142 #endif
143         rs = Safe_calloc (1, strlen (buffer) + 1);
144         return strcpy (rs, buffer);
145 }
146
147 /*-----------------------------------------------------------------*/
148 /* aopLiteral - string from a literal value                        */
149 /*-----------------------------------------------------------------*/
150 char *
151 aopLiteral (value * val, int offset)
152 {
153         return aopLiteralLong (val, offset, 1);
154 }
155
156 /*-----------------------------------------------------------------*/
157 /* emitRegularMap - emit code for maps with no special cases       */
158 /*-----------------------------------------------------------------*/
159 static void 
160 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
161 {
162   symbol *sym;
163
164   if (addPublics)
165     {
166       /* PENDING: special case here - should remove */
167       if (!strcmp (map->sname, CODE_NAME))
168         tfprintf (map->oFile, "\t!areacode\n", map->sname);
169       else if (!strcmp (map->sname, DATA_NAME))
170         tfprintf (map->oFile, "\t!areadata\n", map->sname);
171       else if (!strcmp (map->sname, HOME_NAME))
172         tfprintf (map->oFile, "\t!areahome\n", map->sname);
173       else
174         tfprintf (map->oFile, "\t!area\n", map->sname);
175     }
176
177   /* print the area name */
178   for (sym = setFirstItem (map->syms); sym;
179        sym = setNextItem (map->syms))
180     {
181
182       /* if extern then add it into the extern list */
183       if (IS_EXTERN (sym->etype))
184         {
185           addSetHead (&externs, sym);
186           continue;
187         }
188
189       /* if allocation required check is needed
190          then check if the symbol really requires
191          allocation only for local variables */
192       if (arFlag && !IS_AGGREGATE (sym->type) &&
193           !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
194           !sym->allocreq && sym->level)
195         continue;
196
197       /* if global variable & not static or extern
198          and addPublics allowed then add it to the public set */
199       if ((sym->level == 0 ||
200            (sym->_isparm && !IS_REGPARM (sym->etype))) &&
201           addPublics &&
202           !IS_STATIC (sym->etype) &&
203           (sym->used || sym->fbody))
204         {
205           addSetHead (&publics, sym);
206         }
207
208       /* if extern then do nothing or is a function
209          then do nothing */
210       if (IS_FUNC (sym->type))
211         continue;
212
213       /* print extra debug info if required */
214       if ((options.debug || sym->level == 0) && !options.nodebug)
215         {
216
217           cdbSymbol (sym, cdbFile, FALSE, FALSE);
218
219           if (!sym->level)      /* global */
220             if (IS_STATIC (sym->etype))
221               fprintf (map->oFile, "F%s$", moduleName);         /* scope is file */
222             else
223               fprintf (map->oFile, "G$");       /* scope is global */
224           else
225             /* symbol is local */
226             fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
227           fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
228         }
229
230       /* if is has an absolute address then generate
231          an equate for this no need to allocate space */
232       if (SPEC_ABSA (sym->etype))
233         {
234           if ((options.debug || sym->level == 0) && !options.nodebug)
235             fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
236
237           fprintf (map->oFile, "%s\t=\t0x%04x\n",
238                    sym->rname,
239                    SPEC_ADDR (sym->etype));
240         }
241       else
242         {
243           /* allocate space */
244           if ((options.debug || sym->level == 0) && !options.nodebug)
245             fprintf (map->oFile, "==.\n");
246           if (IS_STATIC (sym->etype))
247             tfprintf (map->oFile, "!slabeldef\n", sym->rname);
248           else
249             tfprintf (map->oFile, "!labeldef\n", sym->rname);
250           tfprintf (map->oFile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
251         }
252
253       /* if it has an initial value then do it only if
254          it is a global variable */
255       if (sym->ival && sym->level == 0)
256         {
257           ast *ival = NULL;
258
259           if (IS_AGGREGATE (sym->type))
260             ival = initAggregates (sym, sym->ival, NULL);
261           else
262             ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
263                      decorateType (resolveSymbols (list2expr (sym->ival))));
264           codeOutFile = statsg->oFile;
265           allocInfo = 0;
266           eBBlockFromiCode (iCodeFromAst (ival));
267           allocInfo = 1;
268           sym->ival = NULL;
269         }
270     }
271 }
272
273 /*-----------------------------------------------------------------*/
274 /* initPointer - pointer initialization code massaging             */
275 /*-----------------------------------------------------------------*/
276 value *
277 initPointer (initList * ilist)
278 {
279   value *val;
280   ast *expr = list2expr (ilist);
281
282   if (!expr)
283     goto wrong;
284
285   /* try it the oldway first */
286   if ((val = constExprValue (expr, FALSE)))
287     return val;
288
289   /* no then we have to do these cludgy checks */
290   /* pointers can be initialized with address of
291      a variable or address of an array element */
292   if (IS_AST_OP (expr) && expr->opval.op == '&')
293     {
294       /* address of symbol */
295       if (IS_AST_SYM_VALUE (expr->left))
296         {
297           val = copyValue (AST_VALUE (expr->left));
298           val->type = newLink ();
299           if (SPEC_SCLS (expr->left->etype) == S_CODE)
300             {
301               DCL_TYPE (val->type) = CPOINTER;
302               DCL_PTR_CONST (val->type) = port->mem.code_ro;
303             }
304           else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
305             DCL_TYPE (val->type) = FPOINTER;
306           else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
307             DCL_TYPE (val->type) = PPOINTER;
308           else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
309             DCL_TYPE (val->type) = IPOINTER;
310           else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
311             DCL_TYPE (val->type) = EEPPOINTER;
312           else
313             DCL_TYPE (val->type) = POINTER;
314           val->type->next = expr->left->ftype;
315           val->etype = getSpec (val->type);
316           return val;
317         }
318
319       /* if address of indexed array */
320       if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
321         return valForArray (expr->left);
322
323       /* if address of structure element then
324          case 1. a.b ; */
325       if (IS_AST_OP (expr->left) &&
326           expr->left->opval.op == '.')
327         {
328           return valForStructElem (expr->left->left,
329                                    expr->left->right);
330         }
331
332       /* case 2. (&a)->b ;
333          (&some_struct)->element */
334       if (IS_AST_OP (expr->left) &&
335           expr->left->opval.op == PTR_OP &&
336           IS_ADDRESS_OF_OP (expr->left->left))
337         return valForStructElem (expr->left->left->left,
338                                  expr->left->right);
339
340     }
341   /* case 3. (((char *) &a) +/- constant) */
342   if (IS_AST_OP (expr) &&
343       (expr->opval.op == '+' || expr->opval.op == '-') &&
344       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
345       IS_AST_OP (expr->left->right) &&
346       expr->left->right->opval.op == '&' &&
347       IS_AST_LIT_VALUE (expr->right))
348     {
349
350       return valForCastAggr (expr->left->right->left,
351                              expr->left->left->opval.lnk,
352                              expr->right, expr->opval.op);
353
354     }
355
356 wrong:
357   werror (E_INIT_WRONG);
358   return NULL;
359
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* printChar - formats and prints a characater string with DB      */
364 /*-----------------------------------------------------------------*/
365 void 
366 printChar (FILE * ofile, char *s, int plen)
367 {
368   int i;
369   int len = strlen (s);
370   int pplen = 0;
371   char buf[100];
372   char *p = buf;
373
374   while (len && pplen < plen)
375     {
376       i = 60;
377       while (i && *s && pplen < plen)
378         {
379           if (*s < ' ' || *s == '\"')
380             {
381               *p = '\0';
382               if (p != buf)
383                 tfprintf (ofile, "\t!ascii\n", buf);
384               tfprintf (ofile, "\t!db !constbyte\n", *s);
385               p = buf;
386             }
387           else
388             {
389               *p = *s;
390               p++;
391             }
392           s++;
393           pplen++;
394           i--;
395         }
396       if (p != buf)
397         {
398           *p = '\0';
399           tfprintf (ofile, "\t!ascii\n", buf);
400           p = buf;
401         }
402
403       if (len > 60)
404         len -= 60;
405       else
406         len = 0;
407     }
408   tfprintf (ofile, "\t!db !constbyte\n", 0);
409 }
410
411 /*-----------------------------------------------------------------*/
412 /* return the generic pointer high byte for a given pointer type.  */
413 /*-----------------------------------------------------------------*/
414 int 
415 pointerTypeToGPByte (const int p_type)
416 {
417   switch (p_type)
418     {
419     case IPOINTER:
420     case POINTER:
421       return 0;
422     case GPOINTER:
423       /* hack - if we get a generic pointer, we just assume
424        * it's an FPOINTER (i.e. in XDATA space).
425        */
426     case FPOINTER:
427       return 1;
428     case CPOINTER:
429       return 2;
430     case PPOINTER:
431       return 3;
432     default:
433       fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
434                p_type);
435       break;
436     }
437   return -1;
438 }
439
440
441 /*-----------------------------------------------------------------*/
442 /* printPointerType - generates ival for pointer type              */
443 /*-----------------------------------------------------------------*/
444 void 
445 _printPointerType (FILE * oFile, const char *name)
446 {
447   if (IS_DS390_PORT)
448     {
449       fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
450     }
451   else
452     {
453       fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
454     }
455 }
456
457 /*-----------------------------------------------------------------*/
458 /* printPointerType - generates ival for pointer type              */
459 /*-----------------------------------------------------------------*/
460 void 
461 printPointerType (FILE * oFile, const char *name)
462 {
463   _printPointerType (oFile, name);
464   fprintf (oFile, "\n");
465 }
466
467 /*-----------------------------------------------------------------*/
468 /* printGPointerType - generates ival for generic pointer type     */
469 /*-----------------------------------------------------------------*/
470 void 
471 printGPointerType (FILE * oFile, const char *name,
472                    const unsigned int type)
473 {
474   _printPointerType (oFile, name);
475   fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type));
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* printIvalType - generates ival for int/char                     */
480 /*-----------------------------------------------------------------*/
481 void 
482 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
483 {
484         value *val;
485
486         /* if initList is deep */
487         if (ilist->type == INIT_DEEP)
488                 ilist = ilist->init.deep;
489
490         val = list2val (ilist);
491         switch (getSize (type)) {
492         case 1:
493                 if (!val)
494                         tfprintf (oFile, "\t!db !constbyte\n", 0);
495                 else
496                         tfprintf (oFile, "\t!dbs\n",
497                                   aopLiteral (val, 0));
498                 break;
499
500         case 2:
501                 if (port->use_dw_for_init)
502                         tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
503                 else
504                         fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
505                 break;
506         case 4:
507                 if (!val) {
508                         tfprintf (oFile, "\t!dw !constword\n", 0);
509                         tfprintf (oFile, "\t!dw !constword\n", 0);
510                 }
511                 else {
512                         fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
513                                  aopLiteral (val, 0), aopLiteral (val, 1),
514                                  aopLiteral (val, 2), aopLiteral (val, 3));
515                 }
516                 break;
517         }
518 }
519
520 /*-----------------------------------------------------------------*/
521 /* printIvalBitFields - generate initializer for bitfields         */
522 /*-----------------------------------------------------------------*/
523 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
524 {
525         value *val ;
526         symbol *lsym = *sym;
527         initList *lilist = *ilist ;
528         unsigned long ival = 0;
529         int size =0;
530
531         
532         do {
533                 unsigned long i;
534                 val = list2val(lilist);
535                 if (size) {
536                         if (SPEC_BLEN(lsym->etype) > 8) {
537                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
538                                          (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
539                         }
540                 } else {
541                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
542                                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
543                 }
544                 i = (unsigned long)floatFromVal(val);
545                 i <<= SPEC_BSTR (lsym->etype);
546                 ival |= i;
547                 if (! ( lsym->next &&
548                         (IS_BITFIELD(lsym->next->type)) &&
549                         (SPEC_BSTR(lsym->next->etype)))) break;
550                 lsym = lsym->next;
551                 lilist = lilist->next;
552         } while (1);
553         switch (size) {
554         case 1:
555                 tfprintf (oFile, "\t!db !constbyte\n",ival);
556                 break;
557
558         case 2:
559                 tfprintf (oFile, "\t!dw !constword\n",ival);
560                 break;
561         case 4:
562                 tfprintf (oFile, "\t!db  !constword,!constword\n",
563                          (ival >> 8) & 0xffff, (ival & 0xffff));
564                 break;
565         }
566         *sym = lsym;
567         *ilist = lilist;
568 }
569
570 /*-----------------------------------------------------------------*/
571 /* printIvalStruct - generates initial value for structures        */
572 /*-----------------------------------------------------------------*/
573 void 
574 printIvalStruct (symbol * sym, sym_link * type,
575                  initList * ilist, FILE * oFile)
576 {
577         symbol *sflds;
578         initList *iloop;
579
580         sflds = SPEC_STRUCT (type)->fields;
581         if (ilist->type != INIT_DEEP) {
582                 werror (E_INIT_STRUCT, sym->name);
583                 return;
584         }
585
586         iloop = ilist->init.deep;
587
588         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
589                 if (IS_BITFIELD(sflds->type)) {
590                         printIvalBitFields(&sflds,&iloop,oFile);
591                 } else {
592                         printIval (sflds, sflds->type, iloop, oFile);
593                 }
594         }
595         return;
596 }
597
598 /*-----------------------------------------------------------------*/
599 /* printIvalChar - generates initital value for character array    */
600 /*-----------------------------------------------------------------*/
601 int 
602 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
603 {
604   value *val;
605   int remain;
606
607   if (!s)
608     {
609
610       val = list2val (ilist);
611       /* if the value is a character string  */
612       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
613         {
614           if (!DCL_ELEM (type))
615             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
616
617           printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
618
619           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
620             while (remain--)
621               tfprintf (oFile, "\t!db !constbyte\n", 0);
622
623           return 1;
624         }
625       else
626         return 0;
627     }
628   else
629     printChar (oFile, s, strlen (s) + 1);
630   return 1;
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* printIvalArray - generates code for array initialization        */
635 /*-----------------------------------------------------------------*/
636 void 
637 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
638                 FILE * oFile)
639 {
640   initList *iloop;
641   int lcnt = 0, size = 0;
642
643   /* take care of the special   case  */
644   /* array of characters can be init  */
645   /* by a string                      */
646   if (IS_CHAR (type->next))
647     if (printIvalChar (type,
648                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
649                        oFile, SPEC_CVAL (sym->etype).v_char))
650       return;
651
652   /* not the special case             */
653   if (ilist->type != INIT_DEEP)
654     {
655       werror (E_INIT_STRUCT, sym->name);
656       return;
657     }
658
659   iloop = ilist->init.deep;
660   lcnt = DCL_ELEM (type);
661
662   for (;;)
663     {
664       size++;
665       printIval (sym, type->next, iloop, oFile);
666       iloop = (iloop ? iloop->next : NULL);
667
668
669       /* if not array limits given & we */
670       /* are out of initialisers then   */
671       if (!DCL_ELEM (type) && !iloop)
672         break;
673
674       /* no of elements given and we    */
675       /* have generated for all of them */
676       if (!--lcnt)
677         break;
678     }
679
680   /* if we have not been given a size  */
681   if (!DCL_ELEM (type))
682     DCL_ELEM (type) = size;
683
684   return;
685 }
686
687 /*-----------------------------------------------------------------*/
688 /* printIvalFuncPtr - generate initial value for function pointers */
689 /*-----------------------------------------------------------------*/
690 void 
691 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
692 {
693   value *val;
694   int dLvl = 0;
695
696   val = list2val (ilist);
697   /* check the types   */
698   if ((dLvl = checkType (val->type, type->next)) <= 0)
699     {
700       tfprintf (oFile, "\t!dw !constword\n", 0);
701       return;
702     }
703
704   /* now generate the name */
705   if (!val->sym)
706     {
707       if (port->use_dw_for_init)
708         {
709           tfprintf (oFile, "\t!dws\n", val->name);
710         }
711       else
712         {
713           printPointerType (oFile, val->name);
714         }
715     }
716   else if (port->use_dw_for_init)
717     {
718       tfprintf (oFile, "\t!dws\n", val->sym->rname);
719     }
720   else
721     {
722       printPointerType (oFile, val->sym->rname);
723     }
724
725   return;
726 }
727
728 /*-----------------------------------------------------------------*/
729 /* printIvalCharPtr - generates initial values for character pointers */
730 /*-----------------------------------------------------------------*/
731 int 
732 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
733 {
734   int size = 0;
735
736   /* PENDING: this is _very_ mcs51 specific, including a magic
737      number...
738      It's also endin specific.
739    */
740   size = getSize (type);
741
742   if (val->name && strlen (val->name))
743     {
744       if (size == 1)            /* This appears to be Z80 specific?? */
745         {
746           tfprintf (oFile,
747                     "\t!dbs\n", val->name);
748         }
749       else if (size == FPTRSIZE)
750         {
751           if (port->use_dw_for_init)
752             {
753               tfprintf (oFile, "\t!dws\n", val->name);
754             }
755           else
756             {
757               printPointerType (oFile, val->name);
758             }
759         }
760       else if (size == GPTRSIZE)
761         {
762           /* PENDING: 0x02 or 0x%02x, CDATA? */
763           printGPointerType (oFile, val->name,
764                              (IS_PTR (val->type) ? DCL_TYPE (val->type) :
765                               PTR_TYPE (SPEC_OCLS (val->etype))));
766         }
767       else
768         {
769           fprintf (stderr, "*** internal error: unknown size in "
770                    "printIvalCharPtr.\n");
771         }
772     }
773   else
774     {
775       /* What is this case? Are these pointers? */
776       switch (size)
777         {
778         case 1:
779           tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
780           break;
781         case 2:
782           if (port->use_dw_for_init)
783             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
784           else
785             tfprintf (oFile, "\t.byte %s,%s\n",
786                       aopLiteral (val, 0), aopLiteral (val, 1));
787           break;
788         case 3:
789           /* PENDING: 0x02 or 0x%02x, CDATA? */
790           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
791                    aopLiteral (val, 0), aopLiteral (val, 1));
792           break;
793         default:
794           assert (0);
795         }
796     }
797
798
799   if (val->sym && val->sym->isstrlit)
800     addSet (&statsg->syms, val->sym);
801
802   return 1;
803 }
804
805 /*-----------------------------------------------------------------*/
806 /* printIvalPtr - generates initial value for pointers             */
807 /*-----------------------------------------------------------------*/
808 void 
809 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
810 {
811   value *val;
812   int size;
813
814   /* if deep then   */
815   if (ilist->type == INIT_DEEP)
816     ilist = ilist->init.deep;
817
818   /* function pointer     */
819   if (IS_FUNC (type->next))
820     {
821       printIvalFuncPtr (type, ilist, oFile);
822       return;
823     }
824
825   if (!(val = initPointer (ilist)))
826     return;
827
828   /* if character pointer */
829   if (IS_CHAR (type->next))
830     if (printIvalCharPtr (sym, type, val, oFile))
831       return;
832
833   /* check the type      */
834   if (checkType (type, val->type) != 1)
835     werror (E_INIT_WRONG);
836
837   /* if val is literal */
838   if (IS_LITERAL (val->etype))
839     {
840       switch (getSize (type))
841         {
842         case 1:
843           tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
844           break;
845         case 2:
846           if (port->use_dw_for_init)
847             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
848           else
849             tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
850           break;
851         case 3:
852           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
853                    aopLiteral (val, 0), aopLiteral (val, 1));
854         }
855       return;
856     }
857
858
859   size = getSize (type);
860
861   if (size == 1)                /* Z80 specific?? */
862     {
863       tfprintf (oFile, "\t!dbs\n", val->name);
864     }
865   else if (size == FPTRSIZE)
866     {
867       tfprintf (oFile, "\t!dws\n", val->name);
868     }
869   else if (size == GPTRSIZE)
870     {
871       printGPointerType (oFile, val->name,
872                          (IS_PTR (val->type) ? DCL_TYPE (val->type) :
873                           PTR_TYPE (SPEC_OCLS (val->etype))));
874     }
875   return;
876 }
877
878 /*-----------------------------------------------------------------*/
879 /* printIval - generates code for initial value                    */
880 /*-----------------------------------------------------------------*/
881 void 
882 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
883 {
884   if (!ilist)
885     return;
886
887   /* if structure then    */
888   if (IS_STRUCT (type))
889     {
890       printIvalStruct (sym, type, ilist, oFile);
891       return;
892     }
893
894   /* if this is a pointer */
895   if (IS_PTR (type))
896     {
897       printIvalPtr (sym, type, ilist, oFile);
898       return;
899     }
900
901   /* if this is an array   */
902   if (IS_ARRAY (type))
903     {
904       printIvalArray (sym, type, ilist, oFile);
905       return;
906     }
907
908   /* if type is SPECIFIER */
909   if (IS_SPEC (type))
910     {
911       printIvalType (type, ilist, oFile);
912       return;
913     }
914 }
915
916 /*-----------------------------------------------------------------*/
917 /* emitStaticSeg - emitcode for the static segment                 */
918 /*-----------------------------------------------------------------*/
919 void 
920 emitStaticSeg (memmap * map, FILE * out)
921 {
922   symbol *sym;
923
924   /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
925   if (!out)
926     out = code->oFile;
927
928   /* for all variables in this segment do */
929   for (sym = setFirstItem (map->syms); sym;
930        sym = setNextItem (map->syms))
931     {
932
933       /* if it is "extern" then do nothing */
934       if (IS_EXTERN (sym->etype))
935         continue;
936
937       /* if it is not static add it to the public
938          table */
939       if (!IS_STATIC (sym->etype))
940         addSetHead (&publics, sym);
941
942       /* print extra debug info if required */
943       if ((options.debug || sym->level == 0) && !options.nodebug)
944         {
945
946           cdbSymbol (sym, cdbFile, FALSE, FALSE);
947
948           if (!sym->level)
949             {                   /* global */
950               if (IS_STATIC (sym->etype))
951                 fprintf (out, "F%s$", moduleName);      /* scope is file */
952               else
953                 fprintf (out, "G$");    /* scope is global */
954             }
955           else
956             /* symbol is local */
957             fprintf (out, "L%s$",
958                      (sym->localof ? sym->localof->name : "-null-"));
959           fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
960         }
961
962       /* if it has an absolute address */
963       if (SPEC_ABSA (sym->etype))
964         {
965           if ((options.debug || sym->level == 0) && !options.nodebug)
966             fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
967
968           fprintf (out, "%s\t=\t0x%04x\n",
969                    sym->rname,
970                    SPEC_ADDR (sym->etype));
971         }
972       else
973         {
974           if ((options.debug || sym->level == 0) && !options.nodebug)
975             fprintf (out, " == .\n");
976
977           /* if it has an initial value */
978           if (sym->ival)
979             {
980               fprintf (out, "%s:\n", sym->rname);
981               noAlloc++;
982               resolveIvalSym (sym->ival);
983               printIval (sym, sym->type, sym->ival, out);
984               noAlloc--;
985             }
986           else
987             {
988               /* allocate space */
989               fprintf (out, "%s:\n", sym->rname);
990               /* special case for character strings */
991               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
992                   SPEC_CVAL (sym->etype).v_char)
993                 printChar (out,
994                            SPEC_CVAL (sym->etype).v_char,
995                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);
996               else
997                 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
998             }
999         }
1000     }
1001 }
1002
1003 /*-----------------------------------------------------------------*/
1004 /* emitMaps - emits the code for the data portion the code         */
1005 /*-----------------------------------------------------------------*/
1006 void 
1007 emitMaps ()
1008 {
1009   /* no special considerations for the following
1010      data, idata & bit & xdata */
1011   emitRegularMap (data, TRUE, TRUE);
1012   emitRegularMap (idata, TRUE, TRUE);
1013   emitRegularMap (bit, TRUE, FALSE);
1014   emitRegularMap (xdata, TRUE, TRUE);
1015   emitRegularMap (sfr, FALSE, FALSE);
1016   emitRegularMap (sfrbit, FALSE, FALSE);
1017   emitRegularMap (home, TRUE, FALSE);
1018   emitRegularMap (code, TRUE, FALSE);
1019
1020   emitStaticSeg (statsg, code->oFile);
1021 }
1022
1023 /*-----------------------------------------------------------------*/
1024 /* flushStatics - flush all currently defined statics out to file  */
1025 /*  and delete.  Temporary function                                */
1026 /*-----------------------------------------------------------------*/
1027 void 
1028 flushStatics (void)
1029 {
1030   emitStaticSeg (statsg, codeOutFile);
1031   statsg->syms = NULL;
1032 }
1033
1034 /*-----------------------------------------------------------------*/
1035 /* createInterruptVect - creates the interrupt vector              */
1036 /*-----------------------------------------------------------------*/
1037 void 
1038 createInterruptVect (FILE * vFile)
1039 {
1040   int i = 0;
1041   mainf = newSymbol ("main", 0);
1042   mainf->block = 0;
1043
1044   /* only if the main function exists */
1045   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1046     {
1047       if (!options.cc_only)
1048         werror (E_NO_MAIN);
1049       return;
1050     }
1051
1052   /* if the main is only a prototype ie. no body then do nothing */
1053   if (!mainf->fbody)
1054     {
1055       /* if ! compile only then main function should be present */
1056       if (!options.cc_only)
1057         werror (E_NO_MAIN);
1058       return;
1059     }
1060
1061   tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1062   fprintf (vFile, "__interrupt_vect:\n");
1063
1064
1065   if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1066     {
1067       /* "generic" interrupt table header (if port doesn't specify one).
1068
1069        * Look suspiciously like 8051 code to me...
1070        */
1071
1072       fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1073
1074
1075       /* now for the other interrupts */
1076       for (; i < maxInterrupts; i++)
1077         {
1078           if (interrupts[i])
1079             fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1080           else
1081             fprintf (vFile, "\treti\n\t.ds\t7\n");
1082         }
1083     }
1084 }
1085
1086 char *iComments1 =
1087 {
1088   ";--------------------------------------------------------\n"
1089   "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1090
1091 char *iComments2 =
1092 {
1093   ";--------------------------------------------------------\n"};
1094
1095
1096 /*-----------------------------------------------------------------*/
1097 /* initialComments - puts in some initial comments                 */
1098 /*-----------------------------------------------------------------*/
1099 void 
1100 initialComments (FILE * afile)
1101 {
1102   time_t t;
1103   time (&t);
1104   fprintf (afile, "%s", iComments1);
1105   fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1106   fprintf (afile, "%s", iComments2);
1107 }
1108
1109 /*-----------------------------------------------------------------*/
1110 /* printPublics - generates .global for publics                    */
1111 /*-----------------------------------------------------------------*/
1112 void 
1113 printPublics (FILE * afile)
1114 {
1115   symbol *sym;
1116
1117   fprintf (afile, "%s", iComments2);
1118   fprintf (afile, "; Public variables in this module\n");
1119   fprintf (afile, "%s", iComments2);
1120
1121   for (sym = setFirstItem (publics); sym;
1122        sym = setNextItem (publics))
1123     tfprintf (afile, "\t!global\n", sym->rname);
1124 }
1125
1126 /*-----------------------------------------------------------------*/
1127 /* printExterns - generates .global for externs                    */
1128 /*-----------------------------------------------------------------*/
1129 void 
1130 printExterns (FILE * afile)
1131 {
1132   symbol *sym;
1133
1134   fprintf (afile, "%s", iComments2);
1135   fprintf (afile, "; Externals used\n");
1136   fprintf (afile, "%s", iComments2);
1137
1138   for (sym = setFirstItem (externs); sym;
1139        sym = setNextItem (externs))
1140     tfprintf (afile, "\t!global\n", sym->rname);
1141 }
1142
1143 /*-----------------------------------------------------------------*/
1144 /* emitOverlay - will emit code for the overlay stuff              */
1145 /*-----------------------------------------------------------------*/
1146 static void 
1147 emitOverlay (FILE * afile)
1148 {
1149   set *ovrset;
1150
1151   if (!elementsInSet (ovrSetSets))
1152     tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1153
1154   /* for each of the sets in the overlay segment do */
1155   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1156        ovrset = setNextItem (ovrSetSets))
1157     {
1158
1159       symbol *sym;
1160
1161       if (elementsInSet (ovrset))
1162         {
1163           /* this dummy area is used to fool the assembler
1164              otherwise the assembler will append each of these
1165              declarations into one chunk and will not overlay
1166              sad but true */
1167           fprintf (afile, "\t.area _DUMMY\n");
1168           /* output the area informtion */
1169           fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name);     /* MOF */
1170         }
1171
1172       for (sym = setFirstItem (ovrset); sym;
1173            sym = setNextItem (ovrset))
1174         {
1175
1176           /* if extern then add it to the publics tabledo nothing */
1177           if (IS_EXTERN (sym->etype))
1178             continue;
1179
1180           /* if allocation required check is needed
1181              then check if the symbol really requires
1182              allocation only for local variables */
1183           if (!IS_AGGREGATE (sym->type) &&
1184               !(sym->_isparm && !IS_REGPARM (sym->etype))
1185               && !sym->allocreq && sym->level)
1186             continue;
1187
1188           /* if global variable & not static or extern
1189              and addPublics allowed then add it to the public set */
1190           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1191               && !IS_STATIC (sym->etype))
1192             addSetHead (&publics, sym);
1193
1194           /* if extern then do nothing or is a function
1195              then do nothing */
1196           if (IS_FUNC (sym->type))
1197             continue;
1198
1199           /* print extra debug info if required */
1200           if ((options.debug || sym->level == 0) && !options.nodebug)
1201             {
1202
1203               cdbSymbol (sym, cdbFile, FALSE, FALSE);
1204
1205               if (!sym->level)
1206                 {               /* global */
1207                   if (IS_STATIC (sym->etype))
1208                     fprintf (afile, "F%s$", moduleName);        /* scope is file */
1209                   else
1210                     fprintf (afile, "G$");      /* scope is global */
1211                 }
1212               else
1213                 /* symbol is local */
1214                 fprintf (afile, "L%s$",
1215                          (sym->localof ? sym->localof->name : "-null-"));
1216               fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1217             }
1218
1219           /* if is has an absolute address then generate
1220              an equate for this no need to allocate space */
1221           if (SPEC_ABSA (sym->etype))
1222             {
1223
1224               if ((options.debug || sym->level == 0) && !options.nodebug)
1225                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1226
1227               fprintf (afile, "%s\t=\t0x%04x\n",
1228                        sym->rname,
1229                        SPEC_ADDR (sym->etype));
1230             }
1231           else
1232             {
1233               if ((options.debug || sym->level == 0) && !options.nodebug)
1234                 fprintf (afile, "==.\n");
1235
1236               /* allocate space */
1237               tfprintf (afile, "!labeldef\n", sym->rname);
1238               tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1239             }
1240
1241         }
1242     }
1243 }
1244
1245 /*-----------------------------------------------------------------*/
1246 /* glue - the final glue that hold the whole thing together        */
1247 /*-----------------------------------------------------------------*/
1248 void 
1249 glue ()
1250 {
1251   FILE *vFile;
1252   FILE *asmFile;
1253   FILE *ovrFile = tempfile ();
1254
1255   addSetHead (&tmpfileSet, ovrFile);
1256   /* print the global struct definitions */
1257   if (options.debug && !options.nodebug)
1258     cdbStructBlock (0, cdbFile);
1259
1260   vFile = tempfile ();
1261   /* PENDING: this isnt the best place but it will do */
1262   if (port->general.glue_up_main)
1263     {
1264       /* create the interrupt vector table */
1265       createInterruptVect (vFile);
1266     }
1267
1268   addSetHead (&tmpfileSet, vFile);
1269
1270   /* emit code for the all the variables declared */
1271   emitMaps ();
1272   /* do the overlay segments */
1273   emitOverlay (ovrFile);
1274
1275   /* now put it all together into the assembler file */
1276   /* create the assembler file name */
1277
1278   if (!options.c1mode)
1279     {
1280       sprintf (buffer, srcFileName);
1281       strcat (buffer, ".asm");
1282     }
1283   else
1284     {
1285       strcpy (buffer, options.out_name);
1286     }
1287
1288   if (!(asmFile = fopen (buffer, "w")))
1289     {
1290       werror (E_FILE_OPEN_ERR, buffer);
1291       exit (1);
1292     }
1293
1294   /* initial comments */
1295   initialComments (asmFile);
1296
1297   /* print module name */
1298   tfprintf (asmFile, "\t!module\n", moduleName);
1299   tfprintf (asmFile, "\t!fileprelude\n");
1300
1301   /* Let the port generate any global directives, etc. */
1302   if (port->genAssemblerPreamble)
1303     {
1304       port->genAssemblerPreamble (asmFile);
1305     }
1306
1307   /* print the global variables in this module */
1308   printPublics (asmFile);
1309   if (port->assembler.externGlobal)
1310     printExterns (asmFile);
1311
1312   /* copy the sfr segment */
1313   fprintf (asmFile, "%s", iComments2);
1314   fprintf (asmFile, "; special function registers\n");
1315   fprintf (asmFile, "%s", iComments2);
1316   copyFile (asmFile, sfr->oFile);
1317
1318   /* copy the sbit segment */
1319   fprintf (asmFile, "%s", iComments2);
1320   fprintf (asmFile, "; special function bits \n");
1321   fprintf (asmFile, "%s", iComments2);
1322   copyFile (asmFile, sfrbit->oFile);
1323
1324   /* copy the data segment */
1325   fprintf (asmFile, "%s", iComments2);
1326   fprintf (asmFile, "; internal ram data\n");
1327   fprintf (asmFile, "%s", iComments2);
1328   copyFile (asmFile, data->oFile);
1329
1330
1331   /* create the overlay segments */
1332   fprintf (asmFile, "%s", iComments2);
1333   fprintf (asmFile, "; overlayable items in internal ram \n");
1334   fprintf (asmFile, "%s", iComments2);
1335   copyFile (asmFile, ovrFile);
1336
1337   /* create the stack segment MOF */
1338   if (mainf && mainf->fbody)
1339     {
1340       fprintf (asmFile, "%s", iComments2);
1341       fprintf (asmFile, "; Stack segment in internal ram \n");
1342       fprintf (asmFile, "%s", iComments2);
1343       fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1344                "__start__stack:\n\t.ds\t1\n\n");
1345     }
1346
1347   /* create the idata segment */
1348   fprintf (asmFile, "%s", iComments2);
1349   fprintf (asmFile, "; indirectly addressable internal ram data\n");
1350   fprintf (asmFile, "%s", iComments2);
1351   copyFile (asmFile, idata->oFile);
1352
1353   /* copy the bit segment */
1354   fprintf (asmFile, "%s", iComments2);
1355   fprintf (asmFile, "; bit data\n");
1356   fprintf (asmFile, "%s", iComments2);
1357   copyFile (asmFile, bit->oFile);
1358
1359   /* if external stack then reserve space of it */
1360   if (mainf && mainf->fbody && options.useXstack)
1361     {
1362       fprintf (asmFile, "%s", iComments2);
1363       fprintf (asmFile, "; external stack \n");
1364       fprintf (asmFile, "%s", iComments2);
1365       fprintf (asmFile, "\t.area XSEG (XDATA)\n");      /* MOF */
1366       fprintf (asmFile, "\t.ds 256\n");
1367     }
1368
1369
1370   /* copy xtern ram data */
1371   fprintf (asmFile, "%s", iComments2);
1372   fprintf (asmFile, "; external ram data\n");
1373   fprintf (asmFile, "%s", iComments2);
1374   copyFile (asmFile, xdata->oFile);
1375
1376   /* copy the interrupt vector table */
1377   if (mainf && mainf->fbody)
1378     {
1379       fprintf (asmFile, "%s", iComments2);
1380       fprintf (asmFile, "; interrupt vector \n");
1381       fprintf (asmFile, "%s", iComments2);
1382       copyFile (asmFile, vFile);
1383     }
1384
1385   /* copy global & static initialisations */
1386   fprintf (asmFile, "%s", iComments2);
1387   fprintf (asmFile, "; global & static initialisations\n");
1388   fprintf (asmFile, "%s", iComments2);
1389
1390   /* Everywhere we generate a reference to the static_name area,
1391    * (which is currently only here), we immediately follow it with a
1392    * definition of the post_static_name area. This guarantees that
1393    * the post_static_name area will immediately follow the static_name
1394    * area.
1395    */
1396   tfprintf (asmFile, "\t!area\n", port->mem.static_name);       /* MOF */
1397   tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1398   tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1399
1400   if (mainf && mainf->fbody)
1401     {
1402       fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1403       /* if external stack is specified then the
1404          higher order byte of the xdatalocation is
1405          going into P2 and the lower order going into
1406          spx */
1407       if (options.useXstack)
1408         {
1409           fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1410                    (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1411           fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1412                    (unsigned int) options.xdata_loc & 0xff);
1413         }
1414
1415       /* initialise the stack pointer */
1416       /* if the user specified a value then use it */
1417       if (options.stack_loc)
1418         fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1419       else
1420         /* no: we have to compute it */
1421       if (!options.stackOnData && maxRegBank <= 3)
1422         fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1423       else
1424         fprintf (asmFile, "\tmov\tsp,#__start__stack\n");       /* MOF */
1425
1426       fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1427       fprintf (asmFile, "\tmov\ta,dpl\n");
1428       fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1429       fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1430       fprintf (asmFile, "__sdcc_init_data:\n");
1431
1432     }
1433   copyFile (asmFile, statsg->oFile);
1434
1435   if (port->general.glue_up_main && mainf && mainf->fbody)
1436     {
1437       /* This code is generated in the post-static area.
1438        * This area is guaranteed to follow the static area
1439        * by the ugly shucking and jiving about 20 lines ago.
1440        */
1441       tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1442       fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1443     }
1444
1445   fprintf (asmFile,
1446            "%s"
1447            "; Home\n"
1448            "%s", iComments2, iComments2);
1449   tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1450   copyFile (asmFile, home->oFile);
1451
1452   /* copy over code */
1453   fprintf (asmFile, "%s", iComments2);
1454   fprintf (asmFile, "; code\n");
1455   fprintf (asmFile, "%s", iComments2);
1456   tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1457   if (mainf && mainf->fbody)
1458     {
1459
1460       /* entry point @ start of CSEG */
1461       fprintf (asmFile, "__sdcc_program_startup:\n");
1462
1463       /* put in the call to main */
1464       fprintf (asmFile, "\tlcall\t_main\n");
1465       if (options.mainreturn)
1466         {
1467
1468           fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1469           fprintf (asmFile, "\tret\n");
1470
1471         }
1472       else
1473         {
1474
1475           fprintf (asmFile, ";\treturn from main will lock up\n");
1476           fprintf (asmFile, "\tsjmp .\n");
1477         }
1478     }
1479   copyFile (asmFile, code->oFile);
1480
1481   fclose (asmFile);
1482   applyToSet (tmpfileSet, closeTmpFiles);
1483   applyToSet (tmpfileNameSet, rmTmpFiles);
1484 }
1485
1486 /** Creates a temporary file a'la tmpfile which avoids the bugs
1487     in cygwin wrt c:\tmp.
1488     Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1489 */
1490 FILE *
1491 tempfile (void)
1492 {
1493 #if !defined(_MSC_VER)
1494   const char *tmpdir = NULL;
1495   if (getenv ("TMP"))
1496     tmpdir = getenv ("TMP");
1497   else if (getenv ("TEMP"))
1498     tmpdir = getenv ("TEMP");
1499   else if (getenv ("TMPDIR"))
1500     tmpdir = getenv ("TMPDIR");
1501   if (tmpdir)
1502     {
1503       char *name = tempnam (tmpdir, "sdcc");
1504       if (name)
1505         {
1506           FILE *fp = fopen (name, "w+b");
1507           if (fp)
1508             {
1509               addSetHead (&tmpfileNameSet, name);
1510             }
1511           return fp;
1512         }
1513       return NULL;
1514     }
1515 #endif
1516   return tmpfile ();
1517 }
1518
1519 char *
1520 gc_strdup (const char *s)
1521 {
1522   char *ret;
1523   ret = Safe_calloc (1, strlen (s) + 1);
1524   strcpy (ret, s);
1525   return ret;
1526 }