Changed Safe_calloc to use 2 arguements to mimic teh standard calloc function
[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(1,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(1,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(1,strlen(s)+1);
1382     strcpy(ret, s);
1383     return ret;
1384 }