while emitting maps, we are inInitMode
[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         /* if initializers left */
697         if (iloop) {
698           werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
699         }
700         break;
701       }
702     }
703
704   /* if we have not been given a size  */
705   if (!DCL_ELEM (type))
706     DCL_ELEM (type) = size;
707
708   return;
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* printIvalFuncPtr - generate initial value for function pointers */
713 /*-----------------------------------------------------------------*/
714 void 
715 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
716 {
717   value *val;
718   int dLvl = 0;
719
720   val = list2val (ilist);
721   /* check the types   */
722   if ((dLvl = checkType (val->type, type->next)) <= 0)
723     {
724       tfprintf (oFile, "\t!dw !constword\n", 0);
725       return;
726     }
727
728   /* now generate the name */
729   if (!val->sym)
730     {
731       if (port->use_dw_for_init)
732         {
733           tfprintf (oFile, "\t!dws\n", val->name);
734         }
735       else
736         {
737           printPointerType (oFile, val->name);
738         }
739     }
740   else if (port->use_dw_for_init)
741     {
742       tfprintf (oFile, "\t!dws\n", val->sym->rname);
743     }
744   else
745     {
746       printPointerType (oFile, val->sym->rname);
747     }
748
749   return;
750 }
751
752 /*-----------------------------------------------------------------*/
753 /* printIvalCharPtr - generates initial values for character pointers */
754 /*-----------------------------------------------------------------*/
755 int 
756 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
757 {
758   int size = 0;
759
760   /* PENDING: this is _very_ mcs51 specific, including a magic
761      number...
762      It's also endin specific.
763    */
764   size = getSize (type);
765
766   if (val->name && strlen (val->name))
767     {
768       if (size == 1)            /* This appears to be Z80 specific?? */
769         {
770           tfprintf (oFile,
771                     "\t!dbs\n", val->name);
772         }
773       else if (size == FPTRSIZE)
774         {
775           if (port->use_dw_for_init)
776             {
777               tfprintf (oFile, "\t!dws\n", val->name);
778             }
779           else
780             {
781               printPointerType (oFile, val->name);
782             }
783         }
784       else if (size == GPTRSIZE)
785         {
786           /* PENDING: 0x02 or 0x%02x, CDATA? */
787           printGPointerType (oFile, val->name,
788                              (IS_PTR (val->type) ? DCL_TYPE (val->type) :
789                               PTR_TYPE (SPEC_OCLS (val->etype))));
790         }
791       else
792         {
793           fprintf (stderr, "*** internal error: unknown size in "
794                    "printIvalCharPtr.\n");
795         }
796     }
797   else
798     {
799       /* What is this case? Are these pointers? */
800       switch (size)
801         {
802         case 1:
803           tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
804           break;
805         case 2:
806           if (port->use_dw_for_init)
807             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
808           else
809             tfprintf (oFile, "\t.byte %s,%s\n",
810                       aopLiteral (val, 0), aopLiteral (val, 1));
811           break;
812         case 3:
813           /* PENDING: 0x02 or 0x%02x, CDATA? */
814           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
815                    aopLiteral (val, 0), aopLiteral (val, 1));
816           break;
817         default:
818           assert (0);
819         }
820     }
821
822   if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
823     addSet (&statsg->syms, val->sym);
824   }
825
826   return 1;
827 }
828
829 /*-----------------------------------------------------------------*/
830 /* printIvalPtr - generates initial value for pointers             */
831 /*-----------------------------------------------------------------*/
832 void 
833 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
834 {
835   value *val;
836   int size;
837
838   /* if deep then   */
839   if (ilist->type == INIT_DEEP)
840     ilist = ilist->init.deep;
841
842   /* function pointer     */
843   if (IS_FUNC (type->next))
844     {
845       printIvalFuncPtr (type, ilist, oFile);
846       return;
847     }
848
849   if (!(val = initPointer (ilist)))
850     return;
851
852   /* if character pointer */
853   if (IS_CHAR (type->next))
854     if (printIvalCharPtr (sym, type, val, oFile))
855       return;
856
857   /* check the type      */
858   if (checkType (type, val->type) == 0)
859     werror (E_INIT_WRONG);
860
861   /* if val is literal */
862   if (IS_LITERAL (val->etype))
863     {
864       switch (getSize (type))
865         {
866         case 1:
867           tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
868           break;
869         case 2:
870           if (port->use_dw_for_init)
871             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
872           else
873             tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
874           break;
875         case 3:
876           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
877                    aopLiteral (val, 0), aopLiteral (val, 1));
878         }
879       return;
880     }
881
882
883   size = getSize (type);
884
885   if (size == 1)                /* Z80 specific?? */
886     {
887       tfprintf (oFile, "\t!dbs\n", val->name);
888     }
889   else if (size == FPTRSIZE)
890     {
891       if (port->use_dw_for_init) {
892         tfprintf (oFile, "\t!dws\n", val->name);
893       } else {
894         printPointerType (oFile, val->name);
895       }
896     }
897   else if (size == GPTRSIZE)
898     {
899       printGPointerType (oFile, val->name,
900                          (IS_PTR (val->type) ? DCL_TYPE (val->type) :
901                           PTR_TYPE (SPEC_OCLS (val->etype))));
902     }
903   return;
904 }
905
906 /*-----------------------------------------------------------------*/
907 /* printIval - generates code for initial value                    */
908 /*-----------------------------------------------------------------*/
909 void 
910 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
911 {
912   if (!ilist)
913     return;
914
915   /* if structure then    */
916   if (IS_STRUCT (type))
917     {
918       printIvalStruct (sym, type, ilist, oFile);
919       return;
920     }
921
922   /* if this is a pointer */
923   if (IS_PTR (type))
924     {
925       printIvalPtr (sym, type, ilist, oFile);
926       return;
927     }
928
929   /* if this is an array   */
930   if (IS_ARRAY (type))
931     {
932       printIvalArray (sym, type, ilist, oFile);
933       return;
934     }
935
936   /* if type is SPECIFIER */
937   if (IS_SPEC (type))
938     {
939       printIvalType (type, ilist, oFile);
940       return;
941     }
942 }
943
944 /*-----------------------------------------------------------------*/
945 /* emitStaticSeg - emitcode for the static segment                 */
946 /*-----------------------------------------------------------------*/
947 void 
948 emitStaticSeg (memmap * map, FILE * out)
949 {
950   symbol *sym;
951
952   /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
953   if (!out)
954     out = code->oFile;
955
956   /* for all variables in this segment do */
957   for (sym = setFirstItem (map->syms); sym;
958        sym = setNextItem (map->syms))
959     {
960
961       /* if it is "extern" then do nothing */
962       if (IS_EXTERN (sym->etype))
963         continue;
964
965       /* if it is not static add it to the public
966          table */
967       if (!IS_STATIC (sym->etype))
968         addSetHead (&publics, sym);
969
970       /* print extra debug info if required */
971       if ((options.debug || sym->level == 0) && !options.nodebug)
972         {
973
974           cdbSymbol (sym, cdbFile, FALSE, FALSE);
975
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 || sym->level == 0) && !options.nodebug)
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 || sym->level == 0) && !options.nodebug)
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)
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)
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 || sym->level == 0) && !options.nodebug)
1231             {
1232
1233               cdbSymbol (sym, cdbFile, FALSE, FALSE);
1234
1235               if (!sym->level)
1236                 {               /* global */
1237                   if (IS_STATIC (sym->etype))
1238                     fprintf (afile, "F%s$", moduleName);        /* scope is file */
1239                   else
1240                     fprintf (afile, "G$");      /* scope is global */
1241                 }
1242               else
1243                 /* symbol is local */
1244                 fprintf (afile, "L%s$",
1245                          (sym->localof ? sym->localof->name : "-null-"));
1246               fprintf (afile, "%s$%d$%d", sym->name, sym->level, sym->block);
1247             }
1248
1249           /* if is has an absolute address then generate
1250              an equate for this no need to allocate space */
1251           if (SPEC_ABSA (sym->etype))
1252             {
1253
1254               if ((options.debug || sym->level == 0) && !options.nodebug)
1255                 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1256
1257               fprintf (afile, "%s\t=\t0x%04x\n",
1258                        sym->rname,
1259                        SPEC_ADDR (sym->etype));
1260             }
1261           else
1262             {
1263               if ((options.debug || sym->level == 0) && !options.nodebug)
1264                 fprintf (afile, "==.\n");
1265
1266               /* allocate space */
1267               tfprintf (afile, "!labeldef\n", sym->rname);
1268               tfprintf (afile, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1269             }
1270
1271         }
1272     }
1273 }
1274
1275 /*-----------------------------------------------------------------*/
1276 /* glue - the final glue that hold the whole thing together        */
1277 /*-----------------------------------------------------------------*/
1278 void 
1279 glue ()
1280 {
1281   FILE *vFile;
1282   FILE *asmFile;
1283   FILE *ovrFile = tempfile ();
1284
1285   addSetHead (&tmpfileSet, ovrFile);
1286   /* print the global struct definitions */
1287   if (options.debug && !options.nodebug)
1288     cdbStructBlock (0, cdbFile);
1289
1290   vFile = tempfile ();
1291   /* PENDING: this isnt the best place but it will do */
1292   if (port->general.glue_up_main)
1293     {
1294       /* create the interrupt vector table */
1295       createInterruptVect (vFile);
1296     }
1297
1298   addSetHead (&tmpfileSet, vFile);
1299
1300   /* emit code for the all the variables declared */
1301   emitMaps ();
1302   /* do the overlay segments */
1303   emitOverlay (ovrFile);
1304
1305   /* now put it all together into the assembler file */
1306   /* create the assembler file name */
1307
1308   if (!options.c1mode)
1309     {
1310       sprintf (scratchFileName, srcFileName);
1311       strcat (scratchFileName, port->assembler.file_ext);
1312     }
1313   else
1314     {
1315       strcpy (scratchFileName, options.out_name);
1316     }
1317
1318   if (!(asmFile = fopen (scratchFileName, "w")))
1319     {
1320       werror (E_FILE_OPEN_ERR, scratchFileName);
1321       exit (1);
1322     }
1323
1324   /* initial comments */
1325   initialComments (asmFile);
1326
1327   /* print module name */
1328   tfprintf (asmFile, "\t!module\n", moduleName);
1329   tfprintf (asmFile, "\t!fileprelude\n");
1330
1331   /* Let the port generate any global directives, etc. */
1332   if (port->genAssemblerPreamble)
1333     {
1334       port->genAssemblerPreamble (asmFile);
1335     }
1336
1337   /* print the global variables in this module */
1338   printPublics (asmFile);
1339   if (port->assembler.externGlobal)
1340     printExterns (asmFile);
1341
1342   /* copy the sfr segment */
1343   fprintf (asmFile, "%s", iComments2);
1344   fprintf (asmFile, "; special function registers\n");
1345   fprintf (asmFile, "%s", iComments2);
1346   copyFile (asmFile, sfr->oFile);
1347
1348   /* copy the sbit segment */
1349   fprintf (asmFile, "%s", iComments2);
1350   fprintf (asmFile, "; special function bits \n");
1351   fprintf (asmFile, "%s", iComments2);
1352   copyFile (asmFile, sfrbit->oFile);
1353
1354   /* copy the data segment */
1355   fprintf (asmFile, "%s", iComments2);
1356   fprintf (asmFile, "; internal ram data\n");
1357   fprintf (asmFile, "%s", iComments2);
1358   copyFile (asmFile, data->oFile);
1359
1360
1361   /* create the overlay segments */
1362   fprintf (asmFile, "%s", iComments2);
1363   fprintf (asmFile, "; overlayable items in internal ram \n");
1364   fprintf (asmFile, "%s", iComments2);
1365   copyFile (asmFile, ovrFile);
1366
1367   /* create the stack segment MOF */
1368   if (mainf && mainf->fbody)
1369     {
1370       fprintf (asmFile, "%s", iComments2);
1371       fprintf (asmFile, "; Stack segment in internal ram \n");
1372       fprintf (asmFile, "%s", iComments2);
1373       fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1374                "__start__stack:\n\t.ds\t1\n\n");
1375     }
1376
1377   /* create the idata segment */
1378   fprintf (asmFile, "%s", iComments2);
1379   fprintf (asmFile, "; indirectly addressable internal ram data\n");
1380   fprintf (asmFile, "%s", iComments2);
1381   copyFile (asmFile, idata->oFile);
1382
1383   /* copy the bit segment */
1384   fprintf (asmFile, "%s", iComments2);
1385   fprintf (asmFile, "; bit data\n");
1386   fprintf (asmFile, "%s", iComments2);
1387   copyFile (asmFile, bit->oFile);
1388
1389   /* if external stack then reserve space of it */
1390   if (mainf && mainf->fbody && options.useXstack)
1391     {
1392       fprintf (asmFile, "%s", iComments2);
1393       fprintf (asmFile, "; external stack \n");
1394       fprintf (asmFile, "%s", iComments2);
1395       fprintf (asmFile, "\t.area XSEG (XDATA)\n");      /* MOF */
1396       fprintf (asmFile, "\t.ds 256\n");
1397     }
1398
1399
1400   /* copy xtern ram data */
1401   fprintf (asmFile, "%s", iComments2);
1402   fprintf (asmFile, "; external ram data\n");
1403   fprintf (asmFile, "%s", iComments2);
1404   copyFile (asmFile, xdata->oFile);
1405
1406   /* copy the interrupt vector table */
1407   if (mainf && mainf->fbody)
1408     {
1409       fprintf (asmFile, "%s", iComments2);
1410       fprintf (asmFile, "; interrupt vector \n");
1411       fprintf (asmFile, "%s", iComments2);
1412       copyFile (asmFile, vFile);
1413     }
1414
1415   /* copy global & static initialisations */
1416   fprintf (asmFile, "%s", iComments2);
1417   fprintf (asmFile, "; global & static initialisations\n");
1418   fprintf (asmFile, "%s", iComments2);
1419
1420   /* Everywhere we generate a reference to the static_name area,
1421    * (which is currently only here), we immediately follow it with a
1422    * definition of the post_static_name area. This guarantees that
1423    * the post_static_name area will immediately follow the static_name
1424    * area.
1425    */
1426   tfprintf (asmFile, "\t!area\n", port->mem.static_name);       /* MOF */
1427   tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1428   tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1429
1430   if (mainf && mainf->fbody)
1431     {
1432       fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1433       /* if external stack is specified then the
1434          higher order byte of the xdatalocation is
1435          going into P2 and the lower order going into
1436          spx */
1437       if (options.useXstack)
1438         {
1439           fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1440                    (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1441           fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1442                    (unsigned int) options.xdata_loc & 0xff);
1443         }
1444
1445       /* initialise the stack pointer */
1446       /* if the user specified a value then use it */
1447       if (options.stack_loc)
1448         fprintf (asmFile, "\tmov\tsp,#%d\n", options.stack_loc);
1449       else
1450         /* no: we have to compute it */
1451       if (!options.stackOnData && maxRegBank <= 3)
1452         fprintf (asmFile, "\tmov\tsp,#%d\n", ((maxRegBank + 1) * 8) - 1);
1453       else
1454         fprintf (asmFile, "\tmov\tsp,#__start__stack\n");       /* MOF */
1455
1456       fprintf (asmFile, "\tlcall\t__sdcc_external_startup\n");
1457       fprintf (asmFile, "\tmov\ta,dpl\n");
1458       fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1459       fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1460       fprintf (asmFile, "__sdcc_init_data:\n");
1461
1462     }
1463   copyFile (asmFile, statsg->oFile);
1464
1465   if (port->general.glue_up_main && mainf && mainf->fbody)
1466     {
1467       /* This code is generated in the post-static area.
1468        * This area is guaranteed to follow the static area
1469        * by the ugly shucking and jiving about 20 lines ago.
1470        */
1471       tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1472       fprintf (asmFile, "\tljmp\t__sdcc_program_startup\n");
1473     }
1474
1475   fprintf (asmFile,
1476            "%s"
1477            "; Home\n"
1478            "%s", iComments2, iComments2);
1479   tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1480   copyFile (asmFile, home->oFile);
1481
1482   /* copy over code */
1483   fprintf (asmFile, "%s", iComments2);
1484   fprintf (asmFile, "; code\n");
1485   fprintf (asmFile, "%s", iComments2);
1486   tfprintf (asmFile, "\t!areacode\n", CODE_NAME);
1487   if (mainf && mainf->fbody)
1488     {
1489
1490       /* entry point @ start of CSEG */
1491       fprintf (asmFile, "__sdcc_program_startup:\n");
1492
1493       /* put in the call to main */
1494       fprintf (asmFile, "\tlcall\t_main\n");
1495       if (options.mainreturn)
1496         {
1497
1498           fprintf (asmFile, ";\treturn from main ; will return to caller\n");
1499           fprintf (asmFile, "\tret\n");
1500
1501         }
1502       else
1503         {
1504
1505           fprintf (asmFile, ";\treturn from main will lock up\n");
1506           fprintf (asmFile, "\tsjmp .\n");
1507         }
1508     }
1509   copyFile (asmFile, code->oFile);
1510
1511   fclose (asmFile);
1512   applyToSet (tmpfileSet, closeTmpFiles);
1513   applyToSet (tmpfileNameSet, rmTmpFiles);
1514 }
1515
1516 /** Creates a temporary file a'la tmpfile which avoids the bugs
1517     in cygwin wrt c:\tmp.
1518     Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1519 */
1520 FILE *
1521 tempfile (void)
1522 {
1523 #if !defined(_MSC_VER)
1524   const char *tmpdir = NULL;
1525   if (getenv ("TMP"))
1526     tmpdir = getenv ("TMP");
1527   else if (getenv ("TEMP"))
1528     tmpdir = getenv ("TEMP");
1529   else if (getenv ("TMPDIR"))
1530     tmpdir = getenv ("TMPDIR");
1531   if (tmpdir)
1532     {
1533       char *name = tempnam (tmpdir, "sdcc");
1534       if (name)
1535         {
1536           FILE *fp = fopen (name, "w+b");
1537           if (fp)
1538             {
1539               addSetHead (&tmpfileNameSet, name);
1540             }
1541           return fp;
1542         }
1543       return NULL;
1544     }
1545 #endif
1546   return tmpfile ();
1547 }
1548
1549 char *
1550 gc_strdup (const char *s)
1551 {
1552   char *ret;
1553   ret = Safe_calloc (1, strlen (s) + 1);
1554   strcpy (ret, s);
1555   return ret;
1556 }