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