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

Stefan Eßer se at FreeBSD.org
Sat Oct 31 15:11:24 UTC 2020


Author: se
Date: Sat Oct 31 15:11:24 2020
New Revision: 367207
URL: https://svnweb.freebsd.org/changeset/base/367207

Log:
  Improve calendar file parsing and consistency tests
  
  Add line number information to more warning and error messages.
  Detect #else and #endif without corresponing #ifdef/#ifndef as error.
  Detect missing #endif at end of file and print warning but continue.
  
  Support for #undef has been added to reverse the effect of a prior #define.
  It is no error if the argument value has not been defined before.
  
  These changes may cause error aborts on malformed input files (e.g. with
  spurious #else or #endif), but no such errors exist in the calendar files
  in the FreeBSD base system and the calendar-data port and all tests pass.
  
  More tests will be added in a follow-up commit to detect regressions that
  might affect the newly added features.
  
  This commit ends a series of updates that enhance the pre-processor and
  make it behave much more like prior versions of the calendar progarm that
  called cpp to pre-process the data files.
  
  MFC after:	3 days
  Relnotes:	yes

Modified:
  head/usr.bin/calendar/io.c

Modified: head/usr.bin/calendar/io.c
==============================================================================
--- head/usr.bin/calendar/io.c	Sat Oct 31 14:59:39 2020	(r367206)
+++ head/usr.bin/calendar/io.c	Sat Oct 31 15:11:24 2020	(r367207)
@@ -153,7 +153,7 @@ cal_fopen(const char *file)
 	warnx(format " in %s/%s/%s line %d", arg1, cal_home, cal_dir, cal_file, cal_line)
 
 static int
-token(char *line, FILE *out, int *skip)
+token(char *line, FILE *out, int *skip, int *unskip)
 {
 	char *walk, c, a;
 	const char *this_cal_home;
@@ -164,6 +164,13 @@ token(char *line, FILE *out, int *skip)
 	if (strncmp(line, "endif", 5) == 0) {
 		if (*skip > 0)
 			--*skip;
+		else if (*unskip > 0)
+			--*unskip;
+		else {
+			WARN0("#endif without prior #ifdef or #ifndef");
+			return (T_ERR);
+		}
+
 		return (T_OK);
 	}
 
@@ -178,7 +185,9 @@ token(char *line, FILE *out, int *skip)
 
 		if (*skip != 0 || definitions == NULL || sl_find(definitions, walk) == NULL)
 			++*skip;
-
+		else
+			++*unskip;
+		
 		return (T_OK);
 	}
 
@@ -193,6 +202,8 @@ token(char *line, FILE *out, int *skip)
 
 		if (*skip != 0 || (definitions != NULL && sl_find(definitions, walk) != NULL))
 			++*skip;
+		else
+			++*unskip;
 
 		return (T_OK);
 	}
@@ -206,10 +217,18 @@ token(char *line, FILE *out, int *skip)
 			return (T_ERR);
 		}
 
-		if (*skip == 0)
+		if (*unskip == 0) {
+			if (*skip == 0) {
+				WARN0("#else without prior #ifdef or #ifndef");
+				return (T_ERR);
+			} else if (*skip == 1) {
+				*skip = 0;
+				*unskip = 1;
+			}
+		} else if (*unskip == 1) {
 			*skip = 1;
-		else if (*skip == 1)
-			*skip = 0;
+			*unskip = 0;
+		}
 
 		return (T_OK);
 	}
@@ -267,10 +286,28 @@ token(char *line, FILE *out, int *skip)
 			return (T_ERR);
 		}
 
-		sl_add(definitions, strdup(walk));
+		if (sl_find(definitions, walk) == NULL)
+			sl_add(definitions, strdup(walk));
 		return (T_OK);
 	}
 
+	if (strncmp(line, "undef", 5) == 0) {
+		if (definitions != NULL) {
+			walk = line + 5;
+			trimlr(&walk);
+
+			if (*walk == '\0') {
+				WARN0("Expecting arguments after #undef");
+				return (T_ERR);
+			}
+
+			walk = sl_find(definitions, walk);
+			if (walk != NULL)
+				walk[0] = '\0';
+		}
+		return (T_OK);
+	}
+
 	return (T_PROCESS);
 
 }
@@ -299,6 +336,7 @@ cal_parse(FILE *in, FILE *out)
 	int day[MAXCOUNT];
 	int year[MAXCOUNT];
 	int skip = 0;
+	int unskip = 0;
 	char dbuf[80];
 	char *pp, p;
 	struct tm tm;
@@ -369,7 +407,7 @@ cal_parse(FILE *in, FILE *out)
 			continue;
 
 		if (buf == line && *buf == '#') {
-			switch (token(buf+1, out, &skip)) {
+			switch (token(buf+1, out, &skip, &unskip)) {
 			case T_ERR:
 				free(line);
 				return (1);
@@ -448,8 +486,7 @@ cal_parse(FILE *in, FILE *out)
 		if (count < 0) {
 			/* Show error status based on return value */
 			if (debug)
-				fprintf(stderr, "Ignored: \"%s\" in %s/%s/%s line %d\n",
-				    buf, cal_home, cal_dir, cal_file, cal_line);
+				WARN1("Ignored: \"%s\"", buf);
 			if (count == -1)
 				continue;
 			count = -count + 1;
@@ -469,12 +506,15 @@ cal_parse(FILE *in, FILE *out)
 			(void)strftime(dbuf, sizeof(dbuf),
 			    d_first ? "%e %b" : "%b %e", &tm);
 			if (debug)
-				fprintf(stderr, "got \"%s\" in  %s/%s/%s line %d\n",
-				    pp, cal_home, cal_dir, cal_file, cal_line);
+				WARN1("got \"%s\"", pp);
 			events[i] = event_add(year[i], month[i], day[i], dbuf,
 			    ((flags &= F_VARIABLE) != 0) ? 1 : 0, pp,
 			    extradata[i]);
 		}
+	}
+	while (skip-- > 0 || unskip-- > 0) {
+		cal_line++;
+		WARN0("Missing #endif assumed");
 	}
 
 	free(line);


More information about the svn-src-all mailing list