Fossil SCM
Extend translator to support two- and three-argument printf specifiers, e.g. "%.*s(len)(str)" or "%*.*d(width)(prec)(val)"
Commit
df7b0c31868613c6560463e63c624ffcce54171d81041fc855752ccb6eb6a992
Parent
a8d90b1f4fe63bb…
1 file changed
+29
-18
+29
-18
| --- src/translate.c | ||
| +++ src/translate.c | ||
| @@ -155,19 +155,24 @@ | ||
| 155 | 155 | fprintf(out,"\n"); |
| 156 | 156 | }else{ |
| 157 | 157 | fprintf(out,"%*s\"%s%s\"\n",indent, "", zOut, zNewline); |
| 158 | 158 | } |
| 159 | 159 | }else{ |
| 160 | - /* Otherwise (if the last non-whitespace was not '=') then generate | |
| 161 | - ** a cgi_printf() statement whose format is the text following the '@'. | |
| 162 | - ** Substrings of the form "%C(...)" (where C is any sequence of | |
| 163 | - ** characters other than \000 and '(') will put "%C" in the | |
| 164 | - ** format and add the "(...)" as an argument to the cgi_printf call. | |
| 160 | + /* Otherwise (if the last non-whitespace was not '=') then generate a | |
| 161 | + ** cgi_printf() statement whose format is the text following the '@'. | |
| 162 | + ** Substrings of the form "%C(...)" (where C is any sequence of characters | |
| 163 | + ** other than \000 and '(') will put "%C" in the format and add the | |
| 164 | + ** "(...)" as an argument to the cgi_printf call. Each '*' character | |
| 165 | + ** present in C (max two) causes one more "(...)" sequence to be consumed. | |
| 166 | + ** For example, "%*.*d(4)(2)(1)" converts to "%*.*d" with arguments "4", | |
| 167 | + ** "2", and "1", which will be used as the field width, precision, and | |
| 168 | + ** value, respectively, producing a final formatted result of " 01". | |
| 165 | 169 | */ |
| 166 | 170 | const char *zNewline = "\\n"; |
| 167 | 171 | int indent; |
| 168 | 172 | int nC; |
| 173 | + int nParam; | |
| 169 | 174 | char c; |
| 170 | 175 | i++; |
| 171 | 176 | if( isspace(zLine[i]) ){ i++; } |
| 172 | 177 | indent = i; |
| 173 | 178 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| @@ -177,25 +182,31 @@ | ||
| 177 | 182 | break; |
| 178 | 183 | } |
| 179 | 184 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 180 | 185 | zOut[j++] = zLine[i]; |
| 181 | 186 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 182 | - for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){} | |
| 187 | + nParam=1; | |
| 188 | + for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){ | |
| 189 | + if( zLine[i+nC]=='*' && nParam < 3 ) nParam++; | |
| 190 | + } | |
| 183 | 191 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| 184 | 192 | while( --nC ) zOut[j++] = zLine[++i]; |
| 185 | - zArg[nArg++] = ','; | |
| 186 | - k = 0; i++; | |
| 187 | - while( (c = zLine[i])!=0 ){ | |
| 188 | - zArg[nArg++] = c; | |
| 189 | - if( c==')' ){ | |
| 190 | - k--; | |
| 191 | - if( k==0 ) break; | |
| 192 | - }else if( c=='(' ){ | |
| 193 | - k++; | |
| 194 | - } | |
| 195 | - i++; | |
| 196 | - } | |
| 193 | + do{ | |
| 194 | + zArg[nArg++] = ','; | |
| 195 | + k = 0; i++; | |
| 196 | + if( zLine[i]!='(' ) break; | |
| 197 | + while( (c = zLine[i])!=0 ){ | |
| 198 | + zArg[nArg++] = c; | |
| 199 | + if( c==')' ){ | |
| 200 | + k--; | |
| 201 | + if( k==0 ) break; | |
| 202 | + }else if( c=='(' ){ | |
| 203 | + k++; | |
| 204 | + } | |
| 205 | + i++; | |
| 206 | + } | |
| 207 | + }while( --nParam ); | |
| 197 | 208 | } |
| 198 | 209 | zOut[j] = 0; |
| 199 | 210 | if( !inPrint ){ |
| 200 | 211 | fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline); |
| 201 | 212 | inPrint = 1; |
| 202 | 213 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -155,19 +155,24 @@ | |
| 155 | fprintf(out,"\n"); |
| 156 | }else{ |
| 157 | fprintf(out,"%*s\"%s%s\"\n",indent, "", zOut, zNewline); |
| 158 | } |
| 159 | }else{ |
| 160 | /* Otherwise (if the last non-whitespace was not '=') then generate |
| 161 | ** a cgi_printf() statement whose format is the text following the '@'. |
| 162 | ** Substrings of the form "%C(...)" (where C is any sequence of |
| 163 | ** characters other than \000 and '(') will put "%C" in the |
| 164 | ** format and add the "(...)" as an argument to the cgi_printf call. |
| 165 | */ |
| 166 | const char *zNewline = "\\n"; |
| 167 | int indent; |
| 168 | int nC; |
| 169 | char c; |
| 170 | i++; |
| 171 | if( isspace(zLine[i]) ){ i++; } |
| 172 | indent = i; |
| 173 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| @@ -177,25 +182,31 @@ | |
| 177 | break; |
| 178 | } |
| 179 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 180 | zOut[j++] = zLine[i]; |
| 181 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 182 | for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){} |
| 183 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| 184 | while( --nC ) zOut[j++] = zLine[++i]; |
| 185 | zArg[nArg++] = ','; |
| 186 | k = 0; i++; |
| 187 | while( (c = zLine[i])!=0 ){ |
| 188 | zArg[nArg++] = c; |
| 189 | if( c==')' ){ |
| 190 | k--; |
| 191 | if( k==0 ) break; |
| 192 | }else if( c=='(' ){ |
| 193 | k++; |
| 194 | } |
| 195 | i++; |
| 196 | } |
| 197 | } |
| 198 | zOut[j] = 0; |
| 199 | if( !inPrint ){ |
| 200 | fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline); |
| 201 | inPrint = 1; |
| 202 |
| --- src/translate.c | |
| +++ src/translate.c | |
| @@ -155,19 +155,24 @@ | |
| 155 | fprintf(out,"\n"); |
| 156 | }else{ |
| 157 | fprintf(out,"%*s\"%s%s\"\n",indent, "", zOut, zNewline); |
| 158 | } |
| 159 | }else{ |
| 160 | /* Otherwise (if the last non-whitespace was not '=') then generate a |
| 161 | ** cgi_printf() statement whose format is the text following the '@'. |
| 162 | ** Substrings of the form "%C(...)" (where C is any sequence of characters |
| 163 | ** other than \000 and '(') will put "%C" in the format and add the |
| 164 | ** "(...)" as an argument to the cgi_printf call. Each '*' character |
| 165 | ** present in C (max two) causes one more "(...)" sequence to be consumed. |
| 166 | ** For example, "%*.*d(4)(2)(1)" converts to "%*.*d" with arguments "4", |
| 167 | ** "2", and "1", which will be used as the field width, precision, and |
| 168 | ** value, respectively, producing a final formatted result of " 01". |
| 169 | */ |
| 170 | const char *zNewline = "\\n"; |
| 171 | int indent; |
| 172 | int nC; |
| 173 | int nParam; |
| 174 | char c; |
| 175 | i++; |
| 176 | if( isspace(zLine[i]) ){ i++; } |
| 177 | indent = i; |
| 178 | for(j=0; zLine[i] && zLine[i]!='\r' && zLine[i]!='\n'; i++){ |
| @@ -177,25 +182,31 @@ | |
| 182 | break; |
| 183 | } |
| 184 | if( zLine[i]=='"' || zLine[i]=='\\' ){ zOut[j++] = '\\'; } |
| 185 | zOut[j++] = zLine[i]; |
| 186 | if( zLine[i]!='%' || zLine[i+1]=='%' || zLine[i+1]==0 ) continue; |
| 187 | nParam=1; |
| 188 | for(nC=1; zLine[i+nC] && zLine[i+nC]!='('; nC++){ |
| 189 | if( zLine[i+nC]=='*' && nParam < 3 ) nParam++; |
| 190 | } |
| 191 | if( zLine[i+nC]!='(' || !isalpha(zLine[i+nC-1]) ) continue; |
| 192 | while( --nC ) zOut[j++] = zLine[++i]; |
| 193 | do{ |
| 194 | zArg[nArg++] = ','; |
| 195 | k = 0; i++; |
| 196 | if( zLine[i]!='(' ) break; |
| 197 | while( (c = zLine[i])!=0 ){ |
| 198 | zArg[nArg++] = c; |
| 199 | if( c==')' ){ |
| 200 | k--; |
| 201 | if( k==0 ) break; |
| 202 | }else if( c=='(' ){ |
| 203 | k++; |
| 204 | } |
| 205 | i++; |
| 206 | } |
| 207 | }while( --nParam ); |
| 208 | } |
| 209 | zOut[j] = 0; |
| 210 | if( !inPrint ){ |
| 211 | fprintf(out,"%*scgi_printf(\"%s%s\"",indent-2,"", zOut, zNewline); |
| 212 | inPrint = 1; |
| 213 |