Oops
[fw/sdcc] / src / asm.c
index 325b28a9f60c7c434e27f0d912e71249645cc10b..1ab5c5275e169fb8296d0fb85216eadc8dd70684 100644 (file)
--- a/src/asm.c
+++ b/src/asm.c
@@ -9,6 +9,15 @@
 #include "common.h"
 #include "asm.h"
 
+#ifdef _WIN32
+   // for O_BINARY in _pipe()
+#  include <fcntl.h>
+#  include <io.h>
+#else
+   // for pipe and close
+#  include <unistd.h>
+#endif
+
 /* A 'token' is like !blah or %24f and is under the programmers
    control. */
 #define MAX_TOKEN_LEN          64
@@ -45,15 +54,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 +76,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 +106,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 +117,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 +145,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 || 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 +227,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,21 +257,70 @@ 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 pipe to fool it     */
+/*-----------------------------------------------------------------*/
+static char verbalICode[1024];
+
+char *printILine (iCode *ic) {
+  int filedes[2];
+  FILE *pipeStream;
+  iCodeTable *icTab=getTableEntry(ic->op);
+  int res;
+
+#ifdef _WIN32
+  res = _pipe(filedes, 256, O_BINARY);
+#else
+  res = pipe(filedes);
+#endif
+  assert(res != -1); // forget it
+  if (res == -1)
+    return "";  // return empty line if pipe creation failed
+
+  // stuff the pipe with the readable icode
+  pipeStream=fdopen(filedes[1],"w");
+  icTab->iCodePrint(pipeStream, ic, icTab->printName);
+  // it really needs an extra push
+  fflush(pipeStream);
+  // now swallow it
+  pipeStream=fdopen(filedes[0],"r");
+  fgets(verbalICode, sizeof(verbalICode), pipeStream);
+  // clean up the mess, we'll return here for all icodes!!
+  assert(!close (filedes[0]));
+  assert(!close (filedes[1]));
+  // kill the trailing NL
+  verbalICode[strlen(verbalICode)-1]='\0';
+  // and throw it up
+  return verbalICode;
+}
+
+/*-----------------------------------------------------------------*/
+/* printCLine - return the c-code for this lineno                  */
 /*-----------------------------------------------------------------*/
 static FILE *inFile=NULL;
 static char inLineString[1024];
 static int inLineNo=0;
+static char lastSrcFile[PATH_MAX];
 int rewinds=0;
 
 char *printCLine (char *srcFile, int lineno) {
   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);
@@ -402,10 +504,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"},