| 289 | /* Unescape STRING in-place. */ |
| 290 | |
| 291 | static void |
| 292 | unescape_string (char *string) |
| 293 | { |
| 294 | char *cursor; /* cursor in result */ |
| 295 | int value; /* value of \nnn escape */ |
| 296 | int length; /* length of \nnn escape */ |
| 297 | |
| 298 | cursor = string; |
| 299 | |
| 300 | while (*string) |
| 301 | { |
| 302 | if (*string == '\\') |
| 303 | { |
| 304 | string++; |
| 305 | switch (*string) |
| 306 | { |
| 307 | case 'x': /* \xhhh escape, 3 chars maximum */ |
| 308 | value = 0; |
| 309 | for (length = 0, string++; |
| 310 | length < 3 && c_isxdigit (*string); |
| 311 | length++, string++) |
| 312 | value = value * 16 + fromhex (*string); |
| 313 | if (length == 0) |
| 314 | { |
| 315 | *cursor++ = '\\'; |
| 316 | *cursor++ = 'x'; |
| 317 | } |
| 318 | else |
| 319 | *cursor++ = value; |
| 320 | break; |
| 321 | |
| 322 | case '0': /* \0ooo escape, 3 chars maximum */ |
| 323 | value = 0; |
| 324 | for (length = 0, string++; |
| 325 | length < 3 && isoct (*string); |
| 326 | length++, string++) |
| 327 | value = value * 8 + fromoct (*string); |
| 328 | *cursor++ = value; |
| 329 | break; |
| 330 | |
| 331 | case 'a': /* alert */ |
| 332 | *cursor++ = '\a'; |
| 333 | string++; |
| 334 | break; |
| 335 | |
| 336 | case 'b': /* backspace */ |
| 337 | *cursor++ = '\b'; |
| 338 | string++; |
| 339 | break; |
| 340 | |
| 341 | case 'c': /* cancel the rest of the output */ |
| 342 | while (*string) |
| 343 | string++; |
| 344 | break; |
| 345 | |
| 346 | case 'f': /* form feed */ |
| 347 | *cursor++ = '\f'; |
| 348 | string++; |