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