Date: Wed, 4 Mar 2015 20:04:23 +0000 (UTC) From: Baptiste Daroussin <bapt@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r279597 - head/usr.bin/calendar Message-ID: <201503042004.t24K4NUQ053921@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bapt Date: Wed Mar 4 20:04:23 2015 New Revision: 279597 URL: https://svnweb.freebsd.org/changeset/base/279597 Log: Rework calendar(1) parser Support includes surrounded by '"' or '<' '>' Print warnings about bad syntax Correctly navigate through include directories to find calendar files Correctly support multiple includes Tested by: gjb MFC after: 1 week Deleted: head/usr.bin/calendar/calcpp.c Modified: head/usr.bin/calendar/Makefile head/usr.bin/calendar/calendar.h head/usr.bin/calendar/io.c Modified: head/usr.bin/calendar/Makefile ============================================================================== --- head/usr.bin/calendar/Makefile Wed Mar 4 19:47:33 2015 (r279596) +++ head/usr.bin/calendar/Makefile Wed Mar 4 20:04:23 2015 (r279597) @@ -5,7 +5,7 @@ PROG= calendar SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \ - ostern.c paskha.c pom.c sunpos.c calcpp.c + ostern.c paskha.c pom.c sunpos.c LIBADD= m INTER= de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \ hr_HR.ISO8859-2 hu_HU.ISO8859-2 pt_BR.ISO8859-1 \ Modified: head/usr.bin/calendar/calendar.h ============================================================================== --- head/usr.bin/calendar/calendar.h Wed Mar 4 19:47:33 2015 (r279596) +++ head/usr.bin/calendar/calendar.h Wed Mar 4 20:04:23 2015 (r279597) @@ -168,10 +168,6 @@ void closecal(FILE *); FILE *opencalin(void); FILE *opencalout(void); -/* calcpp.c */ -void initcpp(void); -FILE *fincludegets(char *buf, int size, FILE *fp); - /* ostern.c / paskha.c */ int paskha(int); int easter(int); Modified: head/usr.bin/calendar/io.c ============================================================================== --- head/usr.bin/calendar/io.c Wed Mar 4 19:47:33 2015 (r279596) +++ head/usr.bin/calendar/io.c Wed Mar 4 20:04:23 2015 (r279597) @@ -51,14 +51,23 @@ __FBSDID("$FreeBSD$"); #include <langinfo.h> #include <locale.h> #include <pwd.h> +#include <stdbool.h> +#define _WITH_GETLINE #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stringlist.h> #include <unistd.h> #include "pathnames.h" #include "calendar.h" +enum { + T_OK = 0, + T_ERR, + T_PROCESS, +}; + const char *calendarFile = "calendar"; /* default calendar file */ static const char *calendarHomes[] = {".calendar", _PATH_INCLUDE}; /* HOME */ static const char *calendarNoMail = "nomail";/* don't sent mail if file exist */ @@ -68,6 +77,147 @@ static char path[MAXPATHLEN]; struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon; struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice; +static int cal_parse(FILE *in, FILE *out); + +static StringList *definitions = NULL; +static struct event *events[MAXCOUNT]; +static char *extradata[MAXCOUNT]; + +static void +trimlr(char **buf) +{ + char *walk = *buf; + + while (isspace(*walk)) + walk++; + while (isspace(walk[strlen(walk) -1])) + walk[strlen(walk) -1] = '\0'; + + *buf = walk; +} + +static FILE * +cal_fopen(const char *file) +{ + FILE *fp; + char *home = getenv("HOME"); + unsigned int i; + + if (home == NULL || *home == '\0') { + warnx("Cannot get home directory"); + return (NULL); + } + + if (chdir(home) != 0) { + warnx("Cannot enter home directory"); + return (NULL); + } + + for (i = 0; i < sizeof(calendarHomes)/sizeof(calendarHomes[0]) ; i++) { + if (chdir(calendarHomes[i]) != 0) + continue; + + if ((fp = fopen(file, "r")) != NULL) + return (fp); + } + + warnx("can't open calendar file \"%s\"", file); + + return (NULL); +} + +static int +token(char *line, FILE *out, bool *skip) +{ + char *walk, c, a; + + if (strncmp(line, "endif", 5) == 0) { + *skip = false; + return (T_OK); + } + + if (*skip) + return (T_OK); + + if (strncmp(line, "include", 7) == 0) { + walk = line + 7; + + trimlr(&walk); + + if (*walk == '\0') { + warnx("Expecting arguments after #include"); + return (T_ERR); + } + + if (*walk != '<' && *walk != '\"') { + warnx("Excecting '<' or '\"' after #include"); + return (T_ERR); + } + + a = *walk; + walk++; + c = walk[strlen(walk) - 1]; + + switch(c) { + case '>': + if (a != '<') { + warnx("Unterminated include expecting '\"'"); + return (T_ERR); + } + break; + case '\"': + if (a != '\"') { + warnx("Unterminated include expecting '>'"); + return (T_ERR); + } + break; + default: + warnx("Unterminated include expecting '%c'", + a == '<' ? '>' : '\"' ); + return (T_ERR); + } + walk[strlen(walk) - 1] = '\0'; + + if (cal_parse(cal_fopen(walk), out)) + return (T_ERR); + + return (T_OK); + } + + if (strncmp(line, "define", 6) == 0) { + if (definitions == NULL) + definitions = sl_init(); + walk = line + 6; + trimlr(&walk); + + if (*walk == '\0') { + warnx("Expecting arguments after #define"); + return (T_ERR); + } + + sl_add(definitions, strdup(walk)); + return (T_OK); + } + + if (strncmp(line, "ifndef", 6) == 0) { + walk = line + 6; + trimlr(&walk); + + if (*walk == '\0') { + warnx("Expecting arguments after #ifndef"); + return (T_ERR); + } + + if (definitions != NULL && sl_find(definitions, walk) != NULL) + *skip = true; + + return (T_OK); + } + + return (T_PROCESS); + +} + #define REPLACE(string, slen, struct_) \ if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \ if (struct_.name != NULL) \ @@ -77,30 +227,25 @@ struct fixs nmarequinox, nsepequinox, nj struct_.len = strlen(buf + (slen)); \ continue; \ } -void -cal(void) +static int +cal_parse(FILE *in, FILE *out) { - char *pp, p; - FILE *fpin; - FILE *fpout; - int l; - int count, i; + char *line = NULL; + char *buf; + size_t linecap = 0; + ssize_t linelen; + ssize_t l; + static int d_first = -1; + static int count = 0; + int i; int month[MAXCOUNT]; int day[MAXCOUNT]; int year[MAXCOUNT]; - char **extradata; /* strings of 20 length */ - int flags; - static int d_first = -1; - char buf[2048 + 1]; - struct event *events[MAXCOUNT]; - struct tm tm; + bool skip = false; char dbuf[80]; - - initcpp(); - extradata = (char **)calloc(MAXCOUNT, sizeof(char *)); - for (i = 0; i < MAXCOUNT; i++) { - extradata[i] = (char *)calloc(1, 20); - } + char *pp, p; + struct tm tm; + int flags; /* Unused */ tm.tm_sec = 0; @@ -108,20 +253,32 @@ cal(void) tm.tm_hour = 0; tm.tm_wday = 0; - count = 0; - if ((fpin = opencalin()) == NULL) { - free(extradata); - return; - } - if ((fpout = opencalout()) == NULL) { - fclose(fpin); - free(extradata); - return; - } - while ((fpin = fincludegets(buf, sizeof(buf), fpin)) != NULL) { - if (*buf == '\0') + if (in == NULL) + return (1); + + while ((linelen = getline(&line, &linecap, in)) > 0) { + if (linelen == 0) + continue; + + if (*line == '#') { + switch (token(line+1, out, &skip)) { + case T_ERR: + free(line); + return (1); + case T_OK: + continue; + case T_PROCESS: + break; + default: + break; + } + } + + if (skip) continue; - for (l = strlen(buf); + + buf = line; + for (l = linelen; l > 0 && isspace((unsigned char)buf[l - 1]); l--) ; @@ -208,16 +365,41 @@ cal(void) } } + free(line); + fclose(in); + + return (0); +} + +void +cal(void) +{ + FILE *fpin; + FILE *fpout; + int i; + + for (i = 0; i < MAXCOUNT; i++) + extradata[i] = (char *)calloc(1, 20); + + + if ((fpin = opencalin()) == NULL) + return; + + if ((fpout = opencalout()) == NULL) { + fclose(fpin); + return; + } + + if (cal_parse(fpin, fpout)) + return; + event_print_all(fpout); closecal(fpout); - free(extradata); } FILE * opencalin(void) { - size_t i; - int found; struct stat sbuf; FILE *fpin; @@ -231,22 +413,7 @@ opencalin(void) if ((fpin = fopen(calendarFile, "r")) == NULL) return (NULL); } else { - char *home = getenv("HOME"); - if (home == NULL || *home == '\0') - errx(1, "cannot get home directory"); - if (chdir(home) != 0) - errx(1, "cannot enter home directory"); - for (found = i = 0; i < sizeof(calendarHomes) / - sizeof(calendarHomes[0]); i++) - if (chdir(calendarHomes[i]) == 0 && - (fpin = fopen(calendarFile, "r")) != NULL) { - found = 1; - break; - } - if (!found) - errx(1, - "can't open calendar file \"%s\": %s (%d)", - calendarFile, strerror(errno), errno); + fpin = cal_fopen(calendarFile); } } return (fpin);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503042004.t24K4NUQ053921>