From 5cd3c7ac6b5406461a36335ae7df9b91f3d892fd Mon Sep 17 00:00:00 2001 From: Neil Date: Sat, 12 Feb 2022 22:17:45 -0800 Subject: [PATCH] yyyy-mm-dd --- src/interpret.re_c.c | 112 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 14 deletions(-) diff --git a/src/interpret.re_c.c b/src/interpret.re_c.c index b030955..182b889 100644 --- a/src/interpret.re_c.c +++ b/src/interpret.re_c.c @@ -11,20 +11,22 @@ #include #include +/*!re2c +re2c:yyfill:enable = 0; +re2c:define:YYCTYPE = char; +*/ + 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; } + if((INT_MAX - d) / 10 < mag) return 0; mag = mag * 10 + d; } *year = sign * mag; @@ -34,6 +36,32 @@ static int looks_like_year(const char *const a, int *const year) { */ } +static int looks_like_month(const char *const a) { + const char *YYCURSOR = a, *YYMARKER = a, *s0; + /*!stags:re2c format = 'const char *@@;\n'; */ + assert(a); + /*!re2c + @s0 [0-1][0-9] "\x00" { + int val = 10 * (s0[0] - '0') + (s0[1] - '0'); + return val < 1 || val > 12 ? 0 : val; + } + * { return 0; } + */ +} + +static int looks_like_day(const char *const a) { + const char *YYCURSOR = a, *YYMARKER = a, *s0; + /*!stags:re2c format = 'const char *@@;\n'; */ + assert(a); + /*!re2c + @s0 [0-3][0-9] ".txt\x00" { + int val = 10 * (s0[0] - '0') + (s0[1] - '0'); + return val < 1 || val > 31 ? 0 : val; + } + * { return 0; } + */ +} + /* This defines `enum condition`. */ /*!types:re2c*/ enum symbol { END, TEXT, BANG, BRACKET, WHITE, MAP }; @@ -52,6 +80,7 @@ struct scanner { }; /*!re2c +re2c:flags:tags = 1; re2c:define:YYCURSOR = s->cursor; re2c:define:YYMARKER = s->marker; re2c:define:YYCTXMARKER = s->ctx_marker; @@ -128,33 +157,88 @@ static int void_int_cmp(const void *const a, const void *const b) int main(int argc, char **argv) { int success = EXIT_FAILURE; - DIR *year_dir; - struct dirent *year_de; - struct int_array years = ARRAY_IDLE; + DIR *dir = 0; + struct dirent *de; + struct int_array years = ARRAY_IDLE, months = ARRAY_IDLE, days = ARRAY_IDLE; + int *y, *y_end; /* Get the years list as directories matching a year in order. */ errno = 0; if(argc != 2) { fprintf(stderr, "Needs journal location.\n" "(should contain //.txt)\n"); goto finally; } - if(chdir(argv[1]) == -1 || !(year_dir = opendir("."))) goto catch; - while((year_de = readdir(year_dir))) { + if(chdir(argv[1]) == -1 || !(dir = opendir("."))) goto catch; + while((de = readdir(dir))) { struct stat st; int year, *p; - if(!looks_like_year(year_de->d_name, &year)) continue; - if(stat(year_de->d_name, &st)) goto catch; + if(!looks_like_year(de->d_name, &year)) continue; + if(stat(de->d_name, &st)) goto catch; if(!S_ISDIR(st.st_mode)) continue; if(!(p = int_array_new(&years))) goto catch; *p = year; } + closedir(dir), dir = 0; 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); + fprintf(stderr, "%s: %s.\n", argv[1], int_array_to_string(&years)); - /* Go though each of the years, in order, and extract meta-information. */ + /* Go though each year. */ + for(y = years.data, y_end = y + years.size; y < y_end; y++) { + char temp[64]; + int *m, *m_end; + sprintf(temp, "%d", *y); + + /* Get the months as directories. */ + if(chdir(temp) == -1 || !(dir = opendir("."))) goto catch; + while((de = readdir(dir))) { + struct stat st; + int month, *p; + if(!(month = looks_like_month(de->d_name))) continue; + if(stat(de->d_name, &st)) goto catch; + if(!S_ISDIR(st.st_mode)) continue; + if(!(p = int_array_new(&months))) goto catch; + *p = month; + } + closedir(dir), dir = 0; + qsort(months.data, months.size, sizeof *months.data, &void_int_cmp); + fprintf(stderr, "%s: %s.\n", temp, int_array_to_string(&months)); + + /* Go though each month. */ + for(m = months.data, m_end = m + months.size; m < m_end; m++) { + int *d, *d_end; + sprintf(temp, "%.2d", *m); + + /* Get the days as files. */ + if(chdir(temp) == -1 || !(dir = opendir("."))) goto catch; + while((de = readdir(dir))) { + struct stat st; + int day, *p; + /* fixme: Have yyyy-mm-dd to figure out how many days. */ + if(!(day = looks_like_day(de->d_name))) continue; + if(stat(de->d_name, &st)) goto catch; + if(S_ISDIR(st.st_mode)) continue; + if(!(p = int_array_new(&days))) goto catch; + *p = day; + } + closedir(dir), dir = 0; + qsort(days.data, days.size, sizeof *days.data, &void_int_cmp); + fprintf(stderr, "%s: %s.\n", temp, int_array_to_string(&days)); + + for(d = days.data, d_end = d + days.size; d < d_end; d++) { + printf("%d-%.2d-%.2d\n", *y, *m, *d); + } + + int_array_clear(&days); + if(chdir("..") == -1) goto catch; + } + + int_array_clear(&months); + if(chdir("..") == -1) goto catch; + } { success = EXIT_SUCCESS; goto finally; } catch: perror("interpret"); finally: + if(dir) closedir(dir); int_array_(&years); + int_array_(&months); return EXIT_FAILURE; }