1 /*-------------------------------------------------------------------------
2   SDCCglue.c - glues everything we have done together into one file.
3 
4   Copyright (C) 1998 Sandeep Dutta . sandeep.dutta@usa.net
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 
21 #include "common.h"
22 #include <time.h>
23 #include "newalloc.h"
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include "dbuf_string.h"
27 
28 #ifdef _WIN32
29 #include <io.h>
30 #else
31 #include <unistd.h>
32 #endif
33 
34 symbol *interrupts[INTNO_MAX + 1];
35 
36 void printIval (symbol *, sym_link *, initList *, struct dbuf_s *, bool check);
37 set *publics = NULL;            /* public variables */
38 set *externs = NULL;            /* Variables that are declared as extern */
39 set *strSym = NULL;             /* string initializers */
40 set *ccpStr = NULL;             /* char * const pointers with a string literal initializer */
41 
42 unsigned maxInterrupts = 0;
43 int allocInfo = 1;
44 symbol *mainf;
45 int noInit = 0;                 /* no initialization */
46 
47 
48 char *
aopLiteralGptr(const char * name,value * val)49 aopLiteralGptr (const char * name, value * val)
50 {
51   unsigned long v = ulFromVal (val);
52   struct dbuf_s dbuf;
53 
54   dbuf_init (&dbuf, 128);
55 
56   v >>= ((GPTRSIZE - 1) * 8);
57 
58   if (IS_FUNCPTR (val->type))
59     dbuf_tprintf (&dbuf, "!immedbyte", v | pointerTypeToGPByte (DCL_TYPE (val->type->next), val->name, name));
60   else if (IS_PTR (val->type) && !IS_GENPTR (val->type))
61     dbuf_tprintf (&dbuf, "!immedbyte", pointerTypeToGPByte (DCL_TYPE (val->type), val->name, name));
62   else
63     dbuf_tprintf (&dbuf, "!immedbyte", (unsigned int) v & 0xff);
64 
65   return dbuf_detach_c_str (&dbuf);
66 }
67 
68 const char *
aopLiteralLong(value * val,int offset,int size)69 aopLiteralLong (value *val, int offset, int size)
70 {
71   unsigned long v;
72   struct dbuf_s dbuf;
73 
74   if (!val)
75     {
76       // assuming we have been warned before
77       val = constCharVal (0);
78     }
79 
80   dbuf_init (&dbuf, 128);
81 
82   switch (size)
83     {
84     case 1:
85       v = byteOfVal (val, offset);
86       dbuf_tprintf (&dbuf, "!immedbyte", (unsigned int) v & 0xff);
87       break;
88     case 2:
89       v = byteOfVal (val, offset+1);
90       v = (v << 8) | byteOfVal (val, offset);
91       dbuf_tprintf (&dbuf, "!immedword", (unsigned int) v & 0xffff);
92       break;
93     case 3:
94       v = byteOfVal (val, offset+2);
95       v = (v << 8) | byteOfVal (val, offset+1);
96       v = (v << 8) | byteOfVal (val, offset);
97       // we don't have a !immedword24 yet for ds390
98       dbuf_printf (&dbuf, "#0x%06X", (unsigned int) v & 0xffffff);
99       break;
100     default:
101       /* Hmm.  Too big for now. */
102       assert (0);
103     }
104   return dbuf_detach_c_str (&dbuf);
105 }
106 
107 /*-----------------------------------------------------------------*/
108 /* aopLiteral - string from a literal value                        */
109 /*-----------------------------------------------------------------*/
110 const char *
aopLiteral(value * val,int offset)111 aopLiteral (value *val, int offset)
112 {
113   return aopLiteralLong (val, offset, 1);
114 }
115 
116 /*-----------------------------------------------------------------*/
117 /* emitDebugSym - emit label for debug symbol                      */
118 /*-----------------------------------------------------------------*/
119 static void
emitDebugSym(struct dbuf_s * oBuf,symbol * sym)120 emitDebugSym (struct dbuf_s *oBuf, symbol * sym)
121 {
122   if (sym->level && sym->localof)       /* symbol scope is local */
123     {
124       dbuf_printf (oBuf, "L%s.%s$", moduleName, sym->localof->name);
125     }
126   else if (IS_STATIC (sym->etype))      /* symbol scope is file */
127     {
128       dbuf_printf (oBuf, "F%s$", moduleName);
129     }
130   else                          /* symbol scope is global */
131     {
132       dbuf_printf (oBuf, "G$");
133     }
134   dbuf_printf (oBuf, "%s$%ld_%ld$%d", sym->name, sym->level / LEVEL_UNIT, sym->level % LEVEL_UNIT, sym->block);
135 }
136 
137 /*-----------------------------------------------------------------*/
138 /* emitRegularMap - emit code for maps with no special cases       */
139 /*-----------------------------------------------------------------*/
140 static void
emitRegularMap(memmap * map,bool addPublics,bool arFlag)141 emitRegularMap (memmap *map, bool addPublics, bool arFlag)
142 {
143   symbol *sym;
144   ast *ival = NULL;
145 
146   if (!map)
147     return;
148 
149   if (addPublics)
150     {
151       /* PENDING: special case here - should remove */
152       if (!strcmp (map->sname, CODE_NAME))
153         dbuf_tprintf (&map->oBuf, "\t!areacode\n", map->sname);
154       else if (!strcmp (map->sname, DATA_NAME))
155         {
156           dbuf_tprintf (&map->oBuf, "\t!areadata\n", map->sname);
157           if (options.data_seg && strcmp (DATA_NAME, options.data_seg))
158             dbuf_tprintf (&map->oBuf, "\t!area\n", options.data_seg);
159         }
160       else if (!strcmp (map->sname, HOME_NAME))
161         dbuf_tprintf (&map->oBuf, "\t!areahome\n", map->sname);
162       else
163         dbuf_tprintf (&map->oBuf, "\t!area\n", map->sname);
164 
165       if (map->regsp)
166         dbuf_tprintf (&map->oBuf, "\t!org\n", 0);
167     }
168 
169   for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
170     {
171       symbol *newSym = NULL;
172 
173       /* if allocation required check is needed
174          then check if the symbol really requires
175          allocation only for local variables */
176 
177       if (arFlag && !IS_AGGREGATE (sym->type) && !(sym->_isparm && !IS_REGPARM (sym->etype)) && !sym->allocreq && sym->level)
178         continue;
179 
180       /* for bitvar locals and parameters */
181       if (!arFlag && !sym->allocreq && sym->level && !SPEC_ABSA (sym->etype))
182         {
183           continue;
184         }
185 
186       /* if global variable & not static or extern
187          and addPublics allowed then add it to the public set */
188       if ((sym->level == 0 ||
189            (sym->_isparm && !IS_REGPARM (sym->etype) && !IS_STATIC (sym->localof->etype))) &&
190           addPublics &&
191           !IS_STATIC (sym->etype) &&
192           (IS_FUNC (sym->type) ? (sym->used || IFFUNC_HASBODY (sym->type)) : (!IS_EXTERN (sym->etype) || sym->ival)) &&
193           !(IFFUNC_ISINLINE (sym->type) && !IS_STATIC (sym->etype) && !IS_EXTERN (sym->etype)))
194         {
195           addSetHead (&publics, sym);
196         }
197 
198       /* if extern then add it into the extern list */
199       if (IS_EXTERN (sym->etype) && !sym->ival)
200         {
201           addSetHead (&externs, sym);
202           continue;
203         }
204 
205       /* if extern then do nothing or is a function
206          then do nothing */
207       if (IS_FUNC (sym->type) && !(sym->isitmp))
208         continue;
209 
210       /* if it has an initial value then do it only if
211          it is a global variable */
212       if (sym->ival && sym->level == 0)
213         {
214           if ((SPEC_OCLS (sym->etype) == xidata || SPEC_OCLS (sym->etype) == initialized) && !SPEC_ABSA (sym->etype) && !SPEC_ADDRSPACE (sym->etype))
215             {
216               sym_link *t;
217               ast *ival = NULL;
218               symbol *tsym = copySymbol (sym);
219 
220               // check for constant
221               if (IS_AGGREGATE (tsym->type))
222                 {
223                   ival = initAggregates (tsym, tsym->ival, NULL);
224                 }
225               else
226                 {
227                   if (getNelements (tsym->type, tsym->ival) > 1)
228                     {
229                       werrorfl (tsym->fileDef, tsym->lineDef, W_EXCESS_INITIALIZERS, "scalar", tsym->name);
230                     }
231                   ival = newNode ('=', newAst_VALUE (symbolVal (tsym)),
232                                   decorateType (resolveSymbols (list2expr (tsym->ival)), RESULT_TYPE_NONE));
233                 }
234               if (ival)
235                 {
236                   // set ival's lineno to where the symbol was defined
237                   setAstFileLine (ival, filename = tsym->fileDef, lineno = tsym->lineDef);
238                   // check if this is not a constant expression
239                   if (!constExprTree (ival))
240                     {
241                       werrorfl (ival->filename, ival->lineno, E_CONST_EXPECTED, "found expression");
242                       // but try to do it anyway
243                     }
244                 }
245 
246               /* create a new "XINIT (CODE)" symbol, that will be emitted later
247                  in the static seg */
248               newSym = copySymbol (sym);
249               SPEC_OCLS (newSym->etype) = (SPEC_OCLS (sym->etype) == xidata) ? xinit : initializer;
250               SNPRINTF (newSym->name, sizeof (newSym->name), "__xinit_%s", sym->name);
251               SNPRINTF (newSym->rname, sizeof (newSym->rname), "__xinit_%s", sym->rname);
252 
253               /* find the first non-array link */
254               t = newSym->type;
255               while (IS_ARRAY (t))
256                 t = t->next;
257               if (IS_SPEC (t))
258                 SPEC_CONST (t) = 1;
259               else
260                 DCL_PTR_CONST (t) = 1;
261               SPEC_STAT (newSym->etype) = 1;
262 
263               strSym = NULL;
264               ++noAlloc;
265               resolveIvalSym (newSym->ival, newSym->type);
266               --noAlloc;
267 
268               // add it to the "XINIT (CODE)" segment
269               addSet ((SPEC_OCLS (sym->etype) == xidata) ? &xinit->syms : &initializer->syms, newSym);
270 
271               if (!SPEC_ABSA (sym->etype))
272                 {
273                   struct dbuf_s tmpBuf;
274                   symbol *ps = NULL;
275                   set *tmpSym = NULL;
276 
277                   wassert(dbuf_init (&tmpBuf, 4096));
278                   // before allocation we must parse the sym->ival tree
279                   // but without actually generating initialization code
280                   ++noAlloc;
281                   resolveIvalSym (sym->ival, sym->type);
282                   ++noInit;
283                   printIval (sym, sym->type, sym->ival, &tmpBuf, TRUE);
284                   --noInit;
285                   --noAlloc;
286 
287                   // delete redundant __str_%d symbols (initializer for char arrays)
288                   for (ps = setFirstItem (statsg->syms); ps; ps = setNextItem (statsg->syms))
289                     if (!strstr (tmpBuf.buf, ps->name) && isinSet (strSym, ps))
290                       addSet (&tmpSym, ps);
291                   for (ps = setFirstItem (tmpSym); ps; ps = setNextItem (tmpSym))
292                     deleteSetItem (&statsg->syms, ps);
293 
294                   deleteSet (&tmpSym);
295                   dbuf_destroy (&tmpBuf);
296                 }
297 
298               if (strSym)
299                 deleteSet (&strSym);
300             }
301           else
302             {
303               if (IS_AGGREGATE (sym->type))
304                 {
305                   ival = initAggregates (sym, sym->ival, NULL);
306                 }
307               else
308                 {
309                   if (getNelements (sym->type, sym->ival) > 1)
310                     {
311                       werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", sym->name);
312                     }
313                   ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
314                                   decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
315                 }
316               codeOutBuf = &statsg->oBuf;
317 
318               if (ival)
319                 {
320                   // set ival's lineno to where the symbol was defined
321                   setAstFileLine (ival, filename = sym->fileDef, lineno = sym->lineDef);
322                   // check if this is not a constant expression
323                   if (!constExprTree (ival))
324                     {
325                       werrorfl (ival->filename, ival->lineno, E_CONST_EXPECTED, "found expression");
326                       // but try to do it anyway
327                     }
328                   allocInfo = 0;
329                   if (!astErrors (ival))
330                     eBBlockFromiCode (iCodeFromAst (ival));
331                   allocInfo = 1;
332                 }
333             }
334         }
335 
336       /* if it has an absolute address then generate
337          an equate for this no need to allocate space */
338       if (SPEC_ABSA (sym->etype) && !sym->ival)
339         {
340           char *equ = "=";
341 
342           /* print extra debug info if required */
343           if (options.debug)
344             {
345               emitDebugSym (&map->oBuf, sym);
346               dbuf_printf (&map->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
347             }
348           dbuf_printf (&map->oBuf, "%s\t%s\t0x%04x\n", sym->rname, equ, SPEC_ADDR (sym->etype));
349         }
350       else
351         {
352           int size = getSize (sym->type) + sym->flexArrayLength;
353           if (size == 0)
354             {
355               werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
356             }
357           /* allocate space */
358           if (SPEC_ABSA (sym->etype))
359             {
360               dbuf_tprintf (&map->oBuf, "\t!org\n", SPEC_ADDR (sym->etype));
361             }
362           /* print extra debug info if required */
363           if (options.debug)
364             {
365               emitDebugSym (&map->oBuf, sym);
366               dbuf_printf (&map->oBuf, "==.\n");
367             }
368           if (IS_STATIC (sym->etype) || sym->level)
369             dbuf_tprintf (&map->oBuf, "!slabeldef\n", sym->rname);
370           else
371             dbuf_tprintf (&map->oBuf, "!labeldef\n", sym->rname);
372           dbuf_tprintf (&map->oBuf, "\t!ds\n", (unsigned int) size & 0xffff);
373         }
374 
375       sym->ival = NULL;
376     }
377 }
378 
379 /*-----------------------------------------------------------------*/
380 /* initValPointer - pointer initialization code massaging          */
381 /*-----------------------------------------------------------------*/
382 value *
initValPointer(ast * expr)383 initValPointer (ast *expr)
384 {
385   value *val;
386 
387   /* no then we have to do these kludgy checks */
388   /* pointers can be initialized with address of
389      a variable or address of an array element */
390   if (IS_ADDRESS_OF_OP (expr))
391     {
392       /* address of symbol */
393       if (IS_AST_SYM_VALUE (expr->left))
394         {
395           STORAGE_CLASS sclass = SPEC_SCLS (expr->left->etype);
396           memmap *oclass = SPEC_OCLS (expr->left->etype);
397 
398           val = AST_VALUE (expr->left);
399           val->type = newLink (DECLARATOR);
400           if (sclass == S_CODE)
401             {
402               DCL_TYPE (val->type) = CPOINTER;
403               CodePtrPointsToConst (val->type);
404             }
405           else if (oclass)
406             DCL_TYPE (val->type) = oclass->ptrType;
407           else if (sclass == S_XDATA)
408             DCL_TYPE (val->type) = FPOINTER;
409           else if (sclass == S_DATA)
410             DCL_TYPE (val->type) = POINTER;
411           else if (sclass == S_IDATA)
412             DCL_TYPE (val->type) = IPOINTER;
413           else if (sclass == S_PDATA)
414             DCL_TYPE (val->type) = PPOINTER;
415           else if (sclass == S_XSTACK)
416             DCL_TYPE (val->type) = PPOINTER;
417           else if (sclass == S_EEPROM)
418             DCL_TYPE (val->type) = EEPPOINTER;
419           else
420             DCL_TYPE (val->type) = POINTER;
421           val->type->next = expr->left->ftype;
422           val->etype = getSpec (val->type);
423           return val;
424         }
425 
426       /* if address of indexed array */
427       if (IS_ARRAY_OP (expr->left))
428         return valForArray (expr->left);
429 
430       /* if address of structure element then
431          case 1. a.b ; */
432       if (IS_AST_OP (expr->left) && expr->left->opval.op == '.')
433         {
434           return valForStructElem (expr->left->left, expr->left->right);
435         }
436 
437       /* case 2. (&a)->b ;
438          (&some_struct)->element */
439       if (IS_AST_OP (expr->left) && expr->left->opval.op == PTR_OP && IS_ADDRESS_OF_OP (expr->left->left))
440         {
441           return valForStructElem (expr->left->left->left, expr->left->right);
442         }
443 
444       /* case 2.1. a->b */
445       if (IS_AST_OP (expr->left) && expr->left->opval.op == PTR_OP)
446         {
447           return valForStructElem (expr->left->left, expr->left->right);
448         }
449     }
450 
451   /* case 3. (((char *) &a) +/- constant) */
452   if (IS_AST_OP (expr) &&
453       (expr->opval.op == '+' || expr->opval.op == '-') &&
454       IS_CAST_OP (expr->left) && IS_ADDRESS_OF_OP (expr->left->right) && IS_AST_LIT_VALUE (expr->right))
455     {
456       return valForCastAggr (expr->left->right->left, expr->left->left->opval.lnk, expr->right, expr->opval.op);
457     }
458 
459   /* case 4. (array type) */
460   if (IS_AST_SYM_VALUE (expr) && IS_ARRAY (expr->ftype))
461     {
462       STORAGE_CLASS sclass = SPEC_SCLS (expr->etype);
463       memmap *oclass = SPEC_OCLS (expr->etype);
464 
465       val = copyValue (AST_VALUE (expr));
466       val->type = newLink (DECLARATOR);
467       if (SPEC_SCLS (expr->etype) == S_CODE)
468         {
469           DCL_TYPE (val->type) = CPOINTER;
470           CodePtrPointsToConst (val->type);
471         }
472       else if (oclass)
473         DCL_TYPE (val->type) = oclass->ptrType;
474       else if (sclass == S_XDATA)
475         DCL_TYPE (val->type) = FPOINTER;
476       else if (sclass == S_DATA)
477         DCL_TYPE (val->type) = POINTER;
478       else if (sclass == S_IDATA)
479         DCL_TYPE (val->type) = IPOINTER;
480       else if (sclass == S_PDATA)
481         DCL_TYPE (val->type) = PPOINTER;
482       else if (sclass == S_XSTACK)
483         DCL_TYPE (val->type) = PPOINTER;
484       else if (sclass == S_EEPROM)
485         DCL_TYPE (val->type) = EEPPOINTER;
486       else
487         DCL_TYPE (val->type) = POINTER;
488       val->type->next = expr->ftype->next;
489       val->etype = getSpec (val->type);
490       return val;
491     }
492 
493   /* if structure element then
494      case 5. a.b ; */
495   if (IS_AST_OP (expr) && expr->opval.op == '.')
496     {
497       return valForStructElem (expr->left, expr->right);
498     }
499 
500   /* case 6. a->b ;
501      some_struct->element */
502   if (IS_AST_OP (expr) && expr->opval.op == PTR_OP)
503     {
504       ast *t = expr->left;
505 
506       /*if (expr->left->left)
507         if (expr->left->left->left)
508           if (expr->left->left->opval.op == '[')
509             t = expr->left->left;
510           else
511             t = expr->left->left->left;
512         else
513           t = expr->left->left;
514       else
515         t = expr->left;*/
516 
517       /* a more generic way of above code */
518       while (t->left != NULL && t->opval.op != '[')
519         t = t->left;
520 
521       return valForStructElem (t, expr->right);
522     }
523 
524   /* case 7. function name */
525   if (IS_AST_SYM_VALUE (expr) && IS_FUNC (expr->ftype))
526     {
527       return AST_VALUE (expr);
528     }
529 
530   return NULL;
531 }
532 
533 /*-----------------------------------------------------------------*/
534 /* initPointer - pointer initialization code massaging             */
535 /*-----------------------------------------------------------------*/
536 value *
initPointer(initList * ilist,sym_link * toType,int showError)537 initPointer (initList *ilist, sym_link *toType, int showError)
538 {
539   value *val;
540   ast *expr;
541 
542   if (!ilist)
543     {
544       return valCastLiteral (toType, 0.0, 0);
545     }
546 
547   expr = list2expr (ilist);
548 
549   if (!expr)
550     {
551       if (showError)
552         werror (E_CONST_EXPECTED);
553       return 0;
554     }
555 
556   /* try it the old way first */
557   if ((val = constExprValue (expr, FALSE)))
558     return val;
559 
560   /* ( ptr + constant ) */
561   if (IS_AST_OP (expr) &&
562       (expr->opval.op == '+' || expr->opval.op == '-') &&
563       IS_AST_SYM_VALUE (expr->left) &&
564       (IS_ARRAY (expr->left->ftype) || IS_PTR (expr->left->ftype)) &&
565       compareType (toType, expr->left->ftype) && IS_AST_LIT_VALUE (expr->right))
566     {
567       return valForCastAggr (expr->left, expr->left->ftype, expr->right, expr->opval.op);
568     }
569 
570   /* (char *)(expr1) */
571   if (IS_CAST_OP (expr))
572     {
573       if (compareType (toType, expr->left->ftype) == 0 && showError)
574         {
575           werror (W_INIT_WRONG);
576           printFromToType (expr->left->ftype, toType);
577         }
578       val = initValPointer (expr->right);
579       if (val)
580         {
581           DECLARATOR_TYPE dcl_type = DCL_TYPE (val->type);
582           val->type = expr->left->ftype;
583           val->etype = getSpec (val->type);
584           if (IS_GENPTR (val->type))
585             DCL_TYPE (val->type) = dcl_type;
586         }
587     }
588   else
589     {
590       val = initValPointer (expr);
591     }
592 
593   if (val)
594     return val;
595 
596   if (showError)
597     {
598       if (expr)
599         werrorfl (expr->filename, expr->lineno, E_CONST_EXPECTED);
600       else
601         werror (E_CONST_EXPECTED);
602     }
603   return 0;
604 }
605 
606 /*-----------------------------------------------------------------*/
607 /* printChar - formats and prints a UTF-8 character string with DB */
608 /*-----------------------------------------------------------------*/
609 void
printChar(struct dbuf_s * oBuf,const char * s,int plen)610 printChar (struct dbuf_s *oBuf, const char *s, int plen)
611 {
612   int i;
613   int pplen = 0;
614   char buf[100];
615   char *p = buf;
616 
617   if (TARGET_PDK_LIKE && !TARGET_IS_PDK16) // Assembler does not support .ascii
618     {
619       while (pplen < plen)
620         {
621           if (isprint((unsigned char) *s))
622             dbuf_tprintf (oBuf, "\t!db !constbyte\t; %c\n", (unsigned char) *s, (unsigned char) *s);
623           else
624             dbuf_tprintf (oBuf, "\t!db !constbyte\n", (unsigned char) *s);
625 
626           s++;
627           pplen++;
628         }
629       return;
630     }
631 
632   while (pplen < plen)
633     {
634       i = 60;
635       while (i && pplen < plen)
636         {
637           if (!isprint((unsigned char) *s) || *s == '\"' || *s == '\\')
638             {
639               *p = '\0';
640               if (p != buf)
641                 dbuf_tprintf (oBuf, "\t!ascii\n", buf);
642               dbuf_tprintf (oBuf, "\t!db !constbyte\n", (unsigned char) *s);
643               p = buf;
644               i = 60;
645             }
646           else
647             {
648               *p = *s;
649               p++;
650               i--;
651             }
652           s++;
653           pplen++;
654         }
655       if (p != buf)
656         {
657           *p = '\0';
658           dbuf_tprintf (oBuf, "\t!ascii\n", buf);
659           p = buf;
660           i = 60;
661         }
662     }
663 }
664 
665 /*-----------------------------------------------------------------*/
666 /* printChar16 - formats and prints a UTF-16 character string with DB*/
667 /*-----------------------------------------------------------------*/
668 void
printChar16(struct dbuf_s * oBuf,const TYPE_TARGET_UINT * s,int plen)669 printChar16 (struct dbuf_s *oBuf, const TYPE_TARGET_UINT *s, int plen)
670 {
671   int pplen = 0;
672 
673   while (pplen < plen)
674     {
675       if (TARGET_PDK_LIKE && !TARGET_IS_PDK16)
676         {
677           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 0) & 0xff);
678           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 8) & 0xff);
679         }
680       else if (port->little_endian)
681         dbuf_printf (oBuf, "\t.byte %d,%d\n", (*s >> 0) & 0xff, (*s >> 8) & 0xff);
682       else
683         dbuf_printf (oBuf, "\t.byte %d,%d\n", (*s >> 8) & 0xff, (*s >> 0) & 0xff);
684 
685       s++;
686       pplen++;
687     }
688   while (pplen < plen)
689     {
690       dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
691       pplen++;
692     }
693 }
694 
695 /*-----------------------------------------------------------------*/
696 /* printChar32 - formats and prints a UTF-32 character string with DB*/
697 /*-----------------------------------------------------------------*/
698 void
printChar32(struct dbuf_s * oBuf,const TYPE_TARGET_ULONG * s,int plen)699 printChar32 (struct dbuf_s *oBuf, const TYPE_TARGET_ULONG *s, int plen)
700 {
701   int pplen = 0;
702 
703   while (pplen < plen)
704     {
705       if (TARGET_PDK_LIKE && !TARGET_IS_PDK16)
706         {
707           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 0) & 0xff);
708           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 8) & 0xff);
709           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 16) & 0xff);
710           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (*s >> 24) & 0xff);
711         }
712       else if (port->little_endian)
713         dbuf_printf (oBuf, "\t.byte %d,%d,%d,%d\n", (*s >> 0) & 0xff, (*s >> 8) & 0xff, (*s >> 16) & 0xff, (*s >> 24) & 0xff);
714       else
715         dbuf_printf (oBuf, "\t.byte %d,%d,%d,%d\n", (*s >> 24) & 0xff, (*s >> 16) & 0xff, (*s >> 8) & 0xff,(*s >> 0) & 0xff);
716 
717       s++;
718       pplen++;
719     }
720   while (pplen < plen)
721     {
722       dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
723       pplen++;
724     }
725 }
726 
727 /*-----------------------------------------------------------------*/
728 /* return the generic pointer high byte for a given pointer type.  */
729 /*-----------------------------------------------------------------*/
730 int
pointerTypeToGPByte(const int p_type,const char * iname,const char * oname)731 pointerTypeToGPByte (const int p_type, const char *iname, const char *oname)
732 {
733   switch (p_type)
734     {
735     case IPOINTER:
736     case POINTER:
737       return GPTYPE_NEAR;
738     case GPOINTER:
739       werror (W_USING_GENERIC_POINTER, iname ? iname : "<null>", oname ? oname : "<null>");
740       return -1;
741     case FPOINTER:
742       return GPTYPE_FAR;
743     case CPOINTER:
744     case FUNCTION:
745       return GPTYPE_CODE;
746     case PPOINTER:
747       return GPTYPE_XSTACK;
748     default:
749       fprintf (stderr, "*** internal error: unknown pointer type %d in GPByte.\n", p_type);
750       exit (EXIT_FAILURE);
751     }
752   return -1;
753 }
754 
755 /*-----------------------------------------------------------------*/
756 /* printIvalVal - generate ival according from value               */
757 /*-----------------------------------------------------------------*/
printIvalVal(struct dbuf_s * oBuf,value * val,int size,bool newline)758 static void printIvalVal(struct dbuf_s *oBuf, value *val, int size, bool newline)
759 {
760   if (size == 2 && port->use_dw_for_init)
761     {
762       dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, 2));
763       return;
764     }
765 
766   const bool use_ret = TARGET_PDK_LIKE && !TARGET_IS_PDK16;
767 
768   if (!use_ret)
769     dbuf_printf (oBuf, "\t.byte ");
770 
771   for (int i = 0; i < size; i++)
772     {
773       const char *inst;
774       const char *byte = aopLiteral (val, port->little_endian ? i : size - 1 - i);
775       if (use_ret)
776         inst = i != size - 1 ? "\tret %s\n" : "\tret %s";
777       else
778         inst = i != size - 1 ? "%s, " : "%s";
779       dbuf_printf (oBuf, inst, byte);
780     }
781   if (newline)
782     dbuf_printf (oBuf, "\n");
783 }
784 
785 /*-----------------------------------------------------------------*/
786 /* _printPointerType - generates ival for pointer type             */
787 /*-----------------------------------------------------------------*/
788 static void
_printPointerType(struct dbuf_s * oBuf,const char * name,int size)789 _printPointerType (struct dbuf_s *oBuf, const char *name, int size)
790 {
791   wassert (!TARGET_PDK_LIKE);
792 
793   if (size == 4)
794     {
795       if (port->little_endian)
796         dbuf_printf (oBuf, "\t.byte %s, (%s >> 8), (%s >> 16), (%s >> 24)", name, name, name, name);
797       else
798         dbuf_printf (oBuf, "\t.byte (%s >> 24), (%s >> 16), (%s >> 8), %s", name, name, name, name);
799     }
800   else if (size == 3)
801     {
802       if (port->little_endian)
803         dbuf_printf (oBuf, "\t.byte %s, (%s >> 8), (%s >> 16)", name, name, name);
804       else
805         dbuf_printf (oBuf, "\t.byte (%s >> 16), (%s >> 8), %s", name, name, name);
806     }
807   else
808     {
809       if (port->little_endian)
810         dbuf_printf (oBuf, "\t.byte %s, (%s >> 8)", name, name);
811       else
812         dbuf_printf (oBuf, "\t.byte (%s >> 8), %s", name, name);
813     }
814 }
815 
816 /*-----------------------------------------------------------------*/
817 /* printPointerType - generates ival for pointer type              */
818 /*-----------------------------------------------------------------*/
819 static void
printPointerType(struct dbuf_s * oBuf,const char * name)820 printPointerType (struct dbuf_s *oBuf, const char *name)
821 {
822   _printPointerType (oBuf, name, (options.model == MODEL_FLAT24) ? 3 : 2);
823   dbuf_printf (oBuf, "\n");
824 }
825 
826 /*-----------------------------------------------------------------*/
827 /* printGPointerType - generates ival for generic pointer type     */
828 /*-----------------------------------------------------------------*/
829 static void
printGPointerType(struct dbuf_s * oBuf,const char * iname,const char * oname,int type)830 printGPointerType (struct dbuf_s *oBuf, const char *iname, const char *oname, int type)
831 {
832   int byte = pointerTypeToGPByte (type, iname, oname);
833   int size = (options.model == MODEL_FLAT24) ? 3 : 2;
834   if (byte == -1)
835     {
836       _printPointerType (oBuf, iname, size + 1);
837       dbuf_printf (oBuf, "\n");
838     }
839   else
840     {
841       _printPointerType (oBuf, iname, size);
842       dbuf_printf (oBuf, ",#0x%02x\n", byte);
843     }
844 }
845 
846 /*-----------------------------------------------------------------*/
847 /* printIvalType - generates ival for int/char                     */
848 /*-----------------------------------------------------------------*/
849 void
printIvalType(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf)850 printIvalType (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf)
851 {
852   value *val;
853   unsigned long ulVal = 0;
854 
855   /* if initList is deep */
856   if (ilist && (ilist->type == INIT_DEEP))
857     ilist = ilist->init.deep;
858 
859   if (!(val = list2val (ilist, FALSE)))
860     {
861       if (!!(val = initPointer (ilist, type, 0)))
862         {
863           int i, size = getSize (type), le = port->little_endian, top = (options.model == MODEL_FLAT24) ? 3 : 2;;
864           dbuf_printf (oBuf, "\t.byte ");
865           for (i = (le ? 0 : size - 1); le ? (i < size) : (i > -1); i += (le ? 1 : -1))
866             {
867               if (i == 0)
868 			    if (val->name && strlen (val->name) > 0)
869                   dbuf_printf (oBuf, "%s", val->name);
870 				else
871                   dbuf_printf (oBuf, "#0x00");
872               else if (0 < i && i < top)
873 			    if (val->name && strlen (val->name) > 0)
874                   dbuf_printf (oBuf, "(%s >> %d)", val->name, i * 8);
875 				else
876                   dbuf_printf (oBuf, "#0x00");
877               else
878                 dbuf_printf (oBuf, "#0x00");
879               if (i == (le ? (size - 1) : 0))
880                 dbuf_printf (oBuf, "\n");
881               else
882                 dbuf_printf (oBuf, ", ");
883             }
884           return;
885         }
886       else
887         {
888           werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
889           val = constCharVal (0);
890         }
891     }
892 
893   if (val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
894     {
895       werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
896       val = constCharVal (0);
897     }
898 
899   /* check if the literal value is within bounds */
900   if (checkConstantRange (type, val->etype, '=', FALSE) == CCR_OVL)
901     {
902       werror (W_LIT_OVERFLOW);
903     }
904 
905   if (val->type != type)
906     {
907       val = valCastLiteral (type, floatFromVal (val), (TYPE_TARGET_ULONGLONG) ullFromVal (val));
908     }
909 
910   if (IS_INTEGRAL (val->type))
911     ulVal = ulFromVal (val);
912 
913   switch (getSize (type))
914     {
915     case 1:
916       if (!val)
917         dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
918       else
919         {
920           if (IS_UNSIGNED (val->type))
921             {
922               dbuf_tprintf (oBuf, "\t!dbs\t; %u", aopLiteral (val, 0), (unsigned int) ulVal);
923             }
924           else
925             {
926               dbuf_tprintf (oBuf, "\t!dbs\t; % d", aopLiteral (val, 0), (int) ulVal);
927             }
928           if (isalnum ((int) ulVal))
929             dbuf_tprintf (oBuf, "\t'%c'\n", (int) ulVal);
930           else
931             dbuf_tprintf (oBuf, "\n");
932         }
933       break;
934 
935     case 2:
936       if (port->use_dw_for_init)
937         {
938           printIvalVal (oBuf, val, 2, true);
939           break;
940         }
941       printIvalVal (oBuf, val, 2, false);
942       if (IS_UNSIGNED (val->type))
943         dbuf_printf (oBuf, "\t; %u\n", (unsigned int) ulVal);
944       else
945         dbuf_printf (oBuf, "\t; % d\n", (int) ulVal);
946       break;
947 
948     case 4:
949       if (!val)
950         {
951           dbuf_tprintf (oBuf, "\t!dw !constword\n", 0);
952           dbuf_tprintf (oBuf, "\t!dw !constword\n", 0);
953         }
954       else
955         {
956           printIvalVal (oBuf, val, 4, false);
957 
958           if (IS_FLOAT (val->type))
959             {
960               dbuf_printf (oBuf, "\t; % e\n", floatFromVal (val));
961             }
962           else
963             {
964               if (IS_UNSIGNED (val->type))
965                 dbuf_printf (oBuf, "\t; %u\n", (unsigned int) ulVal);
966               else
967                 dbuf_printf (oBuf, "\t; % d\n", (int) ulVal);
968             }
969         }
970       break;
971     case 8:
972       printIvalVal (oBuf, val, 8, true); // TODO: Print value as comment. Does dbuf_printf support long long even on MSVC?
973       break;
974     default:
975       wassertl (0, "Attempting to initialize integer of non-handled size.");
976     }
977 }
978 
979 /*-----------------------------------------------------------------*/
980 /* printIvalBitFields - generate initializer for bitfields         */
981 /* return the number of bytes written                              */
982 /*-----------------------------------------------------------------*/
983 static unsigned int
printIvalBitFields(symbol ** sym,initList ** ilist,struct dbuf_s * oBuf)984 printIvalBitFields (symbol ** sym, initList ** ilist, struct dbuf_s *oBuf)
985 {
986   symbol *lsym = *sym;
987   initList *lilist = *ilist;
988   unsigned long ival = 0;
989   unsigned size = 0;
990   unsigned bit_start = 0;
991   unsigned long int bytes_written = 0;
992 
993   while (lsym && IS_BITFIELD (lsym->type))
994     {
995       unsigned bit_length = SPEC_BLEN (lsym->etype);
996       if (0 == bit_length)
997         {
998           /* bit-field structure member with a width of 0 */
999           lsym = lsym->next;
1000           break;
1001         }
1002       else if (!SPEC_BUNNAMED (lsym->etype))
1003         {
1004           /* not an unnamed bit-field structure member */
1005           value *val = list2val (lilist, TRUE);
1006 
1007           if (val && val->etype && SPEC_SCLS (val->etype) != S_LITERAL)
1008             {
1009               werrorfl (lilist->filename, lilist->lineno, E_CONST_EXPECTED);
1010               val = constCharVal (0);
1011             }
1012           if (size)
1013             {
1014               if (bit_length > 8)
1015                 size += (bit_length + 7) / 8;
1016             }
1017           else
1018             size = (bit_length + 7) / 8;
1019 
1020           /* check if the literal value is within bounds */
1021           if (val && checkConstantRange (lsym->etype, val->etype, '=', FALSE) == CCR_OVL)
1022             {
1023               werror (W_LIT_OVERFLOW);
1024             }
1025 
1026           ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << bit_start;
1027           lilist = lilist ? lilist->next : NULL;
1028         }
1029       bit_start += bit_length;
1030       lsym = lsym->next;
1031       if (lsym && IS_BITFIELD (lsym->type) && (0 == SPEC_BSTR (lsym->etype)))
1032         {
1033           /* a new integer */
1034           break;
1035         }
1036     }
1037 
1038   switch (size)
1039     {
1040     case 0:
1041       dbuf_tprintf (oBuf, "\n");
1042       break;
1043 
1044     case 1:
1045       dbuf_tprintf (oBuf, "\t!db !constbyte\n", ival);
1046       bytes_written++;
1047       break;
1048 
1049     case 2:
1050       if (TARGET_PDK_LIKE && !TARGET_IS_PDK16)
1051         {
1052           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (ival & 0xff));
1053           dbuf_tprintf (oBuf, "\t!db !constbyte\n", ((ival >> 8) & 0xff));
1054         }
1055       else
1056         dbuf_tprintf (oBuf, "\t!db !constbyte, !constbyte\n", (ival & 0xff), (ival >> 8) & 0xff);
1057       bytes_written += 2;
1058       break;
1059 
1060     case 4:
1061       dbuf_tprintf (oBuf, "\t!db !constbyte, !constbyte, !constbyte, !constbyte\n",
1062                     (ival & 0xff), (ival >> 8) & 0xff, (ival >> 16) & 0xff, (ival >> 24) & 0xff);
1063       bytes_written += 4;
1064       break;
1065     default:
1066       wassert (0);
1067     }
1068   *sym = lsym;
1069   *ilist = lilist;
1070 
1071   return (bytes_written);
1072 }
1073 
1074 /*-----------------------------------------------------------------*/
1075 /* printIvalStruct - generates initial value for structures        */
1076 /*-----------------------------------------------------------------*/
1077 static void
printIvalStruct(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf)1078 printIvalStruct (symbol *sym, sym_link *type, initList *ilist, struct dbuf_s *oBuf)
1079 {
1080   symbol *sflds;
1081   initList *iloop = NULL;
1082   unsigned int skip_holes = 0;
1083 
1084   sflds = SPEC_STRUCT (type)->fields;
1085 
1086   if (ilist)
1087     {
1088       if (ilist->type != INIT_DEEP)
1089         {
1090           werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
1091           return;
1092         }
1093 
1094       iloop = ilist->init.deep;
1095     }
1096 
1097   if (SPEC_STRUCT (type)->type == UNION)
1098     {
1099       int size;
1100       /* skip past holes, print value */
1101       while (iloop && iloop->type == INIT_HOLE)
1102         {
1103           iloop = iloop->next;
1104           sflds = sflds->next;
1105         }
1106       printIval (sym, sflds->type, iloop, oBuf, 1);
1107       /* pad out with zeros if necessary */
1108       size = getSize(type) - getSize(sflds->type);
1109       for ( ; size > 0 ; size-- )
1110         {
1111           dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
1112         }
1113       /* advance past holes to find out if there were excess initializers */
1114       do
1115         {
1116           iloop = iloop ? iloop->next : NULL;
1117           sflds = sflds->next;
1118         }
1119       while (iloop && iloop->type == INIT_HOLE);
1120     }
1121   else
1122     {
1123       while (sflds)
1124         {
1125           unsigned int oldoffset = sflds->offset;
1126 
1127           if (IS_BITFIELD (sflds->type))
1128             printIvalBitFields (&sflds, &iloop, oBuf);
1129           else
1130             {
1131               printIval (sym, sflds->type, iloop, oBuf, 1);
1132               sflds = sflds->next;
1133               iloop = iloop ? iloop->next : NULL;
1134             }
1135 
1136           // Handle members from anonymous unions. Just a hack to fix bug #2643.
1137           while (sflds && sflds->offset == oldoffset)
1138             {
1139               sflds = sflds->next;
1140               skip_holes++;
1141             }
1142         }
1143 
1144       while (skip_holes && iloop && iloop->type == INIT_HOLE)
1145         {
1146           skip_holes--;
1147           iloop = iloop ? iloop->next : NULL;
1148         }
1149     }
1150 
1151   if (iloop)
1152     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
1153 }
1154 
1155 /*-----------------------------------------------------------------*/
1156 /* printIvalChar - generates initital value for character array    */
1157 /*-----------------------------------------------------------------*/
1158 int
printIvalChar(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf,const char * s,bool check)1159 printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf, const char *s, bool check)
1160 {
1161   value *val;
1162   size_t size = DCL_ELEM(type);
1163   char *p;
1164   size_t asz;
1165 
1166   if (!s)
1167     {
1168       val = list2val (ilist, TRUE);
1169       /* if the value is a character string  */
1170       if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
1171         {
1172           if (!size)
1173             {
1174               /* we have not been given a size, but now we know it */
1175               size = strlen (SPEC_CVAL (val->etype).v_char) + 1;
1176               /* but first check, if it's a flexible array */
1177               if (sym && IS_STRUCT (sym->type))
1178                 sym->flexArrayLength = size;
1179               else
1180                 DCL_ELEM (type) = size;
1181             }
1182 
1183           if (check && DCL_ELEM (val->type) > size)
1184             werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
1185 
1186           if (size > (asz = DCL_ELEM (val->type)) && !!(p = malloc (size)))
1187             {
1188               memcpy (p, SPEC_CVAL (val->etype).v_char, asz);
1189               memset (p + asz, 0x00, size - asz);
1190               printChar (oBuf, p, size);
1191               free (p);
1192             }
1193           else
1194             printChar (oBuf, SPEC_CVAL (val->etype).v_char, size);
1195 
1196           return 1;
1197         }
1198       else
1199         return 0;
1200     }
1201   else
1202     printChar (oBuf, s, strlen (s) + 1);
1203   return 1;
1204 }
1205 
strLen16(const TYPE_TARGET_UINT * s)1206 static size_t strLen16(const TYPE_TARGET_UINT *s)
1207 {
1208   size_t l = 0;
1209   while(*s++)
1210     l++;
1211 
1212   return l;
1213 }
1214 
1215 /*-----------------------------------------------------------------*/
1216 /* printIvalChar16 - generates initital value for character array  */
1217 /*-----------------------------------------------------------------*/
1218 int
printIvalChar16(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf,const TYPE_TARGET_UINT * s,bool check)1219 printIvalChar16 (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf, const TYPE_TARGET_UINT *s, bool check)
1220 {
1221   value *val;
1222   size_t size = DCL_ELEM(type);
1223   TYPE_TARGET_UINT *p;
1224   size_t asz;
1225 
1226   if (!s)
1227     {
1228       val = list2val (ilist, TRUE);
1229       /* if the value is a character string  */
1230       if (IS_ARRAY (val->type) && IS_INT (val->etype) && IS_UNSIGNED (val->etype) && !IS_LONG (val->etype))
1231         {
1232           if (!size)
1233             {
1234               /* we have not been given a size, but now we know it */
1235               size = strLen16 (SPEC_CVAL (val->etype).v_char16) + 1;
1236               /* but first check, if it's a flexible array */
1237               if (sym && IS_STRUCT (sym->type))
1238                 sym->flexArrayLength = size;
1239               else
1240                 DCL_ELEM (type) = size;
1241             }
1242 
1243           if (check && DCL_ELEM (val->type) > size)
1244             werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
1245 
1246           if (size > (asz = DCL_ELEM (val->type)) && !!(p = malloc (size * 2)))
1247             {
1248               memcpy (p, SPEC_CVAL (val->etype).v_char16, asz * 2);
1249               memset (p + asz, 0x00, size * 2 - asz * 2);
1250               printChar16 (oBuf, p, size);
1251               free (p);
1252             }
1253           else
1254             printChar16 (oBuf, SPEC_CVAL (val->etype).v_char16, size);
1255 
1256           return 1;
1257         }
1258       else
1259         return 0;
1260     }
1261   else
1262     printChar16 (oBuf, s, strLen16 (s) + 1);
1263   return 1;
1264 }
1265 
strLen32(const TYPE_TARGET_ULONG * s)1266 static size_t strLen32(const TYPE_TARGET_ULONG *s)
1267 {
1268   size_t l = 0;
1269   while(*s++)
1270     l++;
1271   return l;
1272 }
1273 
1274 /*-----------------------------------------------------------------*/
1275 /* printIvalChar32 - generates initital value for character array  */
1276 /*-----------------------------------------------------------------*/
1277 int
printIvalChar32(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf,const TYPE_TARGET_ULONG * s,bool check)1278 printIvalChar32 (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf, const TYPE_TARGET_ULONG *s, bool check)
1279 {
1280   value *val;
1281   size_t size = DCL_ELEM(type);
1282   TYPE_TARGET_ULONG *p;
1283   size_t asz;
1284 
1285   if (!s)
1286     {
1287       val = list2val (ilist, TRUE);
1288       /* if the value is a character string  */
1289       if (IS_ARRAY (val->type) && IS_INT (val->etype) && IS_UNSIGNED (val->etype) && IS_LONG (val->etype))
1290         {
1291           if (!size)
1292             {
1293               /* we have not been given a size, but now we know it */
1294               size = strLen32 (SPEC_CVAL (val->etype).v_char32) + 1;
1295               /* but first check, if it's a flexible array */
1296               if (sym && IS_STRUCT (sym->type))
1297                 sym->flexArrayLength = size;
1298               else
1299                 DCL_ELEM (type) = size;
1300             }
1301 
1302           if (check && DCL_ELEM (val->type) > size)
1303             werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
1304 
1305           if (size > (asz = DCL_ELEM (val->type)) && !!(p = malloc (size * 4)))
1306             {
1307               memcpy (p, SPEC_CVAL (val->etype).v_char32, asz * 4);
1308               memset (p + asz, 0x00, size * 4 - asz * 4);
1309               printChar32 (oBuf, p, size);
1310               free (p);
1311             }
1312           else
1313             printChar32 (oBuf, SPEC_CVAL (val->etype).v_char32, size);
1314 
1315           return 1;
1316         }
1317       else
1318         return 0;
1319     }
1320   else
1321     printChar32 (oBuf, s, strLen32 (s) + 1);
1322   return 1;
1323 }
1324 
1325 /*-----------------------------------------------------------------*/
1326 /* printIvalArray - generates code for array initialization        */
1327 /*-----------------------------------------------------------------*/
1328 void
printIvalArray(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf,bool check)1329 printIvalArray (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf, bool check)
1330 {
1331   value *val;
1332   initList *iloop;
1333   unsigned int size = 0;
1334 
1335   if (ilist)
1336     {
1337       /* take care of the special   case  */
1338       /* array of characters can be init  */
1339       /* by a string                      */
1340       /* char *p = "abc";                 */
1341       if ((IS_CHAR (type->next) || IS_INT (type->next)) && ilist->type == INIT_NODE)
1342         {
1343           val = list2val (ilist, TRUE);
1344           if (!val)
1345             {
1346               werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
1347               return;
1348             }
1349           if (!IS_LITERAL (val->etype))
1350             {
1351               werrorfl (ilist->filename, ilist->lineno, E_CONST_EXPECTED);
1352               return;
1353             }
1354           if (IS_CHAR (type->next) && printIvalChar (sym, type, ilist, oBuf, SPEC_CVAL (sym->etype).v_char, check))
1355             return;
1356           if (IS_INT (type->next) && IS_UNSIGNED (type->next))
1357             {
1358               if (!IS_LONG (type->next) && printIvalChar16 (sym, type, ilist, oBuf, SPEC_CVAL (sym->etype).v_char16, check))
1359                 return;
1360               if (IS_LONG (type->next) && printIvalChar32 (sym, type, ilist, oBuf, SPEC_CVAL (sym->etype).v_char32, check))
1361                 return;
1362             }
1363         }
1364       /* char *p = {"abc"}; */
1365       if ((IS_CHAR (type->next) || IS_INT (type->next)) && ilist->type == INIT_DEEP && ilist->init.deep && ilist->init.deep->type == INIT_NODE)
1366         {
1367           val = list2val (ilist->init.deep, TRUE);
1368           if (!val)
1369             {
1370               werrorfl (ilist->init.deep->filename, ilist->init.deep->lineno, E_INIT_STRUCT, sym->name);
1371               return;
1372             }
1373           if (!IS_LITERAL (val->etype))
1374             {
1375               werrorfl (ilist->init.deep->filename, ilist->init.deep->lineno, E_CONST_EXPECTED);
1376               return;
1377             }
1378           if (IS_CHAR (type->next) && printIvalChar (sym, type, ilist->init.deep, oBuf, SPEC_CVAL (sym->etype).v_char, check))
1379             return;
1380           if (IS_INT (type->next) && IS_UNSIGNED (type->next))
1381             {
1382               if (!IS_LONG (type->next) && printIvalChar16 (sym, type, ilist->init.deep, oBuf, SPEC_CVAL (sym->etype).v_char16, check))
1383                 return;
1384               if (IS_LONG (type->next) && printIvalChar32 (sym, type, ilist->init.deep, oBuf, SPEC_CVAL (sym->etype).v_char32, check))
1385                 return;
1386             }
1387         }
1388 
1389       /* not the special case             */
1390       if (ilist->type != INIT_DEEP)
1391         {
1392           werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
1393           return;
1394         }
1395 
1396       for (iloop = ilist->init.deep; iloop; iloop = iloop->next)
1397         {
1398           if ((++size > DCL_ELEM (type)) && DCL_ELEM (type))
1399             {
1400               werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
1401               break;
1402             }
1403           printIval (sym, type->next, iloop, oBuf, TRUE);
1404         }
1405     }
1406 
1407   if (DCL_ELEM (type))
1408     {
1409       // pad with zeros if needed
1410       if (size < DCL_ELEM (type))
1411         {
1412           size = (DCL_ELEM (type) - size) * getSize (type->next);
1413           while (size--)
1414             {
1415               dbuf_tprintf (oBuf, "\t!db !constbyte\n", 0);
1416             }
1417         }
1418     }
1419   else
1420     {
1421       /* we have not been given a size, but now we know it */
1422       /* but first check, if it's a flexible array */
1423       if (IS_STRUCT (sym->type))
1424         sym->flexArrayLength = size * getSize (type->next);
1425       else
1426         DCL_ELEM (type) = size;
1427     }
1428 
1429   return;
1430 }
1431 
1432 /*-----------------------------------------------------------------*/
1433 /* printIvalFuncPtr - generate initial value for function pointers */
1434 /*-----------------------------------------------------------------*/
1435 void
printIvalFuncPtr(sym_link * type,initList * ilist,struct dbuf_s * oBuf)1436 printIvalFuncPtr (sym_link * type, initList * ilist, struct dbuf_s *oBuf)
1437 {
1438   value *val;
1439   char *name;
1440   int size;
1441 
1442   if (ilist)
1443     val = list2val (ilist, TRUE);
1444   else
1445     val = valCastLiteral (type, 0.0, 0);
1446 
1447   if (!val)
1448     {
1449       // an error has been thrown already
1450       val = constCharVal (0);
1451     }
1452 
1453   if (IS_LITERAL (val->etype))
1454     {
1455       if (compareType (type, val->type) == 0)
1456         {
1457           if (ilist)
1458             werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1459           else
1460             werror (E_INCOMPAT_TYPES);
1461           printFromToType (val->type, type);
1462         }
1463       printIvalCharPtr (NULL, type, val, oBuf);
1464       return;
1465     }
1466 
1467   /* now generate the name */
1468   if (!val->sym)
1469     name = val->name;
1470   else
1471     name = val->sym->rname;
1472 
1473   size = getSize (type);
1474 
1475   if (size == FUNCPTRSIZE)
1476     {
1477       if (TARGET_PDK_LIKE)
1478         {
1479           dbuf_printf (oBuf, "\tret #<%s\n", name);
1480           dbuf_printf (oBuf, "\tret #>%s\n", name);
1481         }
1482       else if (TARGET_IS_STM8 && FUNCPTRSIZE == 3)
1483         {
1484           _printPointerType (oBuf, name, size);
1485           dbuf_printf (oBuf, "\n");
1486         }
1487       else if (port->use_dw_for_init)
1488         {
1489           dbuf_tprintf (oBuf, "\t!dws\n", name);
1490         }
1491       else
1492         {
1493           printPointerType (oBuf, name);
1494         }
1495     }
1496   else if (size == BFUNCPTRSIZE)
1497     {
1498       _printPointerType (oBuf, name, size);
1499       dbuf_printf (oBuf, "\n");
1500     }
1501   else
1502     {
1503       wassertl (0, "Invalid function pointer size.");
1504     }
1505 
1506   return;
1507 }
1508 
1509 /*--------------------------------------------------------------------*/
1510 /* printIvalCharPtr - generates initial values for character pointers */
1511 /*--------------------------------------------------------------------*/
1512 int
printIvalCharPtr(symbol * sym,sym_link * type,value * val,struct dbuf_s * oBuf)1513 printIvalCharPtr (symbol * sym, sym_link * type, value * val, struct dbuf_s *oBuf)
1514 {
1515   int size = 0;
1516   char *p;
1517 
1518   if (val && !!(p = (char *) malloc (strlen (val->name) + 1)))
1519     {
1520       strcpy (p, val->name);
1521       addSet (&ccpStr, p);
1522     }
1523 
1524   /* PENDING: this is _very_ mcs51 specific, including a magic
1525      number...
1526      It's also endian specific.
1527    */
1528   size = getSize (type);
1529 
1530   if (val->name && strlen (val->name))
1531     {
1532       if (size == 1)            /* This appears to be Z80 specific?? */
1533         {
1534           dbuf_tprintf (oBuf, "\t!dbs\n", val->name);
1535         }
1536       else if (size == FARPTRSIZE)
1537         {
1538           if (TARGET_PDK_LIKE && !TARGET_IS_PDK16)
1539             {
1540               dbuf_printf (oBuf, "\tret #<%s\n", val->name);
1541               dbuf_printf (oBuf, IN_CODESPACE (SPEC_OCLS (val->etype)) ? "\tret #>(%s + 0x8000)\n" : "\tret #0\n", val->name);
1542             }
1543           else if (port->use_dw_for_init)
1544             dbuf_tprintf (oBuf, "\t!dws\n", val->name);
1545           else
1546             printPointerType (oBuf, val->name);
1547         }
1548       else if (size == GPTRSIZE)
1549         {
1550           int type;
1551           if (IS_PTR (val->type))
1552             {
1553               type = DCL_TYPE (val->type);
1554             }
1555           else
1556             {
1557               type = PTR_TYPE (SPEC_OCLS (val->etype));
1558             }
1559           if (val->sym && val->sym->isstrlit)
1560             {
1561               // this is a literal string
1562               type = CPOINTER;
1563             }
1564           printGPointerType (oBuf, val->name, sym->name, type);
1565         }
1566       else
1567         {
1568           fprintf (stderr, "*** internal error: unknown size in " "printIvalCharPtr.\n");
1569         }
1570     }
1571   else
1572     {
1573       // these are literals assigned to pointers
1574       switch (size)
1575         {
1576         case 1:
1577           dbuf_tprintf (oBuf, "\t!dbs\n", aopLiteral (val, 0));
1578           break;
1579         case 2:
1580           if (TARGET_PDK_LIKE && !TARGET_IS_PDK16)
1581             {
1582               dbuf_tprintf (oBuf, "\tret %s\n", aopLiteral (val, 0));
1583               dbuf_tprintf (oBuf, "\tret %s\n", aopLiteral (val, 1));
1584             }
1585           else if (port->use_dw_for_init)
1586             dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, size));
1587           else if (port->little_endian)
1588             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1589           else
1590             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1591           break;
1592         case 3:
1593           if (IS_GENPTR (type) && GPTRSIZE > FARPTRSIZE && floatFromVal (val) != 0)
1594             {
1595               if (!IS_PTR (val->type) && !IS_FUNC (val->type))
1596                 {
1597                   // non-zero mcs51 generic pointer
1598                   werrorfl (sym->fileDef, sym->lineDef, W_LITERAL_GENERIC);
1599                 }
1600               if (port->little_endian)
1601                 dbuf_printf (oBuf, "\t.byte %s,%s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1), aopLiteralGptr (sym->name, val));
1602               else
1603                 dbuf_printf (oBuf, "\t.byte %s,%s,%s\n", aopLiteralGptr (sym->name, val), aopLiteral (val, 1), aopLiteral (val, 0));
1604             }
1605           else
1606             {
1607               if (port->little_endian)
1608                 dbuf_printf (oBuf, "\t.byte %s,%s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1), aopLiteral (val, 2));
1609               else
1610                 dbuf_printf (oBuf, "\t.byte %s,%s,%s\n", aopLiteral (val, 2), aopLiteral (val, 1), aopLiteral (val, 0));
1611             }
1612           break;
1613         case 4:
1614           if (IS_GENPTR (type) && GPTRSIZE > FARPTRSIZE && floatFromVal (val) != 0)
1615             {
1616               if (!IS_PTR (val->type) && !IS_FUNC (val->type))
1617                 {
1618                   // non-zero ds390 generic pointer
1619                   werrorfl (sym->fileDef, sym->lineDef, W_LITERAL_GENERIC);
1620                 }
1621               if (port->little_endian)
1622                 {
1623                   dbuf_printf (oBuf, "\t.byte %s,%s,%s", aopLiteral (val, 0), aopLiteral (val, 1), aopLiteral (val, 2));
1624                   if (IS_PTR (val->type) && !IS_GENPTR (val->type))
1625                     dbuf_tprintf (oBuf, ",!immedbyte\n", pointerTypeToGPByte (DCL_TYPE (val->type), val->name, sym->name));
1626                   else
1627                     dbuf_printf (oBuf, ",%s\n", aopLiteral (val, 3));
1628                 }
1629               else
1630                 {
1631                   if (IS_PTR (val->type) && !IS_GENPTR (val->type))
1632                     dbuf_tprintf (oBuf, "\t.byte !immedbyte\n", pointerTypeToGPByte (DCL_TYPE (val->type), val->name, sym->name));
1633                   else
1634                     dbuf_printf (oBuf, "\t.byte %s\n", aopLiteral (val, 3));
1635                   dbuf_printf (oBuf, ",%s,%s,%s", aopLiteral (val, 2), aopLiteral (val, 1), aopLiteral (val, 0));
1636                 }
1637             }
1638           else
1639             {
1640               if (port->little_endian)
1641                 {
1642                   dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
1643                                aopLiteral (val, 0), aopLiteral (val, 1), aopLiteral (val, 2), aopLiteral (val, 3));
1644                 }
1645               else
1646                 {
1647                   dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n",
1648                                aopLiteral (val, 3), aopLiteral (val, 2), aopLiteral (val, 1), aopLiteral (val, 0));
1649                 }
1650             }
1651           break;
1652         default:
1653           assert (0);
1654         }
1655     }
1656 
1657   if (!noInit && val->sym && val->sym->isstrlit && !isinSet (statsg->syms, val->sym))
1658     {
1659       addSet (&statsg->syms, val->sym);
1660     }
1661 
1662   return 1;
1663 }
1664 
1665 /*-----------------------------------------------------------------*/
1666 /* printIvalPtr - generates initial value for pointers             */
1667 /*-----------------------------------------------------------------*/
1668 void
printIvalPtr(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf)1669 printIvalPtr (symbol *sym, sym_link *type, initList *ilist, struct dbuf_s *oBuf)
1670 {
1671   value *val;
1672   int size;
1673 
1674   /* if deep then   */
1675   if (ilist && (ilist->type == INIT_DEEP))
1676     ilist = ilist->init.deep;
1677 
1678   /* function pointer     */
1679   if (IS_FUNC (type->next))
1680     {
1681       printIvalFuncPtr (type, ilist, oBuf);
1682       return;
1683     }
1684 
1685   if (!(val = initPointer (ilist, type, 1)))
1686     return;
1687 
1688   /* if character pointer */
1689   if (IS_CHAR (type->next) || IS_INT (type->next) && IS_UNSIGNED (type->next))
1690     if (printIvalCharPtr (sym, type, val, oBuf))
1691       return;
1692 
1693   /* check the type      */
1694   if (compareType (type, val->type) == 0)
1695     {
1696       assert (ilist != NULL);
1697       werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1698       printFromToType (val->type, type);
1699     }
1700 
1701   /* if val is literal */
1702   if (IS_LITERAL (val->etype))
1703     {
1704       switch (getSize (type))
1705         {
1706         case 1:
1707           dbuf_tprintf (oBuf, "\t!db !constbyte\n", (unsigned int) ulFromVal (val) & 0xff);
1708           break;
1709         case 2:
1710           if (port->use_dw_for_init)
1711             dbuf_tprintf (oBuf, "\t!dws\n", aopLiteralLong (val, 0, 2));
1712           else if (port->little_endian)
1713             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1));
1714           else
1715             dbuf_tprintf (oBuf, "\t.byte %s,%s\n", aopLiteral (val, 1), aopLiteral (val, 0));
1716           break;
1717         case 3:
1718           dbuf_printf (oBuf, "; generic printIvalPtr\n");
1719           if (port->little_endian)
1720             dbuf_printf (oBuf, "\t.byte %s,%s", aopLiteral (val, 0), aopLiteral (val, 1));
1721           else
1722             dbuf_printf (oBuf, "\t.byte %s,%s", aopLiteral (val, 1), aopLiteral (val, 0));
1723           if (IS_GENPTR (val->type))
1724             dbuf_printf (oBuf, ",%s\n", aopLiteral (val, 2));
1725           else if (IS_PTR (val->type))
1726             dbuf_tprintf (oBuf, ",!immedbyte\n", pointerTypeToGPByte (DCL_TYPE (val->type), val->name, sym->name));
1727           else
1728             dbuf_printf (oBuf, ",%s\n", aopLiteral (val, 2));
1729           break;
1730         case 4:
1731           if (TARGET_IS_DS390 || TARGET_IS_DS400)
1732             dbuf_printf (oBuf, "\t.byte %s,%s,%s,%s\n", aopLiteral (val, 0), aopLiteral (val, 1), aopLiteral (val, 2), aopLiteral (val, 3));
1733           else
1734             wassertl(0, "Printing pointer of invalid size");
1735           break;
1736        default:
1737           wassertl(0, "Printing pointer of invalid size");
1738           break;
1739         }
1740       return;
1741     }
1742 
1743   size = getSize (type);
1744 
1745   if (TARGET_PDK_LIKE && size == 2)
1746     {
1747       if (IN_CODESPACE (SPEC_OCLS (val->etype)))
1748         {
1749           dbuf_printf (oBuf, "\tret #<%s\n", val->name);
1750           dbuf_printf (oBuf, "\tret #>(%s + 0x8000)\n", val->name);
1751         }
1752       else
1753         {
1754           dbuf_printf (oBuf, "\tret #%s\n", val->name);
1755           dbuf_printf (oBuf, "\tret #0\n");
1756         }
1757     }
1758   else if (size == 1)                /* Z80 specific?? */
1759     {
1760       dbuf_tprintf (oBuf, "\t!dbs\n", val->name);
1761     }
1762   else if (size == FARPTRSIZE)
1763     {
1764       if (port->use_dw_for_init)
1765         dbuf_tprintf (oBuf, "\t!dws\n", val->name);
1766       else
1767         printPointerType (oBuf, val->name);
1768     }
1769   else if (size == GPTRSIZE)
1770     {
1771       printGPointerType (oBuf, val->name, sym->name,
1772                          (IS_PTR (val->type) ? DCL_TYPE (val->type) : PTR_TYPE (SPEC_OCLS (val->etype))));
1773     }
1774 
1775   return;
1776 }
1777 
1778 /*-----------------------------------------------------------------*/
1779 /* printIval - generates code for initial value                    */
1780 /*-----------------------------------------------------------------*/
1781 void
printIval(symbol * sym,sym_link * type,initList * ilist,struct dbuf_s * oBuf,bool check)1782 printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *oBuf, bool check)
1783 {
1784   sym_link *itype;
1785 
1786   /* Handle designated initializers */
1787   if (ilist && ilist->type==INIT_DEEP)
1788     ilist = reorderIlist (type, ilist);
1789 
1790   /* If this is a hole, substitute an appropriate initializer. */
1791   if (ilist && ilist->type == INIT_HOLE)
1792     {
1793       if (IS_AGGREGATE (type))
1794         {
1795           ilist = newiList(INIT_DEEP, NULL); /* init w/ {} */
1796         }
1797       else
1798         {
1799           ast *ast = newAst_VALUE (constVal("0"));
1800           ast = decorateType (ast, RESULT_TYPE_NONE);
1801           ilist = newiList(INIT_NODE, ast);
1802         }
1803     }
1804 
1805   /* if structure then    */
1806   if (IS_STRUCT (type))
1807     {
1808       printIvalStruct (sym, type, ilist, oBuf);
1809       return;
1810     }
1811 
1812   /* if this is an array  */
1813   if (IS_ARRAY (type))
1814     {
1815       printIvalArray (sym, type, ilist, oBuf, check);
1816       return;
1817     }
1818 
1819   if (ilist)
1820     {
1821       // not an aggregate, ilist must be a node
1822       if (ilist->type != INIT_NODE)
1823         {
1824           // or a 1-element list
1825           if (ilist->init.deep->next)
1826             {
1827               werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", sym->name);
1828             }
1829           else
1830             {
1831               ilist = ilist->init.deep;
1832             }
1833         }
1834 
1835       // and the type must match
1836       itype = ilist->init.node->ftype;
1837 
1838       if (compareType (type, itype) == 0)
1839         {
1840           // special case for literal strings
1841           if (IS_ARRAY (itype) && IS_CHAR (getSpec (itype)) &&
1842               // which are really code pointers
1843               IS_CODEPTR (type))
1844             {
1845               // no sweat
1846             }
1847           else if (IS_CODEPTR (type) && IS_FUNC (type->next))   /* function pointer */
1848             {
1849               if (ilist)
1850                 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1851               else
1852                 werror (E_INCOMPAT_TYPES);
1853               printFromToType (itype, type->next);
1854             }
1855           else
1856             {
1857               werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1858               printFromToType (itype, type);
1859             }
1860         }
1861     }
1862 
1863   /* if this is a pointer */
1864   if (IS_PTR (type))
1865     {
1866       printIvalPtr (sym, type, ilist, oBuf);
1867       return;
1868     }
1869 
1870   /* if type is SPECIFIER */
1871   if (IS_SPEC (type))
1872     {
1873       printIvalType (sym, type, ilist, oBuf);
1874       return;
1875     }
1876 }
1877 
1878 /*-----------------------------------------------------------------*/
1879 /* emitStaticSeg - emitcode for the static segment                 */
1880 /*-----------------------------------------------------------------*/
1881 void
emitStaticSeg(memmap * map,struct dbuf_s * oBuf)1882 emitStaticSeg (memmap *map, struct dbuf_s *oBuf)
1883 {
1884   symbol *sym;
1885   set *tmpSet = NULL;
1886 
1887   /* fprintf(out, "\t.area\t%s\n", map->sname); */
1888 
1889   /* eliminate redundant __str_%d (generated in stringToSymbol(), SDCCast.c) */
1890   for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1891     addSet (&tmpSet, sym);
1892 
1893   /* for all variables in this segment do */
1894   for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1895     {
1896       /* if it is "extern" then do nothing */
1897       if (IS_EXTERN (sym->etype) && !sym->ival)
1898         continue;
1899 
1900       /* eliminate redundant __str_%d (generated in stringToSymbol(), SDCCast.c) */
1901       if (!isinSet (tmpSet, sym))
1902         {
1903           const char *p;
1904           if (!ccpStr)
1905             continue;
1906           for (p = setFirstItem (ccpStr); p; p = setNextItem (ccpStr))
1907             if (strcmp (p, sym->name) == 0)
1908               break;
1909           if (!p)
1910             continue;
1911         }
1912 
1913       /* if it is not static add it to the public table */
1914       if (!IS_STATIC (sym->etype))
1915         {
1916           addSetHead (&publics, sym);
1917         }
1918 
1919       /* if it has an absolute address and no initializer */
1920       if (SPEC_ABSA (sym->etype) && !sym->ival)
1921         {
1922           if (options.debug)
1923             {
1924               emitDebugSym (oBuf, sym);
1925               dbuf_printf (oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1926             }
1927           dbuf_printf (oBuf, "%s\t=\t0x%04x\n", sym->rname, SPEC_ADDR (sym->etype));
1928         }
1929       else
1930         {
1931           int size = getSize (sym->type);
1932 
1933           if (size == 0)
1934             {
1935               werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
1936             }
1937           /* if it has an initial value */
1938           if (sym->ival)
1939             {
1940               if (SPEC_ABSA (sym->etype))
1941                 {
1942                   dbuf_tprintf (oBuf, "\t!org\n", SPEC_ADDR (sym->etype));
1943                 }
1944               if (options.debug)
1945                 {
1946                   emitDebugSym (oBuf, sym);
1947                   dbuf_printf (oBuf, " == .\n");
1948                 }
1949               dbuf_printf (oBuf, "%s:\n", sym->rname);
1950               ++noAlloc;
1951               resolveIvalSym (sym->ival, sym->type);
1952               printIval (sym, sym->type, sym->ival, oBuf, (map != xinit && map != initializer));
1953               --noAlloc;
1954               /* if sym is a simple string and sym->ival is a string,
1955                  WE don't need it anymore */
1956               if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1957                   IS_AST_SYM_VALUE (list2expr (sym->ival)) && list2val (sym->ival, TRUE)->sym->isstrlit)
1958                 {
1959                   freeStringSymbol (list2val (sym->ival, TRUE)->sym);
1960                 }
1961             }
1962           else
1963             {
1964               /* allocate space */
1965               if (options.debug)
1966                 {
1967                   emitDebugSym (oBuf, sym);
1968                   dbuf_printf (oBuf, " == .\n");
1969                 }
1970               /* special case for character strings */
1971               if (IS_ARRAY (sym->type) &&
1972                 (IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char ||
1973                  IS_INT (sym->type->next) && !IS_LONG (sym->type->next) && SPEC_CVAL (sym->etype).v_char16 ||
1974                  IS_INT (sym->type->next) && IS_LONG (sym->type->next) && SPEC_CVAL (sym->etype).v_char32))
1975                 {
1976                   if (options.const_seg)
1977                     dbuf_tprintf(&code->oBuf, "\t!area\n", options.const_seg);
1978                   dbuf_printf (oBuf, "%s:\n", sym->rname);
1979                   if (IS_CHAR (sym->type->next))
1980                     printChar (oBuf, SPEC_CVAL (sym->etype).v_char, size);
1981                   else if (IS_INT (sym->type->next) && !IS_LONG (sym->type->next))
1982                     printChar16 (oBuf, SPEC_CVAL (sym->etype).v_char16, size / 2);
1983                   else if (IS_INT (sym->type->next) && IS_LONG (sym->type->next))
1984                     printChar32 (oBuf, SPEC_CVAL (sym->etype).v_char32, size / 4);
1985                   else
1986                     wassert (0);
1987                   if (options.const_seg)
1988                     dbuf_tprintf(oBuf, "\t!areacode\n", options.code_seg);
1989                 }
1990               else
1991                 {
1992                   dbuf_printf (oBuf, "%s:\n", sym->rname);
1993                   dbuf_tprintf (oBuf, "\t!ds\n", (unsigned int) size & 0xffff);
1994                 }
1995             }
1996         }
1997     }
1998 
1999   if (tmpSet)
2000     deleteSet (&tmpSet);
2001   if (ccpStr)
2002     {
2003       char *p;
2004       for (p = setFirstItem (ccpStr); p; p = setNextItem (ccpStr))
2005         if (p)
2006           free (p);
2007       deleteSet (&ccpStr);
2008     }
2009 }
2010 
2011 /*-----------------------------------------------------------------*/
2012 /* emitMaps - emits the code for the data portion the code         */
2013 /*-----------------------------------------------------------------*/
2014 void
emitMaps(void)2015 emitMaps (void)
2016 {
2017   namedspacemap *nm;
2018   int publicsfr = TARGET_IS_MCS51 || TARGET_PDK_LIKE;      /* Ideally, this should be true for all  */
2019                                                            /* ports but let's be conservative - EEP */
2020 
2021   inInitMode++;
2022   /* no special considerations for the following
2023      data, idata & bit & xdata */
2024   emitRegularMap (data, TRUE, TRUE);
2025   emitRegularMap (initialized, TRUE, TRUE);
2026   for (nm = namedspacemaps; nm; nm = nm->next)
2027     if (nm->is_const)
2028       {
2029         dbuf_tprintf (&nm->map->oBuf, "\t!areacode\n", nm->map->sname);
2030         emitStaticSeg (nm->map, &nm->map->oBuf);
2031       }
2032     else
2033       emitRegularMap (nm->map, TRUE, TRUE);
2034   emitRegularMap (idata, TRUE, TRUE);
2035   emitRegularMap (d_abs, TRUE, TRUE);
2036   emitRegularMap (i_abs, TRUE, TRUE);
2037   emitRegularMap (bit, TRUE, TRUE);
2038   emitRegularMap (pdata, TRUE, TRUE);
2039   emitRegularMap (xdata, TRUE, TRUE);
2040   emitRegularMap (x_abs, TRUE, TRUE);
2041   if (port->genXINIT)
2042     {
2043       emitRegularMap (xidata, TRUE, TRUE);
2044     }
2045   emitRegularMap (sfr, publicsfr, FALSE);
2046   emitRegularMap (sfrbit, publicsfr, FALSE);
2047   emitRegularMap (home, TRUE, FALSE);
2048   emitRegularMap (code, TRUE, FALSE);
2049 
2050   if (options.const_seg)
2051     dbuf_tprintf (&code->oBuf, "\t!area\n", options.const_seg);
2052   emitStaticSeg (statsg, &code->oBuf);
2053 
2054   if (port->genXINIT)
2055     {
2056       dbuf_tprintf (&code->oBuf, "\t!area\n", xinit->sname);
2057       emitStaticSeg (xinit, &code->oBuf);
2058     }
2059   if (initializer)
2060     {
2061       dbuf_tprintf (&code->oBuf, "\t!area\n", initializer->sname);
2062       emitStaticSeg (initializer, &code->oBuf);
2063     }
2064   dbuf_tprintf (&code->oBuf, "\t!area\n", c_abs->sname);
2065   emitStaticSeg (c_abs, &code->oBuf);
2066   inInitMode--;
2067 }
2068 
2069 /*-----------------------------------------------------------------*/
2070 /* flushStatics - flush all currently defined statics out to file  */
2071 /*  and delete.  Temporary function                                */
2072 /*-----------------------------------------------------------------*/
2073 void
flushStatics(void)2074 flushStatics (void)
2075 {
2076   emitStaticSeg (statsg, codeOutBuf);
2077   statsg->syms = NULL;
2078 }
2079 
2080 /*-----------------------------------------------------------------*/
2081 /* createInterruptVect - creates the interrupt vector              */
2082 /*-----------------------------------------------------------------*/
2083 void
createInterruptVect(struct dbuf_s * vBuf)2084 createInterruptVect (struct dbuf_s *vBuf)
2085 {
2086   mainf = newSymbol ("main", 0);
2087   mainf->block = 0;
2088 
2089   /* only if the main function exists */
2090   if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
2091     {
2092       if (!options.cc_only && !noAssemble && !options.c1mode)
2093         werror (E_NO_MAIN);
2094       return;
2095     }
2096 
2097   /* if the main is only a prototype ie. no body then do nothing */
2098   if (!IFFUNC_HASBODY (mainf->type))
2099     {
2100       /* if ! compile only then main function should be present */
2101       if (!options.cc_only && !noAssemble)
2102         werror (E_NO_MAIN);
2103       return;
2104     }
2105 
2106   dbuf_tprintf (vBuf, "\t!areacode\n", HOME_NAME);
2107   dbuf_printf (vBuf, "__interrupt_vect:\n");
2108 
2109 
2110   if (!port->genIVT || !(port->genIVT (vBuf, interrupts, maxInterrupts)))
2111     {
2112       /* There's no such thing as a "generic" interrupt table header. */
2113       wassert (0);
2114     }
2115 }
2116 
2117 char *iComments1 = {
2118   ";--------------------------------------------------------\n"
2119   "; File Created by SDCC : free open source ANSI-C Compiler\n"
2120 };
2121 
2122 char *iComments2 = {
2123   ";--------------------------------------------------------\n"
2124 };
2125 
2126 
2127 /*-----------------------------------------------------------------*/
2128 /* initialComments - puts in some initial comments                 */
2129 /*-----------------------------------------------------------------*/
2130 void
initialComments(FILE * afile)2131 initialComments (FILE * afile)
2132 {
2133   fprintf (afile, "%s", iComments1);
2134   fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s)\n", getBuildNumber (), getBuildEnvironment ());
2135   fprintf (afile, "%s", iComments2);
2136 }
2137 
2138 /*-----------------------------------------------------------------*/
2139 /* printPublics - generates .global for publics                    */
2140 /*-----------------------------------------------------------------*/
2141 void
printPublics(FILE * afile)2142 printPublics (FILE * afile)
2143 {
2144   symbol *sym;
2145 
2146   fprintf (afile, "%s", iComments2);
2147   fprintf (afile, "; Public variables in this module\n");
2148   fprintf (afile, "%s", iComments2);
2149 
2150   for (sym = setFirstItem (publics); sym; sym = setNextItem (publics))
2151     tfprintf (afile, "\t!global\n", sym->rname);
2152 }
2153 
2154 /*-----------------------------------------------------------------*/
2155 /* printExterns - generates .global for externs                    */
2156 /*-----------------------------------------------------------------*/
2157 void
printExterns(FILE * afile)2158 printExterns (FILE * afile)
2159 {
2160   symbol *sym;
2161 
2162   fprintf (afile, "%s", iComments2);
2163   fprintf (afile, "; Externals used\n");
2164   fprintf (afile, "%s", iComments2);
2165 
2166   for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
2167     tfprintf (afile, "\t!extern\n", sym->rname);
2168 }
2169 
2170 /*-----------------------------------------------------------------*/
2171 /* emitOverlay - will emit code for the overlay stuff              */
2172 /*-----------------------------------------------------------------*/
2173 static void
emitOverlay(struct dbuf_s * aBuf)2174 emitOverlay (struct dbuf_s *aBuf)
2175 {
2176   set *ovrset;
2177 
2178   /* for each of the sets in the overlay segment do */
2179   for (ovrset = setFirstItem (ovrSetSets); ovrset; ovrset = setNextItem (ovrSetSets))
2180     {
2181       symbol *sym;
2182 
2183       if (elementsInSet (ovrset))
2184         {
2185           /* output the area information */
2186           dbuf_printf (aBuf, "\t.area\t%s\n", port->mem.overlay_name);  /* MOF */
2187         }
2188 
2189       for (sym = setFirstItem (ovrset); sym; sym = setNextItem (ovrset))
2190         {
2191           /* if extern then it is in the publics table: do nothing */
2192           if (IS_EXTERN (sym->etype))
2193             continue;
2194 
2195           /* if allocation required check is needed
2196              then check if the symbol really requires
2197              allocation only for local variables */
2198           if (!IS_AGGREGATE (sym->type) && !(sym->_isparm && !IS_REGPARM (sym->etype)) && !sym->allocreq && sym->level)
2199             continue;
2200 
2201           /* if global variable & not static or extern
2202              and addPublics allowed then add it to the public set */
2203           if ((sym->_isparm && !IS_REGPARM (sym->etype)) && !IS_STATIC (sym->etype) && !IS_STATIC (sym->localof->etype))
2204             {
2205               addSetHead (&publics, sym);
2206             }
2207 
2208           /* if extern then do nothing or is a function
2209              then do nothing */
2210           if (IS_FUNC (sym->type))
2211             continue;
2212 
2213           /* if is has an absolute address then generate
2214              an equate for this no need to allocate space */
2215           if (SPEC_ABSA (sym->etype))
2216             {
2217               /* print extra debug info if required */
2218               if (options.debug)
2219                 {
2220                   emitDebugSym (aBuf, sym);
2221                   dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
2222                 }
2223               dbuf_printf (aBuf, "%s\t=\t0x%04x\n", sym->rname, SPEC_ADDR (sym->etype));
2224             }
2225           else
2226             {
2227               int size = getSize (sym->type);
2228 
2229               if (size == 0)
2230                 {
2231                   werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
2232                 }
2233               /* print extra debug info if required */
2234               if (options.debug)
2235                 {
2236                   emitDebugSym (aBuf, sym);
2237                   dbuf_printf (aBuf, "==.\n");
2238                 }
2239 
2240               /* allocate space */
2241               dbuf_tprintf (aBuf, "!slabeldef\n", sym->rname);
2242               dbuf_tprintf (aBuf, "\t!ds\n", (unsigned int) getSize (sym->type) & 0xffff);
2243             }
2244         }
2245     }
2246 }
2247 
2248 /*-----------------------------------------------------------------*/
2249 /* glue - the final glue that hold the whole thing together        */
2250 /*-----------------------------------------------------------------*/
2251 void
glue(void)2252 glue (void)
2253 {
2254   struct dbuf_s vBuf;
2255   struct dbuf_s ovrBuf;
2256   struct dbuf_s asmFileName;
2257   FILE *asmFile;
2258   int mcs51_like;
2259   namedspacemap *nm;
2260 
2261   dbuf_init (&vBuf, 4096);
2262   dbuf_init (&ovrBuf, 4096);
2263 
2264   mcs51_like = (port->general.glue_up_main &&
2265                 (TARGET_IS_MCS51 || TARGET_IS_DS390 || TARGET_IS_DS400));
2266 
2267   /* print the global struct definitions */
2268   if (options.debug)
2269     cdbStructBlock (0);
2270 
2271   /* PENDING: this isn't the best place but it will do */
2272   if (port->general.glue_up_main)
2273     {
2274       /* create the interrupt vector table */
2275       createInterruptVect (&vBuf);
2276     }
2277 
2278   /* emit code for the all the variables declared */
2279   emitMaps ();
2280   /* do the overlay segments */
2281   emitOverlay (&ovrBuf);
2282 
2283   outputDebugSymbols ();
2284 
2285   /* now put it all together into the assembler file */
2286   /* create the assembler file name */
2287 
2288   /* -o option overrides default name? */
2289   dbuf_init (&asmFileName, PATH_MAX);
2290   if ((noAssemble || options.c1mode) && fullDstFileName)
2291     {
2292       dbuf_append_str (&asmFileName, fullDstFileName);
2293     }
2294   else
2295     {
2296       dbuf_append_str (&asmFileName, dstFileName);
2297       dbuf_append_str (&asmFileName, port->assembler.file_ext);
2298     }
2299 
2300   if (!(asmFile = fopen (dbuf_c_str (&asmFileName), "w")))
2301     {
2302       werror (E_FILE_OPEN_ERR, dbuf_c_str (&asmFileName));
2303       dbuf_destroy (&asmFileName);
2304       exit (EXIT_FAILURE);
2305     }
2306   dbuf_destroy (&asmFileName);
2307 
2308   /* initial comments */
2309   initialComments (asmFile);
2310 
2311   if (TARGET_IS_S08)
2312     fprintf (asmFile, "\t.cs08\n");
2313   else if (TARGET_IS_Z180)
2314     fprintf (asmFile, "\t.hd64\n");
2315   else if (TARGET_IS_R3KA)
2316     fprintf (asmFile, "\t.r3k\n");
2317   else if (TARGET_IS_EZ80_Z80)
2318     fprintf (asmFile, "\t.ez80\n");
2319 
2320   /* print module name */
2321   tfprintf (asmFile, "\t!module\n", moduleName);
2322   if (mcs51_like)
2323     {
2324       if(!options.noOptsdccInAsm)
2325         fprintf (asmFile, "\t.optsdcc -m%s", port->target);
2326 
2327       switch (options.model)
2328         {
2329         case MODEL_SMALL:
2330           fprintf (asmFile, " --model-small");
2331           break;
2332         case MODEL_COMPACT:
2333           fprintf (asmFile, " --model-compact");
2334           break;
2335         case MODEL_MEDIUM:
2336           fprintf (asmFile, " --model-medium");
2337           break;
2338         case MODEL_LARGE:
2339           fprintf (asmFile, " --model-large");
2340           break;
2341         case MODEL_FLAT24:
2342           fprintf (asmFile, " --model-flat24");
2343           break;
2344         case MODEL_HUGE:
2345           fprintf (asmFile, " --model-huge");
2346           break;
2347         default:
2348           break;
2349         }
2350       /*if(options.stackAuto)      fprintf (asmFile, " --stack-auto"); */
2351       if (options.useXstack)
2352         fprintf (asmFile, " --xstack");
2353       /*if(options.intlong_rent)   fprintf (asmFile, " --int-long-rent"); */
2354       /*if(options.float_rent)     fprintf (asmFile, " --float-rent"); */
2355       if (options.noRegParams)
2356         fprintf (asmFile, " --no-reg-params");
2357       if (options.parms_in_bank1)
2358         fprintf (asmFile, " --parms-in-bank1");
2359       if (options.all_callee_saves)
2360         fprintf (asmFile, " --all-callee-saves");
2361       fprintf (asmFile, "\n");
2362     }
2363   else if (!TARGET_PIC_LIKE && !options.noOptsdccInAsm)
2364     {
2365       fprintf (asmFile, "\t.optsdcc -m%s\n", port->target);
2366     }
2367 
2368   tfprintf (asmFile, "\t!fileprelude\n");
2369 
2370   /* Let the port generate any global directives, etc. */
2371   if (port->genAssemblerPreamble)
2372     {
2373       port->genAssemblerPreamble (asmFile);
2374     }
2375 
2376   /* print the global variables in this module */
2377   printPublics (asmFile);
2378   if (port->assembler.externGlobal)
2379     printExterns (asmFile);
2380 
2381   if ((mcs51_like) || (TARGET_IS_Z80 || TARGET_IS_GBZ80 || TARGET_IS_Z180 || TARGET_IS_RABBIT || TARGET_IS_EZ80_Z80) || TARGET_PDK_LIKE)  /*.p.t.20030924 need to output SFR table for Z80 as well */
2382     {
2383       /* copy the sfr segment */
2384       fprintf (asmFile, "%s", iComments2);
2385       fprintf (asmFile, "; special function registers\n");
2386       fprintf (asmFile, "%s", iComments2);
2387       dbuf_write_and_destroy (&sfr->oBuf, asmFile);
2388     }
2389 
2390   if (mcs51_like)
2391     {
2392       /* copy the sbit segment */
2393       fprintf (asmFile, "%s", iComments2);
2394       fprintf (asmFile, "; special function bits\n");
2395       fprintf (asmFile, "%s", iComments2);
2396       dbuf_write_and_destroy (&sfrbit->oBuf, asmFile);
2397 
2398       /*JCF: Create the areas for the register banks */
2399       if (RegBankUsed[0] || RegBankUsed[1] || RegBankUsed[2] || RegBankUsed[3])
2400         {
2401           fprintf (asmFile, "%s", iComments2);
2402           fprintf (asmFile, "; overlayable register banks\n");
2403           fprintf (asmFile, "%s", iComments2);
2404           if (RegBankUsed[0])
2405             fprintf (asmFile, "\t.area REG_BANK_0\t(REL,OVR,DATA)\n\t.ds 8\n");
2406           if (RegBankUsed[1] || options.parms_in_bank1)
2407             fprintf (asmFile, "\t.area REG_BANK_1\t(REL,OVR,DATA)\n\t.ds 8\n");
2408           if (RegBankUsed[2])
2409             fprintf (asmFile, "\t.area REG_BANK_2\t(REL,OVR,DATA)\n\t.ds 8\n");
2410           if (RegBankUsed[3])
2411             fprintf (asmFile, "\t.area REG_BANK_3\t(REL,OVR,DATA)\n\t.ds 8\n");
2412         }
2413       if (BitBankUsed)
2414         {
2415           fprintf (asmFile, "%s", iComments2);
2416           fprintf (asmFile, "; overlayable bit register bank\n");
2417           fprintf (asmFile, "%s", iComments2);
2418           fprintf (asmFile, "\t.area BIT_BANK\t(REL,OVR,DATA)\n");
2419           fprintf (asmFile, "bits:\n\t.ds 1\n");
2420           fprintf (asmFile, "\tb0 = bits[0]\n");
2421           fprintf (asmFile, "\tb1 = bits[1]\n");
2422           fprintf (asmFile, "\tb2 = bits[2]\n");
2423           fprintf (asmFile, "\tb3 = bits[3]\n");
2424           fprintf (asmFile, "\tb4 = bits[4]\n");
2425           fprintf (asmFile, "\tb5 = bits[5]\n");
2426           fprintf (asmFile, "\tb6 = bits[6]\n");
2427           fprintf (asmFile, "\tb7 = bits[7]\n");
2428         }
2429     }
2430 
2431   /* copy the data segment */
2432   fprintf (asmFile, "%s", iComments2);
2433   fprintf (asmFile, ";%s ram data\n", mcs51_like ? " internal" : "");
2434   fprintf (asmFile, "%s", iComments2);
2435   dbuf_write_and_destroy (&data->oBuf, asmFile);
2436 
2437   /* copy the initialized segment */
2438   if (initialized)
2439     {
2440       fprintf (asmFile, "%s", iComments2);
2441       fprintf (asmFile, ";%s ram data\n", mcs51_like ? " internal" : "");
2442       fprintf (asmFile, "%s", iComments2);
2443       dbuf_write_and_destroy (&initialized->oBuf, asmFile);
2444     }
2445 
2446   /* copy segments for named address spaces */
2447   for (nm = namedspacemaps; nm; nm = nm->next)
2448     {
2449       fprintf (asmFile, "%s", iComments2);
2450       fprintf (asmFile, "; %s %s data\n", nm->name, nm->is_const ? "rom" : "ram");
2451       fprintf (asmFile, "%s", iComments2);
2452       dbuf_write_and_destroy (&nm->map->oBuf, asmFile);
2453     }
2454 
2455   /* create the overlay segments */
2456   if (overlay)
2457     {
2458       fprintf (asmFile, "%s", iComments2);
2459       fprintf (asmFile, "; overlayable items in%s ram \n", mcs51_like ? " internal" : "");
2460       fprintf (asmFile, "%s", iComments2);
2461       dbuf_write_and_destroy (&ovrBuf, asmFile);
2462     }
2463 
2464   /* create the stack segment MOF */
2465   if (mainf && IFFUNC_HASBODY (mainf->type))
2466     {
2467       fprintf (asmFile, "%s", iComments2);
2468       fprintf (asmFile, "; Stack segment in internal ram \n");
2469       fprintf (asmFile, "%s", iComments2);
2470       fprintf (asmFile, "\t.area\tSSEG\n" "__start__stack:\n\t.ds\t1\n\n");
2471     }
2472 
2473   /* create the idata segment */
2474   if (idata)
2475     {
2476       fprintf (asmFile, "%s", iComments2);
2477       fprintf (asmFile, "; indirectly addressable internal ram data\n");
2478       fprintf (asmFile, "%s", iComments2);
2479       dbuf_write_and_destroy (&idata->oBuf, asmFile);
2480     }
2481 
2482   /* create the absolute idata/data segment */
2483   if (d_abs || i_abs)
2484     {
2485       fprintf (asmFile, "%s", iComments2);
2486       fprintf (asmFile, "; absolute%s ram data\n", mcs51_like ? " internal" : "");
2487       fprintf (asmFile, "%s", iComments2);
2488       if (d_abs)
2489         dbuf_write_and_destroy (&d_abs->oBuf, asmFile);
2490       if (i_abs)
2491         dbuf_write_and_destroy (&i_abs->oBuf, asmFile);
2492     }
2493 
2494   /* copy the bit segment */
2495   if (bit)
2496     {
2497       fprintf (asmFile, "%s", iComments2);
2498       fprintf (asmFile, "; bit data\n");
2499       fprintf (asmFile, "%s", iComments2);
2500       dbuf_write_and_destroy (&bit->oBuf, asmFile);
2501     }
2502 
2503   /* copy paged external ram data */
2504   if (pdata)
2505     {
2506       fprintf (asmFile, "%s", iComments2);
2507       fprintf (asmFile, "; paged external ram data\n");
2508       fprintf (asmFile, "%s", iComments2);
2509       dbuf_write_and_destroy (&pdata->oBuf, asmFile);
2510     }
2511 
2512   /* if external stack then reserve space for it */
2513   if (mainf && IFFUNC_HASBODY (mainf->type) && options.useXstack)
2514     {
2515       fprintf (asmFile, "%s", iComments2);
2516       fprintf (asmFile, "; external stack \n");
2517       fprintf (asmFile, "%s", iComments2);
2518       fprintf (asmFile, "\t.area XSTK (PAG,XDATA)\n" "__start__xstack:\n\t.ds\t1\n\n");
2519     }
2520 
2521   /* copy external ram data */
2522   if (xdata && mcs51_like)
2523     {
2524       fprintf (asmFile, "%s", iComments2);
2525       fprintf (asmFile, "; external ram data\n");
2526       fprintf (asmFile, "%s", iComments2);
2527       dbuf_write_and_destroy (&xdata->oBuf, asmFile);
2528     }
2529 
2530   /* create the absolute xdata segment */
2531   if (x_abs)
2532     {
2533       fprintf (asmFile, "%s", iComments2);
2534       fprintf (asmFile, "; absolute external ram data\n");
2535       fprintf (asmFile, "%s", iComments2);
2536       dbuf_write_and_destroy (&x_abs->oBuf, asmFile);
2537     }
2538 
2539   /* copy external initialized ram data */
2540   if (xidata)
2541     {
2542       fprintf (asmFile, "%s", iComments2);
2543       fprintf (asmFile, "; external initialized ram data\n");
2544       fprintf (asmFile, "%s", iComments2);
2545       dbuf_write_and_destroy (&xidata->oBuf, asmFile);
2546     }
2547 
2548   /* If the port wants to generate any extra areas, let it do so. */
2549   if (port->extraAreas.genExtraAreaDeclaration)
2550     {
2551       port->extraAreas.genExtraAreaDeclaration (asmFile, mainf && IFFUNC_HASBODY (mainf->type));
2552     }
2553 
2554   /* copy the interrupt vector table */
2555   if (mainf && IFFUNC_HASBODY (mainf->type))
2556     {
2557       fprintf (asmFile, "%s", iComments2);
2558       fprintf (asmFile, "; interrupt vector \n");
2559       fprintf (asmFile, "%s", iComments2);
2560       dbuf_write_and_destroy (&vBuf, asmFile);
2561     }
2562 
2563   /* copy global & static initialisations */
2564   fprintf (asmFile, "%s", iComments2);
2565   fprintf (asmFile, "; global & static initialisations\n");
2566   fprintf (asmFile, "%s", iComments2);
2567 
2568   /* Everywhere we generate a reference to the static_name area,
2569    * (which is currently only here), we immediately follow it with a
2570    * definition of the post_static_name area. This guarantees that
2571    * the post_static_name area will immediately follow the static_name
2572    * area.
2573    */
2574   tfprintf (asmFile, "\t!area\n", port->mem.home_name);
2575   tfprintf (asmFile, "\t!area\n", port->mem.static_name);       /* MOF */
2576   tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
2577   tfprintf (asmFile, "\t!area\n", port->mem.static_name);
2578 
2579   if (mainf && IFFUNC_HASBODY (mainf->type))
2580     {
2581       if (port->genInitStartup)
2582         {
2583           port->genInitStartup (asmFile);
2584         }
2585       else
2586         {
2587           assert (0);
2588         }
2589     }
2590   dbuf_write_and_destroy (&statsg->oBuf, asmFile);
2591 
2592   /* STM8 / PDK14 note: there are no such instructions supported.
2593      Also, we don't need this logic as well. */
2594   if (port->general.glue_up_main && mainf && IFFUNC_HASBODY (mainf->type))
2595     {
2596       /* This code is generated in the post-static area.
2597        * This area is guaranteed to follow the static area
2598        * by the ugly shucking and jiving about 20 lines ago.
2599        */
2600       tfprintf (asmFile, "\t!area\n", port->mem.post_static_name);
2601       if(TARGET_IS_STM8)
2602         fprintf (asmFile, "\tjp\t__sdcc_program_startup\n");
2603       else if(TARGET_PDK_LIKE)
2604         fprintf (asmFile, "\tgoto\t__sdcc_program_startup\n");
2605       else
2606         fprintf (asmFile, "\t%cjmp\t__sdcc_program_startup\n", options.acall_ajmp ? 'a' : 'l');
2607     }
2608 
2609   fprintf (asmFile, "%s" "; Home\n" "%s", iComments2, iComments2);
2610   tfprintf (asmFile, "\t!areahome\n", HOME_NAME);
2611   dbuf_write_and_destroy (&home->oBuf, asmFile);
2612 
2613   if (mainf && IFFUNC_HASBODY (mainf->type))
2614     {
2615       /* STM8 note: there is no need to call main().
2616          Instead of that, it's address is specified in the
2617          interrupts table and always equals to 0x8080.
2618        */
2619 
2620       /* entry point @ start of HOME */
2621       fprintf (asmFile, "__sdcc_program_startup:\n");
2622 
2623       /* put in jump or call to main */
2624       if(TARGET_IS_STM8)
2625         fprintf (asmFile, options.model == MODEL_LARGE ? "\tjpf\t_main\n" : "\tjp\t_main\n");
2626       else if(TARGET_PDK_LIKE)
2627         fprintf (asmFile, "\tgoto\t_main\n");
2628       else
2629         fprintf (asmFile, "\t%cjmp\t_main\n", options.acall_ajmp ? 'a' : 'l');        /* needed? */
2630       fprintf (asmFile, ";\treturn from main will return to caller\n");
2631     }
2632   /* copy over code */
2633   fprintf (asmFile, "%s", iComments2);
2634   fprintf (asmFile, "; code\n");
2635   fprintf (asmFile, "%s", iComments2);
2636   tfprintf (asmFile, "\t!areacode\n", options.code_seg);
2637   dbuf_write_and_destroy (&code->oBuf, asmFile);
2638 
2639   if (port->genAssemblerEnd)
2640     {
2641       port->genAssemblerEnd (asmFile);
2642     }
2643   fclose (asmFile);
2644 }
2645 
2646 /* will return 1 if the string is a part
2647    of a target specific keyword */
2648 int
isTargetKeyword(const char * s)2649 isTargetKeyword (const char *s)
2650 {
2651   int i;
2652 
2653   if (port->keywords == NULL)
2654     return 0;
2655 
2656   if (s[0] == '_' && s[1] == '_')
2657     {
2658       /* Keywords in the port's array have either 0 or 1 underscore, */
2659       /* so skip over the appropriate number of chars when comparing */
2660       for (i = 0 ; port->keywords[i] ; i++ )
2661         {
2662           if (port->keywords[i][0] == '_' &&
2663               strcmp(port->keywords[i],s+1) == 0)
2664             return 1;
2665           else if (strcmp(port->keywords[i],s+2) == 0)
2666             return 1;
2667         }
2668     }
2669   else
2670     {
2671       for (i = 0 ; port->keywords[i] ; i++ )
2672         {
2673           if (strcmp(port->keywords[i],s) == 0)
2674             return 1;
2675         }
2676     }
2677 
2678   return 0;
2679 }
2680 
2681