diff --git a/usr.bin/calendar/calendar.1 b/usr.bin/calendar/calendar.1 index cf2db36ca4de..240c74d571fe 100644 --- a/usr.bin/calendar/calendar.1 +++ b/usr.bin/calendar/calendar.1 @@ -28,7 +28,7 @@ .\" @(#)calendar.1 8.1 (Berkeley) 6/29/93 .\" $FreeBSD$ .\" -.Dd October 25, 2020 +.Dd October 28, 2020 .Dt CALENDAR 1 .Os .Sh NAME @@ -198,7 +198,13 @@ file is preprocessed by a limited subset of .Xr cpp 1 internally, allowing the inclusion of shared files such as lists of company holidays or meetings. -This limited subset consists of \fB#include #ifndef #endif\fR and \fB#define\fR. +This limited subset consists of \fB#include #ifdef #ifndef #else +#endif\fR and \fB#define\fR. Conditions can be nested, but not check +for matching begin and end directives is performed. +Included files are parsed in their own scope. +They have no read or write access to condition variables defined in +an outer scope and open conditional blocks are implicitly closed. +.Pp If the shared file is not referenced by a full pathname, .Nm searches in the current (or home) directory first, and then in the @@ -346,9 +352,12 @@ double-check the start and end time of solar and lunar events. .Sh BUGS The .Nm -internal cpp does not support nested conditions and will continue -parsing of the input file on the next #endif even in nested contexts. -It does only recognise #include, #define, #ifdef and #ifndef. +does only recognise the cpp directives #include, #define, #ifdef, +#ifndef and #else. +It supports nested conditions, but does not perform any validation +on the correct use and nesting of conditions. +#endif without prior #ifdef or #define is ignored and #else outside +a conditional section skips input lines up to the next #endif. .Pp There is no possibility to properly specify the local position needed for solar and lunar calculations. diff --git a/usr.bin/calendar/io.c b/usr.bin/calendar/io.c index 25cf9b5d451a..6efbc5ca72a5 100644 --- a/usr.bin/calendar/io.c +++ b/usr.bin/calendar/io.c @@ -140,16 +140,64 @@ cal_fopen(const char *file) } static int -token(char *line, FILE *out, bool *skip) +token(char *line, FILE *out, int *skip) { char *walk, c, a; if (strncmp(line, "endif", 5) == 0) { - *skip = false; + if (*skip > 0) + --*skip; return (T_OK); } - if (*skip) + if (strncmp(line, "ifdef", 5) == 0) { + walk = line + 5; + trimlr(&walk); + + if (*walk == '\0') { + warnx("Expecting arguments after #ifdef"); + return (T_ERR); + } + + if (*skip != 0 || definitions == NULL || sl_find(definitions, walk) == NULL) + ++*skip; + + 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 (*skip != 0 || (definitions != NULL && sl_find(definitions, walk) != NULL)) + ++*skip; + + return (T_OK); + } + + if (strncmp(line, "else", 4) == 0) { + walk = line + 4; + trimlr(&walk); + + if (*walk != '\0') { + warnx("Expecting no arguments after #else"); + return (T_ERR); + } + + if (*skip == 0) + *skip = 1; + else if (*skip == 1) + *skip = 0; + + return (T_OK); + } + + if (*skip != 0) return (T_OK); if (strncmp(line, "include", 7) == 0) { @@ -212,36 +260,6 @@ token(char *line, FILE *out, bool *skip) return (T_OK); } - if (strncmp(line, "ifdef", 5) == 0) { - walk = line + 5; - trimlr(&walk); - - if (*walk == '\0') { - warnx("Expecting arguments after #ifdef"); - return (T_ERR); - } - - if (definitions == NULL || sl_find(definitions, walk) == NULL) - *skip = true; - - 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); } @@ -269,7 +287,7 @@ cal_parse(FILE *in, FILE *out) int month[MAXCOUNT]; int day[MAXCOUNT]; int year[MAXCOUNT]; - bool skip = false; + int skip = 0; char dbuf[80]; char *pp, p; struct tm tm; @@ -299,7 +317,7 @@ cal_parse(FILE *in, FILE *out) } } - if (skip) + if (skip != 0) continue; buf = line;