GNU Binutils with patches for OS216
Révision | 8da25eeed75422a0cc5521e79ea6b897d681d1d1 (tree) |
---|---|
l'heure | 2005-11-18 15:00:25 |
Auteur | Mark Mitchell <mark@code...> |
Commiter | Mark Mitchell |
Issue #488
* libiberty/argv.c (expandargv): Check for errors with ferror,
rather than by looking at return value from fread.
@@ -1,3 +1,9 @@ | ||
1 | +2005-11-17 Carlos O'Donell <carlos@codesourcery.com> | |
2 | + | |
3 | + Issue #488 | |
4 | + * libiberty/argv.c (expandargv): Check for errors with ferror, | |
5 | + rather than by looking at return value from fread. | |
6 | + | |
1 | 7 | 2005-10-13 Mark Mitchell <mark@codesourcery.com> |
2 | 8 | |
3 | 9 | Issue #439 |
@@ -229,7 +229,7 @@ char **buildargv (input) | ||
229 | 229 | arg = copybuf; |
230 | 230 | while (*input != EOS) |
231 | 231 | { |
232 | - if (ISBLANK (*input) && !squote && !dquote && !bsquote) | |
232 | + if (ISSPACE (*input) && !squote && !dquote && !bsquote) | |
233 | 233 | { |
234 | 234 | break; |
235 | 235 | } |
@@ -295,7 +295,7 @@ char **buildargv (input) | ||
295 | 295 | argc++; |
296 | 296 | argv[argc] = NULL; |
297 | 297 | |
298 | - while (ISBLANK (*input)) | |
298 | + while (ISSPACE (*input)) | |
299 | 299 | { |
300 | 300 | input++; |
301 | 301 | } |
@@ -331,90 +331,60 @@ expandargv (argcp, argvp) | ||
331 | 331 | int *argcp; |
332 | 332 | char ***argvp; |
333 | 333 | { |
334 | - /* A dynamically allocated buffer used to hold options read from a | |
335 | - response file. NULL until needed. */ | |
336 | - char *buffer = NULL; | |
337 | - /* The number of bytes in BUFFER. */ | |
338 | - size_t buffer_len = 0; | |
339 | - /* Dynamically allocated storage for the options read from the | |
340 | - response file. NULL until needed. */ | |
341 | - char **file_options = NULL; | |
342 | - /* The number of slots in the FILE_OPTIONS array. */ | |
343 | - size_t file_options_len = 0; | |
344 | - /* If non-NULL, the name of the response file that caused a | |
345 | - failure. */ | |
346 | - const char *error_file = NULL; | |
347 | 334 | /* The argument we are currently processing. */ |
348 | 335 | int i = 0; |
349 | 336 | /* Non-zero if ***argvp has been dynamically allocated. */ |
350 | 337 | int argv_dynamic = 0; |
351 | - | |
352 | 338 | /* Loop over the arguments, handling response files. We always skip |
353 | 339 | ARGVP[0], as that is the name of the program being run. */ |
354 | - while (++i != *argcp) | |
340 | + while (++i < *argcp) | |
355 | 341 | { |
356 | 342 | /* The name of the response file. */ |
357 | 343 | const char *filename; |
358 | 344 | /* The response file. */ |
359 | 345 | FILE *f; |
346 | + /* An upper bound on the number of characters in the response | |
347 | + file. */ | |
348 | + long pos; | |
349 | + /* The number of characters in the response file, when actually | |
350 | + read. */ | |
351 | + size_t len; | |
352 | + /* A dynamically allocated buffer used to hold options read from a | |
353 | + response file. */ | |
354 | + char *buffer; | |
355 | + /* Dynamically allocated storage for the options read from the | |
356 | + response file. */ | |
357 | + char **file_argv; | |
360 | 358 | /* The number of options read from the response file, if any. */ |
361 | - size_t num_options; | |
362 | - | |
359 | + size_t file_argc; | |
363 | 360 | /* We are only interested in options of the form "@file". */ |
364 | 361 | filename = (*argvp)[i]; |
365 | 362 | if (filename[0] != '@') |
366 | 363 | continue; |
367 | - | |
368 | - /* Open the file. */ | |
364 | + /* Read the contents of the file. */ | |
369 | 365 | f = fopen (++filename, "r"); |
370 | 366 | if (!f) |
371 | 367 | continue; |
372 | - | |
373 | - /* Read all the options. */ | |
374 | - num_options = 0; | |
375 | - while (1) | |
376 | - { | |
377 | - /* The insertion point in BUFFER. */ | |
378 | - size_t buffer_pos = 0; | |
379 | - /* The character immediately following the option in | |
380 | - BUFFER. */ | |
381 | - int c; | |
382 | - /* Read the next option from the file. */ | |
383 | - while (1) | |
384 | - { | |
385 | - if (buffer_pos + 32 > buffer_len) | |
386 | - { | |
387 | - buffer_len = buffer_len ? 2 * buffer_len : 32; | |
388 | - buffer = (char *) xrealloc (buffer, buffer_len); | |
389 | - } | |
390 | - c = fscanf (f, "%31s", buffer + buffer_pos); | |
391 | - if (c == EOF) | |
392 | - break; | |
393 | - /* If the next character in the file is not whitespace, | |
394 | - then we didn't yet read the entire argument. */ | |
395 | - c = getc (f); | |
396 | - if (c == EOF || ISSPACE (c)) | |
397 | - break; | |
398 | - /* Put back the character at which we peeked. */ | |
399 | - ungetc (c, f); | |
400 | - buffer_pos += 31; | |
401 | - } | |
402 | - if (c == EOF) | |
403 | - break; | |
404 | - /* Insert the option into FILE_OPTIONS. */ | |
405 | - if (num_options == file_options_len) | |
406 | - { | |
407 | - file_options_len = file_options_len ? 2 * file_options_len : 32; | |
408 | - file_options | |
409 | - = (char **) xrealloc (file_options, | |
410 | - file_options_len * sizeof (char *)); | |
411 | - } | |
412 | - file_options[num_options++] = xstrdup(buffer); | |
413 | - } | |
414 | - | |
415 | - /* We're done with the file now. */ | |
416 | - fclose (f); | |
417 | - /* Insert all the options into ARGV. */ | |
368 | + if (fseek (f, 0L, SEEK_END) == -1) | |
369 | + goto error; | |
370 | + pos = ftell (f); | |
371 | + if (pos == -1) | |
372 | + goto error; | |
373 | + if (fseek (f, 0L, SEEK_SET) == -1) | |
374 | + goto error; | |
375 | + buffer = (char *) xmalloc (pos * sizeof (char) + 1); | |
376 | + len = fread (buffer, sizeof (char), pos, f); | |
377 | + if (len != (size_t) pos | |
378 | + /* On Windows, fread may return a value smaller than POS, | |
379 | + due to CR/LF->CR translation when reading text files. | |
380 | + That does not in-and-of itself indicate failure. */ | |
381 | + && ferror (f)) | |
382 | + goto error; | |
383 | + /* Add a NUL terminator. */ | |
384 | + buffer[len] = '\0'; | |
385 | + /* Parse the string. */ | |
386 | + file_argv = buildargv (buffer); | |
387 | + /* If *ARGVP is not already dynamically allocated, copy it. */ | |
418 | 388 | if (!argv_dynamic) |
419 | 389 | { |
420 | 390 | *argvp = dupargv (*argvp); |
@@ -423,24 +393,33 @@ expandargv (argcp, argvp) | ||
423 | 393 | allocate, so make a guess. */ |
424 | 394 | xmalloc_failed (*argcp * 32); |
425 | 395 | } |
426 | - /* The "+1" below handles the NULL terminator at the end of ARGV. */ | |
396 | + /* Count the number of arguments. */ | |
397 | + file_argc = 0; | |
398 | + while (file_argv[file_argc] && *file_argv[file_argc]) | |
399 | + ++file_argc; | |
400 | + /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the | |
401 | + NULL terminator at the end of ARGV. */ | |
427 | 402 | *argvp = ((char **) |
428 | 403 | xrealloc (*argvp, |
429 | - (*argcp + num_options + 1) * sizeof (char *))); | |
430 | - memmove (*argvp + i + num_options, *argvp + i + 1, | |
404 | + (*argcp + file_argc + 1) * sizeof (char *))); | |
405 | + memmove (*argvp + i + file_argc, *argvp + i + 1, | |
431 | 406 | (*argcp - i) * sizeof (char *)); |
432 | - memcpy (*argvp + i, file_options, num_options * sizeof (char *)); | |
407 | + memcpy (*argvp + i, file_argv, file_argc * sizeof (char *)); | |
433 | 408 | /* The original option has been replaced by all the new |
434 | 409 | options. */ |
435 | - *argcp += num_options - 1; | |
410 | + *argcp += file_argc - 1; | |
411 | + /* Free up memory allocated to process the response file. We do | |
412 | + not use freeargv because the individual options in FILE_ARGV | |
413 | + are now in the main ARGV. */ | |
414 | + free (file_argv); | |
415 | + free (buffer); | |
416 | + /* Rescan all of the arguments just read to support response | |
417 | + files that include other response files. */ | |
418 | + --i; | |
419 | + error: | |
420 | + /* We're all done with the file now. */ | |
421 | + fclose (f); | |
436 | 422 | } |
437 | - | |
438 | - if (buffer) | |
439 | - free (buffer); | |
440 | - if (file_options) | |
441 | - free (file_options); | |
442 | - | |
443 | - return error_file; | |
444 | 423 | } |
445 | 424 | |
446 | 425 | #ifdef MAIN |