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