svn commit: r279597 - head/usr.bin/calendar

Baptiste Daroussin bapt at FreeBSD.org
Wed Mar 4 20:04:24 UTC 2015


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);


More information about the svn-src-head mailing list