Restrict locale settings to the file they occur in
This prevents LANG= in an included file from affecting the interpretation of month and day names in the including file. Make the internal pre-processor accept white space between the "#" at the start of the line and the keyword for better compatibility with cpp. Add support for the cpp keywords #warning and #error. MFC after: 3 days
This commit is contained in:
parent
20172854ab
commit
0357fa2632
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)calendar.1 8.1 (Berkeley) 6/29/93
|
.\" @(#)calendar.1 8.1 (Berkeley) 6/29/93
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd November 4, 2020
|
.Dd November 5, 2020
|
||||||
.Dt CALENDAR 1
|
.Dt CALENDAR 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -199,13 +199,14 @@ file is preprocessed by a limited subset of
|
|||||||
internally, allowing the inclusion of shared files such as
|
internally, allowing the inclusion of shared files such as
|
||||||
lists of company holidays or meetings.
|
lists of company holidays or meetings.
|
||||||
This limited subset consists of \fB#include\fR, \fB#define\fR,
|
This limited subset consists of \fB#include\fR, \fB#define\fR,
|
||||||
\fB#undef\fR, \fB#ifdef\fR, \fB#ifndef\fR, and \fB#else\fR.
|
\fB#undef\fR, \fB#ifdef\fR, \fB#ifndef\fR, \fB#else\fR, \fB#warning\fR,
|
||||||
|
and \fB#error\fR.
|
||||||
.Pp
|
.Pp
|
||||||
Conditions can be nested and the consistency of opening and closing
|
Conditions can be nested and the consistency of opening and closing
|
||||||
instructions is checked.
|
instructions is checked.
|
||||||
Only the first word after #define is used as the name of the
|
Only the first word after #define is used as the name of the
|
||||||
condition variable being defined.
|
condition variable being defined.
|
||||||
More than word following #ifdef, #ifndef, or #undef is a ayntax
|
More than word following #ifdef, #ifndef, or #undef is considered a syntax
|
||||||
error, since names cannot include white-space.
|
error, since names cannot include white-space.
|
||||||
Included files are parsed in a global scope with regard to the condition
|
Included files are parsed in a global scope with regard to the condition
|
||||||
variables being defined or tested therein.
|
variables being defined or tested therein.
|
||||||
|
@ -130,7 +130,6 @@ struct event {
|
|||||||
int month;
|
int month;
|
||||||
int day;
|
int day;
|
||||||
int var;
|
int var;
|
||||||
char *date;
|
|
||||||
char *text;
|
char *text;
|
||||||
char *extra;
|
char *extra;
|
||||||
struct event *next;
|
struct event *next;
|
||||||
|
@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <iconv.h>
|
#include <iconv.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#include <locale.h>
|
|
||||||
|
|
||||||
static iconv_t conv = (iconv_t)-1;
|
static iconv_t conv = (iconv_t)-1;
|
||||||
static char *currentEncoding = NULL;
|
static char *currentEncoding = NULL;
|
||||||
@ -204,13 +203,7 @@ event_print_all(FILE *fp)
|
|||||||
struct tm tm;
|
struct tm tm;
|
||||||
char dbuf[80];
|
char dbuf[80];
|
||||||
static int d_first;
|
static int d_first;
|
||||||
const char *lang;
|
|
||||||
|
|
||||||
lang = getenv("LANG");
|
|
||||||
if (lang == NULL)
|
|
||||||
lang = "C";
|
|
||||||
if (setlocale(LC_ALL, lang) == NULL)
|
|
||||||
(void)setlocale(LC_ALL, "C");
|
|
||||||
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
|
d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
|
||||||
|
|
||||||
while (walkthrough_dates(&e) != 0) {
|
while (walkthrough_dates(&e) != 0) {
|
||||||
|
@ -172,6 +172,16 @@ cal_path(void)
|
|||||||
#define WARN1(format, arg1) \
|
#define WARN1(format, arg1) \
|
||||||
warnx(format " in %s line %d", arg1, cal_path(), cal_line)
|
warnx(format " in %s line %d", arg1, cal_path(), cal_line)
|
||||||
|
|
||||||
|
static char*
|
||||||
|
cmptoken(char *line, const char* token)
|
||||||
|
{
|
||||||
|
char len = strlen(token);
|
||||||
|
|
||||||
|
if (strncmp(line, token, len) != 0)
|
||||||
|
return NULL;
|
||||||
|
return (line + len);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
token(char *line, FILE *out, int *skip, int *unskip)
|
token(char *line, FILE *out, int *skip, int *unskip)
|
||||||
{
|
{
|
||||||
@ -181,7 +191,10 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
const char *this_cal_file;
|
const char *this_cal_file;
|
||||||
int this_cal_line;
|
int this_cal_line;
|
||||||
|
|
||||||
if (strncmp(line, "endif", 5) == 0) {
|
while (isspace(*line))
|
||||||
|
line++;
|
||||||
|
|
||||||
|
if (cmptoken(line, "endif")) {
|
||||||
if (*skip + *unskip == 0) {
|
if (*skip + *unskip == 0) {
|
||||||
WARN0("#endif without prior #ifdef or #ifndef");
|
WARN0("#endif without prior #ifdef or #ifndef");
|
||||||
return (T_ERR);
|
return (T_ERR);
|
||||||
@ -194,8 +207,8 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(line, "ifdef", 5) == 0) {
|
walk = cmptoken(line, "ifdef");
|
||||||
walk = line + 5;
|
if (walk != NULL) {
|
||||||
sep = trimlr(&walk);
|
sep = trimlr(&walk);
|
||||||
|
|
||||||
if (*walk == '\0') {
|
if (*walk == '\0') {
|
||||||
@ -217,8 +230,8 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(line, "ifndef", 6) == 0) {
|
walk = cmptoken(line, "ifndef");
|
||||||
walk = line + 6;
|
if (walk != NULL) {
|
||||||
sep = trimlr(&walk);
|
sep = trimlr(&walk);
|
||||||
|
|
||||||
if (*walk == '\0') {
|
if (*walk == '\0') {
|
||||||
@ -240,8 +253,8 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(line, "else", 4) == 0) {
|
walk = cmptoken(line, "else");
|
||||||
walk = line + 4;
|
if (walk != NULL) {
|
||||||
(void)trimlr(&walk);
|
(void)trimlr(&walk);
|
||||||
|
|
||||||
if (*walk != '\0') {
|
if (*walk != '\0') {
|
||||||
@ -267,9 +280,8 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
if (*skip != 0)
|
if (*skip != 0)
|
||||||
return (T_OK);
|
return (T_OK);
|
||||||
|
|
||||||
if (strncmp(line, "include", 7) == 0) {
|
walk = cmptoken(line, "include");
|
||||||
walk = line + 7;
|
if (walk != NULL) {
|
||||||
|
|
||||||
(void)trimlr(&walk);
|
(void)trimlr(&walk);
|
||||||
|
|
||||||
if (*walk == '\0') {
|
if (*walk == '\0') {
|
||||||
@ -306,10 +318,10 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(line, "define", 6) == 0) {
|
walk = cmptoken(line, "define");
|
||||||
|
if (walk != NULL) {
|
||||||
if (definitions == NULL)
|
if (definitions == NULL)
|
||||||
definitions = sl_init();
|
definitions = sl_init();
|
||||||
walk = line + 6;
|
|
||||||
sep = trimlr(&walk);
|
sep = trimlr(&walk);
|
||||||
*sep = '\0';
|
*sep = '\0';
|
||||||
|
|
||||||
@ -323,9 +335,9 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(line, "undef", 5) == 0) {
|
walk = cmptoken(line, "undef");
|
||||||
|
if (walk != NULL) {
|
||||||
if (definitions != NULL) {
|
if (definitions != NULL) {
|
||||||
walk = line + 5;
|
|
||||||
sep = trimlr(&walk);
|
sep = trimlr(&walk);
|
||||||
|
|
||||||
if (*walk == '\0') {
|
if (*walk == '\0') {
|
||||||
@ -345,8 +357,32 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
return (T_OK);
|
return (T_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (T_PROCESS);
|
walk = cmptoken(line, "warning");
|
||||||
|
if (walk != NULL) {
|
||||||
|
(void)trimlr(&walk);
|
||||||
|
WARN1("Warning: %s", walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
walk = cmptoken(line, "error");
|
||||||
|
if (walk != NULL) {
|
||||||
|
(void)trimlr(&walk);
|
||||||
|
WARN1("Error: %s", walk);
|
||||||
|
return (T_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN1("Undefined pre-processor command \"#%s\"", line);
|
||||||
|
return (T_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup_locale(const char *locale)
|
||||||
|
{
|
||||||
|
(void)setlocale(LC_ALL, locale);
|
||||||
|
#ifdef WITH_ICONV
|
||||||
|
if (!doall)
|
||||||
|
set_new_encoding();
|
||||||
|
#endif
|
||||||
|
setnnames();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define REPLACE(string, slen, struct_) \
|
#define REPLACE(string, slen, struct_) \
|
||||||
@ -361,6 +397,7 @@ token(char *line, FILE *out, int *skip, int *unskip)
|
|||||||
static int
|
static int
|
||||||
cal_parse(FILE *in, FILE *out)
|
cal_parse(FILE *in, FILE *out)
|
||||||
{
|
{
|
||||||
|
char *mylocale = NULL;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t linecap = 0;
|
size_t linecap = 0;
|
||||||
@ -459,12 +496,9 @@ cal_parse(FILE *in, FILE *out)
|
|||||||
* and does not run iconv(), this variable has little use.
|
* and does not run iconv(), this variable has little use.
|
||||||
*/
|
*/
|
||||||
if (strncmp(buf, "LANG=", 5) == 0) {
|
if (strncmp(buf, "LANG=", 5) == 0) {
|
||||||
(void)setlocale(LC_ALL, buf + 5);
|
if (mylocale == NULL)
|
||||||
#ifdef WITH_ICONV
|
mylocale = strdup(setlocale(LC_ALL, NULL));
|
||||||
if (!doall)
|
setup_locale(buf + 5);
|
||||||
set_new_encoding();
|
|
||||||
#endif
|
|
||||||
setnnames();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Parse special definitions: Easter, Paskha etc */
|
/* Parse special definitions: Easter, Paskha etc */
|
||||||
@ -538,6 +572,10 @@ cal_parse(FILE *in, FILE *out)
|
|||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
if (mylocale != NULL) {
|
||||||
|
setup_locale(mylocale);
|
||||||
|
free(mylocale);
|
||||||
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user