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