* src/SDCCast.c (processParms): fixed bug #920866; decorateType() can return an optim...
[fw/sdcc] / src / asm.c
index 66e8d20195a34280569778f7b7d277b99ef9379f..9269fc7ef6a606c900212b3747bf371fc2ffa3a6 100644 (file)
--- a/src/asm.c
+++ b/src/asm.c
@@ -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)
+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,19 +67,20 @@ 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 == '!')
        {
@@ -95,7 +97,7 @@ tvsprintf (char *buffer, const char *format, va_list ap)
          /* Now find the token in the token list */
          if ((t = _findMapping (token)))
            {
-             pInto = _appendAt (pInto, noTokens, t);
+             pInto = _appendAt (pInto, noTokens, t, &pIntoLen);
            }
          else
            {
@@ -106,16 +108,25 @@ tvsprintf (char *buffer, const char *format, va_list ap)
       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 == '%')
        {
@@ -125,48 +136,79 @@ tvsprintf (char *buffer, const char *format, va_list ap)
            {
            case 'C':
              // Code segment name.
-             pInto = _appendAt (pInto, newFormat, CODE_NAME);
+             pInto = _appendAt (pInto, newFormat, CODE_NAME, &pIntoLen);
               sz++;
              break;
            case 'F':
              // Source file name.
-             pInto = _appendAt (pInto, newFormat, srcFileName);
+             pInto = _appendAt (pInto, newFormat, fullSrcFileName, &pIntoLen);
               sz++;
              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);
+               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))
+             pIntoLen--;
+             while (pIntoLen && !isalpha (*sz))
                {
                  *pInto++ = *sz++;
+                 pIntoLen--;
+               }
+               if (pIntoLen)
+               {
+                   *pInto++ = *sz++;
+                   pIntoLen--;
                }
-             *pInto++ = *sz++;
            }
        }
       else
        {
          *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 
@@ -176,16 +218,18 @@ tfprintf (FILE * fp, const char *szFormat,...)
   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,...)
+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 
@@ -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);
 
-char *printCLine (char *srcFile, int lineno) {
+  /* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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++;
@@ -402,14 +502,14 @@ 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"},
-  {"module", ".module %s"},
+  {"module", ".module %s"},
   {"global", ".globl %s"},
   {"fileprelude", ""},
   {"functionheader",