From 8916ed3ae40f01e2b0db6b7a4028a24e593d42a0 Mon Sep 17 00:00:00 2001 From: bobhairgrove Date: Sun, 8 Jan 2017 16:55:58 +0100 Subject: [PATCH] Changed argument of print_version to const char* in version.h and version.c; Eliminated "goto" statements; Added code in many places to free allocated memory where necessary; Added calls to regfree and/or pcre_free in csvgrep.c Added checks so as to avoid calling fclose on stdin/stdout Added (void) casts to avoid warnings about variables not used --- include/version.h | 2 +- src/csvbreak.c | 10 +++++ src/csvcheck.c | 22 +++++----- src/csvcut.c | 55 +++++++++++++++++++----- src/csvfix.c | 17 ++++---- src/csvgrep.c | 107 +++++++++++++++++++++++++++++++--------------- src/version.c | 2 +- 7 files changed, 149 insertions(+), 66 deletions(-) diff --git a/include/version.h b/include/version.h index 0171b79..de6dd51 100644 --- a/include/version.h +++ b/include/version.h @@ -1,6 +1,6 @@ #ifndef CSVUTILS_VERSION_H__ #define CSVUTILS_VERSION_H__ -void print_version(char *program_name); +void print_version(const char *program_name); #endif diff --git a/src/csvbreak.c b/src/csvbreak.c index bc8c147..b386804 100644 --- a/src/csvbreak.c +++ b/src/csvbreak.c @@ -403,6 +403,8 @@ make_file_name(const char *name) void cb1 (void *data, size_t len, void *vp) { + (void)vp; + if (need_name_resolution) { if ((strlen(break_field_name) == len) && !strncmp(break_field_name, data, len)) { break_field = current_field + 1; @@ -437,6 +439,9 @@ cb1 (void *data, size_t len, void *vp) void cb2 (int c, void *vp) { + (void)c; + (void)vp; + /* No longer first record when first non-empty record seen */ if (first_record && current_field > 0) { if (write_header) @@ -556,12 +561,16 @@ main (int argc, char *argv[]) while ((bytes_read=fread(buf, 1, 1024, infile)) > 0) { if (csv_parse(&p, buf, bytes_read, cb1, cb2, NULL) != bytes_read) { fprintf(stderr, "Error while parsing file: %s\n", csv_strerror(csv_error(&p))); + csv_free(&p); + if (infile != stdin) fclose(infile); exit(EXIT_FAILURE); } } if (csv_fini(&p, cb1, cb2, NULL)) { fprintf(stderr, "Error while parsing file: %s\n", csv_strerror(csv_error(&p))); + csv_free(&p); + if (infile != stdin) fclose(infile); exit(EXIT_FAILURE); } @@ -570,6 +579,7 @@ main (int argc, char *argv[]) if (just_print_counts) print_counts(); + if (infile != stdin) fclose(infile); call_remove_files = 0; exit(EXIT_SUCCESS); } diff --git a/src/csvcheck.c b/src/csvcheck.c index ebe1295..98ebbb6 100644 --- a/src/csvcheck.c +++ b/src/csvcheck.c @@ -21,7 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. /*lint -ecall(732, csv_set_delim, csv_set_quote) */ /*lint -esym(750, AUTHORS, PROGRAM_NAME) */ -/*lint -e801 goto used */ #include #include @@ -47,7 +46,7 @@ static struct option const longopts[] = /* The name this program was called with */ -char *program_name; +const char *program_name; /* The delimiter character */ char delimiter = CSV_COMMA; @@ -98,6 +97,7 @@ check_file(char *filename) FILE *fp; size_t bytes_read; size_t retval; + int ok = 1; if (csv_init(&p, CSV_STRICT|CSV_STRICT_FINI) != 0) { fprintf(stderr, "Failed to initialize csv parser\n"); @@ -119,24 +119,26 @@ check_file(char *filename) while ((bytes_read=fread(buf, 1, 1024, fp)) > 0) { if ((retval = csv_parse(&p, buf, bytes_read, NULL, NULL, NULL)) != bytes_read) { + ok = 0; if (csv_error(&p) == CSV_EPARSE) { printf("%s: malformed at byte %lu\n", filename ? filename : "stdin", (unsigned long)pos + retval + 1); - goto end; } else { printf("Error while processing %s: %s\n", filename ? filename : "stdin", csv_strerror(csv_error(&p))); - goto end; } + break; } pos += 1024; } - if (csv_fini(&p, NULL, NULL, NULL) != 0) - printf("%s: missing closing quote at end of input\n", filename ? filename : "stdin"); - else - printf("%s well-formed\n", filename ? filename : "data is"); + if (ok) { + if (csv_fini(&p, NULL, NULL, NULL) != 0) + printf("%s: missing closing quote at end of input\n", filename ? filename : "stdin"); + else + printf("%s well-formed\n", filename ? filename : "data is"); + } - end: - fclose(fp); + csv_free(&p); + if (fp != stdin) fclose(fp); } int diff --git a/src/csvcut.c b/src/csvcut.c index 81e2fa7..3004bd5 100644 --- a/src/csvcut.c +++ b/src/csvcut.c @@ -146,6 +146,16 @@ cleanup(void) for (i = 0; i < entry_array_size; i++) free(entry_array[i].data); free(entry_array); + /* field_spec_array: */ + if (field_spec_array) { + for (i=0; i= 0) err("Invalid field spec"); @@ -391,6 +420,7 @@ void cb1(void *s, size_t len, void *data) { size_t i = 0; + (void)data; if (unresolved_fields) { if (first_record) { @@ -434,11 +464,14 @@ cb1(void *s, size_t len, void *data) } void -cb2 (int c, void *data) +cb2 (int m, void *data) { size_t i, j; int first_field = 1; + (void)m; + (void)data; + if (first_record && current_field > 0) first_record = 0; diff --git a/src/csvfix.c b/src/csvfix.c index 6b402ab..b37c052 100644 --- a/src/csvfix.c +++ b/src/csvfix.c @@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define AUTHORS "Robert Gamble" /* The name this program was called with */ -char *program_name; +const char *program_name; /* The delimiter character */ char delimiter = CSV_COMMA; @@ -119,6 +119,7 @@ cb1 (void *s, size_t i, void *outfile) void cb2 (int c, void *outfile) { + (void)c; fputc('\n', (FILE *)outfile); current_field = 0; } @@ -207,7 +208,7 @@ main (int argc, char *argv[]) outfile = fopen(argv[optind+1], "wb"); if (outfile == NULL) { fprintf(stderr, "Failed to open file %s: %s\n", argv[optind+1], strerror(errno)); - fclose(infile); + if (infile != stdin) fclose(infile); exit(EXIT_FAILURE); } } @@ -216,8 +217,8 @@ main (int argc, char *argv[]) while ((i=fread(buf, 1, 1024, infile)) > 0) { if (csv_parse(&p, buf, i, cb1, cb2, outfile) != i) { fprintf(stderr, "Error parsing file: %s\n", csv_strerror(csv_error(&p))); - fclose(infile); - fclose(outfile); + if (infile != stdin) fclose(infile); + if (outfile != stdout) fclose(outfile); if (argc - optind == 2) remove(argv[optind]); exit(EXIT_FAILURE); } @@ -228,14 +229,14 @@ main (int argc, char *argv[]) if (ferror(infile)) { fprintf(stderr, "Error reading from input file"); - fclose(infile); - fclose(outfile); + if (infile != stdin) fclose(infile); + if (outfile != stdout) fclose(outfile); if (argc - optind == 2) remove(argv[argc - optind]); exit(EXIT_FAILURE); } - fclose(infile); - fclose(outfile); + if (infile != stdin) fclose(infile); + if (outfile != stdout) fclose(outfile); return EXIT_SUCCESS; } diff --git a/src/csvgrep.c b/src/csvgrep.c index 1e093eb..7c1d4ab 100644 --- a/src/csvgrep.c +++ b/src/csvgrep.c @@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. /*lint -esym(715, field_spec_cb1, field_spec_cb2, cb1, cb2) */ /*lint -ecall(732, csv_fwrite2, csv_set_delim, csv_set_quote) */ /*lint -esym(750, AUTHORS) */ -/*lint -e801 goto used */ /*lint -esym(818, cb1) */ /*lint -esym(843, preg) */ /*lint -esym(844, re) */ @@ -275,18 +274,30 @@ void process_field_specs(const char *f) { struct csv_parser p; + const char *errmsg[] = { + "Failed to initialize csv parser", + "Invalid field spec", + "Field list cannot be empty" + }; + const char *errstr = NULL; + size_t len = strlen(f); + if (csv_init(&p, CSV_STRICT|CSV_STRICT_FINI)) - err("Failed to initialize csv parser"); + errstr = errmsg[0]; - if (csv_parse(&p, f, len, field_spec_cb1, field_spec_cb2, NULL) != len) - err("Invalid field spec"); + if ((!errstr) && (csv_parse(&p, f, len, field_spec_cb1, field_spec_cb2, NULL) != len)) + errstr = errmsg[1]; - if (csv_fini(&p, field_spec_cb1, field_spec_cb2, NULL)) - err("Invalid field spec"); + if ((!errstr) && (csv_fini(&p, field_spec_cb1, field_spec_cb2, NULL))) + errstr = errmsg[1]; + + if ((!errstr) && (field_spec_size == 0)) + errstr = errmsg[2]; + + csv_free(&p); - if (field_spec_size == 0) - err("Field list cannot be empty"); + if (errstr) err(errstr); } void @@ -308,15 +319,18 @@ field_spec_cb1(void *s, size_t len, void *data) size_t left_size = 0, right_size = 0; long unsigned left_value = 0, right_value = 0; char *left = NULL, *right = NULL; - char *ptr; + char *ptr = NULL, *s_copy = NULL; int left_ended = 0; - left = ptr = Strndup(s, len); + (void)data; + + ptr = s_copy = Strndup(s, len); while (*ptr) { if (*ptr == '-') { if (left_ended || left_size == 0) err("Invalid field spec"); + if (left) free(left); left = Strndup(s, left_size); if (Is_numeric(left)) { left_value = strtoul(left, NULL, 10); @@ -345,6 +359,7 @@ field_spec_cb1(void *s, size_t len, void *data) } else unresolved_fields++; } else { + if (left) free(left); left = Strndup(s, left_size); if (Is_numeric(left)) { left_value = strtoul(left, NULL, 10); @@ -356,6 +371,7 @@ field_spec_cb1(void *s, size_t len, void *data) } right_value = left_value; } + if (left_value != 0) { free(left); left = NULL; @@ -366,11 +382,15 @@ field_spec_cb1(void *s, size_t len, void *data) } add_field_spec(left, right, left_value, right_value); + + free(s_copy); } void field_spec_cb2(int c, void *data) { + (void)data; + /* Field spec should not contain newlines */ if (c >= 0) err("Invalid field spec"); @@ -475,11 +495,11 @@ matches_pattern (const char *pat, char *data, size_t len) return !retval; } else if (match_type == PCRE) { #ifndef WITHOUT_PCRE + free(temp); return !pcre_exec(re, NULL, data, (int)len, 0, 0, NULL, 0); #endif } else { #ifndef WITHOUT_POSIX - temp = Strndup(data, len); retval = regexec(&preg, temp, (size_t)0, NULL, 0); free(temp); return !retval; @@ -491,6 +511,8 @@ void cb1 (void *data, size_t len, void *vp) { size_t i = 0; + (void)vp; + if (unresolved_fields) { /* Print CSV header if non-numeric fields provided and --no-print-header * not specified */ @@ -538,44 +560,49 @@ cb1 (void *data, size_t len, void *vp) void cb2 (int c, void *vp) { + int done = 0; size_t i, j; + (void)c; + (void)vp; + if (first_record && current_field > 0) { first_record = 0; if (print_header && !unresolved_fields) { print_record(); - goto end; - } - if (no_print_header && !unresolved_fields) { - goto end; + done = 1; + } else if (no_print_header && !unresolved_fields) { + done = 1; } } - if (unresolved_fields && !first_record) + if (!done && (unresolved_fields && !first_record)) print_unresolved_fields(); - if (cur_matches && (print_matching_filenames || print_nonmatching_filenames)) - goto end; + if (!done && (cur_matches && (print_matching_filenames || print_nonmatching_filenames))) + done = 1; - for (i = 1; i <= current_field && !match; i++) { - for (j = 0; j < field_spec_size && !match; j++) { - if (i >= field_spec_array[j].start_value - && i <= field_spec_array[j].stop_value - && matches_pattern(pattern, entry_array[i-1].data, entry_array[i-1].size)) - match = 1; + if (!done) { + for (i = 1; i <= current_field && !match; i++) { + for (j = 0; j < field_spec_size && !match; j++) { + if (i >= field_spec_array[j].start_value + && i <= field_spec_array[j].stop_value + && matches_pattern(pattern, entry_array[i-1].data, entry_array[i-1].size)) + match = 1; + } } - } - if (match != invert_match) { - cur_matches++; - if (print_count || print_matching_filenames || print_nonmatching_filenames) - ; - else { - print_record(); + if (match != invert_match) { + cur_matches++; + if (print_count || print_matching_filenames || print_nonmatching_filenames) + ; + else { + print_record(); + } } } -end: +/* end: */ match = 0; current_field = 0; current_record++; @@ -615,7 +642,7 @@ grep_file(char *filename) if (csv_parse(&p, buf, bytes_read, cb1, cb2, NULL) != bytes_read) { fprintf(stderr, "Error while parsing file: %s\n", csv_strerror(csv_error(&p))); csv_free(&p); - fclose(fp); + if (fp != stdin) fclose(fp); return; } } @@ -623,7 +650,7 @@ grep_file(char *filename) if (csv_fini(&p, cb1, cb2, NULL) != 0) { fprintf(stderr, "Error while parsing file: %s\n", csv_strerror(csv_error(&p))); csv_free(&p); - fclose(fp); + if (fp != stdin) fclose(fp); return; } @@ -635,7 +662,7 @@ grep_file(char *filename) return; } - fclose(fp); + if (fp != stdin) fclose(fp); if (print_matching_filenames && cur_matches) { printf("%s\n", filename); @@ -790,6 +817,7 @@ main (int argc, char *argv[]) #else re = pcre_compile(pattern, 0, &err_ptr, &rv, NULL); if (rv) { + pcre_free(re); fprintf(stderr, "Error parsing pattern expression: %s\n", err_ptr); exit(EXIT_FAILURE); } @@ -800,6 +828,7 @@ main (int argc, char *argv[]) #else if ((rv = regcomp(&preg, pattern, REG_EXTENDED | REG_NOSUB )) != 0) { regerror(rv, &preg, errbuf, sizeof errbuf); + regfree(&preg); fprintf(stderr, "Error parsing pattern expression: %s\n", errbuf); exit(EXIT_FAILURE); } @@ -822,6 +851,14 @@ main (int argc, char *argv[]) grep_file(NULL); } +#ifndef WITHOUT_PCRE + pcre_free(re); +#endif + +#ifndef WITHOUT_POSIX + regfree(&preg); +#endif + exit(EXIT_SUCCESS); } diff --git a/src/version.c b/src/version.c index 45e6618..d02b50d 100644 --- a/src/version.c +++ b/src/version.c @@ -9,7 +9,7 @@ #endif void -print_version(char *program_name) +print_version(const char *program_name) { fprintf(stderr, "\ %s (csvutils) %s\n\