Change IS_DS390 to .model=FLAT24
[fw/sdcc] / src / SDCCglue.c
1 /*-------------------------------------------------------------------------
2
3   SDCCglue.c - glues everything we have done together into one file.
4                 Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24
25 #include "common.h"
26 #include "asm.h"
27 #include <time.h>
28 #include "newalloc.h"
29
30 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
31 #include <unistd.h>
32 #endif
33
34 symbol *interrupts[256];
35
36 void printIval (symbol *, sym_link *, initList *, FILE *);
37 set *publics = NULL;            /* public variables */
38 set *externs = NULL;            /* Varibles that are declared as extern */
39
40 /* TODO: this should be configurable (DS803C90 uses more than 6) */
41 unsigned maxInterrupts = 6;
42 int allocInfo = 1;
43 symbol *mainf;
44 extern char *VersionString;
45 set *tmpfileSet = NULL;         /* set of tmp file created by the compiler */
46 set *tmpfileNameSet = NULL;     /* All are unlinked at close. */
47
48 /*-----------------------------------------------------------------*/
49 /* closeTmpFiles - closes all tmp files created by the compiler    */
50 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
51 /*-----------------------------------------------------------------*/
52 DEFSETFUNC (closeTmpFiles)
53 {
54   FILE *tfile = item;
55
56   if (tfile)
57     fclose (tfile);
58
59   return 0;
60 }
61
62 /*-----------------------------------------------------------------*/
63 /* rmTmpFiles - closes all tmp files created by the compiler    */
64 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
65 /*-----------------------------------------------------------------*/
66 DEFSETFUNC (rmTmpFiles)
67 {
68   char *name = item;
69
70   if (name)
71     {
72       unlink (name);
73       free (name);
74     }
75   return 0;
76 }
77
78 /*-----------------------------------------------------------------*/
79 /* copyFile - copies source file to destination file               */
80 /*-----------------------------------------------------------------*/
81 void 
82 copyFile (FILE * dest, FILE * src)
83 {
84   int ch;
85
86   rewind (src);
87   while (!feof (src))
88     if ((ch = fgetc (src)) != EOF)
89       fputc (ch, dest);
90 }
91
92 char *
93 aopLiteralLong (value * val, int offset, int size)
94 {
95         char *rs;
96         union {
97                 float f;
98                 unsigned char c[4];
99         }
100         fl;
101
102         /* if it is a float then it gets tricky */
103         /* otherwise it is fairly simple */
104         if (!IS_FLOAT (val->type)) {
105                 unsigned long v = (unsigned long) floatFromVal (val);
106
107                 v >>= (offset * 8);
108                 switch (size) {
109                 case 1:
110                         tsprintf (buffer, "!immedbyte", (unsigned int) v & 0xff);
111                         break;
112                 case 2:
113                         tsprintf (buffer, "!immedword", (unsigned int) v & 0xffff);
114                         break;
115                 default:
116                         /* Hmm.  Too big for now. */
117                         assert (0);
118                 }
119                 rs = Safe_calloc (1, strlen (buffer) + 1);
120                 return strcpy (rs, buffer);
121         }
122
123         /* PENDING: For now size must be 1 */
124         assert (size == 1);
125
126         /* it is type float */
127         fl.f = (float) floatFromVal (val);
128 #ifdef _BIG_ENDIAN
129         tsprintf (buffer, "!immedbyte", fl.c[3 - offset]);
130 #else
131         tsprintf (buffer, "!immedbyte", fl.c[offset]);
132 #endif
133         rs = Safe_calloc (1, strlen (buffer) + 1);
134         return strcpy (rs, buffer);
135 }
136
137 /*-----------------------------------------------------------------*/
138 /* aopLiteral - string from a literal value                        */
139 /*-----------------------------------------------------------------*/
140 char *
141 aopLiteral (value * val, int offset)
142 {
143         return aopLiteralLong (val, offset, 1);
144 }
145
146 /*-----------------------------------------------------------------*/
147 /* emitRegularMap - emit code for maps with no special cases       */
148 /*-----------------------------------------------------------------*/
149 static void 
150 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
151 {
152   symbol *sym;
153   ast *ival = NULL;
154
155   if (addPublics)
156     {
157       /* PENDING: special case here - should remove */
158       if (!strcmp (map->sname, CODE_NAME))
159         tfprintf (map->oFile, "\t!areacode\n", map->sname);
160       else if (!strcmp (map->sname, DATA_NAME))
161         tfprintf (map->oFile, "\t!areadata\n", map->sname);
162       else if (!strcmp (map->sname, HOME_NAME))
163         tfprintf (map->oFile, "\t!areahome\n", map->sname);
164       else
165         tfprintf (map->oFile, "\t!area\n", map->sname);
166     }
167
168   /* print the area name */
169   for (sym = setFirstItem (map->syms); sym;
170        sym = setNextItem (map->syms))
171     {
172
173       /* if extern then add it into the extern list */
174       if (IS_EXTERN (sym->etype))
175         {
176           addSetHead (&externs, sym);
177           continue;
178         }
179
180       /* if allocation required check is needed
181          then check if the symbol really requires
182          allocation only for local variables */
183       if (arFlag && !IS_AGGREGATE (sym->type) &&
184           !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
185           !sym->allocreq && sym->level)
186         continue;
187
188       /* if global variable & not static or extern
189          and addPublics allowed then add it to the public set */
190       if ((sym->level == 0 ||
191            (sym->_isparm && !IS_REGPARM (sym->etype))) &&
192           addPublics &&
193           !IS_STATIC (sym->etype) &&
194           (sym->used || sym->fbody))
195         {
196           addSetHead (&publics, sym);
197         }
198
199       /* if extern then do nothing or is a function
200          then do nothing */
201       if (IS_FUNC (sym->type))
202         continue;
203
204       /* print extra debug info if required */
205       if (options.debug) {
206         cdbSymbol (sym, cdbFile, FALSE, FALSE);
207         if (!sym->level) /* global */
208           if (IS_STATIC (sym->etype))
209             fprintf (map->oFile, "F%s$", moduleName); /* scope is file */
210           else
211             fprintf (map->oFile, "G$"); /* scope is global */
212         else
213           /* symbol is local */
214           fprintf (map->oFile, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
215         fprintf (map->oFile, "%s$%d$%d", sym->name, sym->level, sym->block);
216       }
217       
218       /* if is has an absolute address then generate
219          an equate for this no need to allocate space */
220       if (SPEC_ABSA (sym->etype))
221         {
222           if (options.debug) {
223             fprintf (map->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
224           }
225           fprintf (map->oFile, "%s\t=\t0x%04x\n",
226                    sym->rname,
227                    SPEC_ADDR (sym->etype));
228         }
229       else
230         {
231           /* allocate space */
232           if (options.debug) {
233             fprintf (map->oFile, "==.\n");
234           }
235           if (IS_STATIC (sym->etype))
236             tfprintf (map->oFile, "!slabeldef\n", sym->rname);
237           else
238             tfprintf (map->oFile, "!labeldef\n", sym->rname);
239           tfprintf (map->oFile, "\t!ds\n", 
240                     (unsigned int) getSize (sym->type) & 0xffff);
241         }
242
243       /* if it has an initial value then do it only if
244          it is a global variable */
245       if (sym->ival && sym->level == 0)
246         {
247
248           if (IS_AGGREGATE (sym->type))
249             ival = initAggregates (sym, sym->ival, NULL);
250           else
251             ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
252                      decorateType (resolveSymbols (list2expr (sym->ival))));
253           codeOutFile = statsg->oFile;
254           allocInfo = 0;
255
256           // set ival's lineno to where the symbol was defined
257           ival->lineno=sym->lineDef;
258
259           eBBlockFromiCode (iCodeFromAst (ival));
260           allocInfo = 1;
261           sym->ival = NULL;
262         }
263     }
264 }
265
266 /*-----------------------------------------------------------------*/
267 /* initPointer - pointer initialization code massaging             */
268 /*-----------------------------------------------------------------*/
269 value *
270 initPointer (initList * ilist)
271 {
272         value *val;
273         ast *expr = list2expr (ilist);
274         
275         if (!expr)
276                 goto wrong;
277         
278         /* try it the oldway first */
279         if ((val = constExprValue (expr, FALSE)))
280                 return val;
281         
282         /* no then we have to do these cludgy checks */
283         /* pointers can be initialized with address of
284            a variable or address of an array element */
285         if (IS_AST_OP (expr) && expr->opval.op == '&') {
286                 /* address of symbol */
287                 if (IS_AST_SYM_VALUE (expr->left)) {
288                         val = copyValue (AST_VALUE (expr->left));
289                         val->type = newLink ();
290                         if (SPEC_SCLS (expr->left->etype) == S_CODE) {
291                                 DCL_TYPE (val->type) = CPOINTER;
292                                 DCL_PTR_CONST (val->type) = port->mem.code_ro;
293                         }
294                         else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
295                                 DCL_TYPE (val->type) = FPOINTER;
296                         else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
297                                 DCL_TYPE (val->type) = PPOINTER;
298                         else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
299                                 DCL_TYPE (val->type) = IPOINTER;
300                         else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
301                                 DCL_TYPE (val->type) = EEPPOINTER;
302                         else
303                                 DCL_TYPE (val->type) = POINTER;
304                         val->type->next = expr->left->ftype;
305                         val->etype = getSpec (val->type);
306                         return val;
307                 }
308
309                 /* if address of indexed array */
310                 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
311                         return valForArray (expr->left);
312
313                 /* if address of structure element then
314                    case 1. a.b ; */
315                 if (IS_AST_OP (expr->left) &&
316                     expr->left->opval.op == '.') {
317                         return valForStructElem (expr->left->left,
318                                                  expr->left->right);
319                 }
320
321                 /* case 2. (&a)->b ;
322                    (&some_struct)->element */
323                 if (IS_AST_OP (expr->left) &&
324                     expr->left->opval.op == PTR_OP &&
325                     IS_ADDRESS_OF_OP (expr->left->left))
326                         return valForStructElem (expr->left->left->left,
327                                                  expr->left->right);
328
329         }
330         /* case 3. (((char *) &a) +/- constant) */
331         if (IS_AST_OP (expr) &&
332             (expr->opval.op == '+' || expr->opval.op == '-') &&
333             IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
334             IS_AST_OP (expr->left->right) &&
335             expr->left->right->opval.op == '&' &&
336             IS_AST_LIT_VALUE (expr->right)) {
337
338                 return valForCastAggr (expr->left->right->left,
339                                        expr->left->left->opval.lnk,
340                                        expr->right, expr->opval.op);
341
342         }
343         
344         /* case 4. (char *)(array type) */
345         if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
346             IS_ARRAY(expr->right->ftype)) {
347
348                 val = copyValue (AST_VALUE (expr->right));
349                 val->type = newLink ();
350                 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
351                         DCL_TYPE (val->type) = CPOINTER;
352                         DCL_PTR_CONST (val->type) = port->mem.code_ro;
353                 }
354                 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
355                         DCL_TYPE (val->type) = FPOINTER;
356                 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
357                         DCL_TYPE (val->type) = PPOINTER;
358                 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
359                         DCL_TYPE (val->type) = IPOINTER;
360                 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
361                         DCL_TYPE (val->type) = EEPPOINTER;
362                 else
363                         DCL_TYPE (val->type) = POINTER;
364                 val->type->next = expr->right->ftype->next;
365                 val->etype = getSpec (val->type);
366                 return val;
367         }
368  wrong:
369         werror (E_INIT_WRONG);
370         return NULL;
371
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* printChar - formats and prints a characater string with DB      */
376 /*-----------------------------------------------------------------*/
377 void 
378 printChar (FILE * ofile, char *s, int plen)
379 {
380   int i;
381   int len = strlen (s);
382   int pplen = 0;
383   char buf[100];
384   char *p = buf;
385
386   while (len && pplen < plen)
387     {
388       i = 60;
389       while (i && *s && pplen < plen)
390         {
391           if (*s < ' ' || *s == '\"' || *s=='\\')
392             {
393               *p = '\0';
394               if (p != buf)
395                 tfprintf (ofile, "\t!ascii\n", buf);
396               tfprintf (ofile, "\t!db !constbyte\n", (unsigned char)*s);
397               p = buf;
398             }
399           else
400             {
401               *p = *s;
402               p++;
403             }
404           s++;
405           pplen++;
406           i--;
407         }
408       if (p != buf)
409         {
410           *p = '\0';
411           tfprintf (ofile, "\t!ascii\n", buf);
412           p = buf;
413         }
414
415       if (len > 60)
416         len -= 60;
417       else
418         len = 0;
419     }
420   tfprintf (ofile, "\t!db !constbyte\n", 0);
421 }
422
423 /*-----------------------------------------------------------------*/
424 /* return the generic pointer high byte for a given pointer type.  */
425 /*-----------------------------------------------------------------*/
426 int 
427 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
428 {
429   switch (p_type)
430     {
431     case IPOINTER:
432     case POINTER:
433       return 0;
434     case GPOINTER:
435       /* hack - if we get a generic pointer, we just assume
436        * it's an FPOINTER (i.e. in XDATA space).
437        */
438       werror (E_CANNOT_USE_GENERIC_POINTER, iname, oname);
439       exit (1);
440       // fall through
441     case FPOINTER:
442       return 1;
443     case CPOINTER:
444       return 2;
445     case PPOINTER:
446       return 3;
447     default:
448       fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
449                p_type);
450       break;
451     }
452   return -1;
453 }
454
455
456 /*-----------------------------------------------------------------*/
457 /* printPointerType - generates ival for pointer type              */
458 /*-----------------------------------------------------------------*/
459 void 
460 _printPointerType (FILE * oFile, const char *name)
461 {
462   /* if (TARGET_IS_DS390) */
463   if (options.model == MODEL_FLAT24)
464     {
465       fprintf (oFile, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
466     }
467   else
468     {
469       fprintf (oFile, "\t.byte %s,(%s >> 8)", name, name);
470     }
471 }
472
473 /*-----------------------------------------------------------------*/
474 /* printPointerType - generates ival for pointer type              */
475 /*-----------------------------------------------------------------*/
476 void 
477 printPointerType (FILE * oFile, const char *name)
478 {
479   _printPointerType (oFile, name);
480   fprintf (oFile, "\n");
481 }
482
483 /*-----------------------------------------------------------------*/
484 /* printGPointerType - generates ival for generic pointer type     */
485 /*-----------------------------------------------------------------*/
486 void 
487 printGPointerType (FILE * oFile, const char *iname, const char *oname,
488                    const unsigned int type)
489 {
490   _printPointerType (oFile, iname);
491   fprintf (oFile, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* printIvalType - generates ival for int/char                     */
496 /*-----------------------------------------------------------------*/
497 void 
498 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
499 {
500         value *val;
501
502         /* if initList is deep */
503         if (ilist->type == INIT_DEEP)
504                 ilist = ilist->init.deep;
505
506         val = list2val (ilist);
507         switch (getSize (type)) {
508         case 1:
509                 if (!val)
510                         tfprintf (oFile, "\t!db !constbyte\n", 0);
511                 else
512                         tfprintf (oFile, "\t!dbs\n",
513                                   aopLiteral (val, 0));
514                 break;
515
516         case 2:
517                 if (port->use_dw_for_init)
518                         tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
519                 else
520                         fprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
521                 break;
522         case 4:
523                 if (!val) {
524                         tfprintf (oFile, "\t!dw !constword\n", 0);
525                         tfprintf (oFile, "\t!dw !constword\n", 0);
526                 }
527                 else {
528                         fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
529                                  aopLiteral (val, 0), aopLiteral (val, 1),
530                                  aopLiteral (val, 2), aopLiteral (val, 3));
531                 }
532                 break;
533         }
534 }
535
536 /*-----------------------------------------------------------------*/
537 /* printIvalBitFields - generate initializer for bitfields         */
538 /*-----------------------------------------------------------------*/
539 void printIvalBitFields(symbol **sym, initList **ilist, FILE * oFile)
540 {
541         value *val ;
542         symbol *lsym = *sym;
543         initList *lilist = *ilist ;
544         unsigned long ival = 0;
545         int size =0;
546
547         
548         do {
549                 unsigned long i;
550                 val = list2val(lilist);
551                 if (size) {
552                         if (SPEC_BLEN(lsym->etype) > 8) {
553                                 size += ((SPEC_BLEN (lsym->etype) / 8) + 
554                                          (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
555                         }
556                 } else {
557                         size = ((SPEC_BLEN (lsym->etype) / 8) + 
558                                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
559                 }
560                 i = (unsigned long)floatFromVal(val);
561                 i <<= SPEC_BSTR (lsym->etype);
562                 ival |= i;
563                 if (! ( lsym->next &&
564                         (IS_BITFIELD(lsym->next->type)) &&
565                         (SPEC_BSTR(lsym->next->etype)))) break;
566                 lsym = lsym->next;
567                 lilist = lilist->next;
568         } while (1);
569         switch (size) {
570         case 1:
571                 tfprintf (oFile, "\t!db !constbyte\n",ival);
572                 break;
573
574         case 2:
575                 tfprintf (oFile, "\t!dw !constword\n",ival);
576                 break;
577         case 4:
578                 tfprintf (oFile, "\t!db  !constword,!constword\n",
579                          (ival >> 8) & 0xffff, (ival & 0xffff));
580                 break;
581         }
582         *sym = lsym;
583         *ilist = lilist;
584 }
585
586 /*-----------------------------------------------------------------*/
587 /* printIvalStruct - generates initial value for structures        */
588 /*-----------------------------------------------------------------*/
589 void 
590 printIvalStruct (symbol * sym, sym_link * type,
591                  initList * ilist, FILE * oFile)
592 {
593         symbol *sflds;
594         initList *iloop;
595
596         sflds = SPEC_STRUCT (type)->fields;
597         if (ilist->type != INIT_DEEP) {
598                 werror (E_INIT_STRUCT, sym->name);
599                 return;
600         }
601
602         iloop = ilist->init.deep;
603
604         for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
605                 if (IS_BITFIELD(sflds->type)) {
606                         printIvalBitFields(&sflds,&iloop,oFile);
607                 } else {
608                         printIval (sflds, sflds->type, iloop, oFile);
609                 }
610         }
611         return;
612 }
613
614 /*-----------------------------------------------------------------*/
615 /* printIvalChar - generates initital value for character array    */
616 /*-----------------------------------------------------------------*/
617 int 
618 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
619 {
620   value *val;
621   int remain;
622
623   if (!s)
624     {
625
626       val = list2val (ilist);
627       /* if the value is a character string  */
628       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
629         {
630           if (!DCL_ELEM (type))
631             DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
632
633           printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
634
635           if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
636             while (remain--)
637               tfprintf (oFile, "\t!db !constbyte\n", 0);
638
639           return 1;
640         }
641       else
642         return 0;
643     }
644   else
645     printChar (oFile, s, strlen (s) + 1);
646   return 1;
647 }
648
649 /*-----------------------------------------------------------------*/
650 /* printIvalArray - generates code for array initialization        */
651 /*-----------------------------------------------------------------*/
652 void 
653 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
654                 FILE * oFile)
655 {
656   initList *iloop;
657   int lcnt = 0, size = 0;
658
659   /* take care of the special   case  */
660   /* array of characters can be init  */
661   /* by a string                      */
662   if (IS_CHAR (type->next))
663     if (printIvalChar (type,
664                        (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
665                        oFile, SPEC_CVAL (sym->etype).v_char))
666       return;
667
668   /* not the special case             */
669   if (ilist->type != INIT_DEEP)
670     {
671       werror (E_INIT_STRUCT, sym->name);
672       return;
673     }
674
675   iloop = ilist->init.deep;
676   lcnt = DCL_ELEM (type);
677
678   for (;;)
679     {
680       size++;
681       printIval (sym, type->next, iloop, oFile);
682       iloop = (iloop ? iloop->next : NULL);
683
684
685       /* if not array limits given & we */
686       /* are out of initialisers then   */
687       if (!DCL_ELEM (type) && !iloop)
688         break;
689
690       /* no of elements given and we    */
691       /* have generated for all of them */
692       if (!--lcnt) {
693         /* if initializers left */
694         if (iloop) {
695           werror (W_EXESS_ARRAY_INITIALIZERS, sym->name, sym->lineDef);
696         }
697         break;
698       }
699     }
700
701   /* if we have not been given a size  */
702   if (!DCL_ELEM (type))
703     DCL_ELEM (type) = size;
704
705   return;
706 }
707
708 /*-----------------------------------------------------------------*/
709 /* printIvalFuncPtr - generate initial value for function pointers */
710 /*-----------------------------------------------------------------*/
711 void 
712 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
713 {
714   value *val;
715   int dLvl = 0;
716
717   val = list2val (ilist);
718   /* check the types   */
719   if ((dLvl = compareType (val->type, type->next)) <= 0)
720     {
721       tfprintf (oFile, "\t!dw !constword\n", 0);
722       return;
723     }
724
725   /* now generate the name */
726   if (!val->sym)
727     {
728       if (port->use_dw_for_init)
729         {
730           tfprintf (oFile, "\t!dws\n", val->name);
731         }
732       else
733         {
734           printPointerType (oFile, val->name);
735         }
736     }
737   else if (port->use_dw_for_init)
738     {
739       tfprintf (oFile, "\t!dws\n", val->sym->rname);
740     }
741   else
742     {
743       printPointerType (oFile, val->sym->rname);
744     }
745
746   return;
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* printIvalCharPtr - generates initial values for character pointers */
751 /*-----------------------------------------------------------------*/
752 int 
753 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
754 {
755   int size = 0;
756
757   /* PENDING: this is _very_ mcs51 specific, including a magic
758      number...
759      It's also endin specific.
760    */
761   size = getSize (type);
762
763   if (val->name && strlen (val->name))
764     {
765       if (size == 1)            /* This appears to be Z80 specific?? */
766         {
767           tfprintf (oFile,
768                     "\t!dbs\n", val->name);
769         }
770       else if (size == FPTRSIZE)
771         {
772           if (port->use_dw_for_init)
773             {
774               tfprintf (oFile, "\t!dws\n", val->name);
775             }
776           else
777             {
778               printPointerType (oFile, val->name);
779             }
780         }
781       else if (size == GPTRSIZE)
782         {
783           int type;
784           if (IS_PTR (val->type)) {
785             type = DCL_TYPE (val->type);
786           } else {
787             type = PTR_TYPE (SPEC_OCLS (val->etype));
788           }
789           if (val->sym && val->sym->isstrlit) {
790             // this is a literal string
791             type=CPOINTER;
792           }
793           printGPointerType (oFile, val->name, sym->name, type);
794         }
795       else
796         {
797           fprintf (stderr, "*** internal error: unknown size in "
798                    "printIvalCharPtr.\n");
799         }
800     }
801   else
802     {
803       /* What is this case? Are these pointers? */
804       switch (size)
805         {
806         case 1:
807           tfprintf (oFile, "\t!dbs\n", aopLiteral (val, 0));
808           break;
809         case 2:
810           if (port->use_dw_for_init)
811             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, size));
812           else
813             tfprintf (oFile, "\t.byte %s,%s\n",
814                       aopLiteral (val, 0), aopLiteral (val, 1));
815           break;
816         case 3:
817           /* PENDING: 0x02 or 0x%02x, CDATA? */
818           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
819                    aopLiteral (val, 0), aopLiteral (val, 1));
820           break;
821         default:
822           assert (0);
823         }
824     }
825
826   if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
827     addSet (&statsg->syms, val->sym);
828   }
829
830   return 1;
831 }
832
833 /*-----------------------------------------------------------------*/
834 /* printIvalPtr - generates initial value for pointers             */
835 /*-----------------------------------------------------------------*/
836 void 
837 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
838 {
839   value *val;
840   int size;
841
842   /* if deep then   */
843   if (ilist->type == INIT_DEEP)
844     ilist = ilist->init.deep;
845
846   /* function pointer     */
847   if (IS_FUNC (type->next))
848     {
849       printIvalFuncPtr (type, ilist, oFile);
850       return;
851     }
852
853   if (!(val = initPointer (ilist)))
854     return;
855
856   /* if character pointer */
857   if (IS_CHAR (type->next))
858     if (printIvalCharPtr (sym, type, val, oFile))
859       return;
860
861   /* check the type      */
862   if (compareType (type, val->type) == 0)
863     werror (E_INIT_WRONG);
864
865   /* if val is literal */
866   if (IS_LITERAL (val->etype))
867     {
868       switch (getSize (type))
869         {
870         case 1:
871           tfprintf (oFile, "\t!db !constbyte\n", (unsigned int) floatFromVal (val) & 0xff);
872           break;
873         case 2:
874           if (port->use_dw_for_init)
875             tfprintf (oFile, "\t!dws\n", aopLiteralLong (val, 0, 2));
876           else
877             tfprintf (oFile, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
878           break;
879         case 3:
880           fprintf (oFile, "\t.byte %s,%s,#0x02\n",
881                    aopLiteral (val, 0), aopLiteral (val, 1));
882         }
883       return;
884     }
885
886
887   size = getSize (type);
888
889   if (size == 1)                /* Z80 specific?? */
890     {
891       tfprintf (oFile, "\t!dbs\n", val->name);
892     }
893   else if (size == FPTRSIZE)
894     {
895       if (port->use_dw_for_init) {
896         tfprintf (oFile, "\t!dws\n", val->name);
897       } else {
898         printPointerType (oFile, val->name);
899       }
900     }
901   else if (size == GPTRSIZE)
902     {
903       printGPointerType (oFile, val->name, sym->name,
904                          (IS_PTR (val->type) ? DCL_TYPE (val->type) :
905                           PTR_TYPE (SPEC_OCLS (val->etype))));
906     }
907   return;
908 }
909
910 /*-----------------------------------------------------------------*/
911 /* printIval - generates code for initial value                    */
912 /*-----------------------------------------------------------------*/
913 void 
914 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
915 {
916   if (!ilist)
917     return;
918
919   /* if structure then    */
920   if (IS_STRUCT (type))
921     {
922       printIvalStruct (sym, type, ilist, oFile);
923       return;
924     }
925
926   /* if this is a pointer */
927   if (IS_PTR (type))
928     {
929       printIvalPtr (sym, type, ilist, oFile);
930       return;
931     }
932
933   /* if this is an array   */
934   if (IS_ARRAY (type))
935     {
936       printIvalArray (sym, type, ilist, oFile);
937       return;
938     }
939
940   /* if type is SPECIFIER */
941   if (IS_SPEC (type))
942     {
943       printIvalType (type, ilist, oFile);
944       return;
945     }
946 }
947
948 /*-----------------------------------------------------------------*/
949 /* emitStaticSeg - emitcode for the static segment                 */
950 /*-----------------------------------------------------------------*/
951 void 
952 emitStaticSeg (memmap * map, FILE * out)
953 {
954   symbol *sym;
955
956   /*     fprintf(map->oFile,"\t.area\t%s\n",map->sname); */
957   if (!out)
958     out = code->oFile;
959
960   /* for all variables in this segment do */
961   for (sym = setFirstItem (map->syms); sym;
962        sym = setNextItem (map->syms))
963     {
964
965       /* if it is "extern" then do nothing */
966       if (IS_EXTERN (sym->etype))
967         continue;
968
969       /* if it is not static add it to the public
970          table */
971       if (!IS_STATIC (sym->etype))
972         addSetHead (&publics, sym);
973
974       /* print extra debug info if required */
975       if (options.debug) {
976         cdbSymbol (sym, cdbFile, FALSE, FALSE);
977         if (!sym->level)
978           {                     /* global */
979             if (IS_STATIC (sym->etype))
980               fprintf (out, "F%s$", moduleName);        /* scope is file */
981             else
982               fprintf (out, "G$");      /* scope is global */
983           }
984         else
985           /* symbol is local */
986           fprintf (out, "L%s$",
987                    (sym->localof ? sym->localof->name : "-null-"));
988         fprintf (out, "%s$%d$%d", sym->name, sym->level, sym->block);
989       }
990       
991       /* if it has an absolute address */
992       if (SPEC_ABSA (sym->etype))
993         {
994           if (options.debug)
995             fprintf (out, " == 0x%04x\n", SPEC_ADDR (sym->etype));
996           
997           fprintf (out, "%s\t=\t0x%04x\n",
998                    sym->rname,
999                    SPEC_ADDR (sym->etype));
1000         }
1001       else
1002         {
1003           if (options.debug)
1004             fprintf (out, " == .\n");
1005           
1006           /* if it has an initial value */
1007           if (sym->ival)
1008             {
1009               fprintf (out, "%s:\n", sym->rname);
1010               noAlloc++;
1011               resolveIvalSym (sym->ival);
1012               printIval (sym, sym->type, sym->ival, out);
1013               noAlloc--;
1014             }
1015           else
1016             {
1017               /* allocate space */
1018               fprintf (out, "%s:\n", sym->rname);
1019               /* special case for character strings */
1020               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1021                   SPEC_CVAL (sym->etype).v_char)
1022                 printChar (out,
1023                            SPEC_CVAL (sym->etype).v_char,
1024                            strlen (SPEC_CVAL (sym->etype).v_char) + 1);
1025               else
1026                 tfprintf (out, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1027             }
1028         }
1029     }
1030 }
1031
1032 /*-----------------------------------------------------------------*/
1033 /* emitMaps - emits the code for the data portion the code         */
1034 /*-----------------------------------------------------------------*/
1035 void 
1036 emitMaps ()
1037 {
1038   inInitMode++;
1039   /* no special considerations for the following
1040      data, idata & bit & xdata */
1041   emitRegularMap (data, TRUE, TRUE);
1042   emitRegularMap (idata, TRUE, TRUE);
1043   emitRegularMap (bit, TRUE, FALSE);
1044   emitRegularMap (xdata, TRUE, TRUE);
1045   emitRegularMap (sfr, FALSE, FALSE);
1046   emitRegularMap (sfrbit, FALSE, FALSE);
1047   emitRegularMap (home, TRUE, FALSE);
1048   emitRegularMap (code, TRUE, FALSE);
1049
1050   emitStaticSeg (statsg, code->oFile);
1051   inInitMode--;
1052 }
1053
1054 /*-----------------------------------------------------------------*/
1055 /* flushStatics - flush all currently defined statics out to file  */
1056 /*  and delete.  Temporary function                                */
1057 /*-----------------------------------------------------------------*/
1058 void 
1059 flushStatics (void)
1060 {
1061   emitStaticSeg (statsg, codeOutFile);
1062   statsg->syms = NULL;
1063 }
1064
1065 /*-----------------------------------------------------------------*/
1066 /* createInterruptVect - creates the interrupt vector              */
1067 /*-----------------------------------------------------------------*/
1068 void 
1069 createInterruptVect (FILE * vFile)
1070 {
1071   unsigned i = 0;
1072   mainf = newSymbol ("main", 0);
1073   mainf->block = 0;
1074
1075   /* only if the main function exists */
1076   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1077     {
1078       if (!options.cc_only && !noAssemble)
1079         werror (E_NO_MAIN);
1080       return;
1081     }
1082
1083   /* if the main is only a prototype ie. no body then do nothing */
1084   if (!mainf->fbody)
1085     {
1086       /* if ! compile only then main function should be present */
1087       if (!options.cc_only && !noAssemble)
1088         werror (E_NO_MAIN);
1089       return;
1090     }
1091
1092   tfprintf (vFile, "\t!areacode\n", CODE_NAME);
1093   fprintf (vFile, "__interrupt_vect:\n");
1094
1095
1096   if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
1097     {
1098       /* "generic" interrupt table header (if port doesn't specify one).
1099
1100        * Look suspiciously like 8051 code to me...
1101        */
1102
1103       fprintf (vFile, "\tljmp\t__sdcc_gsinit_startup\n");
1104
1105
1106       /* now for the other interrupts */
1107       for (; i < maxInterrupts; i++)
1108         {
1109           if (interrupts[i])
1110             fprintf (vFile, "\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
1111           else
1112             fprintf (vFile, "\treti\n\t.ds\t7\n");
1113         }
1114     }
1115 }
1116
1117 char *iComments1 =
1118 {
1119   ";--------------------------------------------------------\n"
1120   "; File Created by SDCC : FreeWare ANSI-C Compiler\n"};
1121
1122 char *iComments2 =
1123 {
1124   ";--------------------------------------------------------\n"};
1125
1126
1127 /*-----------------------------------------------------------------*/
1128 /* initialComments - puts in some initial comments                 */
1129 /*-----------------------------------------------------------------*/
1130 void 
1131 initialComments (FILE * afile)
1132 {
1133   time_t t;
1134   time (&t);
1135   fprintf (afile, "%s", iComments1);
1136   fprintf (afile, "; Version %s %s\n", VersionString, asctime (localtime (&t)));
1137   fprintf (afile, "%s", iComments2);
1138 }
1139
1140 /*-----------------------------------------------------------------*/
1141 /* printPublics - generates .global for publics                    */
1142 /*-----------------------------------------------------------------*/
1143 void 
1144 printPublics (FILE * afile)
1145 {
1146   symbol *sym;
1147
1148   fprintf (afile, "%s", iComments2);
1149   fprintf (afile, "; Public variables in this module\n");
1150   fprintf (afile, "%s", iComments2);
1151
1152   for (sym = setFirstItem (publics); sym;
1153        sym = setNextItem (publics))
1154     tfprintf (afile, "\t!global\n", sym->rname);
1155 }
1156
1157 /*-----------------------------------------------------------------*/
1158 /* printExterns - generates .global for externs                    */
1159 /*-----------------------------------------------------------------*/
1160 void 
1161 printExterns (FILE * afile)
1162 {
1163   symbol *sym;
1164
1165   fprintf (afile, "%s", iComments2);
1166   fprintf (afile, "; Externals used\n");
1167   fprintf (afile, "%s", iComments2);
1168
1169   for (sym = setFirstItem (externs); sym;
1170        sym = setNextItem (externs))
1171     tfprintf (afile, "\t!global\n", sym->rname);
1172 }
1173
1174 /*-----------------------------------------------------------------*/
1175 /* emitOverlay - will emit code for the overlay stuff              */
1176 /*-----------------------------------------------------------------*/
1177 static void 
1178 emitOverlay (FILE * afile)
1179 {
1180   set *ovrset;
1181
1182   if (!elementsInSet (ovrSetSets))
1183     tfprintf (afile, "\t!area\n", port->mem.overlay_name);
1184
1185   /* for each of the sets in the overlay segment do */
1186   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1187        ovrset = setNextItem (ovrSetSets))
1188     {
1189
1190       symbol *sym;
1191
1192       if (elementsInSet (ovrset))
1193         {
1194           /* this dummy area is used to fool the assembler
1195              otherwise the assembler will append each of these
1196              declarations into one chunk and will not overlay
1197              sad but true */
1198           fprintf (afile, "\t.area _DUMMY\n");
1199           /* output the area informtion */
1200           fprintf (afile, "\t.area\t%s\n", port->mem.overlay_name);     /* MOF */
1201         }
1202
1203       for (sym = setFirstItem (ovrset); sym;
1204            sym = setNextItem (ovrset))
1205         {
1206
1207           /* if extern then add it to the publics tabledo nothing */
1208           if (IS_EXTERN (sym->etype))
1209             continue;
1210
1211           /* if allocation required check is needed
1212              then check if the symbol really requires
1213              allocation only for local variables */
1214           if (!IS_AGGREGATE (sym->type) &&
1215               !(sym->_isparm && !IS_REGPARM (sym->etype))
1216               && !sym->allocreq && sym->level)
1217             continue;
1218
1219           /* if global variable & not static or extern
1220              and addPublics allowed then add it to the public set */
1221           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1222               && !IS_STATIC (sym->etype))
1223             addSetHead (&publics, sym);
1224
1225           /* if extern then do nothing or is a function
1226              then do nothing */
1227           if (IS_FUNC (sym->type))
1228             continue;
1229
1230           /* print extra debug info if required */
1231           if (options.debug)
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)
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)
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)
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 #if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER)
1517 void
1518 rm_tmpfiles (void)
1519 {
1520   applyToSet (tmpfileSet, closeTmpFiles);
1521   applyToSet (tmpfileNameSet, rmTmpFiles);
1522 }
1523 #endif
1524
1525 /** Creates a temporary file a'la tmpfile which avoids the bugs
1526     in cygwin wrt c:\tmp.
1527     Scans, in order: TMP, TEMP, TMPDIR, else uses tmpfile().
1528 */
1529 FILE *
1530 tempfile (void)
1531 {
1532 #if !defined(_MSC_VER)
1533   const char *tmpdir = NULL;
1534   if (getenv ("TMP"))
1535     tmpdir = getenv ("TMP");
1536   else if (getenv ("TEMP"))
1537     tmpdir = getenv ("TEMP");
1538   else if (getenv ("TMPDIR"))
1539     tmpdir = getenv ("TMPDIR");
1540   if (tmpdir)
1541     {
1542       char *name = tempnam (tmpdir, "sdcc");
1543       if (name)
1544         {
1545           FILE *fp = fopen (name, "w+b");
1546           if (fp)
1547             {
1548               addSetHead (&tmpfileNameSet, name);
1549             }
1550           return fp;
1551         }
1552       return NULL;
1553     }
1554 #endif
1555   return tmpfile ();
1556 }
1557
1558 char *
1559 gc_strdup (const char *s)
1560 {
1561   char *ret;
1562   ret = Safe_calloc (1, strlen (s) + 1);
1563   strcpy (ret, s);
1564   return ret;
1565 }