- Timestamp:
- Feb 1, 2015 12:44:30 AM (10 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/expand.c
r2765 r2769 212 212 213 213 #ifdef CONFIG_WITH_VALUE_LENGTH 214 /* Static worker for reference_variable()that expands the recursive214 /* Worker for reference_variable() and kmk_exec_* that expands the recursive 215 215 variable V. The main difference between this and 216 216 recursively_expand[_for_file] is that this worker avoids the temporary 217 217 buffer and outputs directly into the current variable buffer (O). */ 218 staticchar *218 char * 219 219 reference_recursive_variable (char *o, struct variable *v) 220 220 { … … 1218 1218 } 1219 1219 1220 /* Restore a previously-saved variable_buffer setting (free the current one). 1221 */ 1220 #ifdef CONFIG_WITH_COMPILER 1221 /* Same as install_variable_buffer, except we supply a size hint. */ 1222 1223 char * 1224 install_variable_buffer_with_hint (char **bufp, unsigned int *lenp, unsigned int size_hint) 1225 { 1226 struct recycled_buffer *recycled; 1227 char *buf; 1228 1229 *bufp = variable_buffer; 1230 *lenp = variable_buffer_length; 1231 1232 recycled = recycled_head; 1233 if (recycled) 1234 { 1235 recycled_head = recycled->next; 1236 variable_buffer_length = recycled->length; 1237 variable_buffer = buf = (char *)recycled; 1238 } 1239 else 1240 { 1241 if (size_hint < 512) 1242 variable_buffer_length = (size_hint + 1 + 63) & ~(unsigned int)63; 1243 else if (size_hint < 4096) 1244 variable_buffer_length = (size_hint + 1 + 1023) & ~(unsigned int)1023; 1245 else 1246 variable_buffer_length = (size_hint + 1 + 4095) & ~(unsigned int)4095; 1247 variable_buffer = buf = xmalloc (variable_buffer_length); 1248 } 1249 buf[0] = '\0'; 1250 return buf; 1251 } 1252 #endif /* CONFIG_WITH_COMPILER */ 1253 1254 /* Restore a previously-saved variable_buffer setting (free the 1255 current one). */ 1222 1256 1223 1257 void … … 1234 1268 variable_buffer_length = len; 1235 1269 } 1270 1271 1272 /* Used to make sure there is at least SIZE bytes of buffer space 1273 available starting at PTR. */ 1274 char * 1275 ensure_variable_buffer_space(char *ptr, unsigned int size) 1276 { 1277 unsigned int offset = (unsigned int)(ptr - variable_buffer); 1278 assert(offset <= variable_buffer_length); 1279 if (variable_buffer_length - offset < size) 1280 { 1281 unsigned minlen = size + offset; 1282 variable_buffer_length *= 2; 1283 if (variable_buffer_length < minlen + 100) 1284 variable_buffer_length = (minlen + 100 + 63) & ~(unsigned int)63; 1285 variable_buffer = xrealloc (variable_buffer, variable_buffer_length); 1286 ptr = variable_buffer + offset; 1287 } 1288 return ptr; 1289 } 1290 -
trunk/src/kmk/kmk_cc_exec.c
r2768 r2769 65 65 typedef KMKCCBLOCK *PKMKCCBLOCK; 66 66 67 /** Expansion instructions. */ 67 /** 68 * String expansion statistics. 69 */ 70 typedef struct KMKCCEXPSTATS 71 { 72 /** Max expanded size. */ 73 uint32_t cchMax; 74 /** Recent average size. */ 75 uint32_t cchAvg; 76 } KMKCCEXPSTATS; 77 typedef KMKCCEXPSTATS *PKMKCCEXPSTATS; 78 79 /** 80 * Expansion instructions. 81 */ 68 82 typedef enum KMKCCEXPINSTR 69 83 { … … 74 88 /** Insert an expanded variable value, the name is dynamic (sub prog). */ 75 89 kKmkCcExpInstr_DynamicVariable, 90 /** Insert an expanded variable value, which name we already know, doing 91 * search an replace on a string. */ 92 kKmkCcExpInstr_SearchAndReplacePlainVariable, 76 93 /** Insert the output of function that requires no argument expansion. */ 77 94 kKmkCcExpInstr_PlainFunction, 78 95 /** Insert the output of function that requires dynamic expansion of one ore 79 * more arguments. */96 * more arguments. (Dynamic is perhaps not such a great name, but whatever.) */ 80 97 kKmkCcExpInstr_DynamicFunction, 81 98 /** Jump to a new instruction block. */ … … 95 112 typedef KMKCCEXPCORE *PKMKCCEXPCORE; 96 113 114 /** 115 * String expansion sub program. 116 */ 97 117 typedef struct kmk_cc_exp_subprog 98 118 { 99 119 /** Pointer to the first instruction. */ 100 120 PKMKCCEXPCORE pFirstInstr; 101 /** Max expanded size. */ 102 uint32_t cbMax; 103 /** Recent average size. */ 104 uint32_t cbAvg; 121 /** Statistics. */ 122 KMKCCEXPSTATS Stats; 105 123 } KMKCCEXPSUBPROG; 106 124 typedef KMKCCEXPSUBPROG *PKMKCCEXPSUBPROG; 107 125 126 /** 127 * kKmkCcExpInstr_CopyString instruction format. 128 */ 108 129 typedef struct kmk_cc_exp_copy_string 109 130 { … … 117 138 typedef KMKCCEXPCOPYSTRING *PKMKCCEXPCOPYSTRING; 118 139 140 /** 141 * kKmkCcExpInstr_PlainVariable instruction format. 142 */ 119 143 typedef struct kmk_cc_exp_plain_variable 120 144 { 121 145 /** The core instruction. */ 122 146 KMKCCEXPCORE Core; 123 /** The variable strcache entry for this variable. */124 struct strcache2_entry const *pNameEntry;147 /** The name of the variable (points into variable_strcache). */ 148 const char *pszName; 125 149 } KMKCCEXPPLAINVAR; 126 150 typedef KMKCCEXPPLAINVAR *PKMKCCEXPPLAINVAR; 127 151 152 /** 153 * kKmkCcExpInstr_DynamicVariable instruction format. 154 */ 128 155 typedef struct kmk_cc_exp_dynamic_variable 129 156 { 130 157 /** The core instruction. */ 131 158 KMKCCEXPCORE Core; 132 /** Where to continue after this instruction. This is necessary since the 133 * subprogram is allocated after us in the instruction block. Since the sub 134 * program is of variable size, we don't even know if we're still in the same 135 * instruction block. So, we include a jump here. */ 159 /** Where to continue after this instruction. (This is necessary since the 160 * instructions of the subprogram are emitted after this instruction.) */ 136 161 PKMKCCEXPCORE pNext; 137 162 /** The subprogram that will give us the variable name. */ … … 140 165 typedef KMKCCEXPDYNVAR *PKMKCCEXPDYNVAR; 141 166 167 /** 168 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction format. 169 */ 170 typedef struct kmk_cc_exp_sr_plain_variable 171 { 172 /** The core instruction. */ 173 KMKCCEXPCORE Core; 174 /** Where to continue after this instruction. (This is necessary since the 175 * instruction contains string data of variable size.) */ 176 PKMKCCEXPCORE pNext; 177 /** The name of the variable (points into variable_strcache). */ 178 const char *pszName; 179 /** Search pattern. */ 180 const char *pszSearchPattern; 181 /** Replacement pattern. */ 182 const char *pszReplacePattern; 183 /** Offset into pszSearchPattern of the significant '%' char. */ 184 uint32_t offPctSearchPattern; 185 /** Offset into pszReplacePattern of the significant '%' char. */ 186 uint32_t offPctReplacePattern; 187 } KMKCCEXPSRPLAINVAR; 188 typedef KMKCCEXPSRPLAINVAR *PKMKCCEXPSRPLAINVAR; 189 190 /** 191 * Instruction format parts common to both kKmkCcExpInstr_PlainFunction and 192 * kKmkCcExpInstr_DynamicFunction. 193 */ 142 194 typedef struct kmk_cc_exp_function_core 143 195 { … … 146 198 /** Number of arguments. */ 147 199 uint32_t cArgs; 148 /** Where to continue after this instruction. This is necessary since the 149 * instruction is of variable size and we don't even know if we're still in the 150 * same instruction block. So, we include a jump here. */ 200 /** Where to continue after this instruction. (This is necessary since the 201 * instructions are of variable size and may be followed by string data.) */ 151 202 PKMKCCEXPCORE pNext; 152 203 /** … … 164 215 typedef KMKCCEXPFUNCCORE *PKMKCCEXPFUNCCORE; 165 216 217 /** 218 * Instruction format for kKmkCcExpInstr_PlainFunction. 219 */ 166 220 typedef struct kmk_cc_exp_plain_function 167 221 { … … 178 232 #define KMKCCEXPPLAINFUNC_SIZE(a_cArgs) (sizeof(KMKCCEXPFUNCCORE) + (a_cArgs + 1) * sizeof(const char *)) 179 233 234 /** 235 * Instruction format for kKmkCcExpInstr_DynamicFunction. 236 */ 180 237 typedef struct kmk_cc_exp_dyn_function 181 238 { … … 209 266 + (a_cArgs) * sizeof(((PKMKCCEXPDYNFUNC)(uintptr_t)42)->aArgs[0]) ) 210 267 268 /** 269 * Instruction format for kKmkCcExpInstr_Jump. 270 */ 211 271 typedef struct kmk_cc_exp_jump 212 272 { … … 227 287 /** List of blocks for this program (LIFO). */ 228 288 PKMKCCBLOCK pBlockTail; 229 /** Max expanded size. */ 230 uint32_t cbMax; 231 /** Recent average size. */ 232 uint32_t cbAvg; 289 /** Statistics. */ 290 KMKCCEXPSTATS Stats; 233 291 } KMKCCEXPPROG; 234 292 /** Pointer to a string expansion program. */ … … 245 303 *******************************************************************************/ 246 304 static int kmk_cc_exp_compile_subprog(PKMKCCBLOCK *ppBlockTail, const char *pchStr, uint32_t cchStr, PKMKCCEXPSUBPROG pSubProg); 305 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcch); 247 306 248 307 … … 741 800 742 801 /** 743 * Emits a kKmkCcExpInstr_PlainVariable. 802 * Emits either a kKmkCcExpInstr_PlainVariable or 803 * kKmkCcExpInstr_SearchAndReplacePlainVariable instruction. 744 804 * 745 805 * @returns 0 on success, non-zero on failure. … … 750 810 * nothing will be emitted. 751 811 */ 752 static int kmk_cc_exp_emit_plain_variable (PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName)812 static int kmk_cc_exp_emit_plain_variable_maybe_sr(PKMKCCBLOCK *ppBlockTail, const char *pchName, uint32_t cchName) 753 813 { 754 814 if (cchName > 0) 755 815 { 756 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 757 pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable; 758 pInstr->pNameEntry = strcache2_get_entry(&variable_strcache, strcache2_add(&variable_strcache, pchName, cchName)); 816 /* 817 * Hopefully, we're not expected to do any search and replace on the 818 * expanded variable string later... Requires both ':' and '='. 819 */ 820 const char *pchEqual; 821 const char *pchColon = (const char *)memchr(pchName, ':', cchName); 822 if ( pchColon == NULL 823 || (pchEqual = (const char *)memchr(pchColon + 1, ':', cchName - (pchColon - pchName - 1))) == NULL 824 || pchEqual == pchEqual + 1) 825 { 826 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 827 pInstr->Core.enmOpCode = kKmkCcExpInstr_PlainVariable; 828 pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName); 829 } 830 else if (pchColon != pchName) 831 { 832 /* 833 * Okay, we need to do search and replace the variable value. 834 * This is performed by patsubst_expand_pat using '%' patterns. 835 */ 836 uint32_t cchName2 = (uint32_t)(pchColon - pchName); 837 uint32_t cchSearch = (uint32_t)(pchEqual - pchColon - 1); 838 uint32_t cchReplace = cchName - cchName2 - cchSearch - 2; 839 const char *pchPct; 840 char *psz; 841 PKMKCCEXPSRPLAINVAR pInstr; 842 843 pInstr = (PKMKCCEXPSRPLAINVAR)kmk_cc_block_alloc_exp(ppBlockTail, sizeof(*pInstr)); 844 pInstr->Core.enmOpCode = kKmkCcExpInstr_SearchAndReplacePlainVariable; 845 pInstr->pszName = strcache2_add(&variable_strcache, pchName, cchName2); 846 847 /* Figure out the search pattern, unquoting percent chars.. */ 848 psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchSearch + 2); 849 psz[0] = '%'; 850 memcpy(psz + 1, pchColon + 1, cchSearch); 851 psz[1 + cchSearch] = '\0'; 852 pchPct = find_percent(psz + 1); /* also performs unquoting */ 853 if (pchPct) 854 { 855 pInstr->pszSearchPattern = psz + 1; 856 pInstr->offPctSearchPattern = (uint32_t)(pchPct - psz - 1); 857 } 858 else 859 { 860 pInstr->pszSearchPattern = psz; 861 pInstr->offPctSearchPattern = 0; 862 } 863 864 /* Figure out the replacement pattern, unquoting percent chars.. */ 865 if (cchReplace == 0) 866 { 867 pInstr->pszReplacePattern = "%"; 868 pInstr->offPctReplacePattern = 0; 869 } 870 else 871 { 872 psz = (char *)kmk_cc_block_byte_alloc(ppBlockTail, cchReplace + 2); 873 psz[0] = '%'; 874 memcpy(psz + 1, pchEqual + 1, cchReplace); 875 psz[1 + cchReplace] = '\0'; 876 pchPct = find_percent(psz + 1); /* also performs unquoting */ 877 if (pchPct) 878 { 879 pInstr->pszReplacePattern = psz + 1; 880 pInstr->offPctReplacePattern = (uint32_t)(pchPct - psz - 1); 881 } 882 else 883 { 884 pInstr->pszReplacePattern = psz; 885 pInstr->offPctReplacePattern = 0; 886 } 887 } 888 889 /* Note down where the next instruction is after realigning the allocator. */ 890 kmk_cc_block_realign(ppBlockTail); 891 pInstr->pNext = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 892 } 759 893 } 760 894 return 0; … … 837 971 { 838 972 /* There are several alternative ways of finding the ending 839 parenthesis / braces. GNU make only consideres open & 840 close chars of the one we're processing, and it does not 841 matter whether the opening paren / braces are preceeded by 842 any dollar char. Simple and efficient. */ 973 parenthesis / braces. 974 975 GNU make does one thing for functions and variable containing 976 any '$' chars before the first closing char. While for 977 variables where a closing char comes before any '$' char, a 978 simplified approach is taken. This means that for example: 979 980 Given VAR=var, the expressions "$(var())" and 981 "$($(VAR)())" would be expanded differently. 982 In the first case the variable "var(" would be 983 used and in the second "var()". 984 985 This code will not duplicate this weird behavior, but work 986 the same regardless of whether there is a '$' char before 987 the first closing char. */ 843 988 make_function_ptr_t pfnFunction; 844 989 const char *pszFunction; … … 865 1010 cchName++; 866 1011 } 1012 867 1013 if ( cchName >= MIN_FUNCTION_LENGTH 868 1014 && cchName <= MAX_FUNCTION_LENGTH … … 1002 1148 } 1003 1149 if (cDollars == 0) 1004 rc = kmk_cc_exp_emit_plain_variable (ppBlockTail, pchStr, cchName);1150 rc = kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, cchName); 1005 1151 else 1006 1152 rc = kmk_cc_exp_emit_dyn_variable(ppBlockTail, pchStr, cchName); … … 1012 1158 { 1013 1159 /* Single character variable name. */ 1014 rc = kmk_cc_exp_emit_plain_variable (ppBlockTail, pchStr, 1);1160 rc = kmk_cc_exp_emit_plain_variable_maybe_sr(ppBlockTail, pchStr, 1); 1015 1161 pchStr++; 1016 1162 cchStr--; … … 1046 1192 1047 1193 /** 1194 * Initializes string expansion program statistics. 1195 * @param pStats Pointer to the statistics structure to init. 1196 */ 1197 static void kmk_cc_exp_stats_init(PKMKCCEXPSTATS pStats) 1198 { 1199 pStats->cchAvg = 0; 1200 pStats->cchMax = 0; 1201 } 1202 1203 1204 /** 1048 1205 * Compiles a string expansion sub program. 1049 1206 * … … 1064 1221 assert(cchStr); 1065 1222 pSubProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(*ppBlockTail); 1066 pSubProg->cbMax = 0; 1067 pSubProg->cbAvg = 0; 1223 kmk_cc_exp_stats_init(&pSubProg->Stats); 1068 1224 return kmk_cc_exp_compile_common(ppBlockTail, pchStr, cchStr); 1069 1225 } … … 1095 1251 pProg->pBlockTail = pBlock; 1096 1252 pProg->pFirstInstr = (PKMKCCEXPCORE)kmk_cc_block_get_next_ptr(pBlock); 1097 pProg->cbMax = 0; 1098 pProg->cbAvg = 0; 1253 kmk_cc_exp_stats_init(&pProg->Stats); 1099 1254 1100 1255 /* … … 1145 1300 1146 1301 1302 #ifndef NDEBUG 1303 /** 1304 * Used to check that function arguments are left alone. 1305 * @returns Updated hash. 1306 * @param uHash The current hash value. 1307 * @param psz The string to hash. 1308 */ 1309 static uint32_t kmk_exec_debug_string_hash(uint32_t uHash, const char *psz) 1310 { 1311 unsigned char ch; 1312 while ((ch = *(unsigned char const *)psz++) != '\0') 1313 uHash = (uHash << 6) + (uHash << 16) - uHash + (unsigned char)ch; 1314 return uHash; 1315 } 1316 #endif 1317 1318 1319 /** 1320 * String expansion execution worker for outputting a variable. 1321 * 1322 * @returns The new variable buffer position. 1323 * @param pVar The variable to reference. 1324 * @param pchDst The current variable buffer position. 1325 */ 1326 static char *kmk_exec_expand_worker_reference_variable(struct variable *pVar, char *pchDst) 1327 { 1328 if (pVar->value_length > 0) 1329 { 1330 if (!pVar->recursive) 1331 pchDst = variable_buffer_output(pchDst, pVar->value, pVar->value_length); 1332 else 1333 pchDst = reference_recursive_variable(pchDst, pVar); 1334 } 1335 else if (pVar->append) 1336 pchDst = reference_recursive_variable(pchDst, pVar); 1337 return pchDst; 1338 } 1339 1340 1341 /** 1342 * Executes a stream string expansion instructions, outputting to the current 1343 * varaible buffer. 1344 * 1345 * @returns The new variable buffer position. 1346 * @param pInstrCore The instruction to start executing at. 1347 * @param pchDst The current variable buffer position. 1348 */ 1349 static char *kmk_exec_expand_instruction_stream_to_var_buf(PKMKCCEXPCORE pInstrCore, char *pchDst) 1350 { 1351 for (;;) 1352 { 1353 switch (pInstrCore->enmOpCode) 1354 { 1355 case kKmkCcExpInstr_CopyString: 1356 { 1357 PKMKCCEXPCOPYSTRING pInstr = (PKMKCCEXPCOPYSTRING)pInstrCore; 1358 pchDst = variable_buffer_output(pchDst, pInstr->pachSrc, pInstr->cchCopy); 1359 1360 pInstrCore = &(pInstr + 1)->Core; 1361 break; 1362 } 1363 1364 case kKmkCcExpInstr_PlainVariable: 1365 { 1366 PKMKCCEXPPLAINVAR pInstr = (PKMKCCEXPPLAINVAR)pInstrCore; 1367 struct variable *pVar = lookup_variable_strcached(pInstr->pszName); 1368 if (pVar) 1369 pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst); 1370 else 1371 warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName)); 1372 1373 pInstrCore = &(pInstr + 1)->Core; 1374 break; 1375 } 1376 1377 case kKmkCcExpInstr_DynamicVariable: 1378 { 1379 PKMKCCEXPDYNVAR pInstr = (PKMKCCEXPDYNVAR)pInstrCore; 1380 struct variable *pVar; 1381 uint32_t cchName; 1382 char *pszName = kmk_exec_expand_subprog_to_tmp(&pInstr->SubProg, &cchName); 1383 char *pszColon = (char *)memchr(pszName, ':', cchName); 1384 char *pszEqual; 1385 if ( pszColon == NULL 1386 || (pszEqual = (char *)memchr(pszColon + 1, '=', &pszName[cchName] - pszColon - 1)) == NULL 1387 || pszEqual == pszColon + 1) 1388 { 1389 pVar = lookup_variable(pszName, cchName); 1390 if (pVar) 1391 pchDst = kmk_exec_expand_worker_reference_variable(pVar, pchDst); 1392 else 1393 warn_undefined(pszName, cchName); 1394 } 1395 else if (pszColon != pszName) 1396 { 1397 /* 1398 * Oh, we have to do search and replace. How tedious. 1399 * Since the variable name is a temporary buffer, we can transform 1400 * the strings into proper search and replacement patterns directly. 1401 */ 1402 pVar = lookup_variable(pszName, pszColon - pszName); 1403 if (pVar) 1404 { 1405 char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value; 1406 char *pszSearchPat = pszColon + 1; 1407 char *pszReplacePat = pszEqual + 1; 1408 const char *pchPctSearchPat; 1409 const char *pchPctReplacePat; 1410 1411 *pszEqual = '\0'; 1412 pchPctSearchPat = find_percent(pszSearchPat); 1413 pchPctReplacePat = find_percent(pszReplacePat); 1414 1415 if (!pchPctReplacePat) 1416 { 1417 if (pszReplacePat[-2] != '\0') /* On the offchance that a pct was unquoted by find_percent. */ 1418 { 1419 memmove(pszName + 1, pszSearchPat, pszReplacePat - pszSearchPat); 1420 if (pchPctSearchPat) 1421 pchPctSearchPat -= pszSearchPat - &pszName[1]; 1422 pszSearchPat = &pszName[1]; 1423 } 1424 pchPctReplacePat = --pszReplacePat; 1425 *pszReplacePat = '%'; 1426 } 1427 1428 if (!pchPctSearchPat) 1429 { 1430 pchPctSearchPat = --pszSearchPat; 1431 *pszSearchPat = '%'; 1432 } 1433 1434 pchDst = patsubst_expand_pat(pchDst, pszExpandedVarValue, 1435 pszSearchPat, pszReplacePat, 1436 pchPctSearchPat, pchPctReplacePat); 1437 1438 if (pVar->recursive) 1439 free((void *)pszExpandedVarValue); 1440 } 1441 else 1442 warn_undefined(pszName, pszColon - pszName); 1443 } 1444 free(pszName); 1445 1446 pInstrCore = pInstr->pNext; 1447 break; 1448 } 1449 1450 1451 case kKmkCcExpInstr_SearchAndReplacePlainVariable: 1452 { 1453 PKMKCCEXPSRPLAINVAR pInstr = (PKMKCCEXPSRPLAINVAR)pInstrCore; 1454 struct variable *pVar = lookup_variable_strcached(pInstr->pszName); 1455 if (pVar) 1456 { 1457 char const *pszExpandedVarValue = pVar->recursive ? recursively_expand(pVar) : pVar->value; 1458 pchDst = patsubst_expand_pat(pchDst, 1459 pszExpandedVarValue, 1460 pInstr->pszSearchPattern, 1461 pInstr->pszReplacePattern, 1462 &pInstr->pszSearchPattern[pInstr->offPctSearchPattern], 1463 &pInstr->pszReplacePattern[pInstr->offPctReplacePattern]); 1464 if (pVar->recursive) 1465 free((void *)pszExpandedVarValue); 1466 } 1467 else 1468 warn_undefined(pInstr->pszName, strcache2_get_len(&variable_strcache, pInstr->pszName)); 1469 1470 pInstrCore = pInstr->pNext; 1471 break; 1472 } 1473 1474 case kKmkCcExpInstr_PlainFunction: 1475 { 1476 PKMKCCEXPPLAINFUNC pInstr = (PKMKCCEXPPLAINFUNC)pInstrCore; 1477 #ifndef NDEBUG 1478 uint32_t uCrcBefore = 0; 1479 uint32_t uCrcAfter = 0; 1480 uint32_t iArg = pInstr->Core.cArgs; 1481 while (iArg-- > 0) 1482 uCrcBefore = kmk_exec_debug_string_hash(uCrcBefore, pInstr->apszArgs[iArg]); 1483 #endif 1484 1485 pchDst = pInstr->Core.pfnFunction(pchDst, (char **)&pInstr->apszArgs[0], pInstr->Core.pszFuncName); 1486 1487 #ifndef NDEBUG 1488 iArg = pInstr->Core.cArgs; 1489 while (iArg-- > 0) 1490 uCrcAfter = kmk_exec_debug_string_hash(uCrcAfter, pInstr->apszArgs[iArg]); 1491 assert(uCrcBefore == uCrcAfter); 1492 #endif 1493 1494 pInstrCore = pInstr->Core.pNext; 1495 break; 1496 } 1497 1498 case kKmkCcExpInstr_DynamicFunction: 1499 { 1500 PKMKCCEXPDYNFUNC pInstr = (PKMKCCEXPDYNFUNC)pInstrCore; 1501 char **papszArgsShadow = xmalloc( (pInstr->Core.cArgs * 2 + 1) * sizeof(char *)); 1502 char **papszArgs = &papszArgsShadow[pInstr->Core.cArgs]; 1503 uint32_t iArg; 1504 #ifndef NDEBUG 1505 uint32_t uCrcBefore = 0; 1506 uint32_t uCrcAfter = 0; 1507 #endif 1508 iArg = pInstr->Core.cArgs; 1509 papszArgs[iArg] = NULL; 1510 while (iArg-- > 0) 1511 { 1512 char *pszArg; 1513 if (pInstr->aArgs[iArg].fPlain) 1514 pszArg = (char *)pInstr->aArgs[iArg].u.Plain.pszArg; 1515 else 1516 pszArg = kmk_exec_expand_subprog_to_tmp(&pInstr->aArgs[iArg].u.SubProg, NULL); 1517 papszArgsShadow[iArg] = pszArg; 1518 papszArgs[iArg] = pszArg; 1519 #ifndef NDEBUG 1520 uCrcBefore = kmk_exec_debug_string_hash(uCrcBefore, pszArg); 1521 #endif 1522 } 1523 1524 pchDst = pInstr->Core.pfnFunction(pchDst, papszArgs, pInstr->Core.pszFuncName); 1525 1526 iArg = pInstr->Core.cArgs; 1527 while (iArg-- > 0) 1528 { 1529 #ifndef NDEBUG 1530 assert(papszArgsShadow[iArg] == papszArgs[iArg]); 1531 uCrcAfter = kmk_exec_debug_string_hash(uCrcAfter, papszArgsShadow[iArg]); 1532 #endif 1533 if (!pInstr->aArgs[iArg].fPlain) 1534 free(papszArgsShadow); 1535 } 1536 assert(uCrcBefore == uCrcAfter); 1537 free(papszArgsShadow); 1538 1539 pInstrCore = pInstr->Core.pNext; 1540 break; 1541 } 1542 1543 case kKmkCcExpInstr_Jump: 1544 { 1545 PKMKCCEXPJUMP pInstr = (PKMKCCEXPJUMP)pInstrCore; 1546 pInstrCore = pInstr->pNext; 1547 break; 1548 } 1549 1550 case kKmkCcExpInstr_Return: 1551 return pchDst; 1552 1553 default: 1554 fatal(NULL, _("Unknown string expansion opcode: %d (%#x)"), 1555 (int)pInstrCore->enmOpCode, (int)pInstrCore->enmOpCode); 1556 return NULL; 1557 } 1558 } 1559 } 1560 1561 1562 /** 1563 * Updates the string expansion statistics. 1564 * 1565 * @param pStats The statistics structure to update. 1566 * @param cchResult The result lenght. 1567 */ 1568 void kmk_cc_exp_stats_update(PKMKCCEXPSTATS pStats, uint32_t cchResult) 1569 { 1570 /* 1571 * Keep statistics on output size. The average is simplified and not an 1572 * exact average for every expansion that has taken place. 1573 */ 1574 if (cchResult > pStats->cchMax) 1575 { 1576 if (pStats->cchMax) 1577 pStats->cchAvg = cchResult; 1578 pStats->cchMax = cchResult; 1579 } 1580 pStats->cchAvg = (pStats->cchAvg * 7 + cchResult) / 8; 1581 } 1582 1583 1584 /** 1585 * Execute a string expansion sub-program, outputting to a new heap buffer. 1586 * 1587 * @returns Pointer to the output buffer (hand to free when done). 1588 * @param pSubProg The sub-program to execute. 1589 * @param pcchResult Where to return the size of the result. Optional. 1590 */ 1591 static char *kmk_exec_expand_subprog_to_tmp(PKMKCCEXPSUBPROG pSubProg, uint32_t *pcchResult) 1592 { 1593 char *pchOldVarBuf; 1594 unsigned int cbOldVarBuf; 1595 char *pchDst; 1596 char *pszResult; 1597 uint32_t cchResult; 1598 1599 /* 1600 * Temporarily replace the variable buffer while executing the instruction 1601 * stream for this sub program. 1602 */ 1603 pchDst = install_variable_buffer_with_hint(&pchOldVarBuf, &cbOldVarBuf, 1604 pSubProg->Stats.cchAvg ? pSubProg->Stats.cchAvg + 32 : 256); 1605 1606 pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pSubProg->pFirstInstr, pchDst); 1607 1608 /* Ensure that it's terminated. */ 1609 pchDst = variable_buffer_output(pchDst, "\0", 1) - 1; 1610 1611 /* Grab the result buffer before restoring the previous one. */ 1612 pszResult = variable_buffer; 1613 cchResult = (uint32_t)(pchDst - pszResult); 1614 if (pcchResult) 1615 *pcchResult = cchResult; 1616 kmk_cc_exp_stats_update(&pSubProg->Stats, cchResult); 1617 1618 restore_variable_buffer(pchOldVarBuf, cbOldVarBuf); 1619 1620 return pszResult; 1621 } 1622 1623 1624 /** 1625 * Execute a string expansion program, outputting to the current variable 1626 * buffer. 1627 * 1628 * @returns New variable buffer position. 1629 * @param pProg The program to execute. 1630 * @param pchDst The current varaible buffer position. 1631 */ 1632 static char *kmk_exec_expand_prog_to_var_buf(PKMKCCEXPPROG pProg, char *pchDst) 1633 { 1634 uint32_t cchResult; 1635 uint32_t offStart = (uint32_t)(pchDst - variable_buffer); 1636 1637 if (pProg->Stats.cchAvg >= variable_buffer_length - offStart) 1638 pchDst = ensure_variable_buffer_space(pchDst, offStart + pProg->Stats.cchAvg + 32); 1639 1640 pchDst = kmk_exec_expand_instruction_stream_to_var_buf(pProg->pFirstInstr, pchDst); 1641 1642 cchResult = (uint32_t)(pchDst - variable_buffer); 1643 assert(cchResult >= offStart); 1644 cchResult -= offStart; 1645 kmk_cc_exp_stats_update(&pProg->Stats, cchResult); 1646 1647 return pchDst; 1648 } 1649 1650 1147 1651 /** 1148 1652 * Equivalent of eval_buffer, only it's using the evalprog of the variable. … … 1167 1671 { 1168 1672 assert(pVar->expandprog); 1169 assert(0); 1170 return pchDst; 1673 return kmk_exec_expand_prog_to_var_buf(pVar->expandprog, pchDst); 1171 1674 } 1172 1675 … … 1180 1683 { 1181 1684 assert(pVar->evalprog || pVar->expandprog); 1685 #if 0 1686 if (pVar->evalprog) 1687 { 1688 kmk_cc_block_free_list(pVar->evalprog->pBlockTail); 1689 pVar->evalprog = NULL; 1690 } 1691 #endif 1692 if (pVar->expandprog) 1693 { 1694 kmk_cc_block_free_list(pVar->expandprog->pBlockTail); 1695 pVar->expandprog = NULL; 1696 } 1182 1697 } 1183 1698 … … 1191 1706 { 1192 1707 assert(pVar->evalprog || pVar->expandprog); 1708 #if 0 1709 if (pVar->evalprog) 1710 { 1711 kmk_cc_block_free_list(pVar->evalprog->pBlockTail); 1712 pVar->evalprog = NULL; 1713 } 1714 #endif 1715 if (pVar->expandprog) 1716 { 1717 kmk_cc_block_free_list(pVar->expandprog->pBlockTail); 1718 pVar->expandprog = NULL; 1719 } 1193 1720 } 1194 1721 -
trunk/src/kmk/variable.c
r2765 r2769 1035 1035 return 0; 1036 1036 } 1037 1038 #ifdef CONFIG_WITH_STRCACHE2 1039 /* Alternative version of lookup_variable that takes a name that's already in 1040 the variable string cache. */ 1041 struct variable * 1042 lookup_variable_strcached (const char *name) 1043 { 1044 struct variable *v; 1045 #if 1 /*FIX THIS - ndef KMK*/ 1046 const struct variable_set_list *setlist; 1047 struct variable var_key; 1048 #endif /* KMK */ 1049 int is_parent = 0; 1050 1051 #ifndef NDEBUG 1052 strcache2_verify_entry (&variable_strcache, name); 1053 #endif 1054 1055 #ifdef KMK 1056 /* Check for kBuild-define- local variable accesses and handle these first. */ 1057 if (strcache2_get_len(&variable_strcache, name) > 3 && name[0] == '[') 1058 { 1059 v = lookup_kbuild_object_variable_accessor(name, strcache2_get_len(&variable_strcache, name)); 1060 if (v != VAR_NOT_KBUILD_ACCESSOR) 1061 { 1062 MAKE_STATS_2 (v->references++); 1063 return v; 1064 } 1065 } 1066 #endif 1067 1068 #if 1 /*FIX THIS - ndef KMK */ 1069 1070 var_key.name = (char *) name; 1071 var_key.length = strcache2_get_len(&variable_strcache, name); 1072 1073 for (setlist = current_variable_set_list; 1074 setlist != 0; setlist = setlist->next) 1075 { 1076 const struct variable_set *set = setlist->set; 1077 1078 v = (struct variable *) hash_find_item_strcached ((struct hash_table *) &set->table, &var_key); 1079 if (v && (!is_parent || !v->private_var)) 1080 { 1081 # ifdef KMK 1082 RESOLVE_ALIAS_VARIABLE(v); 1083 # endif 1084 MAKE_STATS_2 (v->references++); 1085 return v->special ? lookup_special_var (v) : v; 1086 } 1087 1088 is_parent |= setlist->next_is_parent; 1089 } 1090 1091 #else /* KMK - need for speed */ 1092 1093 v = lookup_cached_variable (name); 1094 assert (lookup_variable_for_assert(name, length) == v); 1095 #ifdef VMS 1096 if (v) 1097 #endif 1098 return v; 1099 #endif /* KMK - need for speed */ 1100 #ifdef VMS 1101 # error "Port me (split out the relevant code from lookup_varaible and call it)" 1102 #endif 1103 return 0; 1104 } 1105 #endif 1106 1037 1107 1038 1108 -
trunk/src/kmk/variable.h
r2768 r2769 244 244 #endif /* CONFIG_WITH_VALUE_LENGTH */ 245 245 void install_variable_buffer (char **bufp, unsigned int *lenp); 246 char *install_variable_buffer_with_hint (char **bufp, unsigned int *lenp, unsigned int size_hint); 246 247 void restore_variable_buffer (char *buf, unsigned int len); 248 char *ensure_variable_buffer_space(char *ptr, unsigned int size); 247 249 #ifdef CONFIG_WITH_VALUE_LENGTH 248 250 void append_expanded_string_to_variable (struct variable *v, const char *value, … … 325 327 unsigned int *value_lenp); 326 328 #define recursively_expand(v) recursively_expand_for_file (v, NULL, NULL) 329 #endif 330 #ifdef CONFIG_WITH_COMPILER 331 char *reference_recursive_variable (char *o, struct variable *v); 327 332 #endif 328 333 … … 369 374 struct variable *lookup_variable_in_set (const char *name, unsigned int length, 370 375 const struct variable_set *set); 376 #ifdef CONFIG_WITH_STRCACHE2 377 struct variable *lookup_variable_strcached (const char *name); 378 #endif 371 379 372 380 #ifdef CONFIG_WITH_VALUE_LENGTH
Note:
See TracChangeset
for help on using the changeset viewer.