Much simpler years.

This commit is contained in:
Neil 2022-02-11 01:46:41 -08:00
parent b87906bb49
commit 39b6e01243

View File

@ -11,6 +11,29 @@
#include <limits.h>
#include <errno.h>
static int looks_like_year(const char *const a, int *const year) {
const char *YYCURSOR = a, *YYMARKER = a, *s0;
/*!stags:re2c format = 'const char *@@;\n'; */
assert(a && year);
/*!re2c
re2c:yyfill:enable = 0;
re2c:define:YYCTYPE = char;
re2c:flags:tags = 1;
@s0 ("-"? [1-9][0-9]* | "0") "\x00" {
int sign = 1, mag;
if(*s0 == '-') { sign = -1; s0++; }
for(mag = 0; *s0 != '\0'; s0++) {
int d = *s0 - '0';
if((INT_MAX - d) / 10 < mag) { printf("ov\n"); return 0; }
mag = mag * 10 + d;
}
*year = sign * mag;
return 1;
}
* { return 0; }
*/
}
/* This defines `enum condition`. */
/*!types:re2c*/
enum symbol { END, TEXT, BANG, WHITE, MAP };
@ -29,9 +52,6 @@ struct scanner {
};
/*!re2c
re2c:yyfill:enable = 0;
re2c:flags:tags = 1;
re2c:define:YYCTYPE = char;
re2c:define:YYCURSOR = s->cursor;
re2c:define:YYMARKER = s->marker;
re2c:define:YYCTXMARKER = s->ctx_marker;
@ -82,57 +102,21 @@ scan:
*/
}
/*#define POOL_NAME char
#define POOL_TYPE char
#include "../src/pool.h"*/
struct year_listlink;
static int year_link_compare(const struct year_listlink *,
const struct year_listlink *);
static void yearlist_to_string(const struct year_listlink *, char (*)[12]);
#define LIST_NAME year
#define LIST_EXPECT_TRAIT
#include "../src/list.h"
#define LIST_COMPARE &year_link_compare
#define LIST_EXPECT_TRAIT
#include "../src/list.h"
#define LIST_TO_STRING &yearlist_to_string
#include "../src/list.h"
struct year {
struct year_listlink link;
int year;
char as_string[8];
};
static const size_t year_string_size = sizeof ((struct year *)0)->as_string;
static int year_link_compare(const struct year_listlink *const al,
const struct year_listlink *const bl) {
const struct year *const a = (const struct year *)al,
*const b = (const struct year *)bl;
return (b->year < a->year) - (a->year < b->year);
}
#define POOL_NAME year
#define POOL_TYPE struct year
#include "../src/pool.h"
static unsigned hash_year(const struct year *const year)
{ return (unsigned)(year->year - INT_MIN); }
static int year_is_equal(const struct year *const a, const struct year *const b)
{ return a->year == b->year; }
static void year_to_string(const struct year *const y, char (*const a)[12])
{ strncpy(*a, y->as_string, sizeof(*a) - 1), (*a)[sizeof(*a) - 1] = '\0'; }
static void yearlist_to_string(const struct year_listlink *const y,
char (*const a)[12]) { year_to_string((const struct year *)y, a); }
#define TABLE_NAME year
#define TABLE_KEY struct year *
#define TABLE_UINT unsigned
#define TABLE_HASH &hash_year
#define TABLE_IS_EQUAL &year_is_equal
#define TABLE_EXPECT_TRAIT
#include "../src/table.h"
#define TABLE_DEFAULT 0
#define TABLE_EXPECT_TRAIT
#include "../src/table.h"
#define TABLE_TO_STRING &year_to_string
#include "../src/table.h"
#if INT_MAX >= 100000000000
#error int_to_string requires truncation on this compiler.
#endif
static void int_to_string(const int *const n,
char (*const a)[12]) { sprintf(*a, "%d", *n); }
#define ARRAY_NAME int
#define ARRAY_TYPE int
#define ARRAY_EXPECT_TRAIT
#include "../src/array.h"
#define ARRAY_TO_STRING &int_to_string
#include "../src/array.h"
static int int_cmp(const int *const a, const int *const b)
{ return (*b < *a) - (*a < *b); }
static int void_int_cmp(const void *const a, const void *const b)
{ return int_cmp(a, b); }
#include <unistd.h> /* chdir (POSIX) */
#include <sys/types.h> /* mode_t (POSIX) */
@ -144,42 +128,31 @@ int main(int argc, char **argv) {
int success = EXIT_FAILURE;
DIR *year_dir;
struct dirent *year_de;
struct year_pool year_pool = POOL_IDLE;
struct year_list order;
struct year_table years = TABLE_IDLE;
struct int_array years = ARRAY_IDLE;
/* Get the years list. fixme: this is way overkill; `int_array`. */
/* Get the years list as directories matching a year in order. */
errno = 0;
year_list_clear(&order);
if(argc != 2) { fprintf(stderr, "Needs journal location.\n"
"(should contain <year>/<month>/<day>.txt)\n"); goto finally; }
if(chdir(argv[1]) == -1 || !(year_dir = opendir("."))) goto catch;
while((year_de = readdir(year_dir))) {
struct stat st;
char *const start = year_de->d_name, *end;
long year = strtol(start, &end, 0); /* Need better. */
struct year *y;
if(errno || *end != '\0' || (size_t)(end - start) >= year_string_size
|| year < INT_MIN || year > INT_MAX)
{ /*fprintf(stderr, "%s: doesn't look like a year.\n",
year_de->d_name);*/ errno = 0; continue; }
int year, *p;
if(!looks_like_year(year_de->d_name, &year)) continue;
if(stat(year_de->d_name, &st)) goto catch;
if(!S_ISDIR(st.st_mode)) { /*fprintf(stderr,
"%s: isn't a directory.\n", year_de->d_name);*/ continue; }
if(!(y = year_pool_new(&year_pool))) goto catch;
y->year = (int)year;
strcpy(y->as_string, year_de->d_name);
year_list_push(&order, &y->link);
if(!S_ISDIR(st.st_mode)) continue;
if(!(p = int_array_new(&years))) goto catch;
*p = year;
}
year_list_sort(&order);
fprintf(stderr, "Years: %s\n", year_list_to_string(&order));
qsort(years.data, years.size, sizeof *years.data, &void_int_cmp);
fprintf(stderr, "Years: %s, size %lu.\n",
int_array_to_string(&years), (unsigned long)years.size);
/* Go though each of the years, in order, and extract meta-information. */
{ success = EXIT_SUCCESS; goto finally; }
catch:
perror("interpret");
finally:
year_table_(&years);
year_pool_(&year_pool);
int_array_(&years);
return EXIT_FAILURE;
}