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