* src/SDCCval.c (constVal): fixed bug 1305065
[fw/sdcc] / src / asm.c
index 325b28a9f60c7c434e27f0d912e71249645cc10b..6fc273a5f773ee8b79fe9f881450978cc522da37 100644 (file)
--- a/src/asm.c
+++ b/src/asm.c
@@ -11,7 +11,7 @@
 
 /* A 'token' is like !blah or %24f and is under the programmers
    control. */
-#define MAX_TOKEN_LEN          64
+#define MAX_TOKEN_LEN           64
 
 static hTab *_h;
 
@@ -27,10 +27,10 @@ FileBaseName (char *fileFullName)
   while (*fileFullName)
     {
       if ((*fileFullName == '/') || (*fileFullName == '\\') || (*fileFullName == ':'))
-       {
-         p = fileFullName;
-         p++;
-       }
+        {
+          p = fileFullName;
+          p++;
+        }
       fileFullName++;
     }
   return p;
@@ -45,15 +45,16 @@ _findMapping (const char *szKey)
 // Append a string onto another, and update the pointer to the end of
 // the new string.
 static char *
-_appendAt (char *at, char *onto, const char *sz)
+_appendAt (char *at, char *onto, const char *sz, size_t *max)
 {
   wassert (at && onto && sz);
-  strcpy (at, sz);
-  return at + strlen (sz);
+  strncpyz (at, sz, *max);
+  *max -= strlen (at);
+  return at + strlen (at);
 }
 
-void 
-tvsprintf (char *buffer, const char *format, va_list ap)
+void
+tvsprintf (char *buffer, size_t len, const char *format, va_list ap)
 {
   // Under Linux PPC va_list is a structure instead of a primitive type,
   // and doesnt like being passed around.  This version turns everything
@@ -66,129 +67,172 @@ tvsprintf (char *buffer, const char *format, va_list ap)
 
   // This is acheived by expanding the tokens and zero arg formats into
   // one big format string, which is passed to the native printf.
-  static int count;
-  char noTokens[INITIAL_INLINEASM];
-  char newFormat[INITIAL_INLINEASM];
-  char *pInto = noTokens;
-  char *p;
-  char token[MAX_TOKEN_LEN];
-  const char *sz = format;
+  static int    count;
+  char          noTokens[INITIAL_INLINEASM];
+  char          newFormat[INITIAL_INLINEASM];
+  char          *pInto = noTokens;
+  size_t        pIntoLen = sizeof(noTokens);
+  char          *p;
+  char          token[MAX_TOKEN_LEN];
+  const char    *sz = format;
 
   // NULL terminate it to let strlen work.
   *pInto = '\0';
 
   /* First pass: expand all of the macros */
-  while (*sz)
+  while (pIntoLen && *sz)
     {
       if (*sz == '!')
-       {
-         /* Start of a token.  Search until the first
-            [non alpha, *] and call it a token. */
-         const char *t;
-         p = token;
-         sz++;
-         while (isalpha (*sz) || *sz == '*')
-           {
-             *p++ = *sz++;
-           }
-         *p = '\0';
-         /* Now find the token in the token list */
-         if ((t = _findMapping (token)))
-           {
-             pInto = _appendAt (pInto, noTokens, t);
-           }
-         else
-           {
-             fprintf (stderr, "Cant find token \"%s\"\n", token);
-             wassert (0);
-           }
-       }
+        {
+          /* Start of a token.  Search until the first
+             [non alpha, *] and call it a token. */
+          const char *t;
+          p = token;
+          sz++;
+          while (isalpha ((unsigned char)*sz) || *sz == '*')
+            {
+              *p++ = *sz++;
+            }
+          *p = '\0';
+          /* Now find the token in the token list */
+          if ((t = _findMapping (token)))
+            {
+              pInto = _appendAt (pInto, noTokens, t, &pIntoLen);
+            }
+          else
+            {
+              fprintf (stderr, "Cant find token \"%s\"\n", token);
+              wassert (0);
+            }
+        }
       else
         {
           *pInto++ = *sz++;
+          pIntoLen--;
         }
     }
 
+  if (!pIntoLen)
+  {
+      fprintf(stderr,
+                "Internal error: tvsprintf overflowed on pass one.\n");
+      // Might as well go on...
+  }
+
   *pInto = '\0';
 
   /* Second pass: Expand any macros that we own */
   sz = noTokens;
   pInto = newFormat;
+  pIntoLen = sizeof(newFormat);
 
-  while (*sz)
+  while (pIntoLen && *sz)
     {
       if (*sz == '%')
-       {
-         // See if its one that we handle.
-         sz++;
-         switch (*sz)
-           {
-           case 'C':
-             // Code segment name.
-             pInto = _appendAt (pInto, newFormat, CODE_NAME);
+        {
+          // See if its one that we handle.
+          sz++;
+          switch (*sz)
+            {
+            case 'C':
+              // Code segment name.
+              pInto = _appendAt (pInto, newFormat, CODE_NAME, &pIntoLen);
               sz++;
-             break;
-           case 'F':
-             // Source file name.
-             pInto = _appendAt (pInto, newFormat, srcFileName);
+              break;
+            case 'F':
+              // Source file name.
+              pInto = _appendAt (pInto, newFormat, fullSrcFileName, &pIntoLen);
               sz++;
-             break;
+              break;
             case 'N':
               // Current function name.
-              pInto = _appendAt (pInto, newFormat, currFunc->rname);
+              pInto = _appendAt (pInto, newFormat, currFunc->rname, &pIntoLen);
               sz++;
               break;
-           case 'I':
-             {
-               // Unique ID.
-               char id[20];
-               sprintf (id, "%u", ++count);
-               pInto = _appendAt (pInto, newFormat, id);
+            case 'I':
+              {
+                // Unique ID.
+                char id[20];
+                SNPRINTF (id, sizeof(id), "%u", ++count);
+                pInto = _appendAt (pInto, newFormat, id, &pIntoLen);
                 sz++;
-               break;
-             }
-           default:
-             // Not one of ours.  Copy until the end.
-             *pInto++ = '%';
-             while (!isalpha (*sz))
-               {
-                 *pInto++ = *sz++;
-               }
-             *pInto++ = *sz++;
-           }
-       }
+                break;
+              }
+            default:
+              // Not one of ours.  Copy until the end.
+              *pInto++ = '%';
+              pIntoLen--;
+              while (pIntoLen && !isalpha ((unsigned char)*sz))
+                {
+                  *pInto++ = *sz++;
+                  pIntoLen--;
+                }
+                if (pIntoLen)
+                {
+                    *pInto++ = *sz++;
+                    pIntoLen--;
+                }
+            }
+        }
       else
-       {
-         *pInto++ = *sz++;
-       }
+        {
+          *pInto++ = *sz++;
+          pIntoLen--;
+        }
     }
 
+  if (!pIntoLen)
+  {
+      fprintf(stderr,
+                "Internal error: tvsprintf overflowed on pass two.\n");
+      // Might as well go on...
+  }
+
   *pInto = '\0';
 
   // Now do the actual printing
-  vsprintf (buffer, newFormat, ap);
+#if defined(HAVE_VSNPRINTF)
+    {
+        int wrlen;
+        wrlen = vsnprintf (buffer, len, newFormat, ap);
+
+        if (wrlen < 0 || (size_t)wrlen >= len)
+        {
+            fprintf(stderr, "Internal error: tvsprintf truncated.\n");
+        }
+    }
+
+#else
+    vsprintf (buffer, newFormat, ap);
+    if (strlen(buffer) >= len)
+    {
+        fprintf(stderr, "Internal error: tvsprintf overflowed.\n");
+    }
+#endif
 }
 
-void 
+void
 tfprintf (FILE * fp, const char *szFormat,...)
 {
   va_list ap;
   char buffer[INITIAL_INLINEASM];
 
   va_start (ap, szFormat);
-  tvsprintf (buffer, szFormat, ap);
+  tvsprintf (buffer, INITIAL_INLINEASM, szFormat, ap);
+  va_end(ap);
   fputs (buffer, fp);
 }
 
-void 
-tsprintf (char *buffer, const char *szFormat,...)
+void
+tsprintf (char *buffer, size_t len, const char *szFormat,...)
 {
   va_list ap;
   va_start (ap, szFormat);
-  tvsprintf (buffer, szFormat, ap);
+  tvsprintf (buffer, len, szFormat, ap);
+  va_end(ap);
 }
 
-void 
+void
 asm_addTree (const ASM_MAPPINGS * pMappings)
 {
   const ASM_MAPPING *pMap;
@@ -204,26 +248,82 @@ asm_addTree (const ASM_MAPPINGS * pMappings)
 }
 
 /*-----------------------------------------------------------------*/
-/* printCLine - try to find the c-code for this lineno             */
+/* printILine - return the readable i-code for this ic             */
+/*                                                                 */
+/* iCodePrint wants a file stream so we need a temporary file to   */
+/* fool it                                                         */
 /*-----------------------------------------------------------------*/
-static FILE *inFile=NULL;
-static char inLineString[1024];
-static int inLineNo=0;
-int rewinds=0;
+char *
+printILine (iCode *ic)
+{
+  static char verbalICode[1024];
+  FILE *tmpFile;
+  iCodeTable *icTab=getTableEntry(ic->op);
+
+  if (INLINEASM == ic->op)
+    return "inline";
+
+  tmpFile = tempfile();
+  assert(NULL != tmpFile);
+  if (NULL == tmpFile)
+    return "";  /* return empty line if temporary file creation failed */
+
+  addSetHead(&tmpfileSet, tmpFile);
+
+  /* stuff the temporary file with the readable icode */
+  icTab->iCodePrint(tmpFile, ic, icTab->printName);
+
+  /* now swallow it */
+  rewind(tmpFile);
+  fgets(verbalICode, sizeof(verbalICode), tmpFile);
+
+  /* clean up the mess, we'll return here for all icodes!!
+   * Actually the temporary file is only closed. It will be
+   * removed by rm_tmpfiles().
+   */
+  assert(!fclose(tmpFile));
+  deleteSetItem(&tmpfileSet, tmpFile);
+
+  /* kill the trailing NL */
+  if ('\n' == verbalICode[strlen(verbalICode) - 1])
+    verbalICode[strlen(verbalICode) - 1] = '\0';
+
+  /* and throw it up */
+  return verbalICode;
+}
 
-char *printCLine (char *srcFile, int lineno) {
+/*-----------------------------------------------------------------*/
+/* printCLine - return the c-code for this lineno                  */
+/*-----------------------------------------------------------------*/
+/* int rewinds=0; */
+char *
+printCLine (char *srcFile, int lineno)
+{
+  static FILE *inFile=NULL;
+  static char inLineString[1024];
+  static int inLineNo=0;
+  static char lastSrcFile[PATH_MAX];
   char *ilsP=inLineString;
+
+  if (inFile) {
+    if (strcmp (lastSrcFile, srcFile) != 0) {
+      fclose (inFile);
+      inFile = NULL;
+      inLineNo = 0;
+    }
+  }
   if (!inFile) {
     inFile=fopen(srcFile, "r");
     if (!inFile) {
       perror ("printCLine");
       exit (1);
     }
+    strncpyz (lastSrcFile, srcFile, PATH_MAX);
   }
   if (lineno<inLineNo) {
     fseek (inFile, 0, SEEK_SET);
     inLineNo=0;
-    rewinds++;
+    /* rewinds++; */
   }
   while (fgets (inLineString, 1024, inFile)) {
     inLineNo++;
@@ -233,7 +333,7 @@ char *printCLine (char *srcFile, int lineno) {
       break;
     }
   }
-  while (isspace ((int)*ilsP))
+  while (isspace ((unsigned char)*ilsP))
     ilsP++;
 
   return ilsP;
@@ -274,7 +374,7 @@ static const ASM_MAPPING _asxxxx_mapping[] =
    "; ---------------------------------"
   },
   {"functionlabeldef", "%s:"},
-  {"bankimmeds", "0    ; PENDING: bank support"},
+  {"bankimmeds", "0     ; PENDING: bank support"},
   {"los","(%s & 0xFF)"},
   {"his","(%s >> 8)"},
   {"hihis","(%s >> 16)"},
@@ -327,7 +427,7 @@ static const ASM_MAPPING _gas_mapping[] =
    "; ---------------------------------"
   },
   {"functionlabeldef", "%s:"},
-  {"bankimmeds", "0    ; PENDING: bank support"},  
+  {"bankimmeds", "0     ; PENDING: bank support"},
   {NULL, NULL}
 };
 
@@ -366,7 +466,7 @@ static const ASM_MAPPING _a390_mapping[] =
    "; ---------------------------------"
   },
   {"functionlabeldef", "%s:"},
-  {"bankimmeds", "0    ; PENDING: bank support"},  
+  {"bankimmeds", "0     ; PENDING: bank support"},
   {"los","(%s & 0FFh)"},
   {"his","((%s / 256) & 0FFh)"},
   {"hihis","((%s / 65536) & 0FFh)"},
@@ -402,10 +502,10 @@ static const ASM_MAPPING _xa_asm_mapping[] =
   {"dbs", ".db \"%s\""},
   {"dw", ".dw"},
   {"dws", ".dw %s"},
-  {"constbyte", "0%02xh"},
-  {"constword", "0%04xh"},
-  {"immedword", "#0%04Xh"},
-  {"immedbyte", "#0%02Xh"},
+  {"constbyte", "0x%02x"},
+  {"constword", "0x%04x"},
+  {"immedword", "0x%04x"},
+  {"immedbyte", "0x%02x"},
   {"hashedstr", "#%s"},
   {"lsbimmeds", "#<%s"},
   {"msbimmeds", "#>%s"},
@@ -418,7 +518,7 @@ static const ASM_MAPPING _xa_asm_mapping[] =
    "; ---------------------------------"
   },
   {"functionlabeldef", "%s:"},
-  {"bankimmeds", "0    ; PENDING: bank support"},  
+  {"bankimmeds", "0     ; PENDING: bank support"},
   {"los","(%s & 0FFh)"},
   {"his","((%s / 256) & 0FFh)"},
   {"hihis","((%s / 65536) & 0FFh)"},