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