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