From 96433cf5b428951bfe0a56ca54058b49091e2d7f Mon Sep 17 00:00:00 2001 From: Neil Date: Sun, 21 Mar 2021 12:45:06 -0700 Subject: [PATCH] Line numbers. --- src/main.c | 38 +++++++++++++++++++++++--------------- src/min_array.h | 4 ++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main.c b/src/main.c index 223f31b..1e58b35 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,10 @@ -#include /* EXIT_ strtol */ -#include /* FILE fopen fclose fread */ +/** This is a test for `min_array.h`: takes an arbitrary stream, (Cntl-d stops + in most implementations of interactive terminal,) and greedily extracts + integers in the style of `strtol` until it gets to the end-of-file or a + null-terminator. */ + +#include /* size_t EXIT_ strtol */ +#include /* FILE fopen fclose fread [f]printf ferror perror */ #include /* errno */ #include /* isdigit */ #include /* LONG_ INT_ _MIN _MAX */ @@ -9,10 +14,10 @@ MIN_ARRAY(char, char) MIN_ARRAY(num, int) -/** Concatenates the contents of `fp` after the file pointer to `string`. The - file pointer is modified. Zeros are preserved, as well as appending a - null-terminator. @return Success, otherwise `string` may have read a partial - read and may not be terminated. @throws[fread, malloc] */ +/** Concatenates the contents after the file pointer of `fp` to `string`. Zeros + are preserved, as well as appending a null-terminator. @return Success, + otherwise `string` may have read a partial read and may not be terminated. + @throws[fread, malloc] */ static int cat_fp_to_str(FILE *const fp, struct char_array *const string) { const size_t granularity = 1024; size_t nread; @@ -27,6 +32,7 @@ static int cat_fp_to_str(FILE *const fp, struct char_array *const string) { return 1; } +/** Stores the entire stream and then stores the extracted `int` numbers. */ int main(void) { int success = EXIT_FAILURE; struct char_array str = MIN_ARRAY_IDLE; @@ -34,28 +40,30 @@ int main(void) { int *num; long big_num; char *a, *anum = 0; - size_t i; + size_t i, line = 1 /* Unix: delimited by '\n'. */; errno = 0; /* In case we are running it as part of another editor. */ if(!cat_fp_to_str(stdin, &str)) goto catch; - /*printf("<<<%s>>>\n", str.data);*/ - /* The first sentinel '\0' it stops, even though it could have more data, - and we could conceivably use the length to continue; it's simple. */ - for(a = str.data; a = strpbrk(a, "-0123456789"); ) { + /* It would be conceivable use the length to continue past the first + sentinel '\0', but not that complex. */ + fprintf(stderr, "Read:\n<<<%s>>>\n", str.data); + for(a = str.data; a = strpbrk(a, "-0123456789\n"); ) { + if(*a == '\n') { line++; a++; continue; } if(*a == '-') { anum = a++; continue; } if(!(num = num_array_new(&nums))) goto catch; if(!anum || anum != a - 1) anum = a; /* Wasn't negative. */ big_num = strtol(anum, &a, 0); if((!big_num || big_num == LONG_MIN || big_num == LONG_MAX) && errno) - goto catch; /* Long conversion failed. */ + goto catch; /* Long conversion failed, (not all platforms.) */ if(big_num < INT_MIN || big_num > INT_MAX) { errno = ERANGE; goto catch; } - *num = (int)big_num; /* Safe now. */ + *num = (int)big_num; } - for(i = 0; i < nums.size; i++) printf("Extracted %d.\n", nums.data[i]); + fprintf(stderr, "Extracted:\n"); + for(i = 0; i < nums.size; i++) printf("%d\n", nums.data[i]); success = EXIT_SUCCESS; goto finally; catch: - perror("stdin"); + fprintf(stderr, "Line %lu ", line), perror("stdin"); finally: char_array_(&str); num_array_(&nums); diff --git a/src/min_array.h b/src/min_array.h index cfdca11..b05e2af 100644 --- a/src/min_array.h +++ b/src/min_array.h @@ -1,4 +1,4 @@ -/** X-macro for a minimal dynamic array. `MIN_ARRAY(name, type)`, where `name` +/** X-macro for a minimal dynamic array: `MIN_ARRAY(name, type)`, where `name` is an identifier prefix that satisfies `C` naming conventions when mangled and `type` is defined tag-type associated therewith. When expanding the array, resizing may be necessary and incurs amortised cost; any pointers to this @@ -72,7 +72,7 @@ static type *name##_array_new(struct name##_array *const a) { \ type *const data = name##_array_buffer(a, 1); \ return data ? name##_array_emplace(a, 1), data : 0; \ } \ -/* They don't have to all be used, (destructor is important.) */ \ +/* It's perfectly valid that these functions are not used. */ \ static void name##_unused_coda(void); static void name##_unused(void) { \ name##_array(0); name##_array_new(0); name##_unused_coda(); } \ static void name##_unused_coda(void) { name##_unused(); }