home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1992 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1992.iso
/
usenet
/
altsrcs
/
3
/
3865
< prev
next >
Wrap
Text File
|
1991-08-22
|
50KB
|
1,771 lines
Path: wupost!uwm.edu!linac!att!cbnews!jbr0
From: jbr0@cbnews.cb.att.com (joseph.a.brownlee)
Newsgroups: alt.sources
Subject: Pcal v4.1, part 5 of 6
Keywords: pcal calendar postscript
Message-ID: <1991Aug19.121859.979@cbnews.cb.att.com>
Date: 19 Aug 91 12:18:59 GMT
Organization: AT&T Bell Laboratories
Lines: 1760
#!/bin/sh
# This is part 05 of a multipart archive
# ============= pcallang.h ==============
if test -f 'pcallang.h' -a X"$1" != X"-c"; then
echo 'x - skipping pcallang.h (File already exists)'
else
echo 'x - extracting pcallang.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pcallang.h' &&
/*
X * pcallang.h - language-dependent strings (month and day names, option file
X * keywords, preprocessor tokens, prepositions, etc.):
X *
X * Revision history:
X *
X * 4.1 AWR 08/16/91 support -G flag (outlined gray)
X *
X * 4.02 AWR 07/02/91 support -v flag (version number);
X * add ordinal_suffix(); add format
X * specifiers to help message
X *
X * 4.0 AWR 03/01/91 expand parameter message to explain
X * parameter meaning when -w specified
X *
X * AWR 02/19/91 revise ordinal definitions for
X * support of negative ordinals
X *
X * AWR 02/06/91 add text describing expression syntax
X *
X * AWR 02/04/91 support "odd" and "even" ordinals
X *
X * AWR 01/28/91 support -B (blank fill squares) flag
X * and -O (outline "gray" dates) flag
X *
X * AWR 01/16/91 added moon file support (tokens, help
X * file text, error messages); define
X * note block heading here
X *
X * AWR 01/07/91 added support for -w (whole year) flag
X *
X * 3.0 AWR 12/10/90 added support for "workday", "weekday",
X * "holiday", et. al.
X *
X * AWR 11/15/90 extracted from pcal.c; revised
X * to contain all language-dependent
X * strings
X */
X
#define ALL "all" /* command-line or date file keyword */
X
#ifdef MAIN_MODULE
X
char *months[12] = {
X "January", "February", "March", "April", "May", "June",
X "July", "August", "September", "October", "November", "December"
X };
X
/* Must be a 2-D array so address within may be used as an initializer;
X * wildcard names must be in same order as symbolic names in pcaldefs.h
X */
char days[14][12] = {
X "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
X "Saturday", /* weekday names */
X "day", "weekday", "workday", "holiday", "nonweekday", "nonworkday",
X "nonholiday" /* wildcards */
X };
X
/* preprocessor tokens: token name, token code, dispatch routine */
X
KWD_F pp_info[] = {
X "define", PP_DEFINE, do_define,
X "else", PP_ELSE, NULL,
X "endif", PP_ENDIF, NULL,
X "ifdef", PP_IFDEF, do_ifdef,
X "ifndef", PP_IFNDEF, do_ifndef,
X "include", PP_INCLUDE, NULL, /* do_include */
X "undef", PP_UNDEF, do_undef,
X NULL, PP_OTHER, NULL }; /* must be last */
X
/* ordinal numbers - e.g. "first Monday in September": ordinal name,
X * ordinal code, ordinal value; note that "all" is parsed as a keyword
X * and (depending on context) may be subsequently treated as an ordinal
X */
X
KWD_O ordinals[] = {
X "first", ORD_POSNUM, 1,
X "second", ORD_POSNUM, 2,
X "third", ORD_POSNUM, 3,
X "fourth", ORD_POSNUM, 4,
X "fifth", ORD_POSNUM, 5,
X "last", ORD_NEGNUM, -1,
X "odd", ORD_ODD, 0,
X "even", ORD_EVEN, 0,
X NULL, ORD_OTHER, 0 }; /* must be last */
X
/* allowable suffixes for ordinal numbers */
X
char *ord_suffix[] = { "st", "nd", "rd", "th", NULL };
X
/* prepositions - e.g., "Friday after fourth Thursday in November" */
X
KWD preps[] = {
X "before", PR_BEFORE,
X "preceding", PR_BEFORE,
X "on_or_before", PR_ON_BEFORE,
X "oob", PR_ON_BEFORE,
X "after", PR_AFTER,
X "following", PR_AFTER,
X "on_or_after", PR_ON_AFTER,
X "ooa", PR_ON_AFTER,
X NULL, PR_OTHER }; /* must be last */
X
/* other keywords */
X
KWD keywds[] = {
X ALL, DT_ALL,
X "each", DT_ALL,
X "every", DT_ALL,
X "note", DT_NOTE,
X "opt", DT_OPT,
X "year", DT_YEAR,
X NULL, DT_OTHER }; /* must be last */
X
/* moon phases (for moon file) */
X
KWD phases[] = {
X "NM", MOON_NM, /* new moon */
X "1Q", MOON_1Q, /* first quarter */
X "FQ", MOON_1Q,
X "FM", MOON_FM, /* full moon */
X "3Q", MOON_3Q, /* third (last) quarter */
X "LQ", MOON_3Q,
X NULL, MOON_OTHER }; /* must be last */
X
#else
extern char *months[];
extern char days[14][12];
extern KWD_F pp_info[];
extern KWD preps[];
extern KWD_O ordinals[];
extern char *ord_suffix[];
extern KWD keywds[];
extern KWD phases[];
#endif
X
/* minimum size of abbreviations */
X
#define MIN_DAY_LEN 3
#define MIN_MONTH_LEN 3
#define MIN_PPTOK_LEN 3
#define MIN_PREP_LEN 7 /* distinguish "on_or_before", "on_or_after" */
#define MIN_ORD_LEN 3 /* distinguish "Thursday" from "third" */
X
X
/*
X * Symbolic names for command-line flags. These may be changed
X * as desired in order to be meaningful in languages other than
X * English.
X */
X
#define F_INITIALIZE 'I' /* re-initialize program defaults */
#define F_BLACK_DAY 'b' /* print day in black */
#define F_GRAY_DAY 'g' /* print day in gray */
X
#define F_DAY_FONT 'd' /* select alternate day font */
#define F_NOTES_FONT 'n' /* select alternate notes font */
#define F_TITLE_FONT 't' /* select alternate title font */
X
#define F_EMPTY_CAL 'e' /* print empty calendar */
#define F_DATE_FILE 'f' /* select alternate date file */
#define F_OUT_FILE 'o' /* select alternate output file */
X
#define F_LANDSCAPE 'l' /* landscape mode */
#define F_PORTRAIT 'p' /* portrait mode */
X
#define F_HELP 'h' /* generate full help message */
#define F_VERSION 'v' /* generate version ID */
X
#define F_MOON_4 'm' /* print new/half/full moons */
#define F_MOON_ALL 'M' /* print all moons */
X
#define F_DEFINE 'D' /* define preprocessor symbol */
#define F_UNDEF 'U' /* undefine preprocessor symbol */
X
#define F_L_FOOT 'L' /* define left foot string */
#define F_C_FOOT 'C' /* define center foot string */
#define F_R_FOOT 'R' /* define right foot string */
X
#define F_FIRST_DAY 'F' /* define alternate starting day */
X
#define F_USA_DATES 'A' /* parse American date format */
#define F_EUR_DATES 'E' /* parse European date format */
X
#define F_X_TRANS 'X' /* X-axis transformation */
#define F_Y_TRANS 'Y' /* Y-axis transformation */
#define F_X_SCALE 'x' /* X-axis scale factor */
#define F_Y_SCALE 'y' /* Y-axis scale factor */
X
#define F_JULIAN 'j' /* print Julian day (day of year) */
#define F_JULIAN_ALL 'J' /* print Julian day and days left */
X
#define F_WHOLE_YEAR 'w' /* print whole year per page */
X /* (cf. W_WYFLAG below) */
X
#define F_BLANK_BOXES 'B' /* don't fill unused boxes */
X
#define F_OUTLINE_GRAY 'G' /* outline and fill "gray" dates */
#define F_OUTLINE 'O' /* draw "gray" dates as outlines */
X
/*
X * Flag usage information - not strictly language-dependent, but here anyway
X * (N.B.: all flags must be represented by an entry in this table!)
X *
X * Flags may appear in any of three places: in environment variable
X * PCAL_OPTS, on the command line, or in "opt" lines in the date file.
X * The command line is actually parsed twice: once before reading the date
X * file to get the flags needed in processing it (-e, -f, -b, -g, -D, -U, -A,
X * -E), and again after reading the date file to give the user one last
X * chance to override any of the other flags set earlier. (Note, however,
X * that the only way to turn off -J|-j [Julian dates], -M|-m [moons], -w
X * [whole year], or -G|-O [outline "gray" dates] once selected is to use -I
X * to reinitialize all program defaults.)
X *
X * The table below supplies the following information about each flag:
X *
X * - Its name (cf. symbolic definitions above)
X *
X * - Whether or not it can take an (optional) argument
X *
X * - Which passes parse it: P_ENV (environment variable), P_CMD1
X * (first command line pass), P_OPT ("opt" lines in date file),
X * and P_CMD2 (second command line pass)
X *
X */
X
#ifdef MAIN_MODULE
X
FLAG_USAGE flag_tbl[] = {
X
/* flag name arg? passes where parsed */
X
X F_INITIALIZE, FALSE, P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
X
X F_BLACK_DAY, TRUE, P_ENV | P_CMD1 | P_OPT ,
X F_GRAY_DAY, TRUE, P_ENV | P_CMD1 | P_OPT ,
X
X F_DAY_FONT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_NOTES_FONT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_TITLE_FONT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X
X F_EMPTY_CAL, FALSE, P_ENV | P_CMD1 ,
X F_DATE_FILE, TRUE, P_ENV | P_CMD1 ,
X F_OUT_FILE, TRUE, P_ENV | P_OPT | P_CMD2 ,
X
X F_LANDSCAPE, FALSE, P_ENV | P_OPT | P_CMD2 ,
X F_PORTRAIT, FALSE, P_ENV | P_OPT | P_CMD2 ,
X
X F_HELP, FALSE, P_CMD1 ,
X F_VERSION, FALSE, P_CMD1 ,
X
X F_MOON_4, FALSE, P_ENV | P_OPT | P_CMD2 ,
X F_MOON_ALL, FALSE, P_ENV | P_OPT | P_CMD2 ,
X
X F_DEFINE, TRUE, P_ENV | P_CMD1 ,
X F_UNDEF, TRUE, P_ENV | P_CMD1 ,
X
X F_L_FOOT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_C_FOOT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_R_FOOT, TRUE, P_ENV | P_OPT | P_CMD2 ,
X
X F_FIRST_DAY, TRUE, P_ENV | P_OPT | P_CMD2 ,
X
X F_USA_DATES, FALSE, P_ENV | P_CMD1 | P_OPT ,
X F_EUR_DATES, FALSE, P_ENV | P_CMD1 | P_OPT ,
X
X F_X_TRANS, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_Y_TRANS, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_X_SCALE, TRUE, P_ENV | P_OPT | P_CMD2 ,
X F_Y_SCALE, TRUE, P_ENV | P_OPT | P_CMD2 ,
X
X F_JULIAN, FALSE, P_ENV | P_OPT | P_CMD2 ,
X F_JULIAN_ALL, FALSE, P_ENV | P_OPT | P_CMD2 ,
X
X F_WHOLE_YEAR, FALSE, P_ENV | P_CMD1 | P_OPT ,
X
X F_BLANK_BOXES, FALSE, P_ENV | P_OPT | P_CMD2 ,
X
X F_OUTLINE_GRAY, FALSE, P_ENV | P_OPT | P_CMD2 ,
X F_OUTLINE, FALSE, P_ENV | P_OPT | P_CMD2 ,
X
X '-', FALSE, P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
X '\0', FALSE, P_ENV | P_CMD1 | P_OPT | P_CMD2 /* must be last */
X };
X
#else
extern FLAG_USAGE flag_tbl[];
#endif
X
/*
X * Words used in usage() message - translate as necessary
X */
X
#define W_DEFAULT "default" /* translate as required */
#define W_USAGE "Usage"
X
#define W_FONT "FONT" /* names of metavariables */
#define W_DAY "DAY"
#define W_STRING "STRING"
#define W_FILE "FILE"
#define W_SYMBOL "SYMBOL"
#define W_VALUE "VALUE"
X
#define W_MM "MM" /* abbrev. for month, year */
#define W_YY "YY"
X
#define W_WYFLAG "-w" /* must conform to F_WHOLE_YEAR */
X
#define W_BLACK "black" /* cf. color_msg() */
#define W_GRAY "gray"
X
X
/* special flag_msg[] entries for end of option group, etc. */
X
#define END_GROUP '\n', NULL, NULL, NULL /* end of option group */
#define END_LIST '\0', NULL, NULL, NULL /* end of list */
#define GROUP_DEFAULT ' ', NULL, " " /* group default */
X
/*
X * Message strings to be printed by usage() - translate as necessary
X */
#ifdef MAIN_MODULE
X
FLAG_MSG flag_msg[] = {
X
/* flag name metasyntax description default */
X
X F_INITIALIZE, NULL, "initialize all parameters to program defaults", NULL,
X END_GROUP,
X
X F_BLACK_DAY, W_DAY, "print weekday in black", NULL,
X F_GRAY_DAY, W_DAY, "print weekday in gray (see below)", NULL,
X END_GROUP,
X
X F_OUTLINE_GRAY, NULL, "print \"gray\" dates as filled outlines", NULL,
X F_OUTLINE, NULL, "print \"gray\" dates as unfilled outlines", NULL,
#if NUM_STYLE == GRAY_NUMS
X GROUP_DEFAULT, "gray characters",
#else
#if NUM_STYLE == OUTLINE_NUMS
X GROUP_DEFAULT, "unfilled outlines",
#else
X GROUP_DEFAULT, "filled outlines",
#endif
#endif
X
X END_GROUP,
X
X F_DAY_FONT, W_FONT, "specify alternate day name font", DAYFONT,
X F_NOTES_FONT, W_FONT, "specify alternate notes font", NOTESFONT,
X F_TITLE_FONT, W_FONT, "specify alternate title font", TITLEFONT,
X END_GROUP,
X
X F_EMPTY_CAL, NULL, "generate empty calendar (ignore date file)", NULL,
X END_GROUP,
X
X F_DATE_FILE, W_FILE, "specify alternate date file", DATEFILE,
X END_GROUP,
X
#ifdef DEFAULT_OUTFILE
X F_OUT_FILE, W_FILE, "specify alternate output file", DEFAULT_OUTFILE,
#else
X F_OUT_FILE, W_FILE, "specify alternate output file", "stdout",
#endif
X END_GROUP,
X
X F_LANDSCAPE, NULL, "generate landscape-style calendar", NULL,
X F_PORTRAIT, NULL, "generate portrait-style calendar", NULL,
#if ROTATE == LANDSCAPE
X GROUP_DEFAULT, "landscape",
#else
X GROUP_DEFAULT, "portrait",
#endif
X END_GROUP,
X
X F_HELP, NULL, "print this help message", NULL,
X F_VERSION, NULL, "print version information", NULL,
X END_GROUP,
X
X F_MOON_4, NULL, "draw a \"moon\" icon at full/new/half moons", NULL,
X F_MOON_ALL, NULL, "draw a \"moon\" icon every day", NULL,
#if DRAW_MOONS == NO_MOONS
X GROUP_DEFAULT, "no moons",
#else
#if DRAW_MOONS == SOME_MOONS
X GROUP_DEFAULT, "full/new/half moons",
#else
X GROUP_DEFAULT, "every day",
#endif
#endif
X END_GROUP,
X
X F_DEFINE, W_SYMBOL, "define preprocessor symbol", NULL,
X F_UNDEF, W_SYMBOL, "undefine preprocessor symbol", NULL,
X END_GROUP,
X
X F_L_FOOT, W_STRING, "specify left foot string", LFOOT,
X F_C_FOOT, W_STRING, "specify center foot string", CFOOT,
X F_R_FOOT, W_STRING, "specify right foot string", RFOOT,
X END_GROUP,
X
X F_FIRST_DAY, W_DAY, "specify starting day of week", days[FIRST_DAY],
X END_GROUP,
X
X F_USA_DATES, NULL, "parse American dates (\"mm/dd{/yy}\" and \"month dd\")", NULL,
X F_EUR_DATES, NULL, "parse European dates (\"dd/mm{/yy}\" and \"dd month\")", NULL,
#if DATE_STYLE == USA_DATES
X GROUP_DEFAULT, "American",
#else
X GROUP_DEFAULT, "European",
#endif
X END_GROUP,
X
X F_X_TRANS, W_VALUE, "specify x-axis translation", XTVAL,
X F_Y_TRANS, W_VALUE, "specify y-axis translation", YTVAL,
X F_X_SCALE, W_VALUE, "specify x-axis scale factor", XSVAL,
X F_Y_SCALE, W_VALUE, "specify y-axis scale factor", YSVAL,
X END_GROUP,
X
X F_JULIAN, NULL, "print Julian day (day of year)", NULL,
X F_JULIAN_ALL, NULL, "print Julian day and days left in year", NULL,
#if JULIAN_DATES == NO_JULIANS
X GROUP_DEFAULT, "neither",
#else
#if JULIAN_DATES == SOME_JULIANS
X GROUP_DEFAULT, "Julian day",
#else
X GROUP_DEFAULT, "both",
#endif
#endif
X END_GROUP,
X
X F_WHOLE_YEAR, NULL, "print whole year (12 consecutive months) per page", NULL,
X END_GROUP,
X
X F_BLANK_BOXES, NULL, "leave unused boxes blank", NULL,
X
X END_GROUP, /* must precede END_LIST */
X
X END_LIST /* must be last */
};
X
#else
extern FLAG_MSG flag_msg[];
#endif
X
/* Numeric parameter descriptions and text */
X
#ifdef MAIN_MODULE
X
#if __STDC__
PARAM_MSG param_msg[] = {
X W_YY, "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
X W_MM " " W_YY, "generate calendar for month " W_MM " (Jan = 1), year " W_YY,
X W_MM " " W_YY " N", "generate calendars for N months, starting at " W_MM "/" W_YY,
X "(" W_DEFAULT ")", "generate calendar for current month and/or year",
X "", "",
X "if " W_WYFLAG " specified:", "",
X "", "",
X W_YY, "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
X W_MM " " W_YY, "generate calendars for 12 months, starting at " W_MM "/" W_YY,
X W_MM " " W_YY " N", "generate calendars for N months, starting at " W_MM "/" W_YY,
X "", " (N rounded up to next multiple of 12)",
X "(" W_DEFAULT ")", "generate calendar for current year",
X NULL, NULL /* must be last */
};
#else
PARAM_MSG param_msg[] = {
X "YY", "generate calendar for year YY (19YY if YY < 100)",
X "MM YY", "generate calendar for month MM (Jan = 1), year YY",
X "MM YY N", "generate calendars for N months, starting at MM/YY",
X "(default)", "generate calendar for current month and year",
X "", "",
X "if -w specified:", "",
X "", "",
X "YY", "generate calendar for year YY (19YY if YY < 100)",
X "MM YY", "generate calendar for 12 months, starting at MM/YY",
X "MM YY N", "generate calendars for N months, starting at MM/YY",
X "", " (N rounded up to next multiple of 12)",
X "(default)", "generate calendar for current year",
X NULL, NULL /* must be last */
};
#endif
X
#else
extern PARAM_MSG param_msg[];
#endif
X
#define PARAM_MSGS 3 /* number of above to print in command-line syntax message */
X
/* Date file syntax message - lines are copied intact */
X
#ifdef MAIN_MODULE
X
char *date_msg[] = {
X "",
X "Date file syntax:",
X "",
X "The following rules describe the syntax of date file entries:",
X "",
X " year <year>",
X "",
X " opt <options>",
X "",
X " note <month_spec> <text>",
X " note <month> <text>",
X "",
X " if -A flag (American date formats) specified:",
X " <month_name> <day>{*} {<text>}",
X " <month><sep><day>{<sep><year>}{*} {<text>}",
X "",
X " if -E flag (European date formats) specified:",
X " <day> <month_name>{*} {<text>}",
X " <day><sep><month>{<sep><year>}{*} {<text>}",
X "",
X " <ordinal> <day_name> in <month_spec>{*} {<text>}",
X " <day_name> <prep> <date_spec>",
X "",
X "where",
X "",
X " {x} means x is optional",
X "",
X " <date_spec> := any of the above date specs (not year, note, or opt)",
X " <month_name> := first 3+ characters of name of month, or \"all\"",
X " <month_spec> := <month_name>, or \"year\"",
X " <day_name> := first 3+ characters of name of weekday, \"day\",",
X " \"weekday\", \"workday\", \"holiday\", \"nonweekday\",",
X " \"nonworkday\", or \"nonholiday\"",
X " <ordinal> := ordinal number (\"1st\", \"2nd\", etc.), \"first\" .. \"fifth\",",
X " \"last\", \"even\", \"odd\", or \"all\"",
X " <prep> := \"before\", \"preceding\", \"after\", \"following\", \"on_or_before\",",
X " or \"on_or_after\"",
X " <sep> := one or more non-numeric, non-space, non-'*' characters",
X " <month>, <day>, <year> are the numeric forms",
X "",
X " <options> := any command-line option except -e, -f, -h, -v, -D, -U",
X "",
X "Comments start with '#' and run through end-of-line.",
X "",
X "Holidays may be flagged by specifying '*' as the last character of",
X "the date field(s), e.g. \"10/12* Columbus Day\", \"July 4* Independence",
X "Day\", etc. Any dates flagged as holidays will be printed in gray, and",
X "any associated text will appear adjacent to the date.",
X "",
X "Note that the numeric date formats (mm/dd{/yy}, dd.mm{.yy}) support",
X "an optional year, which will become the subsequent default year. The",
X "alphabetic date formats (month dd, dd month) do not support a year",
X "field; the \"year yy\" command is provided to reset the default year.",
X "",
X "\"Floating\" days may be specified in the date file as \"first Mon in ",
X "Sep\", \"last Mon in May\", \"4th Thu in Nov\", etc.; any word may be",
X "used in place of \"in\". \"Relative floating\" days (e.g. \"Fri after 4th ",
X "Thu in Nov\") are also accepted; they may span month/year bounds.",
X "Pcal also accepts date specs such as \"all Friday{s} in October\", \"last",
X "Thursday in all\", etc., and produces the expected results; \"each\" and",
X "\"every\" are accepted as synonyms for \"all\". Negative ordinals are",
X "allowed; \"-2nd\" means \"next to last\".",
X "",
X "The words \"day\", \"weekday\", \"workday\", and \"holiday\" may be used as",
X "wildcards: \"day\" matches any day, \"weekday\" matches any day normally",
X "printed in black, \"workday\" matches any day normally printed in black",
X "and not explicitly flagged as a holiday, and \"holiday\" matches any",
X "day explicitly flagged as a holiday. \"Nonweekday\", \"nonworkday\",",
X "and \"nonholiday\" are also supported and have the obvious meanings.",
X "",
X "\"Odd\" and \"even\" do not refer to the actual date; instead, \"odd\"",
X "means \"alternate, starting with the first\"; \"even\" means \"alternate,",
X "starting with the second\". Thus, \"odd Fridays in March\" refers to",
X "the first, third, and (if present) fifth Fridays in March - not to",
X "those Fridays falling on odd dates.",
X "",
X "\"All\" refers to each individual month; \"year\" refers to the year",
X "as an entity. Thus \"odd Fridays in all\" refers to the first/third/",
X "fifth Friday of each month, while \"odd Fridays in year\" refers to",
X "the first Friday of January and every other Friday thereafter.",
X "",
X "Additional notes may be propagated to an empty calendar box by the",
X "inclusion of one or more lines of the form \"note <month> <text>\",",
X "where <month> may be numeric or alphabetic; \"note all <text>\"",
X "propagates <text> to each month in the current year.",
X "",
X "Pcal also allows format specifiers in the text (and foot strings -",
X "cf. the -L, -C, and -R options); each will be replaced by its",
X "equivalent string as outlined in the table below. (Most of these are",
X "derived from the strftime() function; %[lo0+-] are Pcal-specific.)",
X "",
X " %a : abbreviated weekday",
X " %A : full weekday",
X " %b : abbreviated month name",
X " %B : full month name",
X " %d : day of month (1-31)",
X " %j : day of year (1-366)",
X " %l : days left in year (0-365)",
X " %m : month (1-12)",
X " %U : week number (0-53)",
X " %W : week number (0-53)",
X " %y : year w/o century (00-99)",
X " %Y : year w/century",
X " %% : '%' character",
X "",
X " %o : print number as ordinal",
X " %0 : print number with leading zeroes",
X " %+ : use following month or year",
X " %- : use previous month or year",
X "",
X "%U considers the first logical Sunday (the first day of the week as",
X "printed; cf. the -F flag) of the year as the first day of week 1;",
X "%W uses the first logical Monday instead. This is an extension of",
X "strftime()'s behavior.",
X "",
X "%o prints a number as an ordinal, with the appropriate suffix (\"st\",",
X "\"nd\", \"rd\", or \"th\" in English) appended; for example, \"%od\" prints",
X "the day of the month as \"1st\", \"2nd\", \"3rd\", etc.",
X "",
X "Unlike strftime(), Pcal's default is to print numbers (except %y)",
X "without leading zeroes. If leading zeroes are desired, the '0'",
X "prefix may be used; for example, \"%0j\" prints the day of year as",
X "001-365.",
X "",
X "%+ and %- direct Pcal to substitute the following/previous month/year",
X "in the following [bBmyY] specifier; for example, %+B prints the name",
X "of the next month.",
X "",
X "Simple cpp-like functionality is provided. The date file may include",
X "the following commands, which work like their cpp counterparts:",
X "",
X " define <sym>",
X " undef <sym>",
X "",
X " if{n}def <expr>",
X " ...",
X " { else",
X " ... }",
X " endif",
X "",
X " include <file>",
X "",
X "Note that these do not start with '#', which is reserved as a comment",
X "character.",
X "",
X "<sym> is a symbol name consisting of a letter followed by zero or",
X "more letters, digits, or underscores ('_'). Symbol names are always",
X "treated in a case-insensitive manner.",
X "",
X "<expr> is an expression consisting of symbol names joined by the logical",
X "operators (in order of precedence, high to low) '!' (unary negate), '&'",
X "(and), '^' (exclusive or), and '|' (inclusive or). '&&' and '||' are",
X "accepted as synonyms for '&' and '|' respectively; the order of",
X "evaluation may be altered by the use of parentheses. A symbol whose",
X "name is currently defined evaluates to TRUE; one whose name is not",
X "currently defined evaluates to FALSE. Thus \"ifdef A | B | C\" is TRUE",
X "if any of the symbols A, B, and C is currently defined, and",
X "\"ifdef A & B & C\" is TRUE if all of them are.",
X "",
X "\"ifndef A | B | C\" is equivalent to \"ifdef !(A | B | C)\" (or, using",
X "DeMorgan's Law, \"ifdef !A & !B & !C\") - in other words, TRUE if none of",
X "the symbols A, B, and C is currently defined.",
X "",
X "\"define\" alone deletes all the current definitions; \"ifdef\" alone is",
X "always false; \"ifndef\" alone is always true.",
X "",
X "The file name in the \"include\" directive may optionally be surrounded",
X "by \"\" or <>. In any case, path names are taken to be relative to",
X "the location of the file containing the \"include\" directive.",
X "",
X "",
X "Moon file syntax:",
X "",
X "The user may enter the dates and (optionally) times of quarter",
X "moons (from a reliable source such as an almanac or astronomical",
X "table) into a file called .moonXX (moonXX.dat on VMS), where XX is",
X "the last two digits of the year. If such a file exists (in the",
X "same directory as the date file), Pcal will interpolate the phase",
X "of the moon from the information in this file instead of using the",
X "default algorithm.",
X "",
X "(Pcal originally used an extremely simplistic moon phase algorithm;",
X "the moon file was added to v4.0 to enable Pcal to interpolate the",
X "phase of the moon from the [presumably more accurate] information",
X "within. More recently, the original moon phase algorithm was",
X "superseded by an astronomer-strength version, largely obviating",
X "the need for a moon file; however, it will continue to be",
X "supported for the foreseeable future.)",
X "",
X "Entries in the moon file must conform to the following syntax:",
X "",
X " if -A flag (American date formats) specified:",
X " <quarter> <month><sep><day> {<hour><sep><min>}",
X "",
X " if -E flag (European date formats) specified:",
X " <quarter> <day><sep><month> {<hour><sep><min>}",
X "",
X "where",
X "",
X " <quarter> := \"nm\", \"fq\" or \"1q\", \"fm\", \"lq\" or \"3q\" (new",
X " moon, first quarter, full moon, last quarter)",
X " <hour> := number 0-23 (24-hour clock)",
X " <min> := number 0-59",
X "",
X "This file must contain entries for all quarter moons in the year,",
X "in chronological order; if any errors are encountered, Pcal will",
X "revert to using its default algorithm.",
X "",
X "As in the date file, comments start with '#' and run through",
X "end-of-line. ",
X NULL
X };
#else
extern char *date_msg[];
#endif
X
/* format strings for color_msg() - translate as necessary */
#define COLOR_MSG_1 "all days in %s"
#define COLOR_MSG_2 "in %s; others in %s"
X
/* format string for short usage() message */
#define USAGE_MSG "\"%s -%c\" prints full description of flags, parameters, and file formats\n"
X
/* format strings for comment in PostScript output file */
#define VERSION_MSG "Generated by %s %s"
#define DATEFILE_MSG " from %s"
X
#define NOTES_HDR "Notes" /* title of "notes" box */
#define LINE_SEP ".p" /* text line separator */
X
/* strings used in error messages */
#define ENV_VAR "environment variable "
#define DATE_FILE "date file "
X
/* Error and information messages - translate as necessary */
X
/* program error messages */
#define E_ALLOC_ERR "%s: calloc() failed - out of memory\n"
#define E_FOPEN_ERR "%s: can't open file %s\n"
#define E_ILL_LINE "%s: %s in file %s, line %d\n"
#define E_ILL_MONTH "%s: month %d not in range %d .. %d\n"
#define E_ILL_OPT "%s: unrecognized flag %s"
#define E_ILL_OPT2 " (%s\"%s\")"
#define E_ILL_YEAR "%s: year %d not in range %d .. %d\n"
#define E_SYMFULL "%s: symbol table full - can't define %s\n"
#define E_UNT_IFDEF "%s: unterminated if{n}def..{else..}endif in file %s\n"
#define E_FLAG_IGNORED "%s: -%c flag ignored (%s\"%s\")\n"
X
/* preprocessor error strings */
#define E_ELSE_ERR "unmatched \"else\""
#define E_END_ERR "unmatched \"endif\""
#define E_GARBAGE "extraneous data on \"%s\" line"
#define E_INV_DATE "invalid date (or no match for wildcard)"
#define E_INV_LINE "unrecognized line"
#define E_NESTING "maximum file nesting level exceeded"
#define E_EXPR_SYNTAX "syntax error in expression"
X
/* moon file error strings */
#define E_DATE_SEQ "date or phase out of sequence"
#define E_PREM_EOF "premature EOF"
X
/* information message (VMS, Amiga only) */
#define I_OUT_NAME "%s: output is in file %s\n"
X
X
/*
X * Yes, some source code in a header file. This is a language-dependent
X * routine used by writefil.c to translate the %o (ordinal suffix) format
X * specifier into the appropriate string for printing, and seemed to belong
X * here with the other language dependencies.
X */
#ifdef WRITEFIL /* include only in writefil.c */
#ifdef PROTOS
static char *ordinal_suffix(int num)
#else
static char *ordinal_suffix(num)
X int num; /* ordinal number - assumed positive */
#endif
{
X static char buf[10];
X static char *suffix[] = { "th", "st", "nd", "rd" };
X int tens, units;
X
X tens = (num / 10) % 10; /* select suffix */
X units = num % 10;
X strcpy(buf, suffix[(units > 3 || tens == 1) ? 0 : units]);
X
X return buf;
}
#endif
SHAR_EOF
chmod 0666 pcallang.h ||
echo 'restore of pcallang.h failed'
Wc_c="`wc -c < 'pcallang.h'`"
test 27444 -eq "$Wc_c" ||
echo 'pcallang.h: original size 27444, current size' "$Wc_c"
fi
# ============= pcalutil.c ==============
if test -f 'pcalutil.c' -a X"$1" != X"-c"; then
echo 'x - skipping pcalutil.c (File already exists)'
else
echo 'x - extracting pcalutil.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pcalutil.c' &&
/*
X * pcalutil.c - utility routines for Pcal
X *
X * Contents:
X *
X * alloc
X * calc_day
X * calc_weekday
X * calc_year_day
X * ci_strcmp
X * ci_strncmp
X * copy_text
X * find_executable
X * getline
X * is_valid
X * loadwords
X * mk_filespec
X * mk_path
X * normalize
X * split_date
X * trnlog
X *
X * Revision history:
X *
X * 4.02 AWR 06/07/91 added find_executable()
X *
X * 4.0 AWR 02/24/91 Revised getline() and copy_text() to
X * handle C-style escapes of characters
X * and octal/hex numbers
X *
X * AWR 02/19/91 Added support for negative ordinals
X * in calc_day(), calc_year_day()
X *
X * AWR 02/04/91 Added calc_year_day()
X *
X * AWR 01/15/91 Extracted from pcal.c
X *
X */
X
X
/*
X * Standard headers:
X */
X
#include <stdio.h>
#include <ctype.h>
#include <string.h>
X
/*
X * Pcal-specific definitions:
X */
X
#include "pcaldefs.h"
#include "pcalglob.h"
#include "pcallang.h"
X
/*
X * Macros:
X */
X
/* skip over numeric field and subsequent non-numeric characters */
#define SKIP_FIELD(p) \
X do { while (*p && isdigit(*p)) p++; \
X while (*p && !isdigit(*p)) p++; } while (0)
X
X
/*
X * General-purpose utility routines
X */
X
X
/*
X * alloc - interface to calloc(); terminates if unsuccessful
X */
#ifdef PROTOS
char *alloc(int size)
#else
char *alloc(size)
X int size;
#endif
{
X char *p;
X
X if (size == 0) /* not all calloc()s like null requests */
X size = 1;
X
X if ((p = calloc(1, size)) == NULL) {
X FPR(stderr, E_ALLOC_ERR, progname);
X exit(EXIT_FAILURE);
X }
X
X return p;
}
X
X
/*
X * ci_str{n}cmp - case-insensitive flavors of strcmp(), strncmp()
X */
#ifdef PROTOS
int ci_strcmp(register char *s1,
X register char *s2)
#else
int ci_strcmp(s1, s2)
X register char *s1, *s2;
#endif
{
X register char c1, c2;
X
X for ( ; (c1 = TOLOWER(*s1)) == (c2 = TOLOWER(*s2)); s1++, s2++)
X if (c1 == '\0')
X return 0;
X
X return c1 - c2;
}
X
X
#ifdef PROTOS
int ci_strncmp(register char *s1,
X register char *s2,
X int n)
#else
int ci_strncmp(s1, s2, n)
X register char *s1, *s2;
X int n;
#endif
{
X register char c1, c2;
X
X for ( ; --n >= 0 && (c1 = TOLOWER(*s1)) == (c2 = TOLOWER(*s2)); s1++, s2++)
X if (c1 == '\0')
X return 0;
X
X return n < 0 ? 0 : c1 - c2;
}
X
X
/*
X * Date calculation routines (see also macros in pcaldefs.h)
X */
X
X
/*
X * normalize - adjust day in case it has crossed month (or year) bounds
X */
#ifdef PROTOS
void normalize(DATE *pd)
#else
void normalize(pd)
X DATE *pd; /* pointer to date */
#endif
{
X int len;
X
X /* adjust if day is in previous or following month */
X
X while (pd->dd < 1) {
X pd->yy = PREV_YEAR(pd->mm, pd->yy);
X pd->mm = PREV_MONTH(pd->mm, pd->yy);
X pd->dd += LENGTH_OF(pd->mm, pd->yy);
X }
X
X while (pd->dd > (len = LENGTH_OF(pd->mm, pd->yy))) {
X pd->dd -= len;
X pd->yy = NEXT_YEAR(pd->mm, pd->yy);
X pd->mm = NEXT_MONTH(pd->mm, pd->yy);
X }
}
X
X
/*
X * calc_day - calculate calendar date from ordinal date (e.g., "first Friday
X * in November", "last day in October"); return calendar date if it exists,
X * 0 if it does not
X */
#ifdef PROTOS
int calc_day(int ord,
X int wkd,
X int mm)
#else
int calc_day(ord, wkd, mm)
X int ord;
X int wkd;
X int mm;
#endif
{
#ifdef PROTOS
X int first, last, day, (*pfcn)(int, int, int);
#else
X int first, last, day, (*pfcn)();
#endif
X
X if (IS_WILD(wkd)) { /* "day", "weekday", "workday", or "holiday" */
X pfcn = pdatefcn[wkd - WILD_FIRST];
X last = LENGTH_OF(mm, curr_year);
X
X if (ord < 0) { /* search backwards */
X for (day = last;
X day >= 1 &&
X !((*pfcn)(mm, day, curr_year) && ++ord == 0);
X day--)
X ;
X } else { /* search forwards */
X for (day = 1;
X day <= last &&
X !((*pfcn)(mm, day, curr_year) && --ord == 0);
X day++)
X ;
X }
X return is_valid(mm, day, curr_year) ? day : 0;
X
X } else { /* fixed weekday - calculate it */
X first = (wkd - FIRST_OF(mm, curr_year) + 7) % 7 + 1;
X if (ord < 0) { /* get last (try 5th, then 4th) */
X if (!is_valid(mm, last = first + 28, curr_year))
X last -= 7;
X if (!is_valid(mm, day = last + 7 * (ord + 1),
X curr_year))
X day = 0;
X }
X else
X if (!is_valid(mm, day = first + 7 * (ord - 1),
X curr_year))
X day = 0;
X
X return day;
X }
X
}
X
X
/*
X * calc_year_day - calculate calendar date from ordinal date within year
X * (e.g., "last Friday in year", "10th holiday in year"); if date exists,
X * fill in pdate and return TRUE; else return FALSE
X */
#ifdef PROTOS
int calc_year_day(int ord,
X int wkd,
X DATE *pdate)
#else
int calc_year_day(ord, wkd, pdate)
X int ord;
X int wkd;
X DATE *pdate;
#endif
{
#ifdef PROTOS
X int incr, (*pfcn)(int, int, int);
#else
X int incr, (*pfcn)();
#endif
X DATE date;
X
X if (IS_WILD(wkd)) { /* "day", "weekday", "workday", or "holiday" */
X pfcn = pdatefcn[wkd - WILD_FIRST];
X
X if (ord < 0) { /* nth occurrence backwards */
X MAKE_DATE(date, DEC, 31, curr_year);
X ord = -ord;
X incr = -1;
X } else { /* nth occurrence forwards */
X MAKE_DATE(date, JAN, 1, curr_year);
X incr = 1;
X }
X
X /* search for selected occurrence of specified wildcard */
X
X while (date.yy == curr_year &&
X !((*pfcn)(date.mm, date.dd, date.yy) && --ord == 0)) {
X date.dd += incr;
X normalize(&date);
X }
X
X } else { /* fixed weekday - calculate it */
X if (ord < 0)
X MAKE_DATE(date, DEC,
X calc_day(-1, wkd, DEC) + 7 * (ord + 1),
X curr_year);
X else
X MAKE_DATE(date, JAN,
X calc_day(1, wkd, JAN) + 7 * (ord - 1),
X curr_year);
X normalize(&date);
X }
X
X return date.yy == curr_year ? (*pdate = date, TRUE) : FALSE;
}
X
X
/*
X * calc_weekday - return the weekday (0-6) of mm/dd/yy (mm: 1-12)
X */
#ifdef PROTOS
int calc_weekday(int mm,
X int dd,
X int yy)
#else
int calc_weekday(mm, dd, yy)
X int mm;
X int dd;
X int yy;
#endif
{
X return (yy + (yy-1)/4 - (yy-1)/100 + (yy-1)/400 + OFFSET_OF(mm, yy) +
X (dd-1)) % 7;
}
X
X
/*
X * is_valid - return TRUE if m/d/y is a valid date
X */
#ifdef PROTOS
int is_valid(register int m,
X register int d,
X register int y)
#else
int is_valid(m, d, y)
X register int m, d, y;
#endif
{
X return m >= JAN && m <= DEC &&
X d >= 1 && d <= LENGTH_OF(m, y);
}
X
X
X
/*
X * Token parsing/remerging routines:
X */
X
X
/*
X * loadwords - tokenize line buffer into word array, return word count.
X * differs from old loadwords() in that it handles quoted (" or ') strings
X * and removes escaped quotes
X */
#ifdef PROTOS
int loadwords(void)
#else
int loadwords()
#endif
{
X register char *ptok;
X char *delim, **ap, *p1, *p2, c;
X int nwords;
X
X for (ptok = lbuf, ap = words; TRUE; ap++) {
X
X ptok += strspn(ptok, WHITESPACE); /* find next token */
X
X if (! *ptok) { /* end of lbuf? */
X *ap = NULL; /* add null ptr at end */
X nwords = ap - words; /* number of non-null ptrs */
X break; /* exit loop */
X }
X
X delim = *ptok == '"' ? "\"" : /* set closing delimiter */
X *ptok == '\'' ? "'" :
X WHITESPACE;
X
X if (*ptok == *delim) /* skip opening quote */
X ptok++;
X
X *ap = ptok; /* save token ptr */
X
X do { /* find unescaped delimiter */
X ptok += strcspn(ptok, delim);
X if ((c = ptok[-1]) == '\\')
X ptok++;
X } while (c == '\\');
X
X if (*ptok) /* terminate token */
X *ptok++ = '\0';
X }
X
X /* now reprocess the word list, removing escapes from quotes */
X
X for (ap = words; *ap; *ap++)
X for (p1 = p2 = *ap; c = *p2 = *p1++; *p2++)
X if (c == '\\')
X *p2 = *p1++;
X
X return nwords; /* return word count */
X
}
X
X
/*
X * copy_text - retrieve remaining text in lbuf and copy to output string,
X * separating tokens by a single blank and condensing runs of blanks (all
X * other whitespace has been converted to blanks by now) to one blank
X */
#ifdef PROTOS
void copy_text(char *pbuf,
X char **ptext)
#else
void copy_text(pbuf, ptext)
X char *pbuf; /* output buffer - can be lbuf itself */
X char **ptext; /* pointer to first text word in "words" */
#endif
{
X char *p, *pb;
X
X /* copy words to pbuf, separating by one blank */
X
X for (*(pb = pbuf) = '\0'; p = *ptext; *pb++ = *++ptext ? ' ' : '\0') {
X for ( ; *p; *p++)
X if (! (*p == ' ' && (pb == pbuf || pb[-1] == ' ')))
X *pb++ = *p;
X if (pb > pbuf && pb[-1] == ' ')
X pb--;
X }
}
X
X
/*
X * split_date - extract 1-3 numeric fields (separated by one or more
X * non-numeric characters) from date string; return number of fields
X */
#ifdef PROTOS
int split_date(char *pstr,
X int *pn1,
X int *pn2,
X int *pn3)
#else
int split_date(pstr, pn1, pn2, pn3)
X char *pstr; /* input string */
X int *pn1, *pn2, *pn3; /* output numbers */
#endif
{
X int i, n, *pn;
X
X /* attempt to extract up to three numeric fields */
X for (n = 0, i = 1; i <= 3; i++) {
X pn = i == 1 ? pn1 : i == 2 ? pn2 : pn3; /* crude but portable */
X if (pn)
X *pn = *pstr ? (n++, atoi(pstr)) : 0;
X SKIP_FIELD(pstr); /* go to next field */
X }
X
X return n;
}
X
X
X
/*
X * File input routines:
X */
X
X
/*
X * octal_esc - read up to 3 octal digits from file; return value of octal
X * constant and leave file pointer at last character
X */
#ifdef PROTOS
static int octal_esc(FILE *fp)
#else
static int octal_esc(fp)
X FILE *fp;
#endif
{
X int i, n, c;
X
X for (n = 0, i = 0; i < 3; i++) {
X c = getc(fp);
X if (c == EOF)
X return EOF;
X if (!isodigit(c)) {
X ungetc(c, fp);
X break;
X }
X n = n * 8 + (c - '0');
X }
X
X return n & 0377; /* truncate to 8 bits */
}
X
X
/*
X * hex_esc - read 'x' or 'X' followed by 1 or 2 hex digits from file; return
X * value of hexadecimal constant (or letter if no hex digits follow) and
X * leave file pointer at last character
X */
#ifdef PROTOS
static int hex_esc(FILE *fp)
#else
static int hex_esc(fp)
X FILE *fp;
#endif
{
X int i, n, c, sv_c;
X
X sv_c = c = getc(fp); /* read leading 'x' or 'X' */
X if (TOLOWER(c) != 'x')
X return c; /* something else - just return it */
X
X for (n = 0, i = 0; i < 2; i++) {
X c = getc(fp);
X if (c == EOF)
X return EOF;
X if (!isxdigit(c)) {
X ungetc(c, fp);
X break;
X }
X n = n * 16 + (isupper(c) ? c - 'A' + 10 :
X islower(c) ? c - 'a' + 10 :
X c - '0');
X }
X
X return i > 0 ? n & 0377 : sv_c; /* truncate to 8 bits */
}
X
X
/*
X * getline - read next non-null line of input file into lbuf; return 0 on EOF
X * strip leading whitespace, translate other whitespace to blanks, and handle
X * all escapes except \' and \", (cf. loadwords())
X */
#ifdef PROTOS
int getline(FILE *fp,
X int *pline)
#else
int getline(fp, pline)
X FILE *fp;
X int *pline;
#endif
{
X register char *cp;
X register int c, c2;
X static char escape[] = "abfnrtv"; /* cf. ANSI spec, 2.2.2 */
X int in_comment; /* comments: from '#' to end-of-line */
X
X cp = lbuf;
X do {
X in_comment = FALSE;
X while ((c = getc(fp)) != '\n' && c != EOF) {
X if (c == '#')
X in_comment = TRUE;
X
X if (isspace(c)) /* whitespace => blank */
X c = ' ';
X
X /* ignore comments and leading white space */
X if (in_comment || (cp == lbuf && c == ' '))
X continue;
X
X /* handle escape sequences here: escaped whitespace
X * and ANSI escapes are all converted to a space;
X * octal and hex constants are converted in place
X */
X if (c == '\\') {
X if ((c2 = getc(fp)) == EOF)
X return FALSE;
X
X if (isspace(c2) || strchr(escape, c2)) {
X c = ' ';
X if (c2 == '\n')
X (*pline)++;
X }
X else if (isodigit(c2)) { /* octal */
X ungetc(c2, fp);
X if((c = octal_esc(fp)) == EOF)
X return FALSE;
X }
X else if (TOLOWER(c2) == 'x') { /* hex */
X ungetc(c2, fp);
X if((c = hex_esc(fp)) == EOF)
X return FALSE;
X }
X else if (c2 == '\'' || c2 == '"')
X ungetc(c2, fp);
X else
X c = c2;
X
X }
X *cp++ = c;
X }
X
X if (c == EOF) /* no more input lines */
X return FALSE;
X
X (*pline)++; /* bump line number */
X
X } while (cp == lbuf); /* ignore empty lines */
X
X *cp = '\0';
X return TRUE;
}
X
X
/*
X * Routines dealing with translation of file specifications (VMS, Un*x)
X */
X
#ifdef VMS
/*
X * mk_path - extract the path component from VMS file spec
X */
#ifdef PROTOS
char *mk_path(char *path,
X char *filespec)
#else
char *mk_path(path, filespec)
X char *path; /* output path */
X char *filespec; /* input filespec */
#endif
{
X char *p;
X
X strcpy(path, filespec);
X if (!(p = strchr(path, ']')) && !(p = strchr(path, ':')))
X p = path - 1; /* return null string if no path */
X *++p = '\0';
X
X return path;
}
X
X
/*
X * mk_filespec - merge VMS path and file names, where latter can be relative
X */
#ifdef PROTOS
char *mk_filespec(char *filespec,
X char *path,
X char *name)
#else
char *mk_filespec(filespec, path, name)
X char *filespec; /* output filespec */
X char *path; /* input path */
X char *name; /* input file name */
#endif
{
X char *p;
X
X *filespec = '\0';
X
X /* copy name intact if absolute; else merge path and relative name */
X if (!strchr(name, ':')) {
X strcpy(filespec, path);
X if ((p = P_LASTCHAR(filespec)) && *p == END_PATH &&
X name[0] == START_PATH && strchr(".-", name[1]))
X *p = *++name == '-' ? '.' : '\0';
X }
X
X return strcat(filespec, name);
}
X
X
/*
X * trnlog - return translation of VMS logical name (null if missing)
X */
#ifdef PROTOS
char *trnlog(char *logname)
#else
char *trnlog(logname) /* look up logical name */
X char *logname;
#endif
{
X static char trnbuf[STRSIZ];
X
X $DESCRIPTOR(src, logname);
X $DESCRIPTOR(dst, trnbuf);
X short len;
X int ret;
X
X src.dsc$w_length = strlen(logname);
X ret = LIB$SYS_TRNLOG(&src, &len, &dst);
X return ret == SS$_NORMAL ? (trnbuf[len] = '\0', trnbuf) : NULL;
}
X
#else /* apparently DOS and Amiga can use the Un*x flavors */
X
/*
X * mk_path - extract the path component from a Un*x file spec
X */
#ifdef PROTOS
char *mk_path(char *path,
X char *filespec)
#else
char *mk_path(path, filespec)
X char *path; /* output path */
X char *filespec; /* input filespec */
#endif
{
X char *p;
X
X strcpy(path, filespec);
X if (! (p = strrchr(path, END_PATH)) )
X p = path - 1; /* return null string if no path */
X
X *++p = '\0';
X return path;
}
X
X
/*
X * mk_filespec - merge Un*x path and file names, where latter can be relative
X */
#ifdef PROTOS
char *mk_filespec(char *filespec,
X char *path,
X char *name)
#else
char *mk_filespec(filespec, path, name)
X char *filespec; /* output filespec */
X char *path; /* input path */
X char *name; /* input file name */
#endif
{
X char *p;
X
X *filespec = '\0';
X
X /* copy name intact if absolute; else merge path and relative name */
X
X /* if path starts with "~/", translate it for user */
X if (strncmp(name, "~/", 2) == 0 && (p = trnlog(HOME_DIR)) != NULL) {
X strcpy(filespec, p);
X if ((p = P_LASTCHAR(filespec)) && *p != END_PATH)
X *++p = END_PATH, *++p = '\0';
X name += 2; /* skip "~/" */
X }
X else if (*name != START_PATH) { /* relative path */
X strcpy(filespec, path);
X if ((p = P_LASTCHAR(filespec)) && *p != END_PATH)
X *++p = END_PATH, *++p = '\0';
X }
X
X return strcat(filespec, name);
}
X
X
/*
X * trnlog - return translation of Un*x environment variable
X */
#ifdef PROTOS
char *trnlog(char *logname)
#else
char *trnlog(logname) /* look up logical name */
X char *logname;
#endif
{
X return getenv(logname);
}
X
#endif
X
#ifdef UNIXX /* highly Unix-dependent; probably nobody else can use it */
X
#include <sys/types.h>
#include <sys/stat.h>
X
/*
X * find_executable - return full path name of executable
X */
#ifdef PROTOS
char *find_executable(char *prog)
#else
char *find_executable(prog)
X char *prog;
#endif
{
X char pathvar[1000], *p, *pnext;
X struct stat st;
X static char filepath[STRSIZ];
X
X /* if 'prog' is an absolute/relative path name or environment
X * variable 'PATH' does not exist, return 'prog'; otherwise,
X * search the directories specified in 'PATH' for the executable
X */
X if (strchr(prog, END_PATH) == 0 && (p = getenv(PATH_ENV_VAR)) != 0) {
X strcpy(pathvar, p);
X
X /* assumes PATH is of form "dir1:dir2:...:dirN"; strtok()
X * would be handy here, but not everybody has it yet
X */
X for (p = pathvar; *p; p = pnext) {
X if ((pnext = strchr(p, ':')) != NULL)
X *pnext++ = '\0';
X else
X pnext = p + strlen(p);
X strcpy(filepath, p); /* construct file path */
X strcat(filepath, "/");
X strcat(filepath, prog);
X
X /* check that file a) exists, b) is a "normal" file,
X * and c) is executable - if so, return its full path
X */
X if (stat(filepath, &st) >= 0 &&
X (st.st_mode & S_IFMT) == S_IFREG &&
X access(filepath, 01) == 0)
X return filepath;
X }
X }
X return prog; /* just return the original argument */
}
#else
X
X
/*
X * find_executable - return full path name of executable
X */
#ifdef PROTOS
char *find_executable(char *prog)
#else
char *find_executable(prog)
X char *prog;
#endif
{
X return prog; /* non-UNIX flavor always returns its argument */
}
#endif
SHAR_EOF
chmod 0644 pcalutil.c ||
echo 'restore of pcalutil.c failed'
Wc_c="`wc -c < 'pcalutil.c'`"
test 16402 -eq "$Wc_c" ||
echo 'pcalutil.c: original size 16402, current size' "$Wc_c"
fi
# ============= protos.h ==============
if test -f 'protos.h' -a X"$1" != X"-c"; then
echo 'x - skipping protos.h (File already exists)'
else
echo 'x - extracting protos.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'protos.h' &&
/*
X * protos.h - ANSI-style function prototypes for Pcal sources
X *
X * Revision history:
X *
X * 4.02 AWR 06/07/91 added find_executable()
X *
X * 4.0 AWR 03/01/91 use <stdlib.h> where possible
X *
X * AWR 02/19/91 adapted from Bill Hogsett's source
X *
X */
X
X
/*
X * Prototypes for functions defined in exprpars.c:
X */
int parse_expr(char *pbuf);
X
X
/*
X * Prototypes for functions defined in moonphas.c:
X */
double calc_phase(int month, int day, int year);
double find_phase(int month, int day, int year, int *pquarter);
char *find_moonfile(int year);
int read_moonfile(int year);
X
X
/*
X * Prototypes for functions defined in pcal.c:
X */
FILE *alt_fopen(char *fullpath, char *name, char *pathlist[], char *access);
char *color_msg(void);
int get_args(char **argv, int curr_pass, char *where);
FLAG_USAGE *get_flag(char flag);
int main(int argc, char **argv);
void set_color(char *day, int col);
void usage(FILE *fp, int fullmsg);
X
X
/*
X * Prototypes for functions defined in pcalutil.c:
X */
char *alloc(int size);
int calc_day(int ord, int wkd, int mm);
int calc_weekday(int mm, int dd, int yy);
int calc_year_day(int ord, int wkd, DATE *pdate);
int ci_strcmp(register char *s1, register char *s2);
int ci_strncmp(register char *s1, register char *s2, int n);
void copy_text(char *pbuf, char **ptext);
char *find_executable(char *prog);
int getline(FILE *fp, int *pline);
int is_valid(register int m, register int d, register int y);
int loadwords(void);
char *mk_filespec(char *filespec, char *path, char *name);
char *mk_path(char *path, char *filespec);
void normalize(DATE *pd);
int split_date(char *pstr, int *pn1, int *pn2, int *pn3);
char *trnlog(char *logname);
X
X
/*
X * Prototypes for functions defined in readfile.c:
X */
void cleanup(void);
void clear_syms(void);
int date_type(char *cp, int *pn, int *pv);
int do_define(char *sym);
int do_ifdef(char *expr);
int do_ifndef(char *expr);
int do_include(char *path, char *name);
int do_undef(char *sym);
int enter_day_info(int m, int d, int y, int text_type, char **pword);
int find_sym(char *sym);
year_info *find_year(int year, int insert);
int get_keywd(char *cp);
int get_month(char *cp, int numeric_ok, int year_ok);
int get_ordinal(char *cp, int *pval);
int get_prep(char *cp);
int get_token(char *token);
int get_weekday(char *cp, int wild_ok);
int is_anyday(int mm, int dd, int yy);
int is_holiday(int mm, int dd, int yy);
int is_weekday(int mm, int dd, int yy);
int is_workday(int mm, int dd, int yy);
int not_holiday(int mm, int dd, int yy);
int not_weekday(int mm, int dd, int yy);
int not_workday(int mm, int dd, int yy);
int parse(char **pword, char *filename);
int parse_date(char **pword, int *ptype, char ***pptext);
int parse_ord(int ord, int val, char **pword);
int parse_rel(int wkd, char **pword, int *ptype, char ***pptext);
void read_datefile(FILE *fp, char *filename);
X
X
/*
X * Prototypes for functions defined in writefil.c:
X */
void def_footstring(char *p, char c);
void find_daytext(int month, int year, int is_holiday);
void find_holidays(int month, int year);
void print_julian_info(int month, int year);
void print_month(int month, int year);
void print_moon_info(int month, int year);
void print_text(char *p);
char *print_word(char *p);
void write_psfile(int month, int year, int nmonths);
X
X
/*
X * Prototypes for miscellaneous library routines (if not already included
X * via <stdlib.h> - cf. pcaldefs.h):
X */
#ifndef STDLIB
extern int atoi(char *);
extern char *calloc(unsigned int, unsigned int);
extern char *getenv(char *);
#endif
SHAR_EOF
chmod 0666 protos.h ||
echo 'restore of protos.h failed'
Wc_c="`wc -c < 'protos.h'`"
test 3511 -eq "$Wc_c" ||
echo 'protos.h: original size 3511, current size' "$Wc_c"
fi
true || echo 'restore of readfile.c failed'
echo End of part 5, continue with part 6
exit 0