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