* Parse a patch. */
| 1220 | * Parse a patch. |
| 1221 | */ |
| 1222 | const Patch *parsePatch(const ELF &elf, const char *str) |
| 1223 | { |
| 1224 | PatchKind kind; |
| 1225 | Parser parser(str, "patch", elf); |
| 1226 | |
| 1227 | PatchPos pos = POS_BEFORE; |
| 1228 | switch (parser.peekToken()) |
| 1229 | { |
| 1230 | case TOKEN_BEFORE: |
| 1231 | parser.getToken(); pos = POS_BEFORE; break; |
| 1232 | case TOKEN_REPLACE: |
| 1233 | parser.getToken(); pos = POS_REPLACE; break; |
| 1234 | case TOKEN_AFTER: |
| 1235 | parser.getToken(); pos = POS_AFTER; break; |
| 1236 | default: |
| 1237 | break; |
| 1238 | } |
| 1239 | |
| 1240 | bool conditional = false; |
| 1241 | const char *symbol = nullptr; |
| 1242 | switch (parser.getToken()) |
| 1243 | { |
| 1244 | case TOKEN_BREAK: |
| 1245 | kind = PATCH_BREAK; break; |
| 1246 | case TOKEN_EMPTY: |
| 1247 | kind = PATCH_EMPTY; break; |
| 1248 | case TOKEN_EXIT: |
| 1249 | kind = PATCH_EXIT; break; |
| 1250 | case TOKEN_SIGNAL: |
| 1251 | kind = PATCH_SIGNAL; break; |
| 1252 | case TOKEN_PRINT: |
| 1253 | kind = PATCH_PRINT; break; |
| 1254 | case TOKEN_PLUGIN: |
| 1255 | kind = PATCH_PLUGIN; break; |
| 1256 | case TOKEN_TRAP: |
| 1257 | kind = PATCH_TRAP; break; |
| 1258 | case TOKEN_IF: |
| 1259 | conditional = true; |
| 1260 | parser.getToken(); |
| 1261 | // Fallthrough |
| 1262 | default: |
| 1263 | symbol = parseFunctionName(parser); |
| 1264 | kind = PATCH_CALL; break; |
| 1265 | } |
| 1266 | |
| 1267 | // Parse the rest of the patch (if necessary): |
| 1268 | const char *filename = nullptr; |
| 1269 | Plugin *plugin = nullptr; |
| 1270 | CallABI abi = ABI_CLEAN; |
| 1271 | CallJump jmp = JUMP_NONE; |
| 1272 | std::vector<Argument> args; |
| 1273 | int status = 0, signal = 0; |
| 1274 | int t = 0; |
| 1275 | switch (kind) |
| 1276 | { |
| 1277 | case PATCH_EXIT: |
| 1278 | parser.expectToken('('); |
| 1279 | parser.expectToken(TOKEN_INTEGER); |
no test coverage detected