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