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