Fossil SCM
Performance optimizations in the TH1 interpreter.
Commit
b26eea7ee0ffee30020e30f9cd103f46e405db873a00d520f9767f127f99a842
Parent
70cb4fe59e8acb3…
1 file changed
+53
-40
M
src/th.c
+53
-40
| --- src/th.c | ||
| +++ src/th.c | ||
| @@ -199,59 +199,72 @@ | ||
| 199 | 199 | char *zBuf; |
| 200 | 200 | int nBuf; |
| 201 | 201 | int nBufAlloc; |
| 202 | 202 | }; |
| 203 | 203 | typedef struct Buffer Buffer; |
| 204 | -static int thBufferWrite(Th_Interp *interp, Buffer *, const char *, int); | |
| 205 | 204 | static void thBufferInit(Buffer *); |
| 206 | 205 | static void thBufferFree(Th_Interp *interp, Buffer *); |
| 207 | 206 | |
| 208 | 207 | /* |
| 209 | 208 | ** This version of memcpy() allows the first and second argument to |
| 210 | 209 | ** be NULL as long as the number of bytes to copy is zero. |
| 211 | 210 | */ |
| 212 | -static void *th_memcpy(void *dest, const void *src, size_t n){ | |
| 213 | - return n>0 ? memcpy(dest,src,n) : dest; | |
| 211 | +static void th_memcpy(void *dest, const void *src, size_t n){ | |
| 212 | + if( n>0 ) memcpy(dest,src,n); | |
| 214 | 213 | } |
| 215 | 214 | |
| 216 | 215 | /* |
| 217 | 216 | ** Append nAdd bytes of content copied from zAdd to the end of buffer |
| 218 | 217 | ** pBuffer. If there is not enough space currently allocated, resize |
| 219 | 218 | ** the allocation to make space. |
| 220 | 219 | */ |
| 221 | -static int thBufferWrite( | |
| 220 | +static void thBufferWriteResize( | |
| 221 | + Th_Interp *interp, | |
| 222 | + Buffer *pBuffer, | |
| 223 | + const char *zAdd, | |
| 224 | + int nAdd | |
| 225 | +){ | |
| 226 | + char *zNew; | |
| 227 | + int nNew = (pBuffer->nBuf+nAdd)*2+32; | |
| 228 | + zNew = (char *)Th_Malloc(interp, nNew); | |
| 229 | + th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf); | |
| 230 | + Th_Free(interp, pBuffer->zBuf); | |
| 231 | + pBuffer->nBufAlloc = nNew; | |
| 232 | + pBuffer->zBuf = zNew; | |
| 233 | + th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd); | |
| 234 | + pBuffer->nBuf += nAdd; | |
| 235 | +} | |
| 236 | +static void thBufferWriteFast( | |
| 222 | 237 | Th_Interp *interp, |
| 223 | 238 | Buffer *pBuffer, |
| 224 | 239 | const char *zAdd, |
| 225 | 240 | int nAdd |
| 226 | 241 | ){ |
| 227 | - int nReq; | |
| 228 | - | |
| 229 | - if( nAdd<0 ){ | |
| 230 | - nAdd = th_strlen(zAdd); | |
| 231 | - } | |
| 232 | - nReq = pBuffer->nBuf+nAdd+1; | |
| 233 | - | |
| 234 | - if( nReq>pBuffer->nBufAlloc ){ | |
| 235 | - char *zNew; | |
| 236 | - int nNew; | |
| 237 | - | |
| 238 | - nNew = nReq*2; | |
| 239 | - zNew = (char *)Th_Malloc(interp, nNew); | |
| 240 | - th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf); | |
| 241 | - Th_Free(interp, pBuffer->zBuf); | |
| 242 | - pBuffer->nBufAlloc = nNew; | |
| 243 | - pBuffer->zBuf = zNew; | |
| 244 | - } | |
| 245 | - | |
| 246 | - th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd); | |
| 247 | - pBuffer->nBuf += nAdd; | |
| 248 | - pBuffer->zBuf[pBuffer->nBuf] = '\0'; | |
| 249 | - | |
| 250 | - return TH_OK; | |
| 251 | -} | |
| 252 | -#define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d) | |
| 242 | + if( pBuffer->nBuf+nAdd > pBuffer->nBufAlloc ){ | |
| 243 | + thBufferWriteResize(interp, pBuffer, zAdd, nAdd); | |
| 244 | + }else{ | |
| 245 | + char *z = pBuffer->zBuf + pBuffer->nBuf; | |
| 246 | + pBuffer->nBuf += nAdd; | |
| 247 | + memcpy(z, zAdd, nAdd); | |
| 248 | + } | |
| 249 | +} | |
| 250 | +#define thBufferWrite(a,b,c,d) thBufferWriteFast(a,b,(const char *)c,d) | |
| 251 | + | |
| 252 | +/* | |
| 253 | +** Add a single character to a buffer | |
| 254 | +*/ | |
| 255 | +static void thBufferAddChar( | |
| 256 | + Th_Interp *interp, | |
| 257 | + Buffer *pBuffer, | |
| 258 | + char c | |
| 259 | +){ | |
| 260 | + if( pBuffer->nBuf+1 > pBuffer->nBufAlloc ){ | |
| 261 | + thBufferWriteResize(interp, pBuffer, &c, 1); | |
| 262 | + }else{ | |
| 263 | + pBuffer->zBuf[pBuffer->nBuf++] = c; | |
| 264 | + } | |
| 265 | +} | |
| 253 | 266 | |
| 254 | 267 | /* |
| 255 | 268 | ** Initialize the Buffer structure pointed to by pBuffer. |
| 256 | 269 | */ |
| 257 | 270 | static void thBufferInit(Buffer *pBuffer){ |
| @@ -627,11 +640,11 @@ | ||
| 627 | 640 | |
| 628 | 641 | zInner = Th_GetResult(interp, &nInner); |
| 629 | 642 | thBufferInit(&varname); |
| 630 | 643 | thBufferWrite(interp, &varname, &zWord[1], i); |
| 631 | 644 | thBufferWrite(interp, &varname, zInner, nInner); |
| 632 | - thBufferWrite(interp, &varname, ")", 1); | |
| 645 | + thBufferAddChar(interp, &varname, ')'); | |
| 633 | 646 | rc = Th_GetVar(interp, varname.zBuf, varname.nBuf); |
| 634 | 647 | thBufferFree(interp, &varname); |
| 635 | 648 | return rc; |
| 636 | 649 | } |
| 637 | 650 | } |
| @@ -689,11 +702,11 @@ | ||
| 689 | 702 | int i; |
| 690 | 703 | |
| 691 | 704 | thBufferInit(&output); |
| 692 | 705 | |
| 693 | 706 | if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){ |
| 694 | - rc = thBufferWrite(interp, &output, &zWord[1], nWord-2); | |
| 707 | + thBufferWrite(interp, &output, &zWord[1], nWord-2); | |
| 695 | 708 | }else{ |
| 696 | 709 | |
| 697 | 710 | /* If the word is surrounded by double-quotes strip these away. */ |
| 698 | 711 | if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){ |
| 699 | 712 | zWord++; |
| @@ -719,11 +732,11 @@ | ||
| 719 | 732 | if( !interp->isListMode ){ |
| 720 | 733 | xGet = thNextVarname; xSubst = thSubstVarname; |
| 721 | 734 | break; |
| 722 | 735 | } |
| 723 | 736 | default: { |
| 724 | - thBufferWrite(interp, &output, &zWord[i], 1); | |
| 737 | + thBufferAddChar(interp, &output, zWord[i]); | |
| 725 | 738 | continue; /* Go to the next iteration of the for(...) loop */ |
| 726 | 739 | } |
| 727 | 740 | } |
| 728 | 741 | |
| 729 | 742 | rc = xGet(interp, &zWord[i], nWord-i, &nGet); |
| @@ -732,11 +745,11 @@ | ||
| 732 | 745 | } |
| 733 | 746 | if( rc==TH_OK ){ |
| 734 | 747 | const char *zRes; |
| 735 | 748 | int nRes; |
| 736 | 749 | zRes = Th_GetResult(interp, &nRes); |
| 737 | - rc = thBufferWrite(interp, &output, zRes, nRes); | |
| 750 | + thBufferWrite(interp, &output, zRes, nRes); | |
| 738 | 751 | i += (nGet-1); |
| 739 | 752 | } |
| 740 | 753 | } |
| 741 | 754 | } |
| 742 | 755 | |
| @@ -830,11 +843,11 @@ | ||
| 830 | 843 | zInput = &zInput[nWord]; |
| 831 | 844 | nInput = nList-(zInput-zList); |
| 832 | 845 | if( nWord>0 ){ |
| 833 | 846 | zWord = Th_GetResult(interp, &nWord); |
| 834 | 847 | thBufferWrite(interp, &strbuf, zWord, nWord); |
| 835 | - thBufferWrite(interp, &strbuf, "\0", 1); | |
| 848 | + thBufferAddChar(interp, &strbuf, 0); | |
| 836 | 849 | thBufferWrite(interp, &lenbuf, &nWord, sizeof(int)); |
| 837 | 850 | nCount++; |
| 838 | 851 | } |
| 839 | 852 | } |
| 840 | 853 | assert((lenbuf.nBuf/sizeof(int))==nCount); |
| @@ -1734,11 +1747,11 @@ | ||
| 1734 | 1747 | |
| 1735 | 1748 | if( nElem<0 ){ |
| 1736 | 1749 | nElem = th_strlen(zElem); |
| 1737 | 1750 | } |
| 1738 | 1751 | if( output.nBuf>0 ){ |
| 1739 | - thBufferWrite(interp, &output, " ", 1); | |
| 1752 | + thBufferAddChar(interp, &output, ' '); | |
| 1740 | 1753 | } |
| 1741 | 1754 | |
| 1742 | 1755 | for(i=0; i<nElem; i++){ |
| 1743 | 1756 | char c = zElem[i]; |
| 1744 | 1757 | if( th_isspecial(c) ) hasSpecialChar = 1; |
| @@ -1746,18 +1759,18 @@ | ||
| 1746 | 1759 | if( c=='{' ) nBrace++; |
| 1747 | 1760 | if( c=='}' ) nBrace--; |
| 1748 | 1761 | } |
| 1749 | 1762 | |
| 1750 | 1763 | if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){ |
| 1751 | - thBufferWrite(interp, &output, "{", 1); | |
| 1764 | + thBufferAddChar(interp, &output, '{'); | |
| 1752 | 1765 | thBufferWrite(interp, &output, zElem, nElem); |
| 1753 | - thBufferWrite(interp, &output, "}", 1); | |
| 1766 | + thBufferAddChar(interp, &output, '}'); | |
| 1754 | 1767 | }else{ |
| 1755 | 1768 | for(i=0; i<nElem; i++){ |
| 1756 | 1769 | char c = zElem[i]; |
| 1757 | - if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1); | |
| 1758 | - thBufferWrite(interp, &output, &c, 1); | |
| 1770 | + if( th_isspecial(c) ) thBufferAddChar(interp, &output, '\\'); | |
| 1771 | + thBufferAddChar(interp, &output, c); | |
| 1759 | 1772 | } |
| 1760 | 1773 | } |
| 1761 | 1774 | |
| 1762 | 1775 | *pzList = output.zBuf; |
| 1763 | 1776 | *pnList = output.nBuf; |
| 1764 | 1777 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -199,59 +199,72 @@ | |
| 199 | char *zBuf; |
| 200 | int nBuf; |
| 201 | int nBufAlloc; |
| 202 | }; |
| 203 | typedef struct Buffer Buffer; |
| 204 | static int thBufferWrite(Th_Interp *interp, Buffer *, const char *, int); |
| 205 | static void thBufferInit(Buffer *); |
| 206 | static void thBufferFree(Th_Interp *interp, Buffer *); |
| 207 | |
| 208 | /* |
| 209 | ** This version of memcpy() allows the first and second argument to |
| 210 | ** be NULL as long as the number of bytes to copy is zero. |
| 211 | */ |
| 212 | static void *th_memcpy(void *dest, const void *src, size_t n){ |
| 213 | return n>0 ? memcpy(dest,src,n) : dest; |
| 214 | } |
| 215 | |
| 216 | /* |
| 217 | ** Append nAdd bytes of content copied from zAdd to the end of buffer |
| 218 | ** pBuffer. If there is not enough space currently allocated, resize |
| 219 | ** the allocation to make space. |
| 220 | */ |
| 221 | static int thBufferWrite( |
| 222 | Th_Interp *interp, |
| 223 | Buffer *pBuffer, |
| 224 | const char *zAdd, |
| 225 | int nAdd |
| 226 | ){ |
| 227 | int nReq; |
| 228 | |
| 229 | if( nAdd<0 ){ |
| 230 | nAdd = th_strlen(zAdd); |
| 231 | } |
| 232 | nReq = pBuffer->nBuf+nAdd+1; |
| 233 | |
| 234 | if( nReq>pBuffer->nBufAlloc ){ |
| 235 | char *zNew; |
| 236 | int nNew; |
| 237 | |
| 238 | nNew = nReq*2; |
| 239 | zNew = (char *)Th_Malloc(interp, nNew); |
| 240 | th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf); |
| 241 | Th_Free(interp, pBuffer->zBuf); |
| 242 | pBuffer->nBufAlloc = nNew; |
| 243 | pBuffer->zBuf = zNew; |
| 244 | } |
| 245 | |
| 246 | th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd); |
| 247 | pBuffer->nBuf += nAdd; |
| 248 | pBuffer->zBuf[pBuffer->nBuf] = '\0'; |
| 249 | |
| 250 | return TH_OK; |
| 251 | } |
| 252 | #define thBufferWrite(a,b,c,d) thBufferWrite(a,b,(const char *)c,d) |
| 253 | |
| 254 | /* |
| 255 | ** Initialize the Buffer structure pointed to by pBuffer. |
| 256 | */ |
| 257 | static void thBufferInit(Buffer *pBuffer){ |
| @@ -627,11 +640,11 @@ | |
| 627 | |
| 628 | zInner = Th_GetResult(interp, &nInner); |
| 629 | thBufferInit(&varname); |
| 630 | thBufferWrite(interp, &varname, &zWord[1], i); |
| 631 | thBufferWrite(interp, &varname, zInner, nInner); |
| 632 | thBufferWrite(interp, &varname, ")", 1); |
| 633 | rc = Th_GetVar(interp, varname.zBuf, varname.nBuf); |
| 634 | thBufferFree(interp, &varname); |
| 635 | return rc; |
| 636 | } |
| 637 | } |
| @@ -689,11 +702,11 @@ | |
| 689 | int i; |
| 690 | |
| 691 | thBufferInit(&output); |
| 692 | |
| 693 | if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){ |
| 694 | rc = thBufferWrite(interp, &output, &zWord[1], nWord-2); |
| 695 | }else{ |
| 696 | |
| 697 | /* If the word is surrounded by double-quotes strip these away. */ |
| 698 | if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){ |
| 699 | zWord++; |
| @@ -719,11 +732,11 @@ | |
| 719 | if( !interp->isListMode ){ |
| 720 | xGet = thNextVarname; xSubst = thSubstVarname; |
| 721 | break; |
| 722 | } |
| 723 | default: { |
| 724 | thBufferWrite(interp, &output, &zWord[i], 1); |
| 725 | continue; /* Go to the next iteration of the for(...) loop */ |
| 726 | } |
| 727 | } |
| 728 | |
| 729 | rc = xGet(interp, &zWord[i], nWord-i, &nGet); |
| @@ -732,11 +745,11 @@ | |
| 732 | } |
| 733 | if( rc==TH_OK ){ |
| 734 | const char *zRes; |
| 735 | int nRes; |
| 736 | zRes = Th_GetResult(interp, &nRes); |
| 737 | rc = thBufferWrite(interp, &output, zRes, nRes); |
| 738 | i += (nGet-1); |
| 739 | } |
| 740 | } |
| 741 | } |
| 742 | |
| @@ -830,11 +843,11 @@ | |
| 830 | zInput = &zInput[nWord]; |
| 831 | nInput = nList-(zInput-zList); |
| 832 | if( nWord>0 ){ |
| 833 | zWord = Th_GetResult(interp, &nWord); |
| 834 | thBufferWrite(interp, &strbuf, zWord, nWord); |
| 835 | thBufferWrite(interp, &strbuf, "\0", 1); |
| 836 | thBufferWrite(interp, &lenbuf, &nWord, sizeof(int)); |
| 837 | nCount++; |
| 838 | } |
| 839 | } |
| 840 | assert((lenbuf.nBuf/sizeof(int))==nCount); |
| @@ -1734,11 +1747,11 @@ | |
| 1734 | |
| 1735 | if( nElem<0 ){ |
| 1736 | nElem = th_strlen(zElem); |
| 1737 | } |
| 1738 | if( output.nBuf>0 ){ |
| 1739 | thBufferWrite(interp, &output, " ", 1); |
| 1740 | } |
| 1741 | |
| 1742 | for(i=0; i<nElem; i++){ |
| 1743 | char c = zElem[i]; |
| 1744 | if( th_isspecial(c) ) hasSpecialChar = 1; |
| @@ -1746,18 +1759,18 @@ | |
| 1746 | if( c=='{' ) nBrace++; |
| 1747 | if( c=='}' ) nBrace--; |
| 1748 | } |
| 1749 | |
| 1750 | if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){ |
| 1751 | thBufferWrite(interp, &output, "{", 1); |
| 1752 | thBufferWrite(interp, &output, zElem, nElem); |
| 1753 | thBufferWrite(interp, &output, "}", 1); |
| 1754 | }else{ |
| 1755 | for(i=0; i<nElem; i++){ |
| 1756 | char c = zElem[i]; |
| 1757 | if( th_isspecial(c) ) thBufferWrite(interp, &output, "\\", 1); |
| 1758 | thBufferWrite(interp, &output, &c, 1); |
| 1759 | } |
| 1760 | } |
| 1761 | |
| 1762 | *pzList = output.zBuf; |
| 1763 | *pnList = output.nBuf; |
| 1764 |
| --- src/th.c | |
| +++ src/th.c | |
| @@ -199,59 +199,72 @@ | |
| 199 | char *zBuf; |
| 200 | int nBuf; |
| 201 | int nBufAlloc; |
| 202 | }; |
| 203 | typedef struct Buffer Buffer; |
| 204 | static void thBufferInit(Buffer *); |
| 205 | static void thBufferFree(Th_Interp *interp, Buffer *); |
| 206 | |
| 207 | /* |
| 208 | ** This version of memcpy() allows the first and second argument to |
| 209 | ** be NULL as long as the number of bytes to copy is zero. |
| 210 | */ |
| 211 | static void th_memcpy(void *dest, const void *src, size_t n){ |
| 212 | if( n>0 ) memcpy(dest,src,n); |
| 213 | } |
| 214 | |
| 215 | /* |
| 216 | ** Append nAdd bytes of content copied from zAdd to the end of buffer |
| 217 | ** pBuffer. If there is not enough space currently allocated, resize |
| 218 | ** the allocation to make space. |
| 219 | */ |
| 220 | static void thBufferWriteResize( |
| 221 | Th_Interp *interp, |
| 222 | Buffer *pBuffer, |
| 223 | const char *zAdd, |
| 224 | int nAdd |
| 225 | ){ |
| 226 | char *zNew; |
| 227 | int nNew = (pBuffer->nBuf+nAdd)*2+32; |
| 228 | zNew = (char *)Th_Malloc(interp, nNew); |
| 229 | th_memcpy(zNew, pBuffer->zBuf, pBuffer->nBuf); |
| 230 | Th_Free(interp, pBuffer->zBuf); |
| 231 | pBuffer->nBufAlloc = nNew; |
| 232 | pBuffer->zBuf = zNew; |
| 233 | th_memcpy(&pBuffer->zBuf[pBuffer->nBuf], zAdd, nAdd); |
| 234 | pBuffer->nBuf += nAdd; |
| 235 | } |
| 236 | static void thBufferWriteFast( |
| 237 | Th_Interp *interp, |
| 238 | Buffer *pBuffer, |
| 239 | const char *zAdd, |
| 240 | int nAdd |
| 241 | ){ |
| 242 | if( pBuffer->nBuf+nAdd > pBuffer->nBufAlloc ){ |
| 243 | thBufferWriteResize(interp, pBuffer, zAdd, nAdd); |
| 244 | }else{ |
| 245 | char *z = pBuffer->zBuf + pBuffer->nBuf; |
| 246 | pBuffer->nBuf += nAdd; |
| 247 | memcpy(z, zAdd, nAdd); |
| 248 | } |
| 249 | } |
| 250 | #define thBufferWrite(a,b,c,d) thBufferWriteFast(a,b,(const char *)c,d) |
| 251 | |
| 252 | /* |
| 253 | ** Add a single character to a buffer |
| 254 | */ |
| 255 | static void thBufferAddChar( |
| 256 | Th_Interp *interp, |
| 257 | Buffer *pBuffer, |
| 258 | char c |
| 259 | ){ |
| 260 | if( pBuffer->nBuf+1 > pBuffer->nBufAlloc ){ |
| 261 | thBufferWriteResize(interp, pBuffer, &c, 1); |
| 262 | }else{ |
| 263 | pBuffer->zBuf[pBuffer->nBuf++] = c; |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | /* |
| 268 | ** Initialize the Buffer structure pointed to by pBuffer. |
| 269 | */ |
| 270 | static void thBufferInit(Buffer *pBuffer){ |
| @@ -627,11 +640,11 @@ | |
| 640 | |
| 641 | zInner = Th_GetResult(interp, &nInner); |
| 642 | thBufferInit(&varname); |
| 643 | thBufferWrite(interp, &varname, &zWord[1], i); |
| 644 | thBufferWrite(interp, &varname, zInner, nInner); |
| 645 | thBufferAddChar(interp, &varname, ')'); |
| 646 | rc = Th_GetVar(interp, varname.zBuf, varname.nBuf); |
| 647 | thBufferFree(interp, &varname); |
| 648 | return rc; |
| 649 | } |
| 650 | } |
| @@ -689,11 +702,11 @@ | |
| 702 | int i; |
| 703 | |
| 704 | thBufferInit(&output); |
| 705 | |
| 706 | if( nWord>1 && (zWord[0]=='{' && zWord[nWord-1]=='}') ){ |
| 707 | thBufferWrite(interp, &output, &zWord[1], nWord-2); |
| 708 | }else{ |
| 709 | |
| 710 | /* If the word is surrounded by double-quotes strip these away. */ |
| 711 | if( nWord>1 && (zWord[0]=='"' && zWord[nWord-1]=='"') ){ |
| 712 | zWord++; |
| @@ -719,11 +732,11 @@ | |
| 732 | if( !interp->isListMode ){ |
| 733 | xGet = thNextVarname; xSubst = thSubstVarname; |
| 734 | break; |
| 735 | } |
| 736 | default: { |
| 737 | thBufferAddChar(interp, &output, zWord[i]); |
| 738 | continue; /* Go to the next iteration of the for(...) loop */ |
| 739 | } |
| 740 | } |
| 741 | |
| 742 | rc = xGet(interp, &zWord[i], nWord-i, &nGet); |
| @@ -732,11 +745,11 @@ | |
| 745 | } |
| 746 | if( rc==TH_OK ){ |
| 747 | const char *zRes; |
| 748 | int nRes; |
| 749 | zRes = Th_GetResult(interp, &nRes); |
| 750 | thBufferWrite(interp, &output, zRes, nRes); |
| 751 | i += (nGet-1); |
| 752 | } |
| 753 | } |
| 754 | } |
| 755 | |
| @@ -830,11 +843,11 @@ | |
| 843 | zInput = &zInput[nWord]; |
| 844 | nInput = nList-(zInput-zList); |
| 845 | if( nWord>0 ){ |
| 846 | zWord = Th_GetResult(interp, &nWord); |
| 847 | thBufferWrite(interp, &strbuf, zWord, nWord); |
| 848 | thBufferAddChar(interp, &strbuf, 0); |
| 849 | thBufferWrite(interp, &lenbuf, &nWord, sizeof(int)); |
| 850 | nCount++; |
| 851 | } |
| 852 | } |
| 853 | assert((lenbuf.nBuf/sizeof(int))==nCount); |
| @@ -1734,11 +1747,11 @@ | |
| 1747 | |
| 1748 | if( nElem<0 ){ |
| 1749 | nElem = th_strlen(zElem); |
| 1750 | } |
| 1751 | if( output.nBuf>0 ){ |
| 1752 | thBufferAddChar(interp, &output, ' '); |
| 1753 | } |
| 1754 | |
| 1755 | for(i=0; i<nElem; i++){ |
| 1756 | char c = zElem[i]; |
| 1757 | if( th_isspecial(c) ) hasSpecialChar = 1; |
| @@ -1746,18 +1759,18 @@ | |
| 1759 | if( c=='{' ) nBrace++; |
| 1760 | if( c=='}' ) nBrace--; |
| 1761 | } |
| 1762 | |
| 1763 | if( nElem==0 || (!hasEscapeChar && hasSpecialChar && nBrace==0) ){ |
| 1764 | thBufferAddChar(interp, &output, '{'); |
| 1765 | thBufferWrite(interp, &output, zElem, nElem); |
| 1766 | thBufferAddChar(interp, &output, '}'); |
| 1767 | }else{ |
| 1768 | for(i=0; i<nElem; i++){ |
| 1769 | char c = zElem[i]; |
| 1770 | if( th_isspecial(c) ) thBufferAddChar(interp, &output, '\\'); |
| 1771 | thBufferAddChar(interp, &output, c); |
| 1772 | } |
| 1773 | } |
| 1774 | |
| 1775 | *pzList = output.zBuf; |
| 1776 | *pnList = output.nBuf; |
| 1777 |