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