* as/link/lkar.h: sgetl and sputl are independent of endianness
[fw/sdcc] / src / SDCCglue.c
index c35f114acd24e4477aa54cdc20ebf9e0b8922e91..19c452ea17571170913290e4404f3bea74cee696 100644 (file)
 
 symbol *interrupts[INTNO_MAX+1];
 
-void printIval (symbol *, sym_link *, initList *, struct dbuf_s *);
+void printIval (symbol *, sym_link *, initList *, struct dbuf_s *, bool check);
 set *publics = NULL;            /* public variables */
 set *externs = NULL;            /* Variables that are declared as extern */
 
 unsigned maxInterrupts = 0;
 int allocInfo = 1;
 symbol *mainf;
-set *pipeSet = NULL;            /* set of pipes */
-set *tmpfileSet = NULL;         /* set of tmp file created by the compiler */
-set *tmpfileNameSet = NULL;     /* All are unlinked at close. */
+int noInit = 0;                 /* no initialization */
 
-/*-----------------------------------------------------------------*/
-/* closePipes - closes all pipes created by the compiler           */
-/*-----------------------------------------------------------------*/
-DEFSETFUNC (closePipes)
-{
-  FILE *pfile = item;
-  int ret;
-
-  if (pfile) {
-    ret = pclose (pfile);
-    assert(ret != -1);
-  }
-
-  return 0;
-}
-
-/*-----------------------------------------------------------------*/
-/* closeTmpFiles - closes all tmp files created by the compiler    */
-/*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
-/*-----------------------------------------------------------------*/
-DEFSETFUNC (closeTmpFiles)
-{
-  FILE *tfile = item;
-  int ret;
-
-  if (tfile) {
-    ret = fclose (tfile);
-    assert(ret == 0);
-  }
-
-  return 0;
-}
-
-/*-----------------------------------------------------------------*/
-/* rmTmpFiles - unlinks all tmp files created by the compiler      */
-/*                 because of BRAIN DEAD MS/DOS & CYGNUS Libraries */
-/*-----------------------------------------------------------------*/
-DEFSETFUNC (rmTmpFiles)
-{
-  char *name = item;
-  int ret;
-
-  if (name) {
-      ret = remove (name);
-      assert(ret == 0);
-      Safe_free (name);
-  }
-
-  return 0;
-}
 
 char *
 aopLiteralLong (value * val, int offset, int size)
@@ -184,10 +132,9 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag)
         dbuf_tprintf (&map->oBuf, "\t!area\n", map->sname);
     }
 
-  for (sym = setFirstItem (map->syms); sym;
-       sym = setNextItem (map->syms))
+  for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
     {
-      symbol *newSym=NULL;
+      symbol *newSym = NULL;
 
       /* if extern then add it into the extern list */
       if (IS_EXTERN (sym->etype))
@@ -207,9 +154,10 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag)
 
       /* for bitvar locals and parameters */
       if (!arFlag && !sym->allocreq && sym->level
-          && !SPEC_ABSA (sym->etype)) {
-        continue;
-      }
+          && !SPEC_ABSA (sym->etype))
+        {
+          continue;
+        }
 
       /* if global variable & not static or extern
          and addPublics allowed then add it to the public set */
@@ -217,7 +165,7 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag)
            (sym->_isparm && !IS_REGPARM (sym->etype))) &&
           addPublics &&
           !IS_STATIC (sym->etype) &&
-          (IS_FUNC(sym->type) ? (sym->used || IFFUNC_HASBODY(sym->type)) : 1))
+          (IS_FUNC (sym->type) ? (sym->used || IFFUNC_HASBODY (sym->type)) : 1))
         {
           addSetHead (&publics, sym);
         }
@@ -247,95 +195,110 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag)
 
       /* if it has an initial value then do it only if
          it is a global variable */
-      if (sym->ival && sym->level == 0) {
-        if ((SPEC_OCLS(sym->etype)==xidata) && !SPEC_ABSA (sym->etype)) {
-          /* create a new "XINIT (CODE)" symbol, that will be emitted later
-             in the static seg */
-          newSym=copySymbol (sym);
-          SPEC_OCLS(newSym->etype)=xinit;
-          SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
-          SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
-          if (IS_SPEC (newSym->type))
-            SPEC_CONST (newSym->type) = 1;
-          else
-            DCL_PTR_CONST (newSym->type) = 1;
-          SPEC_STAT(newSym->etype)=1;
-          resolveIvalSym(newSym->ival, newSym->type);
+      if (sym->ival && sym->level == 0)
+        {
+          if ((SPEC_OCLS (sym->etype) == xidata) && !SPEC_ABSA (sym->etype))
+            {
+              /* create a new "XINIT (CODE)" symbol, that will be emitted later
+                 in the static seg */
+              newSym=copySymbol (sym);
+              SPEC_OCLS(newSym->etype)=xinit;
+              SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
+              SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
+              if (IS_SPEC (newSym->type))
+                SPEC_CONST (newSym->type) = 1;
+              else
+                DCL_PTR_CONST (newSym->type) = 1;
+              SPEC_STAT(newSym->etype)=1;
+              resolveIvalSym(newSym->ival, newSym->type);
 
-          // add it to the "XINIT (CODE)" segment
-          addSet(&xinit->syms, newSym);
+              // add it to the "XINIT (CODE)" segment
+              addSet(&xinit->syms, newSym);
 
-          if (!SPEC_ABSA (sym->etype))
+              if (!SPEC_ABSA (sym->etype))
+                {
+                  struct dbuf_s tmpBuf;
+
+                  dbuf_init(&tmpBuf, 4096);
+                  // before allocation we must parse the sym->ival tree
+                  // but without actually generating initialization code
+                  ++noAlloc;
+                  resolveIvalSym (sym->ival, sym->type);
+                  ++noInit;
+                  printIval (sym, sym->type, sym->ival, &tmpBuf, TRUE);
+                  --noInit;
+                  --noAlloc;
+                  dbuf_destroy(&tmpBuf);
+                }
+            }
+          else
             {
-              struct dbuf_s tmpBuf;
+              if (IS_AGGREGATE (sym->type))
+                {
+                  ival = initAggregates (sym, sym->ival, NULL);
+                }
+              else
+                {
+                  if (getNelements (sym->type, sym->ival)>1)
+                    {
+                      werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar", sym->name);
+                    }
+                  ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
+                                  decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
+                }
+              codeOutBuf = &statsg->oBuf;
 
-              dbuf_init(&tmpBuf, 4096);
-              // before allocation we must parse the sym->ival tree
-              // but without actually generating initialization code
-              noAlloc++;
-              resolveIvalSym (sym->ival, sym->type);
-              printIval (sym, sym->type, sym->ival, &tmpBuf);
-              noAlloc--;
-              dbuf_destroy(&tmpBuf);
-            }
-        } else {
-          if (IS_AGGREGATE (sym->type)) {
-            ival = initAggregates (sym, sym->ival, NULL);
-          } else {
-            if (getNelements(sym->type, sym->ival)>1) {
-              werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
-                      sym->name);
-            }
-            ival = newNode ('=', newAst_VALUE (symbolVal (sym)),
-                            decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
-          }
-          codeOutBuf = &statsg->oBuf;
-
-          if (ival) {
-            // set ival's lineno to where the symbol was defined
-            setAstFileLine (ival, filename = sym->fileDef, lineno = sym->lineDef);
-            // check if this is not a constant expression
-            if (!constExprTree(ival)) {
-              werror (E_CONST_EXPECTED, "found expression");
-              // but try to do it anyway
+              if (ival)
+                {
+                  // set ival's lineno to where the symbol was defined
+                  setAstFileLine (ival, filename = sym->fileDef, lineno = sym->lineDef);
+                  // check if this is not a constant expression
+                  if (!constExprTree (ival))
+                    {
+                      werror (E_CONST_EXPECTED, "found expression");
+                    // but try to do it anyway
+                    }
+                  allocInfo = 0;
+                  if (!astErrors (ival))
+                    eBBlockFromiCode (iCodeFromAst (ival));
+                  allocInfo = 1;
+                }
             }
-            allocInfo = 0;
-            if (!astErrors(ival))
-              eBBlockFromiCode (iCodeFromAst (ival));
-            allocInfo = 1;
-          }
         }
-      }
 
       /* if it has an absolute address then generate
          an equate for this no need to allocate space */
       if (SPEC_ABSA (sym->etype) && !sym->ival)
         {
-          char *equ="=";
+          char *equ = "=";
           if (options.debug) {
             dbuf_printf (&map->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
           }
-          if (TARGET_IS_XA51) {
-            if (map==sfr) {
-              equ="sfr";
-            } else if (map==bit || map==sfrbit) {
-              equ="bit";
+          if (TARGET_IS_XA51)
+            {
+              if (map == sfr)
+                {
+                  equ = "sfr";
+                }
+              else if (map == bit || map == sfrbit)
+                {
+                  equ="bit";
+                }
             }
-          }
-          dbuf_printf (&map->oBuf, "%s\t%s\t0x%04x\n",
-                   sym->rname, equ,
-                   SPEC_ADDR (sym->etype));
+          dbuf_printf (&map->oBuf, "%s\t%s\t0x%04x\n", sym->rname, equ, SPEC_ADDR (sym->etype));
         }
       else
         {
           int size = getSize (sym->type) + sym->flexArrayLength;
-          if (size==0) {
-            werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
-          }
+          if (size == 0)
+            {
+              werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
+            }
           /* allocate space */
-          if (options.debug) {
-            dbuf_printf (&map->oBuf, "==.\n");
-          }
+          if (options.debug)
+            {
+              dbuf_printf (&map->oBuf, "==.\n");
+            }
           if (SPEC_ABSA (sym->etype))
             {
               dbuf_tprintf (&map->oBuf, "\t!org\n", SPEC_ADDR (sym->etype));
@@ -633,6 +596,13 @@ printIvalType (symbol *sym, sym_link * type, initList * ilist, struct dbuf_s * o
     val = constCharVal (0);
   }
 
+  /* check if the literal value is within bounds */
+  if (checkConstantRange (type, val->etype, '=', FALSE) == CCR_OVL &&
+      !options.lessPedantic)
+    {
+      werror (W_LIT_OVERFLOW);
+    }
+
   if (val->type != type) {
     val = valCastLiteral(type, floatFromVal(val));
   }
@@ -676,49 +646,66 @@ printIvalType (symbol *sym, sym_link * type, initList * ilist, struct dbuf_s * o
 /*-----------------------------------------------------------------*/
 /* printIvalBitFields - generate initializer for bitfields         */
 /*-----------------------------------------------------------------*/
-void printIvalBitFields(symbol **sym, initList **ilist, struct dbuf_s * oBuf)
+static void
+printIvalBitFields (symbol **sym, initList **ilist, struct dbuf_s * oBuf)
 {
-  value *val ;
   symbol *lsym = *sym;
-  initList *lilist = *ilist ;
+  initList *lilist = *ilist;
   unsigned long ival = 0;
-  int size =0;
+  int size = 0;
+
+  while (lsym)
+    {
 
+      if (0 == SPEC_BLEN (lsym->etype))
+        {
+          /* bit-field structure member with a width of 0 */
+          lsym = lsym->next;
+          break;
+        }
+      else if (!SPEC_BUNNAMED (lsym->etype))
+        {
+          /* not an unnamed bit-field structure member */
+          value *val = list2val (lilist);
+          int bit_length = SPEC_BLEN (lsym->etype);
 
-  do {
-    unsigned long i;
-    val = list2val(lilist);
-    if (size) {
-      if (SPEC_BLEN(lsym->etype) > 8) {
-        size += ((SPEC_BLEN (lsym->etype) / 8) +
-                 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
-      }
-    } else {
-      size = ((SPEC_BLEN (lsym->etype) / 8) +
-              (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
-    }
-    i = ulFromVal(val);
-    i <<= SPEC_BSTR (lsym->etype);
-    ival |= i;
-    if (! ( lsym->next &&
-          (IS_BITFIELD(lsym->next->type)) &&
-          (SPEC_BSTR(lsym->next->etype)))) break;
-    lsym = lsym->next;
-    lilist = lilist->next;
-  } while (1);
-  switch (size) {
-  case 1:
-    dbuf_tprintf (oBuf, "\t!db !constbyte\n",ival);
-    break;
+          if (size)
+            {
+              if (bit_length > 8)
+                size += (bit_length + 7) / 8;
+            }
+          else
+            size = (bit_length + 7) / 8;
 
-  case 2:
-    dbuf_tprintf (oBuf, "\t!dw !constword\n",ival);
-    break;
-  case 4: /* EEP: why is this db and not dw? */
-    dbuf_tprintf (oBuf, "\t!db  !constword,!constword\n",
-             (ival >> 8) & 0xffff, (ival & 0xffff));
-    break;
-  }
+          /* check if the literal value is within bounds */
+          if (val &&
+            checkConstantRange (lsym->etype, val->etype, '=', FALSE) == CCR_OVL &&
+            !options.lessPedantic)
+            {
+              werror (W_LIT_OVERFLOW);
+            }
+
+          ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << SPEC_BSTR (lsym->etype);
+          lilist = lilist ? lilist->next : NULL;
+        }
+      lsym = lsym->next;
+    }
+
+  switch (size)
+    {
+    case 1:
+      dbuf_tprintf (oBuf, "\t!db !constbyte\n", ival);
+      break;
+
+    case 2:
+      dbuf_tprintf (oBuf, "\t!dw !constword\n", ival);
+      break;
+
+    case 4:
+      dbuf_tprintf (oBuf, "\t!dw  !constword,!constword\n",
+        (ival >> 16) & 0xffff, (ival & 0xffff));
+      break;
+    }
   *sym = lsym;
   *ilist = lilist;
 }
@@ -726,7 +713,7 @@ void printIvalBitFields(symbol **sym, initList **ilist, struct dbuf_s * oBuf)
 /*-----------------------------------------------------------------*/
 /* printIvalStruct - generates initial value for structures        */
 /*-----------------------------------------------------------------*/
-void
+static void
 printIvalStruct (symbol * sym, sym_link * type,
                  initList * ilist, struct dbuf_s * oBuf)
 {
@@ -735,38 +722,46 @@ printIvalStruct (symbol * sym, sym_link * type,
 
   sflds = SPEC_STRUCT (type)->fields;
 
-  if (ilist) {
-    if (ilist->type != INIT_DEEP) {
-      werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
-      return;
-    }
+  if (ilist)
+    {
+      if (ilist->type != INIT_DEEP)
+        {
+          werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
+          return;
+        }
 
-    iloop = ilist->init.deep;
-  }
+      iloop = ilist->init.deep;
+    }
 
-  if (SPEC_STRUCT (type)->type == UNION) {
-    printIval (sym, sflds->type, iloop, oBuf);
-    iloop = iloop ? iloop->next : NULL;
-  } else {
-    for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
-      if (IS_BITFIELD(sflds->type)) {
-        printIvalBitFields(&sflds, &iloop, oBuf);
-      } else {
-        printIval (sym, sflds->type, iloop, oBuf);
-      }
+  if (SPEC_STRUCT (type)->type == UNION)
+    {
+      printIval (sym, sflds->type, iloop, oBuf, 1);
+      iloop = iloop ? iloop->next : NULL;
     }
-  }
-  if (iloop) {
+  else
+    {
+      while (sflds)
+        {
+          if (IS_BITFIELD (sflds->type))
+            printIvalBitFields(&sflds, &iloop, oBuf);
+          else
+            {
+              printIval (sym, sflds->type, iloop, oBuf, 1);
+              sflds = sflds->next;
+              iloop = iloop ? iloop->next : NULL;
+            }
+        }
+    }
+
+  if (iloop)
     werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
-  }
-  return;
 }
 
 /*-----------------------------------------------------------------*/
 /* printIvalChar - generates initital value for character array    */
 /*-----------------------------------------------------------------*/
 int
-printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf, char *s)
+printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf, char *s, bool check)
 {
   value *val;
   unsigned int size = DCL_ELEM (type);
@@ -788,6 +783,9 @@ printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *
                 DCL_ELEM (type) = size;
             }
 
+          if (check && DCL_ELEM (val->type) > size)
+            werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
+
           printChar (oBuf, SPEC_CVAL (val->etype).v_char, size);
 
           return 1;
@@ -805,7 +803,7 @@ printIvalChar (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s *
 /*-----------------------------------------------------------------*/
 void
 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
-                struct dbuf_s * oBuf)
+                struct dbuf_s * oBuf, bool check)
 {
   value *val;
   initList *iloop;
@@ -827,7 +825,7 @@ printIvalArray (symbol * sym, sym_link * type, initList * ilist,
       }
       if (printIvalChar (sym, type,
                          (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
-                         oBuf, SPEC_CVAL (sym->etype).v_char))
+                         oBuf, SPEC_CVAL (sym->etype).v_char, check))
         return;
     }
     /* not the special case             */
@@ -841,7 +839,7 @@ printIvalArray (symbol * sym, sym_link * type, initList * ilist,
         werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
         break;
       }
-      printIval (sym, type->next, iloop, oBuf);
+      printIval (sym, type->next, iloop, oBuf, TRUE);
     }
   }
 
@@ -1035,7 +1033,7 @@ printIvalCharPtr (symbol * sym, sym_link * type, value * val, struct dbuf_s * oB
         }
     }
 
-  if (val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
+  if (!noInit && val->sym && val->sym->isstrlit && !isinSet(statsg->syms, val->sym)) {
     addSet (&statsg->syms, val->sym);
   }
 
@@ -1142,7 +1140,7 @@ printIvalPtr (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * o
 /* printIval - generates code for initial value                    */
 /*-----------------------------------------------------------------*/
 void
-printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf)
+printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf, bool check)
 {
   sym_link *itype;
 
@@ -1156,7 +1154,7 @@ printIval (symbol * sym, sym_link * type, initList * ilist, struct dbuf_s * oBuf
   /* if this is an array   */
   if (IS_ARRAY (type))
     {
-      printIvalArray (sym, type, ilist, oBuf);
+      printIvalArray (sym, type, ilist, oBuf, check);
       return;
     }
 
@@ -1230,21 +1228,23 @@ emitStaticSeg (memmap * map, struct dbuf_s * oBuf)
         }
 
       /* print extra debug info if required */
-      if (options.debug) {
-
-        if (!sym->level)
-          {                     /* global */
-            if (IS_STATIC (sym->etype))
-              dbuf_printf (oBuf, "F%s$", moduleName);        /* scope is file */
-            else
-              dbuf_printf (oBuf, "G$");      /* scope is global */
-          }
-        else
-          /* symbol is local */
-          dbuf_printf (oBuf, "L%s$",
-                   (sym->localof ? sym->localof->name : "-null-"));
-        dbuf_printf (oBuf, "%s$%d$%d", sym->name, sym->level, sym->block);
-      }
+      if (options.debug)
+        {
+          if (!sym->level)
+            {                     /* global */
+              if (IS_STATIC (sym->etype))
+                dbuf_printf (oBuf, "F%s$", moduleName);        /* scope is file */
+              else
+                dbuf_printf (oBuf, "G$");      /* scope is global */
+            }
+          else
+            {
+              /* symbol is local */
+              dbuf_printf (oBuf, "L%s$",
+                           (sym->localof ? sym->localof->name : "-null-"));
+            }
+          dbuf_printf (oBuf, "%s$%d$%d", sym->name, sym->level, sym->block);
+        }
 
       /* if it has an absolute address and no initializer */
       if (SPEC_ABSA (sym->etype) && !sym->ival)
@@ -1271,7 +1271,7 @@ emitStaticSeg (memmap * map, struct dbuf_s * oBuf)
               dbuf_printf (oBuf, "%s:\n", sym->rname);
               ++noAlloc;
               resolveIvalSym (sym->ival, sym->type);
-              printIval (sym, sym->type, sym->ival, oBuf);
+              printIval (sym, sym->type, sym->ival, oBuf, map != xinit);
               --noAlloc;
               /* if sym is a simple string and sym->ival is a string,
                  WE don't need it anymore */
@@ -1411,7 +1411,7 @@ initialComments (FILE * afile)
   time (&t);
   fprintf (afile, "%s", iComments1);
   fprintf (afile, "; Version " SDCC_VERSION_STR " #%s (%s) (%s)\n",
-           getBuildNumber(), __DATE__, getBuildEnvironment());
+           getBuildNumber(), getBuildDate(), getBuildEnvironment());
   fprintf (afile, "; This file was generated %s", asctime (localtime (&t)));
   fprintf (afile, "%s", iComments2);
 }
@@ -1531,7 +1531,8 @@ emitOverlay (struct dbuf_s * aBuf)
                        sym->rname,
                        SPEC_ADDR (sym->etype));
             }
-          else {
+          else
+            {
               int size = getSize(sym->type);
 
               if (size==0) {