boolean read_into_MethodTypeSet(MethodTypeSet * mts,FILE * ifp) { char buffer[MAXLINE]; Method * me; Type * ty; Input * in; while( fgets(buffer,MAXLINE,ifp) != NULL) { chop_newline(buffer); if( buffer[0] == '#' || strwhitestartcmp(buffer,"#",spacestr) == 0 ) continue; if( only_whitespace(buffer,spacestr) == TRUE) continue; if( strstartcmp(buffer,"method") == 0 ) { if( (me=read_Method_line(buffer,ifp)) == NULL ) { warn("Unable to read method in line [%s] ",buffer); } else { add_me_MethodTypeSet(mts,me); } } else if ( strstartcmp(buffer,"type") == 0 ) { if( (ty=read_Type_line(buffer,ifp)) == NULL ) { warn("Unable to read type in line [%s] ",buffer); } else { add_ty_MethodTypeSet(mts,ty); } } else if ( strstartcmp(buffer,"input") == 0 ) { if( (in = read_Input_line(buffer,ifp)) == NULL ) { warn("Unable to read type in line [%s]",buffer); } else { add_in_MethodTypeSet(mts,in); } } else { warn("In reading only method/types got an impossible line [%s]",buffer); } } return TRUE; }
void expandargv (int *argcp, char ***argvp) { /* The argument we are currently processing. */ int i = 0; /* Non-zero if ***argvp has been dynamically allocated. */ int argv_dynamic = 0; /* Limit the number of response files that we parse in order to prevent infinite recursion. */ unsigned int iteration_limit = 2000; /* Loop over the arguments, handling response files. We always skip ARGVP[0], as that is the name of the program being run. */ while (++i < *argcp) { /* The name of the response file. */ const char *filename; /* The response file. */ FILE *f; /* An upper bound on the number of characters in the response file. */ long pos; /* The number of characters in the response file, when actually read. */ size_t len; /* A dynamically allocated buffer used to hold options read from a response file. */ char *buffer; /* Dynamically allocated storage for the options read from the response file. */ char **file_argv; /* The number of options read from the response file, if any. */ size_t file_argc; /* We are only interested in options of the form "@file". */ filename = (*argvp)[i]; if (filename[0] != '@') continue; /* If we have iterated too many times then stop. */ if (-- iteration_limit == 0) { fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]); xexit (1); } /* Read the contents of the file. */ f = fopen (++filename, "r"); if (!f) continue; if (fseek (f, 0L, SEEK_END) == -1) goto error; pos = ftell (f); if (pos == -1) goto error; if (fseek (f, 0L, SEEK_SET) == -1) goto error; buffer = (char *) xmalloc (pos * sizeof (char) + 1); len = fread (buffer, sizeof (char), pos, f); if (len != (size_t) pos /* On Windows, fread may return a value smaller than POS, due to CR/LF->CR translation when reading text files. That does not in-and-of itself indicate failure. */ && ferror (f)) goto error; /* Add a NUL terminator. */ buffer[len] = '\0'; /* If the file is empty or contains only whitespace, buildargv would return a single empty argument. In this context we want no arguments, instead. */ if (only_whitespace (buffer)) { file_argv = (char **) xmalloc (sizeof (char *)); file_argv[0] = NULL; } else /* Parse the string. */ file_argv = buildargv (buffer); /* If *ARGVP is not already dynamically allocated, copy it. */ if (!argv_dynamic) *argvp = dupargv (*argvp); /* Count the number of arguments. */ file_argc = 0; while (file_argv[file_argc]) ++file_argc; /* Now, insert FILE_ARGV into ARGV. The "+1" below handles the NULL terminator at the end of ARGV. */ *argvp = ((char **) xrealloc (*argvp, (*argcp + file_argc + 1) * sizeof (char *))); memmove (*argvp + i + file_argc, *argvp + i + 1, (*argcp - i) * sizeof (char *)); memcpy (*argvp + i, file_argv, file_argc * sizeof (char *)); /* The original option has been replaced by all the new options. */ *argcp += file_argc - 1; /* Free up memory allocated to process the response file. We do not use freeargv because the individual options in FILE_ARGV are now in the main ARGV. */ free (file_argv); free (buffer); /* Rescan all of the arguments just read to support response files that include other response files. */ --i; error: /* We're all done with the file now. */ fclose (f); } }