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