* device/include/pic16/pic18f*.h: add bit aliases in INTCONbits_t
[fw/sdcc] / src / SDCCmacro.c
index c93a11bbe842f2601d8b3e38cfa8644187f4a805..73be7495cd6e2e6187c81d73f345aee22baf6330 100644 (file)
 
 #include "common.h"
 
-enum 
+enum
   {
-    MAX_STRING_LENGTH  = FILENAME_MAX,
+    MAX_STRING_LENGTH     = 2048,
     MAX_MACRO_NAME_LENGTH = 128
   };
 
 void
-_evalMacros(char *apinto, hTab *pvals, const char *pfrom)
+_evalMacros(char *apinto, hTab *pvals, const char *pfrom, size_t alen)
 {
-  bool fdidsomething = FALSE;
-  char *pinto = apinto;
+  bool  fdidsomething = FALSE;
+  char  *pinto = apinto;
+  size_t plen = alen;
+  char quote = '\0';
+
+  assert(pinto);
+  assert(pvals);
+  assert(pfrom);
+
+  while (plen > 0 && *pfrom) {
+    switch (*pfrom) {
+    case '"':
+    case '\'':
+      if (quote != '\0') {
+        /* write previous quote */
+        *pinto++ = quote;
+        --plen;
+      }
+      quote = *pfrom++;
+      break;
+
+    case '{':
+      {
+        const char *pend = ++pfrom;
+        char name[MAX_MACRO_NAME_LENGTH];
+        const char *pval;
+
+        /* Find the end of macro */
+        while (*pend && '}' != *pend) {
+          pend++;
+        }
+        if ('}' != *pend) {
+          wassertl(0, "Unterminated macro expansion");
+        }
 
-  assert(pinto && pvals && pfrom);
+        /* Pull out the macro name */
+        if (pend - pfrom >= MAX_MACRO_NAME_LENGTH) {
+          wassertl(0, "macro name too long");
+        }
 
-  while (*pfrom)
-    {
-      if (*pfrom == '{')
-        {
-          const char *pend = ++pfrom;
-          char name[MAX_MACRO_NAME_LENGTH];
-          const char *pval;
+        strncpy(name, pfrom, pend - pfrom);
+        name[pend - pfrom] = '\0';
 
-          while (*pend && *pend != '}')
-            {
-              pend++;
-            }
-          if (*pend != '}')
-            {
-              wassertl(0, "Unterminated macro expansion");
+        /* Look up the value in the hash table */
+        pval = shash_find (pvals, name);
+
+        if (NULL == pval) {
+          /* Empty macro value */
+          if ('\0' != quote) {
+            /* It was a quote */
+            if (pend[1] == quote) {
+              /* Start quote equals end quote: skip both */
+              ++pend;
             }
-          /* Pull out the macro name */
-          strncpy(name, pfrom, pend-pfrom);
-          name[pend-pfrom] = '\0';
-
-          /* Look up the value in the hash table */
-          pval = shash_find (pvals, name);
-          
-          if (pval == NULL)
-            {
-             fprintf (stderr, "Cant find macro \"%s\"\n", name);
-             wassertl (0, "Invalid macro name");
+            else {
+              /* Start quote not equals end quote: add both */
+              *pinto++ = quote;
+              --plen;
             }
-
-          /* Replace */
-          strcpy(pinto, pval);
-          pinto += strlen(pval);
-          fdidsomething = TRUE;
-
-          pfrom = pend+1;
+          }
         }
-      else
-        {
-          /* Pass through */
-          *pinto++ = *pfrom++;
+        else {
+          if ('\0' != quote) {
+            /* It was a quote, add it */
+            *pinto++ = quote;
+            --plen;
+          }
+          if (plen > 0) {
+            /* Replace macro */
+            strncpy(pinto, pval, plen);
+            pinto += strlen(pval);
+            plen -= plen > strlen(pval) ? strlen(pval) : plen;
+            fdidsomething = TRUE;
+          }
         }
+
+        quote = '\0';
+        pfrom = pend + 1;
+      }
+      break;
+
+    default:
+      if ('\0' != quote) {
+        *pinto++ = quote;
+        --plen;
+        quote = '\0';
+      }
+
+      if (plen > 0) {
+        /* Pass through */
+        *pinto++ = *pfrom++;
+        --plen;
+      }
     }
+  }
+
+  if (plen > 0 && '\0' != quote) {
+    *pinto++ = quote;
+    --plen;
+  }
+
+  if (plen <= 0) {
+    wassertl(0, "macro expansion too long");
+  }
 
   *pinto = '\0';
 
   /* If we did something then recursivly expand any expanded macros */
-  if (fdidsomething)
-    {
-      char ainto[MAX_STRING_LENGTH];
-      _evalMacros(ainto, pvals, apinto);
-      strcpy(apinto, ainto);
-    }
+  if (fdidsomething) {
+    char ainto[MAX_STRING_LENGTH];
+    _evalMacros(ainto, pvals, apinto, MAX_STRING_LENGTH);
+    strncpyz(apinto, ainto, alen);
+  }
 }
 
 char *
@@ -99,14 +155,31 @@ mvsprintf(hTab *pvals, const char *pformat, va_list ap)
   char atmp[MAX_STRING_LENGTH];
 
   /* Recursivly evaluate all the macros in the string */
-  _evalMacros(ainto, pvals, pformat);
+  _evalMacros(ainto, pvals, pformat, MAX_STRING_LENGTH);
   /* Evaluate all the arguments */
-  vsprintf(atmp, ainto, ap);
+#if defined(HAVE_VSNPRINTF)
+    if (vsnprintf(atmp, MAX_STRING_LENGTH, ainto, ap) >= MAX_STRING_LENGTH)
+    {
+        fprintf(stderr, "Internal error: mvsprintf output truncated.\n");
+    }
+#else
+    {
+        int wlen; 
+        
+        wlen = vsprintf(atmp, ainto, ap);
+        
+        if (wlen < 0 || wlen >= MAX_STRING_LENGTH)
+        {
+            wassertl(0, "mvsprintf overflowed.");
+        }
+    }
+#endif
+
   /* Recursivly evaluate any macros that were used as arguments */
-  _evalMacros(ainto, pvals, atmp);
+  _evalMacros(ainto, pvals, atmp, MAX_STRING_LENGTH);
 
   /* Return a copy of the evaluated string. */
-  return gc_strdup(ainto);
+  return Safe_strdup(ainto);
 }
 
 char *msprintf(hTab *pvals, const char *pformat, ...)
@@ -122,3 +195,19 @@ char *msprintf(hTab *pvals, const char *pformat, ...)
 
   return pret;
 }
+
+void
+mfprintf(FILE *fp, hTab *pvals, const char *pformat, ...)
+{
+  va_list ap;
+  char *p;
+
+  va_start(ap, pformat);
+
+  p = mvsprintf(pvals, pformat, ap);
+
+  va_end(ap);
+
+  fputs(p, fp);
+  Safe_free(p);
+}