X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCmacro.c;h=73be7495cd6e2e6187c81d73f345aee22baf6330;hb=bb226788dab3832b0ec0cda70874ce3fce4eebc6;hp=c93a11bbe842f2601d8b3e38cfa8644187f4a805;hpb=fdc44b6814e4e6b0161c4fb8466230bf6f5e65a3;p=fw%2Fsdcc diff --git a/src/SDCCmacro.c b/src/SDCCmacro.c index c93a11bb..73be7495 100644 --- a/src/SDCCmacro.c +++ b/src/SDCCmacro.c @@ -24,72 +24,128 @@ #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); +}