/* * This function reads from a file a list of file names. Each name * starts with the first non-space character, and ends with the last * non-space character. Spaces in the middle are OK. */ static int flist_read_names(const char*path) { char line_buf[2048]; FILE*fd = fopen(path, "r"); if (fd == 0) { fprintf(stderr, "%s: unable to open for reading.\n", path); return 1; } while (fgets(line_buf, sizeof line_buf, fd) != 0) { char*cp = line_buf + strspn(line_buf, " \t\r\b\f"); char*tail = cp + strlen(cp); while (tail > cp) { if (! isspace((int)tail[-1])) break; tail -= 1; tail[0] = 0; } if (cp < tail) add_source_file(cp); } fclose(fd); return 0; }
int main(int argc, char*argv[]) { int opt, idx; unsigned lp; const char*flist_path = 0; unsigned flag_errors = 0; char*out_path = 0; FILE*out; char*precomp_out_path = 0; FILE*precomp_out = NULL; /* Define preprocessor keywords that I plan to just pass. */ /* From 1364-2005 Chapter 19. */ define_macro("begin_keywords", "`begin_keywords", 1, 0); define_macro("celldefine", "`celldefine", 1, 0); define_macro("default_nettype", "`default_nettype", 1, 0); define_macro("end_keywords", "`end_keywords", 1, 0); define_macro("endcelldefine", "`endcelldefine", 1, 0); define_macro("line", "`line", 1, 0); define_macro("nounconnected_drive", "`nounconnected_drive", 1, 0); define_macro("pragma", "`pragma", 1, 0); define_macro("resetall", "`resetall", 1, 0); define_macro("timescale", "`timescale", 1, 0); define_macro("unconnected_drive", "`unconnected_drive", 1, 0); /* From 1364-2005 Annex D. */ define_macro("default_decay_time", "`default_decay_time", 1, 0); define_macro("default_trireg_strength", "`default_trireg_strength", 1, 0); define_macro("delay_mode_distributed", "`delay_mode_distributed", 1, 0); define_macro("delay_mode_path", "`delay_mode_path", 1, 0); define_macro("delay_mode_unit", "`delay_mode_unit", 1, 0); define_macro("delay_mode_zero", "`delay_mode_zero", 1, 0); /* From other places. */ define_macro("disable_portfaults", "`disable_portfaults", 1, 0); define_macro("enable_portfaults", "`enable_portfaults", 1, 0); define_macro("endprotect", "`endprotect", 1, 0); define_macro("nosuppress_faults", "`nosuppress_faults", 1, 0); define_macro("protect", "`protect", 1, 0); define_macro("suppress_faults", "`suppress_faults", 1, 0); define_macro("uselib", "`uselib", 1, 0); include_cnt = 2; include_dir = malloc(include_cnt*sizeof(char*)); include_dir[0] = 0; /* 0 is reserved for the current files path. */ include_dir[1] = strdup("."); while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) { case 'F': flist_read_flags(optarg); break; case 'f': if (flist_path) { fprintf(stderr, "%s: duplicate -f flag\n", argv[0]); flag_errors += 1; } flist_path = optarg; break; case 'K': { char*buf = malloc(strlen(optarg) + 2); buf[0] = '`'; strcpy(buf+1, optarg); define_macro(optarg, buf, 1, 0); free(buf); break; } case 'L': line_direct_flag = 1; break; case 'o': if (out_path) { fprintf(stderr, "duplicate -o flag.\n"); } else { out_path = optarg; } break; case 'p': if (precomp_out_path) { fprintf(stderr, "duplicate -p flag.\n"); } else { precomp_out_path = optarg; } break; case 'P': { FILE*src = fopen(optarg, "rb"); if (src == 0) { perror(optarg); exit(1); } load_precompiled_defines(src); fclose(src); break; } case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version " VERSION " (" VERSION_TAG ")\n\n"); fprintf(stderr, "%s\n\n", COPYRIGHT); fputs(NOTICE, stderr); verbose_flag = 1; break; case 'V': fprintf(stdout, "Icarus Verilog Preprocessor version " VERSION " (" VERSION_TAG ")\n\n"); fprintf(stdout, "%s\n", COPYRIGHT); fputs(NOTICE, stdout); return 0; default: flag_errors += 1; break; } if (flag_errors) { fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n" " -F<fil> - Get defines and includes from file\n" " -f<fil> - Read the sources listed in the file\n" " -K<def> - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -o<fil> - Send the output to <fil>\n" " -p<fil> - Write precompiled defines to <fil>\n" " -P<fil> - Read precompiled defines from <fil>\n" " -v - Verbose\n" " -V - Print version information and quit\n", argv[0]); return flag_errors; } /* Collect the file names on the command line in the source file list, then if there is a file list, read more file names from there. */ for (idx = optind ; idx < argc ; idx += 1) add_source_file(argv[idx]); if (flist_path) { int rc = flist_read_names(flist_path); if (rc != 0) return rc; } /* Figure out what to use for an output file. Write to stdout if no path is specified. */ if (out_path) { out = fopen(out_path, "w"); if (out == 0) { perror(out_path); exit(1); } } else { out = stdout; } if (precomp_out_path) { precomp_out = fopen(precomp_out_path, "wb"); if (precomp_out == 0) { if (out_path) fclose(out); perror(precomp_out_path); exit(1); } } if (dep_path) { depend_file = fopen(dep_path, "a"); if (depend_file == 0) { if (out_path) fclose(out); if (precomp_out) fclose(precomp_out); perror(dep_path); exit(1); } } if (source_cnt == 0) { fprintf(stderr, "%s: No input files given.\n", argv[0]); if (out_path) fclose(out); if (depend_file) fclose(depend_file); if (precomp_out) fclose(precomp_out); return 1; } if (vhdlpp_work == 0) { vhdlpp_work = strdup("ivl_vhdl_work"); } /* Pass to the lexical analyzer the list of input file, and start scanning. */ reset_lexor(out, source_list); if (yylex()) { if (out_path) fclose(out); if (depend_file) fclose(depend_file); if (precomp_out) fclose(precomp_out); return -1; } destroy_lexor(); if (depend_file) fclose(depend_file); if (precomp_out) { dump_precompiled_defines(precomp_out); fclose(precomp_out); } if (out_path) fclose(out); /* Free the source and include directory lists. */ for (lp = 0; lp < source_cnt; lp += 1) { free(source_list[lp]); } free(source_list); for (lp = 0; lp < include_cnt; lp += 1) { free(include_dir[lp]); } free(include_dir); /* Free the VHDL library directories, the path and work directory. */ for (lp = 0; lp < vhdlpp_libdir_cnt; lp += 1) { free(vhdlpp_libdir[lp]); } free(vhdlpp_libdir); free(vhdlpp_path); free(vhdlpp_work); free_macros(); return error_count; }
/** * This directive will insert definitions from another file into * the current collection. If the file name is adorned with * double quotes or angle brackets (as in a C program), then the * include is ignored. */ char * doDir_include(directive_enum_t id, char const * dir, char * scan_next) { static char const * const apzSfx[] = { DIRECT_INC_DEF_SFX, NULL }; scan_ctx_t * new_ctx; size_t inc_sz; char full_name[ AG_PATH_MAX + 1 ]; (void)id; dir = SPN_WHITESPACE_CHARS(dir); /* * Ignore C-style includes. This allows "C" files to be processed * for their "#define"s. */ if ((*dir == '"') || (*dir == '<')) return scan_next; if (! SUCCESSFUL( find_file(dir, full_name, apzSfx, cctx->scx_fname))) { errno = ENOENT; fswarn("search for", cctx->scx_fname); return scan_next; } /* * Make sure the specified file is a regular file and we can get * the correct size for it. */ inc_sz = file_size(full_name); if (inc_sz == 0) return scan_next; /* * Get the space for the output data and for context overhead. * This is an extra allocation and copy, but easier than rewriting * 'loadData()' for this special context. */ { size_t sz = sizeof(scan_ctx_t) + 4 + inc_sz; new_ctx = (scan_ctx_t *)AGALOC(sz, "inc def head"); memset(VOIDP(new_ctx), 0, sz); new_ctx->scx_line = 1; } /* * Link it into the context stack */ cctx->scx_scan = scan_next; new_ctx->scx_next = cctx; cctx = new_ctx; AGDUPSTR(new_ctx->scx_fname, full_name, "def file"); new_ctx->scx_scan = new_ctx->scx_data = scan_next = (char *)(new_ctx + 1); /* * Read all the data. Usually in a single read, but loop * in case multiple passes are required. */ { FILE * fp = fopen(full_name, "r" FOPEN_TEXT_FLAG); char * pz = scan_next; if (fp == NULL) AG_CANT(DIRECT_INC_CANNOT_OPEN, full_name); if (dep_fp != NULL) add_source_file(full_name); do { size_t rdct = fread(VOIDP(pz), (size_t)1, inc_sz, fp); if (rdct == 0) AG_CANT(DIRECT_INC_CANNOT_READ, full_name); pz += rdct; inc_sz -= rdct; } while (inc_sz > 0); fclose(fp); *pz = NUL; } return scan_next; }
int main(int argc, char*argv[]) { int opt, idx; const char*flist_path = 0; unsigned flag_errors = 0; const char*out_path = 0; const char*dep_path = NULL; FILE*out; /* Define preprocessor keywords that I plan to just pass. */ define_macro("celldefine", "`celldefine", 1); define_macro("default_nettype", "`default_nettype", 1); define_macro("delay_mode_distributed", "`delay_mode_distributed", 1); define_macro("delay_mode_unit", "`delay_mode_unit", 1); define_macro("delay_mode_path", "`delay_mode_path", 1); define_macro("disable_portfaults", "`disable_portfaults", 1); define_macro("enable_portfaults", "`enable_portfaults", 1); define_macro("endcelldefine", "`endcelldefine", 1); define_macro("endprotect", "`endprotect", 1); define_macro("nosuppress_faults", "`nosuppress_faults", 1); define_macro("nounconnected_drive", "`nounconnected_drive", 1); define_macro("protect", "`protect", 1); define_macro("resetall", "`resetall", 1); define_macro("suppress_faults", "`suppress_faults", 1); define_macro("timescale", "`timescale", 1); define_macro("unconnected_drive", "`unconnected_drive", 1); define_macro("uselib", "`uselib", 1); include_dir = malloc(sizeof(char*)); include_dir[0] = strdup("."); include_cnt = 1; while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) { case 'D': { char*tmp = strdup(optarg); char*val = strchr(tmp, '='); if (val) *val++ = 0; else val = "1"; define_macro(tmp, val, 0); free(tmp); break; } case 'f': if (flist_path) { fprintf(stderr, "%s: duplicate -f flag\n", argv[0]); flag_errors += 1; } flist_path = optarg; break; case 'I': include_dir = realloc(include_dir, (include_cnt+1)*sizeof(char*)); include_dir[include_cnt] = strdup(optarg); include_cnt += 1; break; case 'K': { char*buf = malloc(strlen(optarg) + 2); buf[0] = '`'; strcpy(buf+1, optarg); define_macro(optarg, buf, 1); free(buf); break; } case 'L': line_direct_flag = 1; break; case 'M': if (dep_path) { fprintf(stderr, "duplicate -M flag.\n"); } else { dep_path = optarg; } break; case 'o': if (out_path) { fprintf(stderr, "duplicate -o flag.\n"); } else { out_path = optarg; } break; case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version %s\n\n", VERSION); fprintf(stderr, "%s\n", COPYRIGHT); fputs(NOTICE, stderr); break; default: flag_errors += 1; break; } if (flag_errors) { fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n" " -D<def> - Predefine a value.\n" " -f<fil> - Read the sources listed in the file\n" " -I<dir> - Add an include file search directory\n" " -K<def> - Define a keyword macro that I just pass\n" " -L - Emit line number directives\n" " -M<fil> - Write dependencies to <fil>\n" " -o<fil> - Send the output to <fil>\n" " -v - Print version information\n", argv[0]); return flag_errors; } /* Collect the file names on the command line in the source file list, then if there is a file list, read more file names from there. */ for (idx = optind ; idx < argc ; idx += 1) add_source_file(argv[idx]); if (flist_path) { int rc = flist_read_names(flist_path); if (rc != 0) return rc; } /* Figure out what to use for an output file. Write to stdout if no path is specified. */ if (out_path) { out = fopen(out_path, "w"); if (out == 0) { perror(out_path); exit(1); } } else { out = stdout; } if(dep_path) { depend_file = fopen(dep_path, "w"); if (depend_file == 0) { perror(dep_path); exit(1); } } if (source_cnt == 0) { fprintf(stderr, "%s: No input files given.\n", argv[0]); return 1; } /* Pass to the lexical analyzer the list of input file, and start the parser. */ reset_lexor(out, source_list); if (yyparse()) return -1; if(depend_file) { fclose(depend_file); } return error_count; }
main(int argc, char **argv) { extern int optind; /* for use of getopt() */ extern char *optarg; /* for use of getopt() */ int ch; /* command-line option letter */ static char *ProgName = "esig2fea"; /* name of this program */ static char *Version = SCCS_VERSION; /* program SCCS version */ static char *Date = SCCS_DATE; /* program SCCS date */ char **field_names = NULL; int num_fields = 0; int alloc_fields = 0; int rflag = NO; /* -r option specified? */ char *rrange; /* arguments of -r option */ long start_rec; /* starting record number */ long end_rec; /* ending record number */ long num_recs; /* number of records to read (0 means all up to end of file) */ long num_read; /* number of records actually read */ char *iname; /* input file name */ FILE *ifile; /* input stream */ FieldList list; /* input field list */ int inord; /* input: field order or type order? */ FieldSpec **ifields; /* input fields in field or type order */ char *subtype = NULL; /* FEA subtype name */ int subtype_code = NONE; /* numeric subtype code */ FieldSpec *fld; /* spec of various special fields */ char *oname; /* output file name */ FILE *ofile; /* output stream */ struct header *ohd; /* output file header */ struct fea_data *orec; /* output record */ int outord = TYPE_ORDER; char *version; /* version from input preamble */ int arch; /* architecture from input preamble */ long pre_size; /* preamble size */ long hdr_size; /* header size (bytes) from preamble */ long rec_size; /* record size from preamble */ double rec_freq; double start_time_offset; double *data; long len, i; struct header *source; /* embedded source-file header */ while ((ch = getopt(argc, argv, "f:r:x:FT:")) != EOF) switch (ch) { case 'f': if (num_fields >= alloc_fields) { size_t size; alloc_fields = num_fields + 1 + num_fields/2; size = (alloc_fields + 1) * sizeof(char *); field_names = (char **) ((field_names == NULL) ? malloc(size) : realloc(field_names, size)); } field_names[num_fields++] = optarg; field_names[num_fields] = NULL; break; case 'r': rflag = YES; rrange = optarg; break; case 'x': debug_level = atoi(optarg); break; case 'F': outord = FIELD_ORDER; break; case 'T': subtype = optarg; break; default: SYNTAX; break; } if (argc - optind > 2) { fprintf(stderr, "%s: too many file names specified.\n", ProgName); SYNTAX; } if (argc - optind < 2) { fprintf(stderr, "%s: too few file names specified.\n", ProgName); SYNTAX; } DebugMsgLevel = debug_level; DebugMsgFunc = DebugPrint; iname = argv[optind++]; list = OpenIn(iname, &version, &arch, &pre_size, &hdr_size, &rec_size, &ifile); REQUIRE(list != NULL, "read header failed"); if (ifile == stdin) iname = "<stdin>"; oname = argv[optind++]; start_rec = 0; end_rec = LONG_MAX; num_recs = 0; /* 0 means continue to end of file */ if (rflag) { lrange_switch(rrange, &start_rec, &end_rec, 0); if (end_rec != LONG_MAX) num_recs = end_rec - start_rec + 1; } REQUIRE(start_rec >= 0, "can't start before beginning of file"); REQUIRE(end_rec >= start_rec, "empty range of records specified"); if (debug_level) fprintf(stderr, "start_rec: %ld. end_rec: %ld. num_recs: %ld.\n", start_rec, end_rec, num_recs); REQUIRE(GetFieldOrdering(list, &inord), "cant get field ordering of input"); switch (inord) { case TYPE_ORDER: if (debug_level) fprintf(stderr, "making type-ordered field array.\n"); ifields = TypeOrder(list); break; case FIELD_ORDER: if (debug_level) fprintf(stderr, "making field-ordered field array.\n"); ifields = FieldOrder(list); break; default: REQUIRE(0, "input order neither TYPE_ORDER nor FIELD_ORDER"); break; } ohd = FieldList_to_fea(list, &orec, field_names, FALSE); REQUIRE(ohd != NULL, "failure converting input field list to header & record struct"); if (subtype != NULL) { subtype_code = lin_search(fea_file_type, subtype); if (subtype_code == -1) fprintf(stderr, "%s: unknown FEA file subtype \"%s\" ignored.\n", ProgName, subtype); else ohd->hd.fea->fea_type = subtype_code; } if (outord == FIELD_ORDER) ohd->hd.fea->field_order = YES; fld = FindField(list, "recordFreq"); if (fld != NULL && fld->occurrence == GLOBAL && fld->data != NULL) { (void) type_convert(1L, (char *) fld->data, ElibTypeToEsps(fld->type), (char *) &rec_freq, FDOUBLE, (void (*)()) NULL); *add_genhd_d("record_freq", NULL, 1, ohd) = rec_freq; } else rec_freq = 1.0; fld = FindField(list, "startTime"); if (fld != NULL && fld->occurrence == GLOBAL && fld->data != NULL && rec_freq != 0) { start_time_offset = start_rec / rec_freq; len = FieldLength(fld); data = (double *) type_convert(len, (char *) fld->data, ElibTypeToEsps(fld->type), (char *) NULL, FDOUBLE, (void (*)()) NULL); if (start_time_offset != 0) { for (i = 0; i < len; i++) data[i] += start_time_offset; } (void) add_genhd_d("start_time", data, len, ohd); } (void) strcpy(ohd->common.prog, ProgName); (void) strcpy(ohd->common.vers, Version); (void) strcpy(ohd->common.progdate, Date); source = FieldList_to_fea(list, NULL, NULL, TRUE); add_source_file(ohd, savestring(iname), source); add_comment(ohd, get_cmd_line(argc, argv)); oname = eopen(ProgName, oname, "w", NONE, NONE, NULL, &ofile); write_header(ohd, ofile); num_read = SkipRecs(ifile, start_rec, RecordSize(list, arch), ifields, arch); if (num_read != start_rec) { fprintf(stderr, "%s: couldn't reach starting record; only %ld skipped.\n", ProgName, num_read); exit(0); } for ( ; num_read <= end_rec && ReadRecord(ifields, arch, ifile); num_read++) { put_fea_rec(orec, ohd, ofile); } if (num_read <= end_rec && num_recs != 0) fprintf(stderr, "esig2fea: only %ld records read.\n", num_read - start_rec); exit(0); /*NOTREACHED*/ }
static struct header * FieldList_to_fea(FieldList list, struct fea_data **rec, char **fnames, int copy_sources) { struct header *hdr; int i, j; FieldSpec *fld; char **codes; FieldList subfields; FieldSpec *subf; char *name; void *ptr; int spstype; long *dim; struct fea_header *fea; struct header *source; if (list == NULL) return NULL; hdr = new_header(FT_FEA); for (i = 0; (fld = list[i]) != NULL; i++) { codes = NULL; if (fld->occurrence != VIRTUAL && (subfields = fld->subfields) != NULL) { for (j = 0; (subf = subfields[j]) != NULL; j++) { if (strcmp(subf->name, "enumStrings") != 0) { if (debug_level) fprintf(stderr, "FieldList_to_fea: subfields " "not supported in ESPS FEA files.\n"); } else if (fld->type != SHORT) { if (debug_level) fprintf(stderr, "FieldList_to_fea: Non-SHORT field " "has subfield enumStrings.\n"); } else if (subf->type != CHAR) { if (debug_level) fprintf(stderr, "FieldList_to_fea: enumStrings not CHAR.\n"); } else if (subf->rank != 2) { if (debug_level) fprintf(stderr, "FieldList_to_fea: enumStrings " "not of rank 2.\n"); } else codes = StrArrayFromRect(subf->dim, subf->data); } } if (FieldIsTag(fld) && FindStr(ESPS_TAG, fnames)) hdr->common.tag = TRUE; else if (FieldIsFeaSubtype(fld)) hdr->hd.fea->fea_type = *(short *) fld->data; else { name = fld->name; switch(fld->occurrence) { case GLOBAL: { int size = (int) FieldLength(fld); ptr = fld->data; if (debug_level >= 2) fprintf(stderr, "FieldList_to_fea: " "global field[%d]: \"%s\".\n", i, name); if (fld->rank > 1) { if (debug_level) fprintf(stderr, "FieldList_to_fea: rank %d globals " "not supported in ESPS FEA files.\n", fld->rank); } if (size == 0) { if (debug_level) fprintf(stderr, "FieldList_to_fea: empty globals " "not supported in ESPS FEA files.\n"); } else if (codes != NULL) (void) add_genhd_e(name, (short *) ptr, size, codes, hdr); else switch (fld->type) { case DOUBLE: (void) add_genhd_d(name, (double *) ptr, size, hdr); break; case FLOAT: (void) add_genhd_f(name, (float *) ptr, size, hdr); break; case LONG: (void) add_genhd_l(name, (long *) ptr, size, hdr); break; case SHORT: (void) add_genhd_s(name, (short *) ptr, size, hdr); break; case SCHAR: case UCHAR: case CHAR: (void) add_genhd_c(name, (char *) ptr, size, hdr); break; default: if (debug_level) fprintf(stderr, "FieldList_to_fea: global type %d " "not supported in ESPS FEA files.\n", fld->type); } } break; case REQUIRED: { long size = FieldLength(fld); if (debug_level >= 2) fprintf(stderr, "FieldList_to_fea: " "required field[%d]: \"%s\".\n", i, name); if (FindStr(name, fnames)) { spstype = (codes != NULL) ? CODED : ElibTypeToEsps(fld->type); if (spstype != UNDEF) { dim = (long *) malloc(fld->rank * sizeof(long)); for (j = 0; j < fld->rank; j++) dim[j] = fld->dim[j]; add_fea_fld(name, size, fld->rank, dim, spstype, codes, hdr); } } } break; case OPTIONAL: if (debug_level) fprintf(stderr, "FieldList_to_fea: optional fields " "not supported in ESPS FEA files.\n"); break; case VIRTUAL: if (copy_sources) { if (strncmp(name, "source_", 7) != 0) { if (debug_level) fprintf(stderr, "Field_List_to_fea: VIRTUAL " "field other than source_<n>.\n"); } else if ((subfields = fld->subfields) != NULL || fld->type == CHAR) { size_t len; char *data; source = FieldList_to_fea(subfields, NULL, NULL, TRUE); len = FieldLength(fld); data = (char *) malloc(len + 1); strncpy(data, fld->data, len); data[len] = '\0'; add_source_file(hdr, data, source); } } break; case INCLUDED: if (debug_level) fprintf(stderr, "FieldList_to_fea: included fields " "not supported in ESPS FEA files.\n"); break; default: spsassert(0, "FieldList_to_fea: " "unrecognized occurrence code.\n"); break; } } } if (rec != NULL) { *rec = allo_fea_rec(hdr); fea = hdr->hd.fea; if (hdr->common.tag) { fld = FindField(list, ESPS_TAG); fld->data = &(*rec)->tag; } for (i = 0; i < (int) fea->field_count; i++) { name = fea->names[i]; fld = FindField(list, name); fld->data = get_fea_ptr(*rec, name, hdr); } } return hdr; }
/** * Load a file into memory. Keep it in memory and try to reuse it * if we get called again. Likely, there will be several extractions * from a single file. */ static char const* load_extract_file(char const* pzNewFile) { static char const * pzFile = NULL; static char const * pzText = NULL; struct stat sbuf; char* pzIn; /* * Make sure that we: * * o got the file name from the SCM value * o return the old text if we are searching the same file * o have a regular file with some data * o can allocate the space we need... * * If we don't know about the current file, we leave the data * from any previous file we may have loaded. * * DO *NOT* include this file in dependency output. The output may vary * based on its contents, but since it is always optional input, it cannot * be made to be required by make. */ if (pzNewFile == NULL) return NULL; if ( (pzFile != NULL) && (strcmp(pzFile, pzNewFile) == 0)) return pzText; if ( (stat(pzNewFile, &sbuf) != 0) || (! S_ISREG(sbuf.st_mode)) || (sbuf.st_size < 10) ) return NULL; if (pzFile != NULL) { AGFREE((void*)pzFile); AGFREE((void*)pzText); pzFile = pzText = NULL; } AGDUPSTR(pzFile, pzNewFile, "extract file"); pzIn = (char*)AGALOC(sbuf.st_size + 1, "Extract Text"); if (! HAVE_OPT(WRITABLE)) SET_OPT_WRITABLE; pzText = (char const*)pzIn; /* * Suck up the file. We must read it all. */ { struct stat stbf; FILE* fp = fopen(pzNewFile, "r"); if (fp == NULL) goto bad_return; if (fstat(fileno(fp), &stbf) != 0) { fclose(fp); goto bad_return; } if (outTime <= stbf.st_mtime) outTime = stbf.st_mtime + 1; do { size_t sz = fread(pzIn, (size_t)1, (size_t)sbuf.st_size, fp); if (sz == 0) { fprintf(stderr, LD_EXTRACT_BAD_READ, errno, strerror(errno), (int)sbuf.st_size, pzFile); AG_ABEND(LD_EXTRACT_READ_FAIL); } pzIn += sz; sbuf.st_size -= sz; } while (sbuf.st_size > 0); *pzIn = NUL; fclose(fp); if (pfDepends != NULL) add_source_file(pzNewFile); } return pzText; bad_return: AGFREE((void*)pzFile); pzFile = NULL; AGFREE((void*)pzText); pzText = NULL; return pzText; }