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