* doc/Makefile,
[fw/sdcc] / src / asm.c
index b22d352e269232a584926633aa9f1c73e3133afe..9269fc7ef6a606c900212b3747bf371fc2ffa3a6 100644 (file)
--- a/src/asm.c
+++ b/src/asm.c
@@ -9,14 +9,6 @@
 #include "common.h"
 #include "asm.h"
 
-#if defined __MINGW32__
-   // for O_BINARY in _pipe()
-#  include <fcntl.h>
-#elif !defined(__BORLANDC__) && !defined(_MSC_VER)
-   // 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
@@ -53,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
@@ -74,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 == '!')
        {
@@ -103,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
            {
@@ -114,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 == '%')
        {
@@ -133,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, fullSrcFileName);
+             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 
@@ -184,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 
@@ -214,48 +250,59 @@ asm_addTree (const ASM_MAPPINGS * pMappings)
 /*-----------------------------------------------------------------*/
 /* printILine - return the readable i-code for this ic             */
 /*                                                                 */
-/* iCodePrint wants a file stream so we need a pipe to fool it     */
+/* iCodePrint wants a file stream so we need a temporary file to   */
+/* fool it                                                         */
 /*-----------------------------------------------------------------*/
-static char verbalICode[1024];
-
-char *printILine (iCode *ic) {
-  int filedes[2];
-  FILE *pipeStream;
+char *
+printILine (iCode *ic)
+{
+  static char verbalICode[1024];
+  FILE *tmpFile;
   iCodeTable *icTab=getTableEntry(ic->op);
-  
-#if defined __MINGW32__
-  assert(_pipe(filedes, 256, O_BINARY)!=-1); // forget it
-#else
-  assert(pipe(filedes)!=-1); // forget it
-#endif
-
-  // 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
+
+  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;
 }
 
 /*-----------------------------------------------------------------*/
 /* 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) {
+/* 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) {
@@ -271,12 +318,12 @@ char *printCLine (char *srcFile, int lineno) {
       perror ("printCLine");
       exit (1);
     }
-    strcpy (lastSrcFile, srcFile);
+    strncpyz (lastSrcFile, srcFile, PATH_MAX);
   }
   if (lineno<inLineNo) {
     fseek (inFile, 0, SEEK_SET);
     inLineNo=0;
-    rewinds++;
+    /* rewinds++; */
   }
   while (fgets (inLineString, 1024, inFile)) {
     inLineNo++;