Fixed compilation warning about nested comments
[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 <time.h>
27 #include "newalloc.h"
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include "dbuf_string.h"
31
32 #ifdef _WIN32
33 #include <io.h>
34 #else
35 #include <unistd.h>
36 #endif
37
38 symbol *interrupts[INTNO_MAX+1];
39
40 void printIval (symbol *, sym_link *, initList *, struct dbuf_s *);
41 set *publics = NULL;            /* public variables */
42 set *externs = NULL;            /* Variables that are declared as extern */
43
44 unsigned maxInterrupts = 0;
45 int allocInfo = 1;
46 symbol *mainf;
47 int noInit = 0;                 /* no initialization */
48
49
50 /*-----------------------------------------------------------------*/
51 /* closePipes - closes all pipes created by the compiler           */
52 /*-----------------------------------------------------------------*/
53 DEFSETFUNC (closePipes)
54 {
55   FILE *pfile = item;
56   int ret;
57
58   if (pfile) {
59     ret = pclose (pfile);
60     assert(ret != -1);
61   }
62
63   return 0;
64 }
65
66 /*-----------------------------------------------------------------*/
67 /* closeTmpFiles - closes all tmp files created by the compiler    */
68 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
69 /*-----------------------------------------------------------------*/
70 DEFSETFUNC (closeTmpFiles)
71 {
72   FILE *tfile = item;
73   int ret;
74
75   if (tfile) {
76     ret = fclose (tfile);
77     assert(ret == 0);
78   }
79
80   return 0;
81 }
82
83 /*-----------------------------------------------------------------*/
84 /* rmTmpFiles - unlinks all tmp files created by the compiler      */
85 /*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
86 /*-----------------------------------------------------------------*/
87 DEFSETFUNC (rmTmpFiles)
88 {
89   char *name = item;
90   int ret;
91
92   if (name) {
93       ret = remove (name);
94       assert(ret == 0);
95       Safe_free (name);
96   }
97
98   return 0;
99 }
100
101 char *
102 aopLiteralLong (value * val, int offset, int size)
103 {
104   union {
105     float f;
106     unsigned char c[4];
107   }
108   fl;
109
110   if (!val) {
111     // assuming we have been warned before
112     val = constCharVal (0);
113   }
114
115   /* if it is a float then it gets tricky */
116   /* otherwise it is fairly simple */
117   if (!IS_FLOAT (val->type)) {
118     unsigned long v = ulFromVal (val);
119
120     v >>= (offset * 8);
121     switch (size) {
122     case 1:
123       tsprintf (buffer, sizeof(buffer),
124           "!immedbyte", (unsigned int) v & 0xff);
125       break;
126     case 2:
127       tsprintf (buffer, sizeof(buffer),
128           "!immedword", (unsigned int) v & 0xffff);
129       break;
130     default:
131       /* Hmm.  Too big for now. */
132       assert (0);
133     }
134     return Safe_strdup (buffer);
135   }
136
137   /* PENDING: For now size must be 1 */
138   assert (size == 1);
139
140   /* it is type float */
141   fl.f = (float) floatFromVal (val);
142 #ifdef WORDS_BIGENDIAN
143   tsprintf (buffer, sizeof(buffer),
144       "!immedbyte", fl.c[3 - offset]);
145 #else
146   tsprintf (buffer, sizeof(buffer),
147       "!immedbyte", fl.c[offset]);
148 #endif
149   return Safe_strdup (buffer);
150 }
151
152 /*-----------------------------------------------------------------*/
153 /* aopLiteral - string from a literal value                        */
154 /*-----------------------------------------------------------------*/
155 char *
156 aopLiteral (value * val, int offset)
157 {
158   return aopLiteralLong (val, offset, 1);
159 }
160
161 /*-----------------------------------------------------------------*/
162 /* emitRegularMap - emit code for maps with no special cases       */
163 /*-----------------------------------------------------------------*/
164 static void
165 emitRegularMap (memmap * map, bool addPublics, bool arFlag)
166 {
167   symbol *sym;
168   ast *ival = NULL;
169
170   if (!map)
171     return;
172
173   if (addPublics)
174     {
175       /* PENDING: special case here - should remove */
176       if (!strcmp (map->sname, CODE_NAME))
177         dbuf_tprintf (&map->oBuf, "\t!areacode\n", map->sname);
178       else if (!strcmp (map->sname, DATA_NAME))
179         dbuf_tprintf (&map->oBuf, "\t!areadata\n", map->sname);
180       else if (!strcmp (map->sname, HOME_NAME))
181         dbuf_tprintf (&map->oBuf, "\t!areahome\n", map->sname);
182       else
183         dbuf_tprintf (&map->oBuf, "\t!area\n", map->sname);
184     }
185
186   for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
187     {
188       symbol *newSym = NULL;
189
190       /* if extern then add it into the extern list */
191       if (IS_EXTERN (sym->etype))
192         {
193           addSetHead (&externs, sym);
194           continue;
195         }
196
197       /* if allocation required check is needed
198          then check if the symbol really requires
199          allocation only for local variables */
200
201       if (arFlag && !IS_AGGREGATE (sym->type) &&
202           !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
203           !sym->allocreq && sym->level)
204         continue;
205
206       /* for bitvar locals and parameters */
207       if (!arFlag && !sym->allocreq && sym->level
208           && !SPEC_ABSA (sym->etype))
209         {
210           continue;
211         }
212
213       /* if global variable & not static or extern
214          and addPublics allowed then add it to the public set */
215       if ((sym->level == 0 ||
216            (sym->_isparm && !IS_REGPARM (sym->etype))) &&
217           addPublics &&
218           !IS_STATIC (sym->etype) &&
219           (IS_FUNC (sym->type) ? (sym->used || IFFUNC_HASBODY (sym->type)) : 1))
220         {
221           addSetHead (&publics, sym);
222         }
223
224       /* if extern then do nothing or is a function
225          then do nothing */
226       if (IS_FUNC (sym->type) && !(sym->isitmp))
227         continue;
228
229       /* print extra debug info if required */
230       if (options.debug)
231         {
232           if (!sym->level) /* global */
233             {
234               if (IS_STATIC (sym->etype))
235                 dbuf_printf (&map->oBuf, "F%s$", moduleName); /* scope is file */
236               else
237                 dbuf_printf (&map->oBuf, "G$");     /* scope is global */
238             }
239           else
240             {
241               /* symbol is local */
242               dbuf_printf (&map->oBuf, "L%s$", (sym->localof ? sym->localof->name : "-null-"));
243             }
244           dbuf_printf (&map->oBuf, "%s$%d$%d", sym->name, sym->level, sym->block);
245         }
246
247       /* if it has an initial value then do it only if
248          it is a global variable */
249       if (sym->ival && sym->level == 0)
250         {
251           if ((SPEC_OCLS (sym->etype) == xidata) && !SPEC_ABSA (sym->etype))
252             {
253               /* create a new "XINIT (CODE)" symbol, that will be emitted later
254                  in the static seg */
255               newSym=copySymbol (sym);
256               SPEC_OCLS(newSym->etype)=xinit;
257               SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
258               SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
259               if (IS_SPEC (newSym->type))
260                 SPEC_CONST (newSym->type) = 1;
261               else
262                 DCL_PTR_CONST (newSym->type) = 1;
263               SPEC_STAT(newSym->etype)=1;
264               resolveIvalSym(newSym->ival, newSym->type);
265
266               // add it to the "XINIT (CODE)" segment
267               addSet(&xinit->syms, newSym);
268
269               if (!SPEC_ABSA (sym->etype))
270                 {
271                   struct dbuf_s tmpBuf;
272
273                   dbuf_init(&tmpBuf, 4096);
274                   // before allocation we must parse the sym->ival tree
275                   // but without actually generating initialization code
276                   ++noAlloc;
277                   resolveIvalSym (sym->ival, sym->type);
278                   ++noInit;
279                   printIval (sym, sym->type, sym->ival, &tmpBuf);
280                   --noInit;
281                   --noAlloc;
282                   dbuf_destroy(&tmpBuf);
283                 }
284             }
285           else
286             {
287               if (IS_AGGREGATE (sym->type))
288                 {
289                   ival = initAggregates (sym, sym->ival, NULL);
290                 }
291               else
292                 {
293                   if (getNelements (sym->type, sym->ival)>1)
294                     {
295                       werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", sym->name);
296                     }
297                   ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
298                                   decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
299                 }
300               codeOutBuf = &statsg->oBuf;
301
302               if (ival)
303                 {
304                   // set ival's lineno to where the symbol was defined
305                   setAstFileLine (ival, filename = sym->fileDef, lineno = sym->lineDef);
306                   // check if this is not a constant expression
307                   if (!constExprTree (ival))
308                     {
309                       werror (E_CONST_EXPECTED, "found expression");
310                     // but try to do it anyway
311                     }
312                   allocInfo = 0;
313                   if (!astErrors (ival))
314                     eBBlockFromiCode (iCodeFromAst (ival));
315                   allocInfo = 1;
316                 }
317             }
318         }
319
320       /* if it has an absolute address then generate
321          an equate for this no need to allocate space */
322       if (SPEC_ABSA (sym->etype) && !sym->ival)
323         {
324           char *equ = "=";
325           if (options.debug) {
326             dbuf_printf (&map->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
327           }
328           if (TARGET_IS_XA51)
329             {
330               if (map == sfr)
331                 {
332                   equ = "sfr";
333                 }
334               else if (map == bit || map == sfrbit)
335                 {
336                   equ="bit";
337                 }
338             }
339           dbuf_printf (&map->oBuf, "%s\t%s\t0x%04x\n", sym->rname, equ, SPEC_ADDR (sym->etype));
340         }
341       else
342         {
343           int size = getSize (sym->type) + sym->flexArrayLength;
344           if (size == 0)
345             {
346               werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
347             }
348           /* allocate space */
349           if (options.debug)
350             {
351               dbuf_printf (&map->oBuf, "==.\n");
352             }
353           if (SPEC_ABSA (sym->etype))
354             {
355               dbuf_tprintf (&map->oBuf, "\t!org\n", SPEC_ADDR (sym->etype));
356             }
357           if (IS_STATIC (sym->etype) || sym->level)
358             dbuf_tprintf (&map->oBuf, "!slabeldef\n", sym->rname);
359           else
360             dbuf_tprintf (&map->oBuf, "!labeldef\n", sym->rname);
361           dbuf_tprintf (&map->oBuf, "\t!ds\n", (unsigned int) size & 0xffff);
362         }
363       sym->ival = NULL;
364     }
365 }
366
367 /*-----------------------------------------------------------------*/
368 /* initPointer - pointer initialization code massaging             */
369 /*-----------------------------------------------------------------*/
370 value *
371 initPointer (initList * ilist, sym_link *toType)
372 {
373   value *val;
374   ast *expr;
375
376   if (!ilist) {
377       return valCastLiteral(toType, 0.0);
378   }
379
380   expr = list2expr (ilist);
381
382   if (!expr)
383     goto wrong;
384
385   /* try it the old way first */
386   if ((val = constExprValue (expr, FALSE)))
387     return val;
388
389   /* ( ptr + constant ) */
390   if (IS_AST_OP (expr) &&
391       (expr->opval.op == '+' || expr->opval.op == '-') &&
392       IS_AST_SYM_VALUE (expr->left) &&
393       (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
394       compareType(toType, expr->left->ftype) &&
395       IS_AST_LIT_VALUE (expr->right)) {
396     return valForCastAggr (expr->left, expr->left->ftype,
397                            expr->right,
398                            expr->opval.op);
399   }
400
401   /* (char *)&a */
402   if (IS_AST_OP(expr) && expr->opval.op==CAST &&
403       IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
404     if (compareType(toType, expr->left->ftype)!=1) {
405       werror (W_INIT_WRONG);
406       printFromToType(expr->left->ftype, toType);
407     }
408     // skip the cast ???
409     expr=expr->right;
410   }
411
412   /* no then we have to do these cludgy checks */
413   /* pointers can be initialized with address of
414      a variable or address of an array element */
415   if (IS_AST_OP (expr) && expr->opval.op == '&') {
416     /* address of symbol */
417     if (IS_AST_SYM_VALUE (expr->left)) {
418       val = AST_VALUE (expr->left);
419       val->type = newLink (DECLARATOR);
420       if (SPEC_SCLS (expr->left->etype) == S_CODE) {
421         DCL_TYPE (val->type) = CPOINTER;
422         DCL_PTR_CONST (val->type) = port->mem.code_ro;
423       }
424       else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
425         DCL_TYPE (val->type) = FPOINTER;
426       else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
427         DCL_TYPE (val->type) = PPOINTER;
428       else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
429         DCL_TYPE (val->type) = IPOINTER;
430       else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
431         DCL_TYPE (val->type) = EEPPOINTER;
432       else
433         DCL_TYPE (val->type) = POINTER;
434       val->type->next = expr->left->ftype;
435       val->etype = getSpec (val->type);
436       return val;
437     }
438
439     /* if address of indexed array */
440     if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
441       return valForArray (expr->left);
442
443     /* if address of structure element then
444        case 1. a.b ; */
445     if (IS_AST_OP (expr->left) &&
446         expr->left->opval.op == '.') {
447       return valForStructElem (expr->left->left,
448                                expr->left->right);
449     }
450
451     /* case 2. (&a)->b ;
452        (&some_struct)->element */
453     if (IS_AST_OP (expr->left) &&
454         expr->left->opval.op == PTR_OP &&
455         IS_ADDRESS_OF_OP (expr->left->left)) {
456       return valForStructElem (expr->left->left->left,
457                                expr->left->right);
458     }
459   }
460   /* case 3. (((char *) &a) +/- constant) */
461   if (IS_AST_OP (expr) &&
462       (expr->opval.op == '+' || expr->opval.op == '-') &&
463       IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
464       IS_AST_OP (expr->left->right) &&
465       expr->left->right->opval.op == '&' &&
466       IS_AST_LIT_VALUE (expr->right)) {
467
468     return valForCastAggr (expr->left->right->left,
469                            expr->left->left->opval.lnk,
470                            expr->right, expr->opval.op);
471
472   }
473   /* case 4. (char *)(array type) */
474   if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
475       IS_ARRAY(expr->right->ftype)) {
476
477     val = copyValue (AST_VALUE (expr->right));
478     val->type = newLink (DECLARATOR);
479     if (SPEC_SCLS (expr->right->etype) == S_CODE) {
480       DCL_TYPE (val->type) = CPOINTER;
481       DCL_PTR_CONST (val->type) = port->mem.code_ro;
482     }
483     else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
484       DCL_TYPE (val->type) = FPOINTER;
485     else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
486       DCL_TYPE (val->type) = PPOINTER;
487     else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
488       DCL_TYPE (val->type) = IPOINTER;
489     else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
490       DCL_TYPE (val->type) = EEPPOINTER;
491     else
492       DCL_TYPE (val->type) = POINTER;
493     val->type->next = expr->right->ftype->next;
494     val->etype = getSpec (val->type);
495     return val;
496   }
497  wrong:
498   if (expr)
499     werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
500   else
501     werror (E_INCOMPAT_PTYPES);
502   return NULL;
503
504 }
505
506 /*-----------------------------------------------------------------*/
507 /* printChar - formats and prints a characater string with DB      */
508 /*-----------------------------------------------------------------*/
509 void
510 printChar (struct dbuf_s * oBuf, char *s, int plen)
511 {
512   int i;
513   int len = plen;
514   int pplen = 0;
515   char buf[100];
516   char *p = buf;
517
518   while (len && pplen < plen)
519     {
520       i = 60;
521       while (i && pplen < plen)
522         {
523           if (*s < ' ' || *s == '\"' || *s=='\\')
524             {
525               *p = '\0';
526               if (p != buf)
527                 dbuf_tprintf (oBuf, "\t!ascii\n", buf);
528               dbuf_tprintf (oBuf, "\t!db !constbyte\n", (unsigned char)*s);
529               p = buf;
530             }
531           else
532             {
533               *p = *s;
534               p++;
535             }
536           s++;
537           pplen++;
538           i--;
539         }
540       if (p != buf)
541         {
542           *p = '\0';
543           dbuf_tprintf (oBuf, "\t!ascii\n", buf);
544           p = buf;
545         }
546
547       if (len > 60)
548         len -= 60;
549       else
550         len = 0;
551     }
552   while (pplen < plen)
553     {
554       dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
555       pplen++;
556     }
557 }
558
559 /*-----------------------------------------------------------------*/
560 /* return the generic pointer high byte for a given pointer type.  */
561 /*-----------------------------------------------------------------*/
562 int
563 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
564 {
565   switch (p_type)
566     {
567     case IPOINTER:
568     case POINTER:
569       return GPTYPE_NEAR;
570     case GPOINTER:
571       werror (E_CANNOT_USE_GENERIC_POINTER,
572               iname ? iname : "<null>",
573               oname ? oname : "<null>");
574       exit (1);
575     case FPOINTER:
576       return GPTYPE_FAR;
577     case CPOINTER:
578       return GPTYPE_CODE;
579     case PPOINTER:
580       return GPTYPE_XSTACK;
581     default:
582       fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n",
583                p_type);
584       break;
585     }
586   return -1;
587 }
588
589
590 /*-----------------------------------------------------------------*/
591 /* printPointerType - generates ival for pointer type              */
592 /*-----------------------------------------------------------------*/
593 void
594 _printPointerType (struct dbuf_s * oBuf, const char *name)
595 {
596   if (options.model == MODEL_FLAT24)
597     {
598       if (port->little_endian)
599         dbuf_printf (oBuf, "\t.byte %s,(%s >> 8),(%s >> 16)", name, name, name);
600       else
601         dbuf_printf (oBuf, "\t.byte (%s >> 16),(%s >> 8),%s", name, name, name);
602     }
603   else
604     {
605       if (port->little_endian)
606         dbuf_printf (oBuf, "\t.byte %s,(%s >> 8)", name, name);
607       else
608         dbuf_printf (oBuf, "\t.byte (%s >> 8),%s", name, name);
609     }
610 }
611
612 /*-----------------------------------------------------------------*/
613 /* printPointerType - generates ival for pointer type              */
614 /*-----------------------------------------------------------------*/
615 void
616 printPointerType (struct dbuf_s * oBuf, const char *name)
617 {
618   _printPointerType (oBuf, name);
619   dbuf_printf (oBuf, "\n");
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* printGPointerType - generates ival for generic pointer type     */
624 /*-----------------------------------------------------------------*/
625 void
626 printGPointerType (struct dbuf_s * oBuf, const char *iname, const char *oname,
627                    const unsigned int type)
628 {
629   _printPointerType (oBuf, iname);
630   dbuf_printf (oBuf, ",#0x%02x\n", pointerTypeToGPByte (type, iname, oname));
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* printIvalType - generates ival for int/char                     */
635 /*-----------------------------------------------------------------*/
636 void
637 printIvalType (symbol *sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf)
638 {
639   value *val;
640
641   /* if initList is deep */
642   if (ilist && (ilist->type == INIT_DEEP))
643     ilist = ilist->init.deep;
644
645   if (!(val = list2val (ilist))) {
646     // assuming a warning has been thrown
647     val = constCharVal (0);
648   }
649
650   if (val->type != type) {
651     val = valCastLiteral(type, floatFromVal(val));
652   }
653
654   switch (getSize (type)) {
655   case 1:
656     if (!val)
657       dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
658     else
659       dbuf_tprintf (oBuf, "\t!dbs\n",
660                 aopLiteral (val, 0));
661     break;
662
663   case 2:
664     if (port->use_dw_for_init)
665       dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, 2));
666     else if (port->little_endian)
667       dbuf_printf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
668     else
669       dbuf_printf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
670     break;
671   case 4:
672     if (!val) {
673       dbuf_tprintf (oBuf, "\t!dw !constword\n", 0);
674       dbuf_tprintf (oBuf, "\t!dw !constword\n", 0);
675     }
676     else if (port->little_endian) {
677       dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
678                aopLiteral (val, 0), aopLiteral (val, 1),
679                aopLiteral (val, 2), aopLiteral (val, 3));
680     }
681     else {
682       dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
683                aopLiteral (val, 3), aopLiteral (val, 2),
684                aopLiteral (val, 1), aopLiteral (val, 0));
685     }
686     break;
687   }
688 }
689
690 /*-----------------------------------------------------------------*/
691 /* printIvalBitFields - generate initializer for bitfields         */
692 /*-----------------------------------------------------------------*/
693 void printIvalBitFields(symbol **sym, initList **ilist, struct dbuf_s * oBuf)
694 {
695   value *val ;
696   symbol *lsym = *sym;
697   initList *lilist = *ilist ;
698   unsigned long ival = 0;
699   int size =0;
700
701
702   do {
703     unsigned long i;
704     val = list2val(lilist);
705     if (size) {
706       if (SPEC_BLEN(lsym->etype) > 8) {
707         size += ((SPEC_BLEN (lsym->etype) / 8) +
708                  (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
709       }
710     } else {
711       size = ((SPEC_BLEN (lsym->etype) / 8) +
712               (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
713     }
714     i = ulFromVal(val);
715     i <<= SPEC_BSTR (lsym->etype);
716     ival |= i;
717     if (! ( lsym->next &&
718           (IS_BITFIELD(lsym->next->type)) &&
719           (SPEC_BSTR(lsym->next->etype)))) break;
720     lsym = lsym->next;
721     lilist = lilist ? lilist->next : NULL;
722   } while (1);
723   switch (size) {
724   case 1:
725     dbuf_tprintf (oBuf, "\t!db !constbyte\n",ival);
726     break;
727
728   case 2:
729     dbuf_tprintf (oBuf, "\t!dw !constword\n",ival);
730     break;
731   case 4:
732     dbuf_tprintf (oBuf, "\t!dw  !constword,!constword\n",
733              (ival >> 16) & 0xffff, (ival & 0xffff));
734     break;
735   }
736   *sym = lsym;
737   *ilist = lilist;
738 }
739
740 /*-----------------------------------------------------------------*/
741 /* printIvalStruct - generates initial value for structures        */
742 /*-----------------------------------------------------------------*/
743 void
744 printIvalStruct (symbol * sym, sym_link * type,
745                  initList * ilist, struct dbuf_s * oBuf)
746 {
747   symbol *sflds;
748   initList *iloop = NULL;
749
750   sflds = SPEC_STRUCT (type)->fields;
751
752   if (ilist) {
753     if (ilist->type != INIT_DEEP) {
754       werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
755       return;
756     }
757
758     iloop = ilist->init.deep;
759   }
760
761   if (SPEC_STRUCT (type)->type == UNION) {
762     printIval (sym, sflds->type, iloop, oBuf);
763     iloop = iloop ? iloop->next : NULL;
764   } else {
765     for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
766       if (IS_BITFIELD(sflds->type)) {
767         printIvalBitFields(&sflds, &iloop, oBuf);
768       } else {
769         printIval (sym, sflds->type, iloop, oBuf);
770       }
771     }
772   }
773   if (iloop) {
774     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
775   }
776   return;
777 }
778
779 /*-----------------------------------------------------------------*/
780 /* printIvalChar - generates initital value for character array    */
781 /*-----------------------------------------------------------------*/
782 int
783 printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf, char *s)
784 {
785   value *val;
786   unsigned int size = DCL_ELEM (type);
787
788   if (!s)
789     {
790       val = list2val (ilist);
791       /* if the value is a character string  */
792       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
793         {
794           if (!size)
795             {
796               /* we have not been given a size, but now we know it */
797               size = strlen (SPEC_CVAL (val->etype).v_char) + 1;
798               /* but first check, if it's a flexible array */
799               if (sym && IS_STRUCT (sym->type))
800                 sym->flexArrayLength = size;
801               else
802                 DCL_ELEM (type) = size;
803             }
804
805           printChar (oBuf, SPEC_CVAL (val->etype).v_char, size);
806
807           return 1;
808         }
809       else
810         return 0;
811     }
812   else
813     printChar (oBuf, s, strlen (s) + 1);
814   return 1;
815 }
816
817 /*-----------------------------------------------------------------*/
818 /* printIvalArray - generates code for array initialization        */
819 /*-----------------------------------------------------------------*/
820 void
821 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
822                 struct dbuf_s * oBuf)
823 {
824   value *val;
825   initList *iloop;
826   unsigned int size = 0;
827
828   if (ilist) {
829     /* take care of the special   case  */
830     /* array of characters can be init  */
831     /* by a string                      */
832     if (IS_CHAR (type->next)) {
833       val = list2val(ilist);
834       if (!val) {
835         werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
836         return;
837       }
838       if (!IS_LITERAL(val->etype)) {
839         werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
840         return;
841       }
842       if (printIvalChar (sym, type,
843                          (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
844                          oBuf, SPEC_CVAL (sym->etype).v_char))
845         return;
846     }
847     /* not the special case             */
848     if (ilist->type != INIT_DEEP) {
849       werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
850       return;
851     }
852
853     for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
854       if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
855         werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
856         break;
857       }
858       printIval (sym, type->next, iloop, oBuf);
859     }
860   }
861
862   if (DCL_ELEM(type)) {
863     // pad with zeros if needed
864     if (size<DCL_ELEM(type)) {
865       size = (DCL_ELEM(type) - size) * getSize(type->next);
866       while (size--) {
867         dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
868       }
869     }
870   } else {
871     /* we have not been given a size, but now we know it */
872     /* but first check, if it's a flexible array */
873     if (IS_STRUCT (sym->type))
874       sym->flexArrayLength = size * getSize (type->next);
875     else
876       DCL_ELEM (type) = size;
877   }
878
879   return;
880 }
881
882 /*-----------------------------------------------------------------*/
883 /* printIvalFuncPtr - generate initial value for function pointers */
884 /*-----------------------------------------------------------------*/
885 void
886 printIvalFuncPtr (sym_link * type, initList * ilist, struct dbuf_s * oBuf)
887 {
888   value *val;
889   int dLvl = 0;
890
891   if (ilist)
892     val = list2val (ilist);
893   else
894     val = valCastLiteral(type, 0.0);
895
896   if (!val) {
897     // an error has been thrown already
898     val = constCharVal (0);
899   }
900
901   if (IS_LITERAL(val->etype)) {
902     if (compareType(type, val->etype) == 0) {
903       werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
904       printFromToType (val->type, type);
905     }
906     printIvalCharPtr (NULL, type, val, oBuf);
907     return;
908   }
909
910   /* check the types   */
911   if ((dLvl = compareType (val->type, type->next)) <= 0)
912     {
913       dbuf_tprintf (oBuf, "\t!dw !constword\n", 0);
914       return;
915     }
916
917   /* now generate the name */
918   if (!val->sym)
919     {
920       if (port->use_dw_for_init)
921         {
922           dbuf_tprintf (oBuf, "\t!dws\n", val->name);
923         }
924       else
925         {
926           printPointerType (oBuf, val->name);
927         }
928     }
929   else if (port->use_dw_for_init)
930     {
931       dbuf_tprintf (oBuf, "\t!dws\n", val->sym->rname);
932     }
933   else
934     {
935       printPointerType (oBuf, val->sym->rname);
936     }
937
938   return;
939 }
940
941 /*-----------------------------------------------------------------*/
942 /* printIvalCharPtr - generates initial values for character pointers */
943 /*-----------------------------------------------------------------*/
944 int
945 printIvalCharPtr (symbol * sym, sym_link * type, value * val, struct dbuf_s * oBuf)
946 {
947   int size = 0;
948
949   /* PENDING: this is _very_ mcs51 specific, including a magic
950      number...
951      It's also endian specific.
952    */
953   size = getSize (type);
954
955   if (val->name && strlen (val->name))
956     {
957       if (size == 1)            /* This appears to be Z80 specific?? */
958         {
959           dbuf_tprintf (oBuf,
960                     "\t!dbs\n", val->name);
961         }
962       else if (size == FPTRSIZE)
963         {
964           if (port->use_dw_for_init)
965             {
966               dbuf_tprintf (oBuf, "\t!dws\n", val->name);
967             }
968           else
969             {
970               printPointerType (oBuf, val->name);
971             }
972         }
973       else if (size == GPTRSIZE)
974         {
975           int type;
976           if (IS_PTR (val->type)) {
977             type = DCL_TYPE (val->type);
978           } else {
979             type = PTR_TYPE (SPEC_OCLS (val->etype));
980           }
981           if (val->sym && val->sym->isstrlit) {
982             // this is a literal string
983             type=CPOINTER;
984           }
985           printGPointerType (oBuf, val->name, sym->name, type);
986         }
987       else
988         {
989           fprintf (stderr, "*** internal error: unknown size in "
990                    "printIvalCharPtr.\n");
991         }
992     }
993   else
994     {
995       // these are literals assigned to pointers
996       switch (size)
997         {
998         case 1:
999           dbuf_tprintf (oBuf, "\t!dbs\n", aopLiteral (val, 0));
1000           break;
1001         case 2:
1002           if (port->use_dw_for_init)
1003             dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, size));
1004           else if (port->little_endian)
1005             dbuf_tprintf (oBuf, "\t.byte %s,%s\n",
1006                       aopLiteral (val, 0), aopLiteral (val, 1));
1007           else
1008             dbuf_tprintf (oBuf, "\t.byte %s,%s\n",
1009                       aopLiteral (val, 1), aopLiteral (val, 0));
1010           break;
1011         case 3:
1012           if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1013             // non-zero mcs51 generic pointer
1014             werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1015           }
1016           if (port->little_endian) {
1017             dbuf_printf (oBuf, "\t.byte %s,%s,%s\n",
1018                      aopLiteral (val, 0),
1019                      aopLiteral (val, 1),
1020                      aopLiteral (val, 2));
1021           } else {
1022             dbuf_printf (oBuf, "\t.byte %s,%s,%s\n",
1023                      aopLiteral (val, 2),
1024                      aopLiteral (val, 1),
1025                      aopLiteral (val, 0));
1026           }
1027           break;
1028         case 4:
1029           if (IS_GENPTR(type) && floatFromVal(val)!=0) {
1030             // non-zero ds390 generic pointer
1031             werrorfl (sym->fileDef, sym->lineDef, E_LITERAL_GENERIC);
1032           }
1033           if (port->little_endian) {
1034             dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
1035                      aopLiteral (val, 0),
1036                      aopLiteral (val, 1),
1037                      aopLiteral (val, 2),
1038                      aopLiteral (val, 3));
1039           } else {
1040             dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
1041                      aopLiteral (val, 3),
1042                      aopLiteral (val, 2),
1043                      aopLiteral (val, 1),
1044                      aopLiteral (val, 0));
1045           }
1046           break;
1047         default:
1048           assert (0);
1049         }
1050     }
1051
1052   if (!noInit && val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
1053     addSet (&statsg->syms, val->sym);
1054   }
1055
1056   return 1;
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* printIvalPtr - generates initial value for pointers             */
1061 /*-----------------------------------------------------------------*/
1062 void
1063 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf)
1064 {
1065   value *val;
1066   int size;
1067
1068   /* if deep then   */
1069   if (ilist && (ilist->type == INIT_DEEP))
1070     ilist = ilist->init.deep;
1071
1072   /* function pointer     */
1073   if (IS_FUNC (type->next))
1074     {
1075       printIvalFuncPtr (type, ilist, oBuf);
1076       return;
1077     }
1078
1079   if (!(val = initPointer (ilist, type)))
1080     return;
1081
1082   /* if character pointer */
1083   if (IS_CHAR (type->next))
1084     if (printIvalCharPtr (sym, type, val, oBuf))
1085       return;
1086
1087   /* check the type      */
1088   if (compareType (type, val->type) == 0) {
1089     werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1090     printFromToType (val->type, type);
1091   }
1092
1093   /* if val is literal */
1094   if (IS_LITERAL (val->etype))
1095     {
1096       switch (getSize (type))
1097         {
1098         case 1:
1099           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (unsigned int) ulFromVal (val) & 0xff);
1100           break;
1101         case 2:
1102           if (port->use_dw_for_init)
1103             dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, 2));
1104           else if (port->little_endian)
1105             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1106           else
1107             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1108           break;
1109         case 3: // how about '390??
1110           dbuf_printf (oBuf, "; generic printIvalPtr\n");
1111           if (port->little_endian)
1112             {
1113               dbuf_printf (oBuf, "\t.byte %s,%s",
1114                        aopLiteral (val, 0), aopLiteral (val, 1));
1115             }
1116           else
1117             {
1118               dbuf_printf (oBuf, "\t.byte %s,%s",
1119                        aopLiteral (val, 1), aopLiteral (val, 0));
1120             }
1121           if (IS_GENPTR (val->type))
1122             dbuf_printf (oBuf, ",%s\n", aopLiteral (val, 2));
1123           else if (IS_PTR (val->type))
1124             dbuf_printf (oBuf, ",#%x\n", pointerTypeToGPByte (DCL_TYPE (val->type), NULL, NULL));
1125           else
1126             dbuf_printf (oBuf, ",%s\n", aopLiteral (val, 2));
1127         }
1128       return;
1129     }
1130
1131
1132   size = getSize (type);
1133
1134   if (size == 1)                /* Z80 specific?? */
1135     {
1136       dbuf_tprintf (oBuf, "\t!dbs\n", val->name);
1137     }
1138   else if (size == FPTRSIZE)
1139     {
1140       if (port->use_dw_for_init) {
1141         dbuf_tprintf (oBuf, "\t!dws\n", val->name);
1142       } else {
1143         printPointerType (oBuf, val->name);
1144       }
1145     }
1146   else if (size == GPTRSIZE)
1147     {
1148       printGPointerType (oBuf, val->name, sym->name,
1149                          (IS_PTR (val->type) ? DCL_TYPE (val->type) :
1150                           PTR_TYPE (SPEC_OCLS (val->etype))));
1151     }
1152   return;
1153 }
1154
1155 /*-----------------------------------------------------------------*/
1156 /* printIval - generates code for initial value                    */
1157 /*-----------------------------------------------------------------*/
1158 void
1159 printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf)
1160 {
1161   sym_link *itype;
1162
1163   /* if structure then    */
1164   if (IS_STRUCT (type))
1165     {
1166       printIvalStruct (sym, type, ilist, oBuf);
1167       return;
1168     }
1169
1170   /* if this is an array   */
1171   if (IS_ARRAY (type))
1172     {
1173       printIvalArray (sym, type, ilist, oBuf);
1174       return;
1175     }
1176
1177   if (ilist)
1178     {
1179       // not an aggregate, ilist must be a node
1180       if (ilist->type!=INIT_NODE) {
1181           // or a 1-element list
1182         if (ilist->init.deep->next) {
1183           werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1184                   sym->name);
1185         } else {
1186           ilist=ilist->init.deep;
1187         }
1188       }
1189
1190       // and the type must match
1191       itype=ilist->init.node->ftype;
1192
1193       if (compareType(type, itype)==0) {
1194         // special case for literal strings
1195         if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1196             // which are really code pointers
1197             IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1198           // no sweat
1199         } else {
1200           werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1201           printFromToType(itype, type);
1202         }
1203       }
1204     }
1205
1206   /* if this is a pointer */
1207   if (IS_PTR (type))
1208     {
1209       printIvalPtr (sym, type, ilist, oBuf);
1210       return;
1211     }
1212
1213   /* if type is SPECIFIER */
1214   if (IS_SPEC (type))
1215     {
1216       printIvalType (sym, type, ilist, oBuf);
1217       return;
1218     }
1219 }
1220
1221 /*-----------------------------------------------------------------*/
1222 /* emitStaticSeg - emitcode for the static segment                 */
1223 /*-----------------------------------------------------------------*/
1224 void
1225 emitStaticSeg (memmap * map, struct dbuf_s * oBuf)
1226 {
1227   symbol *sym;
1228
1229   /* fprintf(out, "\t.area\t%s\n", map->sname); */
1230
1231   /* for all variables in this segment do */
1232   for (sym = setFirstItem (map->syms); sym;
1233        sym = setNextItem (map->syms))
1234     {
1235
1236       /* if it is "extern" then do nothing */
1237       if (IS_EXTERN (sym->etype))
1238         continue;
1239
1240       /* if it is not static add it to the public table */
1241       if (!IS_STATIC (sym->etype))
1242         {
1243           addSetHead (&publics, sym);
1244         }
1245
1246       /* print extra debug info if required */
1247       if (options.debug) {
1248
1249         if (!sym->level)
1250           {                     /* global */
1251             if (IS_STATIC (sym->etype))
1252               dbuf_printf (oBuf, "F%s$", moduleName);        /* scope is file */
1253             else
1254               dbuf_printf (oBuf, "G$");      /* scope is global */
1255           }
1256         else
1257           /* symbol is local */
1258           dbuf_printf (oBuf, "L%s$",
1259                    (sym->localof ? sym->localof->name : "-null-"));
1260         dbuf_printf (oBuf, "%s$%d$%d", sym->name, sym->level, sym->block);
1261       }
1262
1263       /* if it has an absolute address and no initializer */
1264       if (SPEC_ABSA (sym->etype) && !sym->ival)
1265         {
1266           if (options.debug)
1267             dbuf_printf (oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1268
1269           dbuf_printf (oBuf, "%s\t=\t0x%04x\n",
1270                    sym->rname,
1271                    SPEC_ADDR (sym->etype));
1272         }
1273       else
1274         {
1275           if (options.debug)
1276             dbuf_printf (oBuf, " == .\n");
1277
1278           /* if it has an initial value */
1279           if (sym->ival)
1280             {
1281               if (SPEC_ABSA (sym->etype))
1282                 {
1283                   dbuf_tprintf (oBuf, "\t!org\n", SPEC_ADDR (sym->etype));
1284                 }
1285               dbuf_printf (oBuf, "%s:\n", sym->rname);
1286               ++noAlloc;
1287               resolveIvalSym (sym->ival, sym->type);
1288               printIval (sym, sym->type, sym->ival, oBuf);
1289               --noAlloc;
1290               /* if sym is a simple string and sym->ival is a string,
1291                  WE don't need it anymore */
1292               if (IS_ARRAY(sym->type) && IS_CHAR(sym->type->next) &&
1293                   IS_AST_SYM_VALUE(list2expr(sym->ival)) &&
1294                   list2val(sym->ival)->sym->isstrlit) {
1295                 freeStringSymbol(list2val(sym->ival)->sym);
1296               }
1297             }
1298           else {
1299               /* allocate space */
1300               int size = getSize (sym->type);
1301
1302               if (size==0) {
1303                   werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE,sym->name);
1304               }
1305               dbuf_printf (oBuf, "%s:\n", sym->rname);
1306               /* special case for character strings */
1307               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1308                   SPEC_CVAL (sym->etype).v_char)
1309                   printChar (oBuf,
1310                              SPEC_CVAL (sym->etype).v_char,
1311                              size);
1312               else
1313                   dbuf_tprintf (oBuf, "\t!ds\n", (unsigned int) size & 0xffff);
1314             }
1315         }
1316     }
1317 }
1318
1319 /*-----------------------------------------------------------------*/
1320 /* emitMaps - emits the code for the data portion the code         */
1321 /*-----------------------------------------------------------------*/
1322 void
1323 emitMaps (void)
1324 {
1325   int publicsfr = TARGET_IS_MCS51; /* Ideally, this should be true for all  */
1326                                    /* ports but let's be conservative - EEP */
1327
1328   inInitMode++;
1329   /* no special considerations for the following
1330      data, idata & bit & xdata */
1331   emitRegularMap (data, TRUE, TRUE);
1332   emitRegularMap (idata, TRUE, TRUE);
1333   emitRegularMap (d_abs, TRUE, TRUE);
1334   emitRegularMap (i_abs, TRUE, TRUE);
1335   emitRegularMap (bit, TRUE, TRUE);
1336   emitRegularMap (pdata, TRUE, TRUE);
1337   emitRegularMap (xdata, TRUE, TRUE);
1338   emitRegularMap (x_abs, TRUE, TRUE);
1339   if (port->genXINIT) {
1340     emitRegularMap (xidata, TRUE, TRUE);
1341   }
1342   emitRegularMap (sfr, publicsfr, FALSE);
1343   emitRegularMap (sfrbit, publicsfr, FALSE);
1344   emitRegularMap (home, TRUE, FALSE);
1345   emitRegularMap (code, TRUE, FALSE);
1346
1347   if (options.const_seg) {
1348     dbuf_tprintf (&code->oBuf, "\t!area\n", options.const_seg);
1349   }
1350   emitStaticSeg (statsg, &code->oBuf);
1351   if (port->genXINIT) {
1352     dbuf_tprintf (&code->oBuf, "\t!area\n", xinit->sname);
1353     emitStaticSeg (xinit, &code->oBuf);
1354   }
1355   dbuf_tprintf (&code->oBuf, "\t!area\n", c_abs->sname);
1356   emitStaticSeg (c_abs, &code->oBuf);
1357   inInitMode--;
1358 }
1359
1360 /*-----------------------------------------------------------------*/
1361 /* flushStatics - flush all currently defined statics out to file  */
1362 /*  and delete.  Temporary function                                */
1363 /*-----------------------------------------------------------------*/
1364 void
1365 flushStatics (void)
1366 {
1367   emitStaticSeg (statsg, codeOutBuf);
1368   statsg->syms = NULL;
1369 }
1370
1371 /*-----------------------------------------------------------------*/
1372 /* createInterruptVect - creates the interrupt vector              */
1373 /*-----------------------------------------------------------------*/
1374 void
1375 createInterruptVect (struct dbuf_s *vBuf)
1376 {
1377   mainf = newSymbol ("main", 0);
1378   mainf->block = 0;
1379
1380   /* only if the main function exists */
1381   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1382     {
1383       if (!options.cc_only && !noAssemble && !options.c1mode)
1384         werror (E_NO_MAIN);
1385       return;
1386     }
1387
1388   /* if the main is only a prototype ie. no body then do nothing */
1389   if (!IFFUNC_HASBODY(mainf->type))
1390     {
1391       /* if ! compile only then main function should be present */
1392       if (!options.cc_only && !noAssemble)
1393         werror (E_NO_MAIN);
1394       return;
1395     }
1396
1397   dbuf_tprintf (vBuf, "\t!areacode\n", HOME_NAME);
1398   dbuf_printf (vBuf, "__interrupt_vect:\n");
1399
1400
1401   if (!port->genIVT || !(port->genIVT (vBuf, interrupts, maxInterrupts)))
1402     {
1403       /* There's no such thing as a "generic" interrupt table header. */
1404       wassert(0);
1405     }
1406 }
1407
1408 char *iComments1 =
1409 {
1410   ";--------------------------------------------------------\n"
1411   "; File Created by SDCC : free open source ANSI-C Compiler\n"};
1412
1413 char *iComments2 =
1414 {
1415   ";--------------------------------------------------------\n"};
1416
1417
1418 /*-----------------------------------------------------------------*/
1419 /* initialComments - puts in some initial comments                 */
1420 /*-----------------------------------------------------------------*/
1421 void
1422 initialComments (FILE * afile)
1423 {
1424   time_t t;
1425   time (&t);
1426   fprintf (afile, "%s", iComments1);
1427   fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s) (%s)\n",
1428            getBuildNumber(), getBuildDate(), getBuildEnvironment());
1429   fprintf (afile, "; This file was generated %s", asctime (localtime (&t)));
1430   fprintf (afile, "%s", iComments2);
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* printPublics - generates .global for publics                    */
1435 /*-----------------------------------------------------------------*/
1436 void
1437 printPublics (FILE * afile)
1438 {
1439   symbol *sym;
1440
1441   fprintf (afile, "%s", iComments2);
1442   fprintf (afile, "; Public variables in this module\n");
1443   fprintf (afile, "%s", iComments2);
1444
1445   for (sym = setFirstItem (publics); sym;
1446        sym = setNextItem (publics))
1447     tfprintf (afile, "\t!global\n", sym->rname);
1448 }
1449
1450 /*-----------------------------------------------------------------*/
1451 /* printExterns - generates .global for externs                    */
1452 /*-----------------------------------------------------------------*/
1453 void
1454 printExterns (FILE * afile)
1455 {
1456   symbol *sym;
1457
1458   fprintf (afile, "%s", iComments2);
1459   fprintf (afile, "; Externals used\n");
1460   fprintf (afile, "%s", iComments2);
1461
1462   for (sym = setFirstItem (externs); sym;
1463        sym = setNextItem (externs))
1464     tfprintf (afile, "\t!extern\n", sym->rname);
1465 }
1466
1467 /*-----------------------------------------------------------------*/
1468 /* emitOverlay - will emit code for the overlay stuff              */
1469 /*-----------------------------------------------------------------*/
1470 static void
1471 emitOverlay (struct dbuf_s * aBuf)
1472 {
1473   set *ovrset;
1474
1475   if (!elementsInSet (ovrSetSets))
1476     dbuf_tprintf (aBuf, "\t!area\n", port->mem.overlay_name);
1477
1478   /* for each of the sets in the overlay segment do */
1479   for (ovrset = setFirstItem (ovrSetSets); ovrset;
1480        ovrset = setNextItem (ovrSetSets))
1481     {
1482
1483       symbol *sym;
1484
1485       if (elementsInSet (ovrset))
1486         {
1487           /* output the area informtion */
1488           dbuf_printf (aBuf, "\t.area\t%s\n", port->mem.overlay_name);     /* MOF */
1489         }
1490
1491       for (sym = setFirstItem (ovrset); sym;
1492            sym = setNextItem (ovrset))
1493         {
1494           /* if extern then it is in the publics table: do nothing */
1495           if (IS_EXTERN (sym->etype))
1496             continue;
1497
1498           /* if allocation required check is needed
1499              then check if the symbol really requires
1500              allocation only for local variables */
1501           if (!IS_AGGREGATE (sym->type) &&
1502               !(sym->_isparm && !IS_REGPARM (sym->etype))
1503               && !sym->allocreq && sym->level)
1504             continue;
1505
1506           /* if global variable & not static or extern
1507              and addPublics allowed then add it to the public set */
1508           if ((sym->_isparm && !IS_REGPARM (sym->etype))
1509               && !IS_STATIC (sym->etype))
1510             {
1511               addSetHead (&publics, sym);
1512             }
1513
1514           /* if extern then do nothing or is a function
1515              then do nothing */
1516           if (IS_FUNC (sym->type))
1517             continue;
1518
1519           /* print extra debug info if required */
1520           if (options.debug)
1521             {
1522               if (!sym->level)
1523                 {               /* global */
1524                   if (IS_STATIC (sym->etype))
1525                     dbuf_printf (aBuf, "F%s$", moduleName);        /* scope is file */
1526                   else
1527                     dbuf_printf (aBuf, "G$");      /* scope is global */
1528                 }
1529               else
1530                 /* symbol is local */
1531                 dbuf_printf (aBuf, "L%s$",
1532                          (sym->localof ? sym->localof->name : "-null-"));
1533               dbuf_printf (aBuf, "%s$%d$%d", sym->name, sym->level, sym->block);
1534             }
1535
1536           /* if is has an absolute address then generate
1537              an equate for this no need to allocate space */
1538           if (SPEC_ABSA (sym->etype))
1539             {
1540
1541               if (options.debug)
1542                 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1543
1544               dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1545                        sym->rname,
1546                        SPEC_ADDR (sym->etype));
1547             }
1548           else
1549             {
1550               int size = getSize(sym->type);
1551
1552               if (size==0) {
1553                   werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE);
1554               }
1555               if (options.debug)
1556                   dbuf_printf (aBuf, "==.\n");
1557
1558               /* allocate space */
1559               dbuf_tprintf (aBuf, "!labeldef\n", sym->rname);
1560               dbuf_tprintf (aBuf, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
1561           }
1562
1563         }
1564     }
1565 }
1566
1567 /*-----------------------------------------------------------------*/
1568 /* glue - the final glue that hold the whole thing together        */
1569 /*-----------------------------------------------------------------*/
1570 void
1571 glue (void)
1572 {
1573   struct dbuf_s vBuf;
1574   struct dbuf_s ovrBuf;
1575   FILE *asmFile;
1576   int mcs51_like;
1577
1578   dbuf_init (&vBuf, 4096);
1579   dbuf_init (&ovrBuf, 4096);
1580
1581   mcs51_like = (port->general.glue_up_main &&
1582     (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_XA51 || TARGET_IS_DS400));
1583
1584   /* print the global struct definitions */
1585   if (options.debug)
1586     cdbStructBlock (0);
1587
1588   /* PENDING: this isn't the best place but it will do */
1589   if (port->general.glue_up_main)
1590     {
1591       /* create the interrupt vector table */
1592       createInterruptVect (&vBuf);
1593     }
1594
1595   /* emit code for the all the variables declared */
1596   emitMaps ();
1597   /* do the overlay segments */
1598   emitOverlay (&ovrBuf);
1599
1600   outputDebugSymbols ();
1601
1602   /* now put it all together into the assembler file */
1603   /* create the assembler file name */
1604
1605   /* -o option overrides default name? */
1606   if ((noAssemble || options.c1mode) && fullDstFileName)
1607     {
1608       strncpyz (scratchFileName, fullDstFileName, PATH_MAX);
1609     }
1610   else
1611     {
1612       strncpyz (scratchFileName, dstFileName, PATH_MAX);
1613       strncatz (scratchFileName, port->assembler.file_ext, PATH_MAX);
1614     }
1615
1616   if (!(asmFile = fopen (scratchFileName, "w")))
1617     {
1618       werror (E_FILE_OPEN_ERR, scratchFileName);
1619       exit (EXIT_FAILURE);
1620     }
1621
1622   /* initial comments */
1623   initialComments (asmFile);
1624
1625   /* print module name */
1626   tfprintf (asmFile, "\t!module\n", moduleName);
1627   if (mcs51_like)
1628     {
1629       fprintf (asmFile, "\t.optsdcc -m%s", port->target);
1630
1631       switch(options.model)
1632         {
1633         case MODEL_SMALL:   fprintf (asmFile, " --model-small");   break;
1634         case MODEL_COMPACT: fprintf (asmFile, " --model-compact"); break;
1635         case MODEL_MEDIUM:  fprintf (asmFile, " --model-medium");  break;
1636         case MODEL_LARGE:   fprintf (asmFile, " --model-large");   break;
1637         case MODEL_FLAT24:  fprintf (asmFile, " --model-flat24");  break;
1638         case MODEL_PAGE0:   fprintf (asmFile, " --model-page0");   break;
1639         default: break;
1640         }
1641       /*if(options.stackAuto)      fprintf (asmFile, " --stack-auto");*/
1642       if(options.useXstack)      fprintf (asmFile, " --xstack");
1643       /*if(options.intlong_rent)   fprintf (asmFile, " --int-long-rent");*/
1644       /*if(options.float_rent)     fprintf (asmFile, " --float-rent");*/
1645       if(options.noRegParams)    fprintf (asmFile, " --no-reg-params");
1646       if(options.parms_in_bank1) fprintf (asmFile, " --parms-in-bank1");
1647       fprintf (asmFile, "\n");
1648     }
1649   else if (TARGET_Z80_LIKE || TARGET_IS_HC08)
1650     {
1651       fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
1652     }
1653
1654   tfprintf (asmFile, "\t!fileprelude\n");
1655
1656   /* Let the port generate any global directives, etc. */
1657   if (port->genAssemblerPreamble)
1658     {
1659       port->genAssemblerPreamble (asmFile);
1660     }
1661
1662   /* print the global variables in this module */
1663   printPublics (asmFile);
1664   if (port->assembler.externGlobal)
1665     printExterns (asmFile);
1666
1667   if (( mcs51_like )
1668      ||( TARGET_IS_Z80 )) /*.p.t.20030924 need to output SFR table for Z80 as well */
1669     {
1670       /* copy the sfr segment */
1671       fprintf (asmFile, "%s", iComments2);
1672       fprintf (asmFile, "; special function registers\n");
1673       fprintf (asmFile, "%s", iComments2);
1674       dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1675     }
1676
1677   if (mcs51_like)
1678     {
1679       /* copy the sbit segment */
1680       fprintf (asmFile, "%s", iComments2);
1681       fprintf (asmFile, "; special function bits\n");
1682       fprintf (asmFile, "%s", iComments2);
1683       dbuf_write_and_destroy (&sfrbit->oBuf, asmFile);
1684
1685       /*JCF: Create the areas for the register banks*/
1686       if (RegBankUsed[0] || RegBankUsed[1] || RegBankUsed[2] || RegBankUsed[3])
1687         {
1688           fprintf (asmFile, "%s", iComments2);
1689           fprintf (asmFile, "; overlayable register banks\n");
1690           fprintf (asmFile, "%s", iComments2);
1691           if (RegBankUsed[0])
1692             fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
1693           if (RegBankUsed[1] || options.parms_in_bank1)
1694             fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
1695           if (RegBankUsed[2])
1696             fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
1697           if (RegBankUsed[3])
1698             fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
1699         }
1700       if (BitBankUsed)
1701         {
1702           fprintf (asmFile, "%s", iComments2);
1703           fprintf (asmFile, "; overlayable bit register bank\n");
1704           fprintf (asmFile, "%s", iComments2);
1705           fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
1706           fprintf (asmFile, "bits:\n\t.ds 1\n");
1707           fprintf (asmFile, "\tb0 = bits[0]\n");
1708           fprintf (asmFile, "\tb1 = bits[1]\n");
1709           fprintf (asmFile, "\tb2 = bits[2]\n");
1710           fprintf (asmFile, "\tb3 = bits[3]\n");
1711           fprintf (asmFile, "\tb4 = bits[4]\n");
1712           fprintf (asmFile, "\tb5 = bits[5]\n");
1713           fprintf (asmFile, "\tb6 = bits[6]\n");
1714           fprintf (asmFile, "\tb7 = bits[7]\n");
1715         }
1716     }
1717
1718   /* copy the data segment */
1719   fprintf (asmFile, "%s", iComments2);
1720   fprintf (asmFile, "; %s ram data\n", mcs51_like?"internal":"");
1721   fprintf (asmFile, "%s", iComments2);
1722   dbuf_write_and_destroy (&data->oBuf, asmFile);
1723
1724
1725   /* create the overlay segments */
1726   if (overlay)
1727     {
1728       fprintf (asmFile, "%s", iComments2);
1729       fprintf (asmFile, "; overlayable items in %s ram \n", mcs51_like?"internal":"");
1730       fprintf (asmFile, "%s", iComments2);
1731       dbuf_write_and_destroy (&ovrBuf, asmFile);
1732     }
1733
1734   /* create the stack segment MOF */
1735   if (mainf && IFFUNC_HASBODY (mainf->type))
1736     {
1737       fprintf (asmFile, "%s", iComments2);
1738       fprintf (asmFile, "; Stack segment in internal ram \n");
1739       fprintf (asmFile, "%s", iComments2);
1740       fprintf (asmFile, "\t.area\tSSEG\t(DATA)\n"
1741                "__start__stack:\n\t.ds\t1\n\n");
1742     }
1743
1744   /* create the idata segment */
1745   if ((idata) && (mcs51_like))
1746     {
1747       fprintf (asmFile, "%s", iComments2);
1748       fprintf (asmFile, "; indirectly addressable internal ram data\n");
1749       fprintf (asmFile, "%s", iComments2);
1750       dbuf_write_and_destroy (&idata->oBuf, asmFile);
1751     }
1752
1753   /* create the absolute idata/data segment */
1754   if ((i_abs) && (mcs51_like))
1755     {
1756       fprintf (asmFile, "%s", iComments2);
1757       fprintf (asmFile, "; absolute internal ram data\n");
1758       fprintf (asmFile, "%s", iComments2);
1759       dbuf_write_and_destroy (&d_abs->oBuf, asmFile);
1760       dbuf_write_and_destroy (&i_abs->oBuf, asmFile);
1761     }
1762
1763   /* copy the bit segment */
1764   if (mcs51_like)
1765     {
1766       fprintf (asmFile, "%s", iComments2);
1767       fprintf (asmFile, "; bit data\n");
1768       fprintf (asmFile, "%s", iComments2);
1769       dbuf_write_and_destroy (&bit->oBuf, asmFile);
1770     }
1771
1772   /* copy paged external ram data */
1773   if (mcs51_like)
1774     {
1775       fprintf (asmFile, "%s", iComments2);
1776       fprintf (asmFile, "; paged external ram data\n");
1777       fprintf (asmFile, "%s", iComments2);
1778       dbuf_write_and_destroy (&pdata->oBuf, asmFile);
1779     }
1780
1781   /* if external stack then reserve space for it */
1782   if (mainf && IFFUNC_HASBODY (mainf->type) && options.useXstack)
1783     {
1784       fprintf (asmFile, "%s", iComments2);
1785       fprintf (asmFile, "; external stack \n");
1786       fprintf (asmFile, "%s", iComments2);
1787       fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n"
1788                "__start__xstack:\n\t.ds\t1\n\n");
1789     }
1790
1791   /* copy external ram data */
1792   if (mcs51_like)
1793     {
1794       fprintf (asmFile, "%s", iComments2);
1795       fprintf (asmFile, "; external ram data\n");
1796       fprintf (asmFile, "%s", iComments2);
1797       dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1798     }
1799
1800   /* create the absolute xdata segment */
1801   if (mcs51_like || TARGET_IS_HC08)
1802     {
1803       fprintf (asmFile, "%s", iComments2);
1804       fprintf (asmFile, "; absolute external ram data\n");
1805       fprintf (asmFile, "%s", iComments2);
1806       dbuf_write_and_destroy (&x_abs->oBuf, asmFile);
1807     }
1808
1809   /* copy external initialized ram data */
1810   fprintf (asmFile, "%s", iComments2);
1811   fprintf (asmFile, "; external initialized ram data\n");
1812   fprintf (asmFile, "%s", iComments2);
1813   dbuf_write_and_destroy (&xidata->oBuf, asmFile);
1814
1815   /* If the port wants to generate any extra areas, let it do so. */
1816   if (port->extraAreas.genExtraAreaDeclaration)
1817     {
1818       port->extraAreas.genExtraAreaDeclaration(asmFile,
1819                                                mainf && IFFUNC_HASBODY(mainf->type));
1820     }
1821
1822   /* copy the interrupt vector table */
1823   if (mainf && IFFUNC_HASBODY (mainf->type))
1824     {
1825       fprintf (asmFile, "%s", iComments2);
1826       fprintf (asmFile, "; interrupt vector \n");
1827       fprintf (asmFile, "%s", iComments2);
1828       dbuf_write_and_destroy (&vBuf, asmFile);
1829     }
1830
1831   /* copy global & static initialisations */
1832   fprintf (asmFile, "%s", iComments2);
1833   fprintf (asmFile, "; global & static initialisations\n");
1834   fprintf (asmFile, "%s", iComments2);
1835
1836   /* Everywhere we generate a reference to the static_name area,
1837    * (which is currently only here), we immediately follow it with a
1838    * definition of the post_static_name area. This guarantees that
1839    * the post_static_name area will immediately follow the static_name
1840    * area.
1841    */
1842   tfprintf (asmFile, "\t!area\n", port->mem.home_name);
1843   tfprintf (asmFile, "\t!area\n", port->mem.static_name);       /* MOF */
1844   tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1845   tfprintf (asmFile, "\t!area\n", port->mem.static_name);
1846
1847   if (mainf && IFFUNC_HASBODY (mainf->type))
1848     {
1849       if (port->genInitStartup)
1850         {
1851            port->genInitStartup (asmFile);
1852         }
1853       else
1854         {
1855           assert (mcs51_like);
1856           fprintf (asmFile, "__sdcc_gsinit_startup:\n");
1857           /* if external stack is specified then the
1858              higher order byte of the xdatalocation is
1859              going into P2 and the lower order going into
1860              spx */
1861           if (options.useXstack)
1862             {
1863               fprintf (asmFile, "\tmov\tP2,#0x%02x\n",
1864                        (((unsigned int) options.xdata_loc) >> 8) & 0xff);
1865               fprintf (asmFile, "\tmov\t_spx,#0x%02x\n",
1866                        (unsigned int) options.xdata_loc & 0xff);
1867             }
1868
1869           // This should probably be a port option, but I'm being lazy.
1870           // on the 400, the firmware boot loader gives us a valid stack
1871           // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
1872           if (!TARGET_IS_DS400)
1873             {
1874               /* initialise the stack pointer.  JCF: aslink takes care of the location */
1875               fprintf (asmFile, "\tmov\tsp,#__start__stack - 1\n");     /* MOF */
1876             }
1877
1878           fprintf (asmFile, "\t%ccall\t__sdcc_external_startup\n", options.acall_ajmp?'a':'l');
1879           fprintf (asmFile, "\tmov\ta,dpl\n");
1880           fprintf (asmFile, "\tjz\t__sdcc_init_data\n");
1881           fprintf (asmFile, "\t%cjmp\t__sdcc_program_startup\n", options.acall_ajmp?'a':'l');
1882           fprintf (asmFile, "__sdcc_init_data:\n");
1883
1884           // if the port can copy the XINIT segment to XISEG
1885           if (port->genXINIT)
1886             {
1887               port->genXINIT (asmFile);
1888             }
1889         }
1890     }
1891   dbuf_write_and_destroy (&statsg->oBuf, asmFile);
1892
1893   if (port->general.glue_up_main && mainf && IFFUNC_HASBODY (mainf->type))
1894     {
1895       /* This code is generated in the post-static area.
1896        * This area is guaranteed to follow the static area
1897        * by the ugly shucking and jiving about 20 lines ago.
1898        */
1899       tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
1900       fprintf (asmFile, "\t%cjmp\t__sdcc_program_startup\n", options.acall_ajmp?'a':'l');
1901     }
1902
1903   fprintf (asmFile,
1904            "%s"
1905            "; Home\n"
1906            "%s", iComments2, iComments2);
1907   tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
1908   dbuf_write_and_destroy (&home->oBuf, asmFile);
1909
1910   if (mainf && IFFUNC_HASBODY (mainf->type))
1911     {
1912       /* entry point @ start of HOME */
1913       fprintf (asmFile, "__sdcc_program_startup:\n");
1914
1915       /* put in jump or call to main */
1916       if (options.mainreturn)
1917         {
1918           fprintf (asmFile, "\t%cjmp\t_main\n", options.acall_ajmp?'a':'l');   /* needed? */
1919           fprintf (asmFile, ";\treturn from main will return to caller\n");
1920         }
1921       else
1922         {
1923           fprintf (asmFile, "\t%ccall\t_main\n", options.acall_ajmp?'a':'l');
1924           fprintf (asmFile, ";\treturn from main will lock up\n");
1925           fprintf (asmFile, "\tsjmp .\n");
1926         }
1927     }
1928   /* copy over code */
1929   fprintf (asmFile, "%s", iComments2);
1930   fprintf (asmFile, "; code\n");
1931   fprintf (asmFile, "%s", iComments2);
1932   tfprintf (asmFile, "\t!areacode\n", options.code_seg);
1933   dbuf_write_and_destroy (&code->oBuf, asmFile);
1934
1935   if (port->genAssemblerEnd)
1936     {
1937       port->genAssemblerEnd (asmFile);
1938     }
1939   fclose (asmFile);
1940 }