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