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 >
Text File  |  1991-08-22  |  50KB  |  1,771 lines

  1. Path: wupost!uwm.edu!linac!att!cbnews!jbr0
  2. From: jbr0@cbnews.cb.att.com (joseph.a.brownlee)
  3. Newsgroups: alt.sources
  4. Subject: Pcal v4.1, part 5 of 6
  5. Keywords: pcal calendar postscript
  6. Message-ID: <1991Aug19.121859.979@cbnews.cb.att.com>
  7. Date: 19 Aug 91 12:18:59 GMT
  8. Organization: AT&T Bell Laboratories
  9. Lines: 1760
  10.  
  11. #!/bin/sh
  12. # This is part 05 of a multipart archive
  13. # ============= pcallang.h ==============
  14. if test -f 'pcallang.h' -a X"$1" != X"-c"; then
  15.     echo 'x - skipping pcallang.h (File already exists)'
  16. else
  17. echo 'x - extracting pcallang.h (Text)'
  18. sed 's/^X//' << 'SHAR_EOF' > 'pcallang.h' &&
  19. /*
  20. X * pcallang.h - language-dependent strings (month and day names, option file 
  21. X * keywords, preprocessor tokens, prepositions, etc.):
  22. X *
  23. X * Revision history:
  24. X *
  25. X *    4.1    AWR    08/16/91    support -G flag (outlined gray)
  26. X *
  27. X *    4.02    AWR    07/02/91    support -v flag (version number);
  28. X *                    add ordinal_suffix(); add format
  29. X *                    specifiers to help message
  30. X *
  31. X *    4.0    AWR    03/01/91    expand parameter message to explain
  32. X *                    parameter meaning when -w specified
  33. X *
  34. X *        AWR    02/19/91    revise ordinal definitions for
  35. X *                    support of negative ordinals
  36. X *
  37. X *        AWR    02/06/91    add text describing expression syntax
  38. X *
  39. X *        AWR    02/04/91    support "odd" and "even" ordinals
  40. X *
  41. X *        AWR    01/28/91    support -B (blank fill squares) flag
  42. X *                    and -O (outline "gray" dates) flag
  43. X *
  44. X *        AWR    01/16/91    added moon file support (tokens, help
  45. X *                    file text, error messages); define
  46. X *                    note block heading here
  47. X *
  48. X *        AWR    01/07/91    added support for -w (whole year) flag
  49. X *
  50. X *    3.0    AWR    12/10/90    added support for "workday", "weekday",
  51. X *                    "holiday", et. al.
  52. X *
  53. X *        AWR    11/15/90    extracted from pcal.c; revised
  54. X *                    to contain all language-dependent
  55. X *                    strings
  56. X */
  57. X
  58. #define ALL    "all"        /* command-line or date file keyword */
  59. X
  60. #ifdef MAIN_MODULE
  61. X
  62. char *months[12] = {
  63. X    "January", "February", "March", "April", "May", "June",
  64. X    "July", "August", "September", "October", "November", "December"
  65. X    };
  66. X
  67. /* Must be a 2-D array so address within may be used as an initializer;
  68. X * wildcard names must be in same order as symbolic names in pcaldefs.h
  69. X */
  70. char days[14][12] = {
  71. X        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
  72. X        "Saturday",         /* weekday names */
  73. X    "day", "weekday", "workday", "holiday", "nonweekday", "nonworkday",
  74. X    "nonholiday"        /* wildcards */
  75. X    };
  76. X
  77. /* preprocessor tokens: token name, token code, dispatch routine */
  78. X
  79. KWD_F pp_info[] = {
  80. X    "define",    PP_DEFINE,    do_define,
  81. X    "else",        PP_ELSE,    NULL,
  82. X    "endif",    PP_ENDIF,    NULL,
  83. X    "ifdef",    PP_IFDEF,    do_ifdef,
  84. X    "ifndef",    PP_IFNDEF,    do_ifndef,
  85. X    "include",    PP_INCLUDE,    NULL,        /* do_include */
  86. X    "undef",    PP_UNDEF,    do_undef,
  87. X    NULL,        PP_OTHER,    NULL };        /* must be last */
  88. X
  89. /* ordinal numbers - e.g. "first Monday in September": ordinal name,
  90. X * ordinal code, ordinal value; note that "all" is parsed as a keyword
  91. X * and (depending on context) may be subsequently treated as an ordinal
  92. X */
  93. X
  94. KWD_O ordinals[] = {
  95. X    "first",    ORD_POSNUM,     1,
  96. X    "second",    ORD_POSNUM,     2,
  97. X    "third",    ORD_POSNUM,     3,
  98. X    "fourth",    ORD_POSNUM,     4,
  99. X    "fifth",    ORD_POSNUM,     5,
  100. X    "last",        ORD_NEGNUM,    -1,
  101. X    "odd",        ORD_ODD,     0,
  102. X    "even",        ORD_EVEN,     0,
  103. X    NULL,        ORD_OTHER,     0 };        /* must be last */
  104. X
  105. /* allowable suffixes for ordinal numbers */
  106. X
  107. char *ord_suffix[] = { "st", "nd", "rd", "th", NULL };
  108. X
  109. /* prepositions - e.g., "Friday after fourth Thursday in November" */
  110. X
  111. KWD preps[] = {
  112. X    "before",    PR_BEFORE,
  113. X    "preceding",    PR_BEFORE,
  114. X    "on_or_before",    PR_ON_BEFORE,
  115. X    "oob",        PR_ON_BEFORE,
  116. X    "after",    PR_AFTER,
  117. X    "following",    PR_AFTER,
  118. X    "on_or_after",    PR_ON_AFTER,
  119. X    "ooa",        PR_ON_AFTER,
  120. X    NULL,        PR_OTHER };    /* must be last */
  121. X
  122. /* other keywords */
  123. X
  124. KWD keywds[] = {
  125. X    ALL,         DT_ALL,
  126. X    "each",        DT_ALL,
  127. X    "every",    DT_ALL,
  128. X    "note",        DT_NOTE,
  129. X    "opt",        DT_OPT,
  130. X    "year",        DT_YEAR,
  131. X    NULL,        DT_OTHER };    /* must be last */
  132. X
  133. /* moon phases (for moon file) */
  134. X
  135. KWD phases[] = {
  136. X    "NM",        MOON_NM,    /* new moon */
  137. X    "1Q",        MOON_1Q,    /* first quarter */
  138. X    "FQ",        MOON_1Q,    
  139. X    "FM",        MOON_FM,    /* full moon */
  140. X    "3Q",        MOON_3Q,    /* third (last) quarter */
  141. X    "LQ",        MOON_3Q,
  142. X    NULL,        MOON_OTHER };    /* must be last */
  143. X
  144. #else
  145. extern char *months[];
  146. extern char days[14][12];
  147. extern KWD_F pp_info[];
  148. extern KWD preps[];
  149. extern KWD_O ordinals[];
  150. extern char *ord_suffix[];
  151. extern KWD keywds[];
  152. extern KWD phases[];
  153. #endif
  154. X
  155. /* minimum size of abbreviations  */
  156. X
  157. #define MIN_DAY_LEN    3
  158. #define MIN_MONTH_LEN    3
  159. #define MIN_PPTOK_LEN    3
  160. #define MIN_PREP_LEN    7    /* distinguish "on_or_before", "on_or_after" */
  161. #define MIN_ORD_LEN    3    /* distinguish "Thursday" from "third" */
  162. X
  163. X
  164. /*
  165. X * Symbolic names for command-line flags.  These may be changed
  166. X * as desired in order to be meaningful in languages other than
  167. X * English.
  168. X */
  169. X
  170. #define F_INITIALIZE    'I'        /* re-initialize program defaults */
  171. #define    F_BLACK_DAY    'b'        /* print day in black */
  172. #define F_GRAY_DAY    'g'        /* print day in gray */
  173. X
  174. #define F_DAY_FONT    'd'        /* select alternate day font */
  175. #define F_NOTES_FONT    'n'        /* select alternate notes font */
  176. #define F_TITLE_FONT    't'        /* select alternate title font */
  177. X
  178. #define F_EMPTY_CAL    'e'        /* print empty calendar */
  179. #define F_DATE_FILE    'f'        /* select alternate date file */
  180. #define F_OUT_FILE    'o'        /* select alternate output file */
  181. X
  182. #define F_LANDSCAPE    'l'        /* landscape mode */
  183. #define F_PORTRAIT    'p'        /* portrait mode */
  184. X
  185. #define F_HELP        'h'        /* generate full help message */
  186. #define F_VERSION    'v'        /* generate version ID */
  187. X
  188. #define F_MOON_4    'm'        /* print new/half/full moons */
  189. #define F_MOON_ALL    'M'        /* print all moons */
  190. X
  191. #define F_DEFINE    'D'        /* define preprocessor symbol */
  192. #define F_UNDEF        'U'        /* undefine preprocessor symbol */
  193. X
  194. #define F_L_FOOT    'L'        /* define left foot string */
  195. #define F_C_FOOT    'C'        /* define center foot string */
  196. #define F_R_FOOT    'R'        /* define right foot string */
  197. X
  198. #define F_FIRST_DAY    'F'        /* define alternate starting day */
  199. X
  200. #define F_USA_DATES    'A'        /* parse American date format */
  201. #define F_EUR_DATES    'E'        /* parse European date format */
  202. X
  203. #define F_X_TRANS    'X'        /* X-axis transformation */
  204. #define F_Y_TRANS    'Y'        /* Y-axis transformation */
  205. #define F_X_SCALE    'x'        /* X-axis scale factor */
  206. #define F_Y_SCALE    'y'        /* Y-axis scale factor */
  207. X
  208. #define F_JULIAN    'j'        /* print Julian day (day of year) */
  209. #define F_JULIAN_ALL    'J'        /* print Julian day and days left */
  210. X
  211. #define F_WHOLE_YEAR    'w'        /* print whole year per page */
  212. X                    /* (cf. W_WYFLAG below) */
  213. X
  214. #define F_BLANK_BOXES    'B'        /* don't fill unused boxes */
  215. X
  216. #define F_OUTLINE_GRAY    'G'        /* outline and fill "gray" dates */
  217. #define F_OUTLINE    'O'        /* draw "gray" dates as outlines */
  218. X
  219. /*
  220. X * Flag usage information - not strictly language-dependent, but here anyway
  221. X * (N.B.: all flags must be represented by an entry in this table!)
  222. X *
  223. X * Flags may appear in any of three places: in environment variable
  224. X * PCAL_OPTS, on the command line, or in "opt" lines in the date file.
  225. X * The command line is actually parsed twice: once before reading the date
  226. X * file to get the flags needed in processing it (-e, -f, -b, -g, -D, -U, -A,
  227. X * -E), and again after reading the date file to give the user one last
  228. X * chance to override any of the other flags set earlier.  (Note, however,
  229. X * that the only way to turn off -J|-j [Julian dates], -M|-m [moons], -w
  230. X * [whole year], or -G|-O [outline "gray" dates] once selected is to use -I
  231. X * to reinitialize all program defaults.)
  232. X *
  233. X * The table below supplies the following information about each flag:
  234. X *
  235. X *    - Its name (cf. symbolic definitions above)
  236. X *
  237. X *    - Whether or not it can take an (optional) argument
  238. X *
  239. X *    - Which passes parse it: P_ENV (environment variable), P_CMD1
  240. X *      (first command line pass), P_OPT ("opt" lines in date file), 
  241. X *      and P_CMD2 (second command line pass)
  242. X *
  243. X */
  244. X
  245. #ifdef MAIN_MODULE
  246. X
  247. FLAG_USAGE flag_tbl[] = {
  248. X
  249. /*    flag name    arg?    passes where parsed        */
  250. X
  251. X    F_INITIALIZE,    FALSE,    P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  252. X
  253. X    F_BLACK_DAY,    TRUE,    P_ENV | P_CMD1 | P_OPT          ,
  254. X    F_GRAY_DAY,    TRUE,    P_ENV | P_CMD1 | P_OPT          ,
  255. X
  256. X    F_DAY_FONT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  257. X    F_NOTES_FONT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  258. X    F_TITLE_FONT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  259. X
  260. X    F_EMPTY_CAL,    FALSE,    P_ENV | P_CMD1                  ,
  261. X    F_DATE_FILE,    TRUE,    P_ENV | P_CMD1                  ,
  262. X    F_OUT_FILE,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  263. X
  264. X    F_LANDSCAPE,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  265. X    F_PORTRAIT,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  266. X
  267. X    F_HELP,        FALSE,            P_CMD1                  ,
  268. X    F_VERSION,    FALSE,            P_CMD1                  ,
  269. X
  270. X    F_MOON_4,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  271. X    F_MOON_ALL,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  272. X
  273. X    F_DEFINE,    TRUE,    P_ENV | P_CMD1                  ,
  274. X    F_UNDEF,    TRUE,    P_ENV | P_CMD1                  ,
  275. X
  276. X    F_L_FOOT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  277. X    F_C_FOOT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  278. X    F_R_FOOT,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  279. X
  280. X    F_FIRST_DAY,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  281. X
  282. X    F_USA_DATES,    FALSE,    P_ENV | P_CMD1 | P_OPT          ,
  283. X    F_EUR_DATES,    FALSE,    P_ENV | P_CMD1 | P_OPT          ,
  284. X
  285. X    F_X_TRANS,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  286. X    F_Y_TRANS,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  287. X    F_X_SCALE,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  288. X    F_Y_SCALE,    TRUE,    P_ENV          | P_OPT | P_CMD2 ,
  289. X
  290. X    F_JULIAN,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  291. X    F_JULIAN_ALL,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  292. X
  293. X    F_WHOLE_YEAR,    FALSE,    P_ENV | P_CMD1 | P_OPT          ,
  294. X
  295. X    F_BLANK_BOXES,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  296. X
  297. X    F_OUTLINE_GRAY,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  298. X    F_OUTLINE,    FALSE,    P_ENV          | P_OPT | P_CMD2 ,
  299. X
  300. X    '-',        FALSE,    P_ENV | P_CMD1 | P_OPT | P_CMD2 ,
  301. X    '\0',        FALSE,    P_ENV | P_CMD1 | P_OPT | P_CMD2        /* must be last */
  302. X    };
  303. X
  304. #else
  305. extern FLAG_USAGE flag_tbl[];
  306. #endif
  307. X
  308. /*
  309. X * Words used in usage() message - translate as necessary
  310. X */
  311. X
  312. #define W_DEFAULT    "default"        /* translate as required */
  313. #define W_USAGE        "Usage"
  314. X
  315. #define W_FONT        "FONT"            /* names of metavariables */
  316. #define W_DAY        "DAY"
  317. #define W_STRING    "STRING"
  318. #define W_FILE        "FILE"
  319. #define W_SYMBOL    "SYMBOL"
  320. #define W_VALUE        "VALUE"
  321. X
  322. #define W_MM        "MM"            /* abbrev. for month, year */
  323. #define W_YY        "YY"
  324. X
  325. #define W_WYFLAG    "-w"            /* must conform to F_WHOLE_YEAR */
  326. X
  327. #define W_BLACK        "black"            /* cf. color_msg() */
  328. #define W_GRAY        "gray"
  329. X
  330. X
  331. /* special flag_msg[] entries for end of option group, etc. */
  332. X
  333. #define END_GROUP    '\n', NULL, NULL, NULL        /* end of option group */
  334. #define END_LIST    '\0', NULL, NULL, NULL        /* end of list */
  335. #define GROUP_DEFAULT    ' ', NULL, " "            /* group default */
  336. X
  337. /*
  338. X * Message strings to be printed by usage() - translate as necessary
  339. X */
  340. #ifdef MAIN_MODULE
  341. X
  342. FLAG_MSG flag_msg[] = {
  343. X
  344. /*    flag name    metasyntax    description                        default */
  345. X
  346. X    F_INITIALIZE,    NULL,        "initialize all parameters to program defaults",    NULL,
  347. X    END_GROUP,
  348. X
  349. X    F_BLACK_DAY,    W_DAY,        "print weekday in black",                NULL,
  350. X    F_GRAY_DAY,    W_DAY,        "print weekday in gray (see below)",            NULL,
  351. X    END_GROUP,
  352. X
  353. X    F_OUTLINE_GRAY,    NULL,        "print \"gray\" dates as filled outlines",        NULL,
  354. X    F_OUTLINE,    NULL,        "print \"gray\" dates as unfilled outlines",        NULL,
  355. #if NUM_STYLE == GRAY_NUMS
  356. X    GROUP_DEFAULT,                                        "gray characters",
  357. #else
  358. #if NUM_STYLE == OUTLINE_NUMS
  359. X    GROUP_DEFAULT,                                        "unfilled outlines",
  360. #else
  361. X    GROUP_DEFAULT,                                        "filled outlines",
  362. #endif
  363. #endif
  364. X
  365. X    END_GROUP,
  366. X
  367. X    F_DAY_FONT,    W_FONT,        "specify alternate day name font",            DAYFONT,
  368. X    F_NOTES_FONT,    W_FONT,        "specify alternate notes font",                NOTESFONT,
  369. X    F_TITLE_FONT,    W_FONT,        "specify alternate title font",                TITLEFONT,
  370. X    END_GROUP,
  371. X
  372. X    F_EMPTY_CAL,    NULL,        "generate empty calendar (ignore date file)",        NULL,
  373. X    END_GROUP,
  374. X
  375. X    F_DATE_FILE,    W_FILE,        "specify alternate date file",                DATEFILE,
  376. X    END_GROUP,
  377. X
  378. #ifdef DEFAULT_OUTFILE
  379. X    F_OUT_FILE,    W_FILE,        "specify alternate output file",            DEFAULT_OUTFILE,
  380. #else
  381. X    F_OUT_FILE,    W_FILE,        "specify alternate output file",            "stdout",
  382. #endif
  383. X    END_GROUP,
  384. X
  385. X    F_LANDSCAPE,    NULL,        "generate landscape-style calendar",            NULL,
  386. X    F_PORTRAIT,    NULL,        "generate portrait-style calendar",            NULL,
  387. #if ROTATE == LANDSCAPE
  388. X    GROUP_DEFAULT,                                        "landscape",
  389. #else    
  390. X    GROUP_DEFAULT,                                        "portrait",
  391. #endif
  392. X    END_GROUP,
  393. X
  394. X    F_HELP,        NULL,        "print this help message",                NULL,
  395. X    F_VERSION,    NULL,        "print version information",                NULL,
  396. X    END_GROUP,
  397. X
  398. X    F_MOON_4,    NULL,        "draw a \"moon\" icon at full/new/half moons",        NULL,
  399. X    F_MOON_ALL,    NULL,        "draw a \"moon\" icon every day",            NULL,
  400. #if DRAW_MOONS == NO_MOONS
  401. X    GROUP_DEFAULT,                                        "no moons",
  402. #else
  403. #if DRAW_MOONS == SOME_MOONS
  404. X    GROUP_DEFAULT,                                        "full/new/half moons",
  405. #else
  406. X    GROUP_DEFAULT,                                        "every day",
  407. #endif
  408. #endif
  409. X    END_GROUP,
  410. X
  411. X    F_DEFINE,    W_SYMBOL,    "define preprocessor symbol",                NULL,
  412. X    F_UNDEF,    W_SYMBOL,    "undefine preprocessor symbol",                NULL,
  413. X    END_GROUP,
  414. X
  415. X    F_L_FOOT,    W_STRING,    "specify left foot string",                LFOOT,
  416. X    F_C_FOOT,    W_STRING,    "specify center foot string",                CFOOT,
  417. X    F_R_FOOT,    W_STRING,    "specify right foot string",                RFOOT,
  418. X    END_GROUP,
  419. X
  420. X    F_FIRST_DAY,    W_DAY,        "specify starting day of week",                days[FIRST_DAY],
  421. X    END_GROUP,
  422. X
  423. X    F_USA_DATES,    NULL,        "parse American dates (\"mm/dd{/yy}\" and \"month dd\")", NULL,
  424. X    F_EUR_DATES,    NULL,        "parse European dates (\"dd/mm{/yy}\" and \"dd month\")", NULL,
  425. #if DATE_STYLE == USA_DATES
  426. X    GROUP_DEFAULT,                                        "American",
  427. #else
  428. X    GROUP_DEFAULT,                                        "European",
  429. #endif
  430. X    END_GROUP,
  431. X
  432. X    F_X_TRANS,    W_VALUE,    "specify x-axis translation",                XTVAL,
  433. X    F_Y_TRANS,    W_VALUE,    "specify y-axis translation",                YTVAL,
  434. X    F_X_SCALE,    W_VALUE,    "specify x-axis scale factor",                XSVAL,
  435. X    F_Y_SCALE,    W_VALUE,    "specify y-axis scale factor",                YSVAL,
  436. X    END_GROUP,
  437. X
  438. X    F_JULIAN,    NULL,        "print Julian day (day of year)",            NULL,
  439. X    F_JULIAN_ALL,    NULL,        "print Julian day and days left in year",        NULL,
  440. #if JULIAN_DATES == NO_JULIANS
  441. X    GROUP_DEFAULT,                                        "neither",
  442. #else
  443. #if JULIAN_DATES == SOME_JULIANS
  444. X    GROUP_DEFAULT,                                        "Julian day",
  445. #else
  446. X    GROUP_DEFAULT,                                        "both",
  447. #endif
  448. #endif
  449. X    END_GROUP,
  450. X
  451. X    F_WHOLE_YEAR,    NULL,        "print whole year (12 consecutive months) per page",    NULL,
  452. X    END_GROUP,
  453. X
  454. X    F_BLANK_BOXES,    NULL,        "leave unused boxes blank",                NULL,
  455. X
  456. X    END_GROUP,            /* must precede END_LIST */
  457. X
  458. X    END_LIST            /* must be last */
  459. };
  460. X
  461. #else
  462. extern FLAG_MSG flag_msg[];
  463. #endif
  464. X
  465. /* Numeric parameter descriptions and text */
  466. X
  467. #ifdef MAIN_MODULE
  468. X
  469. #if __STDC__
  470. PARAM_MSG param_msg[] = {
  471. X    W_YY,            "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
  472. X    W_MM " " W_YY,        "generate calendar for month " W_MM " (Jan = 1), year " W_YY,
  473. X    W_MM " " W_YY " N",    "generate calendars for N months, starting at " W_MM "/" W_YY,
  474. X    "(" W_DEFAULT ")",    "generate calendar for current month and/or year",
  475. X    "",            "",
  476. X    "if " W_WYFLAG " specified:",    "",
  477. X    "",            "",
  478. X    W_YY,            "generate calendar for year " W_YY " (19" W_YY " if " W_YY " < 100)",
  479. X    W_MM " " W_YY,        "generate calendars for 12 months, starting at " W_MM "/" W_YY,
  480. X    W_MM " " W_YY " N",    "generate calendars for N months, starting at " W_MM "/" W_YY,
  481. X    "",            "  (N rounded up to next multiple of 12)",
  482. X    "(" W_DEFAULT ")",    "generate calendar for current year",
  483. X    NULL,        NULL        /* must be last */
  484. };
  485. #else
  486. PARAM_MSG param_msg[] = {
  487. X    "YY",        "generate calendar for year YY (19YY if YY < 100)",
  488. X    "MM YY",    "generate calendar for month MM (Jan = 1), year YY",
  489. X    "MM YY N",    "generate calendars for N months, starting at MM/YY",
  490. X    "(default)",    "generate calendar for current month and year",
  491. X    "",        "",
  492. X    "if -w specified:",    "",
  493. X    "",        "",
  494. X    "YY",        "generate calendar for year YY (19YY if YY < 100)",
  495. X    "MM YY",    "generate calendar for 12 months, starting at MM/YY",
  496. X    "MM YY N",    "generate calendars for N months, starting at MM/YY",
  497. X    "",        "  (N rounded up to next multiple of 12)",
  498. X    "(default)",    "generate calendar for current year",
  499. X    NULL,        NULL        /* must be last */
  500. };
  501. #endif
  502. X
  503. #else
  504. extern PARAM_MSG param_msg[];
  505. #endif
  506. X
  507. #define PARAM_MSGS    3    /* number of above to print in command-line syntax message */
  508. X
  509. /* Date file syntax message - lines are copied intact */
  510. X
  511. #ifdef MAIN_MODULE
  512. X
  513. char *date_msg[] = {
  514. X    "",
  515. X    "Date file syntax:",
  516. X    "",
  517. X    "The following rules describe the syntax of date file entries:",
  518. X    "",
  519. X    "  year <year>",
  520. X    "",
  521. X    "  opt <options>",
  522. X    "",
  523. X    "  note <month_spec> <text>",
  524. X    "  note <month> <text>",
  525. X    "",
  526. X    "  if -A flag (American date formats) specified:",
  527. X    "    <month_name> <day>{*} {<text>}",
  528. X    "    <month><sep><day>{<sep><year>}{*} {<text>}",
  529. X    "",
  530. X    "  if -E flag (European date formats) specified:",
  531. X    "    <day> <month_name>{*} {<text>}",
  532. X    "    <day><sep><month>{<sep><year>}{*} {<text>}",
  533. X    "",
  534. X    "  <ordinal> <day_name> in <month_spec>{*} {<text>}",
  535. X    "  <day_name> <prep> <date_spec>",
  536. X    "",
  537. X    "where",
  538. X    "",
  539. X    "  {x}          means x is optional",
  540. X    "",
  541. X    "  <date_spec> := any of the above date specs (not year, note, or opt)",
  542. X    "  <month_name> := first 3+ characters of name of month, or \"all\"",
  543. X    "  <month_spec> := <month_name>, or \"year\"",
  544. X    "  <day_name> := first 3+ characters of name of weekday, \"day\",",
  545. X    "                \"weekday\", \"workday\", \"holiday\", \"nonweekday\",",
  546. X    "                \"nonworkday\", or \"nonholiday\"",
  547. X    "  <ordinal> := ordinal number (\"1st\", \"2nd\", etc.), \"first\" .. \"fifth\",",
  548. X    "                \"last\", \"even\", \"odd\", or \"all\"",
  549. X    "  <prep> := \"before\", \"preceding\", \"after\", \"following\", \"on_or_before\",",
  550. X    "                or \"on_or_after\"",
  551. X    "  <sep> := one or more non-numeric, non-space, non-'*' characters",
  552. X    "  <month>, <day>, <year> are the numeric forms",
  553. X    "",
  554. X    "  <options> := any command-line option except -e, -f, -h, -v, -D, -U",
  555. X    "",
  556. X    "Comments start with '#' and run through end-of-line.",
  557. X    "",
  558. X    "Holidays may be flagged by specifying '*' as the last character of",
  559. X    "the date field(s), e.g. \"10/12* Columbus Day\", \"July 4* Independence",
  560. X    "Day\", etc.  Any dates flagged as holidays will be printed in gray, and",
  561. X    "any associated text will appear adjacent to the date.",
  562. X    "",
  563. X    "Note that the numeric date formats (mm/dd{/yy}, dd.mm{.yy}) support",
  564. X    "an optional year, which will become the subsequent default year.  The",
  565. X    "alphabetic date formats (month dd, dd month) do not support a year",
  566. X    "field; the \"year yy\" command is provided to reset the default year.",
  567. X    "",
  568. X    "\"Floating\" days may be specified in the date file as \"first Mon in ",
  569. X    "Sep\", \"last Mon in May\", \"4th Thu in Nov\", etc.; any word may be",
  570. X    "used in place of \"in\".  \"Relative floating\" days (e.g. \"Fri after 4th ",
  571. X    "Thu in Nov\") are also accepted; they may span month/year bounds.",
  572. X    "Pcal also accepts date specs such as \"all Friday{s} in October\", \"last",
  573. X    "Thursday in all\", etc., and produces the expected results; \"each\" and",
  574. X    "\"every\" are accepted as synonyms for \"all\".  Negative ordinals are",
  575. X    "allowed; \"-2nd\" means \"next to last\".",
  576. X    "",
  577. X    "The words \"day\", \"weekday\", \"workday\", and \"holiday\" may be used as",
  578. X    "wildcards: \"day\" matches any day, \"weekday\" matches any day normally",
  579. X    "printed in black, \"workday\" matches any day normally printed in black",
  580. X    "and not explicitly flagged as a holiday, and \"holiday\" matches any",
  581. X    "day explicitly flagged as a holiday.  \"Nonweekday\", \"nonworkday\",",
  582. X    "and \"nonholiday\" are also supported and have the obvious meanings.",
  583. X    "",
  584. X    "\"Odd\" and \"even\" do not refer to the actual date; instead, \"odd\"",
  585. X    "means \"alternate, starting with the first\"; \"even\" means \"alternate,",
  586. X    "starting with the second\".  Thus, \"odd Fridays in March\" refers to",
  587. X    "the first, third, and (if present) fifth Fridays in March - not to",
  588. X    "those Fridays falling on odd dates.",
  589. X    "",
  590. X    "\"All\" refers to each individual month; \"year\" refers to the year",
  591. X    "as an entity.  Thus \"odd Fridays in all\" refers to the first/third/",
  592. X    "fifth Friday of each month, while \"odd Fridays in year\" refers to",
  593. X    "the first Friday of January and every other Friday thereafter.",
  594. X    "",
  595. X    "Additional notes may be propagated to an empty calendar box by the",
  596. X    "inclusion of one or more lines of the form \"note <month> <text>\",",
  597. X    "where <month> may be numeric or alphabetic; \"note all <text>\"",
  598. X    "propagates <text> to each month in the current year.",
  599. X    "",
  600. X    "Pcal also allows format specifiers in the text (and foot strings -",
  601. X    "cf. the -L, -C, and -R options); each will be replaced by its",
  602. X    "equivalent string as outlined in the table below.  (Most of these are",
  603. X    "derived from the strftime() function; %[lo0+-] are Pcal-specific.)",
  604. X    "",
  605. X    "        %a : abbreviated weekday",
  606. X    "        %A : full weekday",
  607. X    "        %b : abbreviated month name",
  608. X    "        %B : full month name",
  609. X    "        %d : day of month (1-31)",
  610. X    "        %j : day of year (1-366)",
  611. X    "        %l : days left in year (0-365)",
  612. X    "        %m : month (1-12)",
  613. X    "        %U : week number (0-53)",
  614. X    "        %W : week number (0-53)",
  615. X    "        %y : year w/o century (00-99)",
  616. X    "        %Y : year w/century",
  617. X    "        %% : '%' character",
  618. X    "",
  619. X    "        %o : print number as ordinal",
  620. X    "        %0 : print number with leading zeroes",
  621. X    "        %+ : use following month or year",
  622. X    "        %- : use previous month or year",
  623. X    "",
  624. X    "%U considers the first logical Sunday (the first day of the week as",
  625. X    "printed; cf. the -F flag) of the year as the first day of week 1;",
  626. X    "%W uses the first logical Monday instead.  This is an extension of",
  627. X    "strftime()'s behavior.",
  628. X    "",
  629. X    "%o prints a number as an ordinal, with the appropriate suffix (\"st\",",
  630. X    "\"nd\", \"rd\", or \"th\" in English) appended; for example, \"%od\" prints",
  631. X    "the day of the month as \"1st\", \"2nd\", \"3rd\", etc.",
  632. X    "",
  633. X    "Unlike strftime(), Pcal's default is to print numbers (except %y)",
  634. X    "without leading zeroes.  If leading zeroes are desired, the '0'",
  635. X    "prefix may be used; for example, \"%0j\" prints the day of year as",
  636. X    "001-365.",
  637. X    "",
  638. X    "%+ and %- direct Pcal to substitute the following/previous month/year",
  639. X    "in the following [bBmyY] specifier; for example, %+B prints the name",
  640. X    "of the next month.",
  641. X    "",
  642. X    "Simple cpp-like functionality is provided.  The date file may include",
  643. X    "the following commands, which work like their cpp counterparts:",
  644. X    "",
  645. X    "        define <sym>",
  646. X    "        undef <sym>",
  647. X    "",
  648. X    "        if{n}def <expr>",
  649. X    "           ...",
  650. X    "        { else",
  651. X    "           ... }",
  652. X    "        endif",
  653. X    "",
  654. X    "        include <file>",
  655. X    "",
  656. X    "Note that these do not start with '#', which is reserved as a comment",
  657. X    "character.",
  658. X    "",
  659. X    "<sym> is a symbol name consisting of a letter followed by zero or",
  660. X    "more letters, digits, or underscores ('_').  Symbol names are always",
  661. X    "treated in a case-insensitive manner.",
  662. X    "",
  663. X    "<expr> is an expression consisting of symbol names joined by the logical",
  664. X    "operators (in order of precedence, high to low) '!' (unary negate), '&'",
  665. X    "(and), '^' (exclusive or), and '|' (inclusive or).  '&&' and '||' are",
  666. X    "accepted as synonyms for '&' and '|' respectively; the order of",
  667. X    "evaluation may be altered by the use of parentheses.  A symbol whose",
  668. X    "name is currently defined evaluates to TRUE; one whose name is not",
  669. X    "currently defined evaluates to FALSE.  Thus \"ifdef A | B | C\" is TRUE",
  670. X    "if any of the symbols A, B, and C is currently defined, and",
  671. X    "\"ifdef A & B & C\" is TRUE if all of them are.",
  672. X    "",
  673. X    "\"ifndef A | B | C\" is equivalent to \"ifdef !(A | B | C)\" (or, using",
  674. X    "DeMorgan's Law, \"ifdef !A & !B & !C\") - in other words, TRUE if none of",
  675. X    "the symbols A, B, and C is currently defined.",
  676. X    "",
  677. X    "\"define\" alone deletes all the current definitions; \"ifdef\" alone is",
  678. X    "always false; \"ifndef\" alone is always true.",
  679. X    "",
  680. X    "The file name in the \"include\" directive may optionally be surrounded",
  681. X    "by \"\" or <>.  In any case, path names are taken to be relative to",
  682. X    "the location of the file containing the \"include\" directive.",
  683. X    "",
  684. X    "",
  685. X    "Moon file syntax:",
  686. X    "",
  687. X    "The user may enter the dates and (optionally) times of quarter",
  688. X    "moons (from a reliable source such as an almanac or astronomical",
  689. X    "table) into a file called .moonXX (moonXX.dat on VMS), where XX is",
  690. X    "the last two digits of the year.  If such a file exists (in the",
  691. X    "same directory as the date file), Pcal will interpolate the phase",
  692. X    "of the moon from the information in this file instead of using the",
  693. X    "default algorithm.",
  694. X    "",
  695. X    "(Pcal originally used an extremely simplistic moon phase algorithm;",
  696. X    "the moon file was added to v4.0 to enable Pcal to interpolate the",
  697. X    "phase of the moon from the [presumably more accurate] information",
  698. X    "within.  More recently, the original moon phase algorithm was",
  699. X    "superseded by an astronomer-strength version, largely obviating",
  700. X    "the need for a moon file; however, it will continue to be",
  701. X    "supported for the foreseeable future.)",
  702. X    "",
  703. X    "Entries in the moon file must conform to the following syntax:",
  704. X    "",
  705. X    "  if -A flag (American date formats) specified:",
  706. X    "    <quarter> <month><sep><day> {<hour><sep><min>}",
  707. X    "",
  708. X    "  if -E flag (European date formats) specified:",
  709. X    "    <quarter> <day><sep><month> {<hour><sep><min>}",
  710. X    "",
  711. X    "where",
  712. X    "",
  713. X    "  <quarter> := \"nm\", \"fq\" or \"1q\", \"fm\", \"lq\" or \"3q\" (new",
  714. X    "                moon, first quarter, full moon, last quarter)",
  715. X    "  <hour>    := number 0-23 (24-hour clock)",
  716. X    "  <min>     := number 0-59",
  717. X    "",
  718. X    "This file must contain entries for all quarter moons in the year,",
  719. X    "in chronological order; if any errors are encountered, Pcal will",
  720. X    "revert to using its default algorithm.",
  721. X    "",
  722. X    "As in the date file, comments start with '#' and run through",
  723. X    "end-of-line.  ",
  724. X    NULL
  725. X    };
  726. #else
  727. extern char *date_msg[];
  728. #endif
  729. X
  730. /* format strings for color_msg() - translate as necessary */
  731. #define COLOR_MSG_1    "all days in %s"
  732. #define COLOR_MSG_2    "in %s; others in %s"
  733. X
  734. /* format string for short usage() message */
  735. #define USAGE_MSG    "\"%s -%c\" prints full description of flags, parameters, and file formats\n"
  736. X
  737. /* format strings for comment in PostScript output file */
  738. #define VERSION_MSG    "Generated by %s %s"
  739. #define DATEFILE_MSG    " from %s"
  740. X
  741. #define NOTES_HDR    "Notes"        /* title of "notes" box */
  742. #define LINE_SEP    ".p"        /* text line separator */
  743. X
  744. /* strings used in error messages */
  745. #define ENV_VAR        "environment variable "
  746. #define DATE_FILE    "date file "
  747. X
  748. /* Error and information messages - translate as necessary */
  749. X
  750. /* program error messages */
  751. #define    E_ALLOC_ERR    "%s: calloc() failed - out of memory\n"
  752. #define    E_FOPEN_ERR    "%s: can't open file %s\n"
  753. #define    E_ILL_LINE    "%s: %s in file %s, line %d\n"
  754. #define    E_ILL_MONTH    "%s: month %d not in range %d .. %d\n"
  755. #define    E_ILL_OPT    "%s: unrecognized flag %s"
  756. #define E_ILL_OPT2    " (%s\"%s\")"
  757. #define    E_ILL_YEAR    "%s: year %d not in range %d .. %d\n"
  758. #define    E_SYMFULL    "%s: symbol table full - can't define %s\n"
  759. #define    E_UNT_IFDEF    "%s: unterminated if{n}def..{else..}endif in file %s\n"
  760. #define E_FLAG_IGNORED    "%s: -%c flag ignored (%s\"%s\")\n"
  761. X
  762. /* preprocessor error strings */
  763. #define E_ELSE_ERR    "unmatched \"else\""
  764. #define E_END_ERR    "unmatched \"endif\""
  765. #define E_GARBAGE    "extraneous data on \"%s\" line"
  766. #define E_INV_DATE    "invalid date (or no match for wildcard)"
  767. #define E_INV_LINE    "unrecognized line"
  768. #define E_NESTING    "maximum file nesting level exceeded"
  769. #define E_EXPR_SYNTAX    "syntax error in expression"
  770. X
  771. /* moon file error strings */
  772. #define E_DATE_SEQ    "date or phase out of sequence"
  773. #define E_PREM_EOF    "premature EOF"
  774. X
  775. /* information message (VMS, Amiga only) */
  776. #define    I_OUT_NAME    "%s: output is in file %s\n"
  777. X
  778. X
  779. /*
  780. X * Yes, some source code in a header file.  This is a language-dependent
  781. X * routine used by writefil.c to translate the %o (ordinal suffix) format
  782. X * specifier into the appropriate string for printing, and seemed to belong
  783. X * here with the other language dependencies.
  784. X */
  785. #ifdef WRITEFIL            /* include only in writefil.c */
  786. #ifdef PROTOS
  787. static char *ordinal_suffix(int num)
  788. #else
  789. static char *ordinal_suffix(num)
  790. X    int num;        /* ordinal number - assumed positive */
  791. #endif
  792. {
  793. X    static char buf[10];
  794. X    static char *suffix[] = { "th", "st", "nd", "rd" };
  795. X    int tens, units;
  796. X
  797. X    tens = (num / 10) % 10;        /* select suffix */
  798. X    units = num % 10;
  799. X    strcpy(buf, suffix[(units > 3 || tens == 1) ? 0 : units]);
  800. X
  801. X    return buf;
  802. }
  803. #endif
  804. SHAR_EOF
  805. chmod 0666 pcallang.h ||
  806. echo 'restore of pcallang.h failed'
  807. Wc_c="`wc -c < 'pcallang.h'`"
  808. test 27444 -eq "$Wc_c" ||
  809.     echo 'pcallang.h: original size 27444, current size' "$Wc_c"
  810. fi
  811. # ============= pcalutil.c ==============
  812. if test -f 'pcalutil.c' -a X"$1" != X"-c"; then
  813.     echo 'x - skipping pcalutil.c (File already exists)'
  814. else
  815. echo 'x - extracting pcalutil.c (Text)'
  816. sed 's/^X//' << 'SHAR_EOF' > 'pcalutil.c' &&
  817. /*
  818. X * pcalutil.c - utility routines for Pcal
  819. X *
  820. X * Contents:
  821. X *
  822. X *        alloc
  823. X *        calc_day
  824. X *        calc_weekday
  825. X *        calc_year_day
  826. X *        ci_strcmp
  827. X *        ci_strncmp
  828. X *        copy_text
  829. X *        find_executable
  830. X *        getline
  831. X *        is_valid
  832. X *        loadwords
  833. X *        mk_filespec
  834. X *        mk_path
  835. X *        normalize
  836. X *        split_date
  837. X *        trnlog
  838. X *
  839. X * Revision history:
  840. X *
  841. X *    4.02    AWR    06/07/91    added find_executable()
  842. X *
  843. X *    4.0    AWR    02/24/91    Revised getline() and copy_text() to
  844. X *                    handle C-style escapes of characters
  845. X *                    and octal/hex numbers
  846. X *
  847. X *        AWR    02/19/91    Added support for negative ordinals
  848. X *                    in calc_day(), calc_year_day()
  849. X *
  850. X *        AWR    02/04/91    Added calc_year_day()
  851. X *
  852. X *        AWR    01/15/91    Extracted from pcal.c
  853. X *
  854. X */
  855. X
  856. X
  857. /*
  858. X * Standard headers:
  859. X */
  860. X
  861. #include <stdio.h>
  862. #include <ctype.h>
  863. #include <string.h>
  864. X
  865. /*
  866. X * Pcal-specific definitions:
  867. X */
  868. X
  869. #include "pcaldefs.h"
  870. #include "pcalglob.h"
  871. #include "pcallang.h"
  872. X
  873. /*
  874. X * Macros:
  875. X */
  876. X
  877. /* skip over numeric field and subsequent non-numeric characters */
  878. #define SKIP_FIELD(p) \
  879. X    do { while (*p && isdigit(*p)) p++; \
  880. X         while (*p && !isdigit(*p)) p++; } while (0)
  881. X
  882. X
  883. /*
  884. X * General-purpose utility routines
  885. X */
  886. X
  887. X
  888. /*
  889. X * alloc - interface to calloc(); terminates if unsuccessful
  890. X */
  891. #ifdef PROTOS
  892. char *alloc(int size)
  893. #else
  894. char *alloc(size)
  895. X    int size;
  896. #endif
  897. {
  898. X    char *p;
  899. X
  900. X    if (size == 0)        /* not all calloc()s like null requests */
  901. X        size = 1;
  902. X
  903. X    if ((p = calloc(1, size)) == NULL) {
  904. X        FPR(stderr, E_ALLOC_ERR, progname);
  905. X        exit(EXIT_FAILURE);
  906. X    }
  907. X
  908. X    return p;
  909. }
  910. X
  911. X
  912. /*
  913. X * ci_str{n}cmp - case-insensitive flavors of strcmp(), strncmp()
  914. X */
  915. #ifdef PROTOS
  916. int ci_strcmp(register char *s1,
  917. X          register char *s2)
  918. #else
  919. int ci_strcmp(s1, s2)
  920. X    register char *s1, *s2;
  921. #endif
  922. {
  923. X    register char c1, c2;
  924. X
  925. X    for ( ; (c1 = TOLOWER(*s1)) == (c2 = TOLOWER(*s2)); s1++, s2++)
  926. X        if (c1 == '\0')
  927. X            return 0;
  928. X
  929. X    return c1 - c2;
  930. }
  931. X
  932. X
  933. #ifdef PROTOS
  934. int ci_strncmp(register char *s1,
  935. X           register char *s2,
  936. X           int n)
  937. #else
  938. int ci_strncmp(s1, s2, n)
  939. X    register char *s1, *s2;
  940. X    int n;
  941. #endif
  942. {
  943. X    register char c1, c2;
  944. X
  945. X    for ( ; --n >= 0 && (c1 = TOLOWER(*s1)) == (c2 = TOLOWER(*s2)); s1++, s2++)
  946. X        if (c1 == '\0')
  947. X            return 0;
  948. X
  949. X    return n < 0 ? 0 : c1 - c2;
  950. }
  951. X
  952. X
  953. /*
  954. X * Date calculation routines (see also macros in pcaldefs.h)
  955. X */
  956. X
  957. X
  958. /*
  959. X * normalize - adjust day in case it has crossed month (or year) bounds 
  960. X */
  961. #ifdef PROTOS
  962. void normalize(DATE *pd)
  963. #else
  964. void normalize(pd)
  965. X    DATE *pd;        /* pointer to date */
  966. #endif
  967. {
  968. X    int len;
  969. X
  970. X    /* adjust if day is in previous or following month */
  971. X
  972. X    while (pd->dd < 1) {
  973. X        pd->yy = PREV_YEAR(pd->mm, pd->yy);
  974. X        pd->mm = PREV_MONTH(pd->mm, pd->yy);
  975. X        pd->dd += LENGTH_OF(pd->mm, pd->yy);
  976. X    }
  977. X
  978. X    while (pd->dd > (len = LENGTH_OF(pd->mm, pd->yy))) {
  979. X        pd->dd -= len;
  980. X        pd->yy = NEXT_YEAR(pd->mm, pd->yy);
  981. X        pd->mm = NEXT_MONTH(pd->mm, pd->yy);
  982. X    }
  983. }
  984. X
  985. X
  986. /*
  987. X * calc_day - calculate calendar date from ordinal date (e.g., "first Friday
  988. X * in November", "last day in October"); return calendar date if it exists, 
  989. X * 0 if it does not
  990. X */
  991. #ifdef PROTOS
  992. int calc_day(int ord,
  993. X         int wkd,
  994. X         int mm)
  995. #else
  996. int calc_day(ord, wkd, mm)
  997. X    int ord;
  998. X    int wkd;
  999. X    int mm;
  1000. #endif
  1001. {
  1002. #ifdef PROTOS
  1003. X    int first, last, day, (*pfcn)(int, int, int);
  1004. #else
  1005. X    int first, last, day, (*pfcn)();
  1006. #endif
  1007. X
  1008. X    if (IS_WILD(wkd)) {    /* "day", "weekday", "workday", or "holiday" */
  1009. X        pfcn = pdatefcn[wkd - WILD_FIRST];
  1010. X        last = LENGTH_OF(mm, curr_year);
  1011. X
  1012. X        if (ord < 0) {            /* search backwards */
  1013. X            for (day = last; 
  1014. X                 day >= 1 &&
  1015. X                !((*pfcn)(mm, day, curr_year) && ++ord == 0);
  1016. X                 day--)
  1017. X                ;
  1018. X        } else {            /* search forwards */
  1019. X            for (day = 1; 
  1020. X                 day <= last && 
  1021. X                !((*pfcn)(mm, day, curr_year) && --ord == 0);
  1022. X                 day++)    
  1023. X                ;
  1024. X        }
  1025. X        return is_valid(mm, day, curr_year) ? day : 0; 
  1026. X
  1027. X    } else {        /* fixed weekday - calculate it */
  1028. X        first = (wkd - FIRST_OF(mm, curr_year) + 7) % 7 + 1;
  1029. X        if (ord < 0) {        /* get last (try 5th, then 4th) */
  1030. X            if (!is_valid(mm, last = first + 28, curr_year))
  1031. X                last -= 7;
  1032. X            if (!is_valid(mm, day = last + 7 * (ord + 1),
  1033. X                curr_year))
  1034. X                day = 0;    
  1035. X        }
  1036. X        else 
  1037. X            if (!is_valid(mm, day = first + 7 * (ord - 1),
  1038. X                curr_year))
  1039. X                day = 0;
  1040. X
  1041. X        return day;
  1042. X    }
  1043. X
  1044. }
  1045. X
  1046. X
  1047. /*
  1048. X * calc_year_day - calculate calendar date from ordinal date within year
  1049. X * (e.g., "last Friday in year", "10th holiday in year"); if date exists,
  1050. X * fill in pdate and return TRUE; else return FALSE
  1051. X */
  1052. #ifdef PROTOS
  1053. int calc_year_day(int ord,
  1054. X          int wkd,
  1055. X          DATE *pdate)
  1056. #else
  1057. int calc_year_day(ord, wkd, pdate)
  1058. X    int ord;
  1059. X    int wkd;
  1060. X    DATE *pdate;
  1061. #endif
  1062. {
  1063. #ifdef PROTOS
  1064. X    int incr, (*pfcn)(int, int, int);
  1065. #else
  1066. X    int incr, (*pfcn)();
  1067. #endif
  1068. X    DATE date;
  1069. X
  1070. X    if (IS_WILD(wkd)) {    /* "day", "weekday", "workday", or "holiday" */
  1071. X        pfcn = pdatefcn[wkd - WILD_FIRST];
  1072. X
  1073. X        if (ord < 0) {            /* nth occurrence backwards */
  1074. X            MAKE_DATE(date, DEC, 31, curr_year);
  1075. X            ord = -ord;
  1076. X            incr = -1;
  1077. X        } else {            /* nth occurrence forwards */
  1078. X            MAKE_DATE(date, JAN, 1, curr_year);
  1079. X            incr = 1;
  1080. X        }
  1081. X
  1082. X        /* search for selected occurrence of specified wildcard */
  1083. X
  1084. X        while (date.yy == curr_year &&
  1085. X               !((*pfcn)(date.mm, date.dd, date.yy) && --ord == 0)) {
  1086. X            date.dd += incr;
  1087. X            normalize(&date);
  1088. X        }
  1089. X
  1090. X    } else {        /* fixed weekday - calculate it */
  1091. X        if (ord < 0)
  1092. X            MAKE_DATE(date, DEC,
  1093. X                  calc_day(-1, wkd, DEC) + 7 * (ord + 1),
  1094. X                  curr_year);
  1095. X        else
  1096. X            MAKE_DATE(date, JAN,
  1097. X                  calc_day(1, wkd, JAN) + 7 * (ord - 1),
  1098. X                  curr_year);
  1099. X        normalize(&date);
  1100. X    }
  1101. X
  1102. X    return date.yy == curr_year ? (*pdate = date, TRUE) : FALSE;
  1103. }
  1104. X
  1105. X
  1106. /*
  1107. X * calc_weekday - return the weekday (0-6) of mm/dd/yy (mm: 1-12)
  1108. X */
  1109. #ifdef PROTOS
  1110. int calc_weekday(int mm,
  1111. X         int dd,
  1112. X         int yy)
  1113. #else
  1114. int calc_weekday(mm, dd, yy)
  1115. X    int mm;
  1116. X    int dd;
  1117. X    int yy;
  1118. #endif
  1119. {
  1120. X    return (yy + (yy-1)/4 - (yy-1)/100 + (yy-1)/400 + OFFSET_OF(mm, yy) +
  1121. X        (dd-1)) % 7;
  1122. }
  1123. X
  1124. X
  1125. /*
  1126. X * is_valid - return TRUE if m/d/y is a valid date
  1127. X */
  1128. #ifdef PROTOS
  1129. int is_valid(register int m,
  1130. X         register int d,
  1131. X         register int y)
  1132. #else
  1133. int is_valid(m, d, y)
  1134. X    register int m, d, y;
  1135. #endif
  1136. {
  1137. X    return m >= JAN && m <= DEC && 
  1138. X        d >= 1 && d <= LENGTH_OF(m, y);
  1139. }
  1140. X
  1141. X
  1142. X
  1143. /*
  1144. X * Token parsing/remerging routines:
  1145. X */
  1146. X
  1147. X
  1148. /*
  1149. X * loadwords - tokenize line buffer into word array, return word count.
  1150. X * differs from old loadwords() in that it handles quoted (" or ') strings
  1151. X * and removes escaped quotes
  1152. X */
  1153. #ifdef PROTOS
  1154. int loadwords(void)
  1155. #else
  1156. int loadwords()
  1157. #endif
  1158. {
  1159. X    register char *ptok;
  1160. X    char *delim, **ap, *p1, *p2, c;
  1161. X    int nwords;
  1162. X
  1163. X    for (ptok = lbuf, ap = words; TRUE; ap++) {
  1164. X
  1165. X        ptok += strspn(ptok, WHITESPACE); /* find next token */
  1166. X
  1167. X        if (! *ptok) {            /* end of lbuf? */
  1168. X            *ap = NULL;        /* add null ptr at end */
  1169. X            nwords = ap - words;    /* number of non-null ptrs */
  1170. X            break;            /* exit loop */
  1171. X            }
  1172. X
  1173. X        delim =    *ptok == '"'  ? "\"" :    /* set closing delimiter */
  1174. X            *ptok == '\'' ? "'"  :
  1175. X            WHITESPACE;
  1176. X
  1177. X        if (*ptok == *delim)        /* skip opening quote */
  1178. X            ptok++;
  1179. X
  1180. X        *ap = ptok;            /* save token ptr */
  1181. X
  1182. X        do {                /* find unescaped delimiter */
  1183. X            ptok += strcspn(ptok, delim);
  1184. X            if ((c = ptok[-1]) == '\\')
  1185. X                ptok++;
  1186. X        } while (c == '\\');
  1187. X
  1188. X        if (*ptok)            /* terminate token */
  1189. X            *ptok++ = '\0';
  1190. X    }
  1191. X
  1192. X    /* now reprocess the word list, removing escapes from quotes */
  1193. X
  1194. X    for (ap = words; *ap; *ap++)
  1195. X        for (p1 = p2 = *ap; c = *p2 = *p1++; *p2++)
  1196. X            if (c == '\\')
  1197. X                *p2 = *p1++;
  1198. X
  1199. X    return nwords;                /* return word count */
  1200. X
  1201. }
  1202. X
  1203. X
  1204. /*
  1205. X * copy_text - retrieve remaining text in lbuf and copy to output string,
  1206. X * separating tokens by a single blank and condensing runs of blanks (all
  1207. X * other whitespace has been converted to blanks by now) to one blank
  1208. X */
  1209. #ifdef PROTOS
  1210. void copy_text(char *pbuf,
  1211. X           char **ptext)
  1212. #else
  1213. void copy_text(pbuf, ptext)
  1214. X    char *pbuf;        /* output buffer - can be lbuf itself */
  1215. X    char **ptext;        /* pointer to first text word in "words" */
  1216. #endif
  1217. {
  1218. X    char *p, *pb;
  1219. X
  1220. X    /* copy words to pbuf, separating by one blank */
  1221. X
  1222. X    for (*(pb = pbuf) = '\0'; p = *ptext; *pb++ = *++ptext ? ' ' : '\0') {
  1223. X        for ( ; *p; *p++)
  1224. X            if (! (*p == ' ' && (pb == pbuf || pb[-1] == ' ')))
  1225. X                *pb++ = *p;
  1226. X        if (pb > pbuf && pb[-1] == ' ')
  1227. X            pb--;
  1228. X    }
  1229. }
  1230. X
  1231. X
  1232. /*
  1233. X * split_date - extract 1-3 numeric fields (separated by one or more
  1234. X * non-numeric characters) from date string; return number of fields
  1235. X */
  1236. #ifdef PROTOS
  1237. int split_date(char *pstr,
  1238. X           int *pn1,
  1239. X           int *pn2,
  1240. X           int *pn3)
  1241. #else
  1242. int split_date(pstr, pn1, pn2, pn3)
  1243. X    char *pstr;            /* input string */
  1244. X    int *pn1, *pn2, *pn3;        /* output numbers */
  1245. #endif
  1246. {
  1247. X    int i, n, *pn;
  1248. X
  1249. X    /* attempt to extract up to three numeric fields */
  1250. X    for (n = 0, i = 1; i <= 3; i++) {
  1251. X        pn = i == 1 ? pn1 : i == 2 ? pn2 : pn3;    /* crude but portable */
  1252. X        if (pn)
  1253. X            *pn = *pstr ? (n++, atoi(pstr)) : 0;
  1254. X        SKIP_FIELD(pstr);        /* go to next field */
  1255. X    }
  1256. X
  1257. X    return n;
  1258. }
  1259. X
  1260. X
  1261. X
  1262. /*
  1263. X * File input routines:
  1264. X */
  1265. X
  1266. X
  1267. /*
  1268. X * octal_esc - read up to 3 octal digits from file; return value of octal
  1269. X * constant and leave file pointer at last character
  1270. X */
  1271. #ifdef PROTOS
  1272. static int octal_esc(FILE *fp)
  1273. #else
  1274. static int octal_esc(fp)
  1275. X    FILE *fp;
  1276. #endif
  1277. {
  1278. X    int i, n, c;
  1279. X
  1280. X    for (n = 0, i = 0; i < 3; i++) {
  1281. X        c = getc(fp);
  1282. X        if (c == EOF)
  1283. X            return EOF;
  1284. X        if (!isodigit(c)) {
  1285. X            ungetc(c, fp);
  1286. X            break;
  1287. X        }
  1288. X        n = n * 8 + (c - '0');
  1289. X    }
  1290. X
  1291. X    return n & 0377;        /* truncate to 8 bits */
  1292. }
  1293. X
  1294. X
  1295. /*
  1296. X * hex_esc - read 'x' or 'X' followed by 1 or 2 hex digits from file; return
  1297. X * value of hexadecimal constant (or letter if no hex digits follow) and
  1298. X * leave file pointer at last character
  1299. X */
  1300. #ifdef PROTOS
  1301. static int hex_esc(FILE *fp)
  1302. #else
  1303. static int hex_esc(fp)
  1304. X    FILE *fp;
  1305. #endif
  1306. {
  1307. X    int i, n, c, sv_c;
  1308. X
  1309. X    sv_c = c = getc(fp);        /* read leading 'x' or 'X' */
  1310. X    if (TOLOWER(c) != 'x')
  1311. X        return c;        /* something else - just return it */
  1312. X
  1313. X    for (n = 0, i = 0; i < 2; i++) {
  1314. X        c = getc(fp);
  1315. X        if (c == EOF)
  1316. X            return EOF;
  1317. X        if (!isxdigit(c)) {
  1318. X            ungetc(c, fp);
  1319. X            break;
  1320. X        }
  1321. X        n = n * 16 + (isupper(c) ? c - 'A' + 10 :
  1322. X                  islower(c) ? c - 'a' + 10 :
  1323. X                  c - '0');
  1324. X    }
  1325. X
  1326. X    return i > 0 ? n & 0377 : sv_c;        /* truncate to 8 bits */
  1327. }
  1328. X
  1329. X
  1330. /*
  1331. X * getline - read next non-null line of input file into lbuf; return 0 on EOF
  1332. X * strip leading whitespace, translate other whitespace to blanks, and handle
  1333. X * all escapes except \' and \", (cf. loadwords())
  1334. X */
  1335. #ifdef PROTOS
  1336. int getline(FILE *fp,
  1337. X        int *pline)
  1338. #else
  1339. int getline(fp, pline)
  1340. X    FILE *fp;
  1341. X    int *pline;
  1342. #endif
  1343. {
  1344. X    register char *cp;
  1345. X    register int c, c2;
  1346. X    static char escape[] = "abfnrtv";    /* cf. ANSI spec, 2.2.2 */
  1347. X    int in_comment;        /* comments: from '#' to end-of-line */
  1348. X
  1349. X    cp = lbuf;
  1350. X    do {
  1351. X        in_comment = FALSE;
  1352. X        while ((c = getc(fp)) != '\n' && c != EOF) {
  1353. X            if (c == '#')
  1354. X                in_comment = TRUE;
  1355. X
  1356. X            if (isspace(c))        /* whitespace => blank */
  1357. X                c = ' ';
  1358. X
  1359. X            /* ignore comments and leading white space */
  1360. X            if (in_comment || (cp == lbuf && c == ' '))
  1361. X                continue;
  1362. X
  1363. X            /* handle escape sequences here: escaped whitespace
  1364. X             * and ANSI escapes are all converted to a space;
  1365. X             * octal and hex constants are converted in place
  1366. X             */
  1367. X            if (c == '\\') {
  1368. X                if ((c2 = getc(fp)) == EOF)
  1369. X                    return FALSE;
  1370. X
  1371. X                if (isspace(c2) || strchr(escape, c2)) {
  1372. X                    c = ' ';
  1373. X                    if (c2 == '\n')
  1374. X                        (*pline)++;
  1375. X                }
  1376. X                else if (isodigit(c2)) {    /* octal */    
  1377. X                    ungetc(c2, fp);
  1378. X                    if((c = octal_esc(fp)) == EOF)
  1379. X                        return FALSE;
  1380. X                }
  1381. X                else if (TOLOWER(c2) == 'x') {    /* hex */
  1382. X                    ungetc(c2, fp);
  1383. X                    if((c = hex_esc(fp)) == EOF)
  1384. X                        return FALSE;
  1385. X                }
  1386. X                else if (c2 == '\'' || c2 == '"')
  1387. X                    ungetc(c2, fp);
  1388. X                else
  1389. X                    c = c2;
  1390. X
  1391. X            }
  1392. X            *cp++ = c;
  1393. X        }
  1394. X
  1395. X        if (c == EOF)            /* no more input lines */
  1396. X            return FALSE;
  1397. X
  1398. X        (*pline)++;            /* bump line number */
  1399. X
  1400. X    } while (cp == lbuf);            /* ignore empty lines */
  1401. X
  1402. X    *cp = '\0';
  1403. X    return TRUE;
  1404. }
  1405. X
  1406. X
  1407. /*
  1408. X * Routines dealing with translation of file specifications (VMS, Un*x)
  1409. X */
  1410. X
  1411. #ifdef VMS
  1412. /*
  1413. X * mk_path - extract the path component from VMS file spec
  1414. X */
  1415. #ifdef PROTOS
  1416. char *mk_path(char *path,
  1417. X          char *filespec)
  1418. #else
  1419. char *mk_path(path, filespec)
  1420. X    char *path;        /* output path */
  1421. X    char *filespec;        /* input filespec */
  1422. #endif
  1423. {
  1424. X    char *p;
  1425. X
  1426. X    strcpy(path, filespec);
  1427. X    if (!(p = strchr(path, ']')) && !(p = strchr(path, ':')))
  1428. X        p = path - 1;    /* return null string if no path */
  1429. X    *++p = '\0';
  1430. X
  1431. X    return path;
  1432. }
  1433. X
  1434. X
  1435. /*
  1436. X * mk_filespec - merge VMS path and file names, where latter can be relative
  1437. X */
  1438. #ifdef PROTOS
  1439. char *mk_filespec(char *filespec,
  1440. X          char *path,
  1441. X          char *name)
  1442. #else
  1443. char *mk_filespec(filespec, path, name)
  1444. X    char *filespec;        /* output filespec */
  1445. X    char *path;        /* input path */
  1446. X    char *name;        /* input file name */
  1447. #endif
  1448. {
  1449. X    char *p;
  1450. X
  1451. X    *filespec = '\0';
  1452. X
  1453. X    /* copy name intact if absolute; else merge path and relative name */
  1454. X    if (!strchr(name, ':')) {
  1455. X        strcpy(filespec, path);
  1456. X        if ((p = P_LASTCHAR(filespec)) && *p == END_PATH &&
  1457. X            name[0] == START_PATH && strchr(".-", name[1]))
  1458. X            *p = *++name == '-' ? '.' : '\0';
  1459. X    }
  1460. X
  1461. X    return strcat(filespec, name);
  1462. }
  1463. X
  1464. X
  1465. /*
  1466. X * trnlog - return translation of VMS logical name (null if missing)
  1467. X */
  1468. #ifdef PROTOS
  1469. char *trnlog(char *logname)
  1470. #else
  1471. char *trnlog(logname)    /* look up logical name */
  1472. X    char *logname;
  1473. #endif
  1474. {
  1475. X    static char trnbuf[STRSIZ];
  1476. X    
  1477. X    $DESCRIPTOR(src, logname);
  1478. X    $DESCRIPTOR(dst, trnbuf);
  1479. X    short len;
  1480. X    int ret;
  1481. X    
  1482. X    src.dsc$w_length  = strlen(logname);
  1483. X    ret = LIB$SYS_TRNLOG(&src, &len, &dst);
  1484. X    return ret == SS$_NORMAL ? (trnbuf[len] = '\0', trnbuf) : NULL;
  1485. }
  1486. X
  1487. #else        /* apparently DOS and Amiga can use the Un*x flavors */
  1488. X
  1489. /*
  1490. X * mk_path - extract the path component from a Un*x file spec
  1491. X */
  1492. #ifdef PROTOS
  1493. char *mk_path(char *path,
  1494. X          char *filespec)
  1495. #else
  1496. char *mk_path(path, filespec)
  1497. X    char *path;        /* output path */
  1498. X    char *filespec;        /* input filespec */
  1499. #endif
  1500. {
  1501. X    char *p;
  1502. X
  1503. X    strcpy(path, filespec);
  1504. X    if (! (p = strrchr(path, END_PATH)) )
  1505. X        p = path - 1;    /* return null string if no path */
  1506. X
  1507. X    *++p = '\0';
  1508. X    return path;
  1509. }
  1510. X
  1511. X
  1512. /*
  1513. X * mk_filespec - merge Un*x path and file names, where latter can be relative
  1514. X */
  1515. #ifdef PROTOS
  1516. char *mk_filespec(char *filespec,
  1517. X          char *path,
  1518. X          char *name)
  1519. #else
  1520. char *mk_filespec(filespec, path, name)
  1521. X    char *filespec;        /* output filespec */
  1522. X    char *path;        /* input path */
  1523. X    char *name;        /* input file name */
  1524. #endif
  1525. {
  1526. X    char *p;
  1527. X
  1528. X    *filespec = '\0';
  1529. X
  1530. X    /* copy name intact if absolute; else merge path and relative name */
  1531. X
  1532. X    /* if path starts with "~/", translate it for user */
  1533. X    if (strncmp(name, "~/", 2) == 0 && (p = trnlog(HOME_DIR)) != NULL) {
  1534. X        strcpy(filespec, p);
  1535. X        if ((p = P_LASTCHAR(filespec)) && *p != END_PATH)
  1536. X            *++p = END_PATH, *++p = '\0';
  1537. X        name += 2;        /* skip "~/" */
  1538. X    }
  1539. X    else if (*name != START_PATH) {        /* relative path */
  1540. X        strcpy(filespec, path);
  1541. X        if ((p = P_LASTCHAR(filespec)) && *p != END_PATH)
  1542. X            *++p = END_PATH, *++p = '\0';
  1543. X    }
  1544. X
  1545. X    return strcat(filespec, name);
  1546. }
  1547. X
  1548. X
  1549. /*
  1550. X * trnlog - return translation of Un*x environment variable
  1551. X */
  1552. #ifdef PROTOS
  1553. char *trnlog(char *logname)
  1554. #else
  1555. char *trnlog(logname)    /* look up logical name */
  1556. X    char *logname;
  1557. #endif
  1558. {
  1559. X    return getenv(logname);
  1560. }
  1561. X
  1562. #endif
  1563. X
  1564. #ifdef UNIXX    /* highly Unix-dependent; probably nobody else can use it */
  1565. X
  1566. #include <sys/types.h>
  1567. #include <sys/stat.h>
  1568. X
  1569. /*
  1570. X * find_executable - return full path name of executable
  1571. X */
  1572. #ifdef PROTOS
  1573. char *find_executable(char *prog)
  1574. #else
  1575. char *find_executable(prog)
  1576. X    char *prog;
  1577. #endif
  1578. {
  1579. X    char pathvar[1000], *p, *pnext;
  1580. X    struct stat st;
  1581. X    static char filepath[STRSIZ];
  1582. X    
  1583. X    /* if 'prog' is an absolute/relative path name or environment
  1584. X     * variable 'PATH' does not exist, return 'prog'; otherwise,
  1585. X     * search the directories specified in 'PATH' for the executable
  1586. X     */
  1587. X    if (strchr(prog, END_PATH) == 0 && (p = getenv(PATH_ENV_VAR)) != 0) {
  1588. X        strcpy(pathvar, p);
  1589. X
  1590. X        /* assumes PATH is of form "dir1:dir2:...:dirN"; strtok()
  1591. X         * would be handy here, but not everybody has it yet
  1592. X         */
  1593. X        for (p = pathvar; *p; p = pnext) {
  1594. X            if ((pnext = strchr(p, ':')) != NULL)
  1595. X                *pnext++ = '\0';
  1596. X            else
  1597. X                pnext = p + strlen(p); 
  1598. X            strcpy(filepath, p);    /* construct file path */
  1599. X            strcat(filepath, "/");
  1600. X            strcat(filepath, prog);
  1601. X
  1602. X            /* check that file a) exists, b) is a "normal" file,
  1603. X             * and c) is executable - if so, return its full path
  1604. X             */
  1605. X            if (stat(filepath, &st) >= 0 &&
  1606. X               (st.st_mode & S_IFMT) == S_IFREG &&
  1607. X                    access(filepath, 01) == 0)
  1608. X                return filepath;
  1609. X        }
  1610. X    }
  1611. X    return prog;    /* just return the original argument */
  1612. }
  1613. #else
  1614. X
  1615. X
  1616. /*
  1617. X * find_executable - return full path name of executable
  1618. X */
  1619. #ifdef PROTOS
  1620. char *find_executable(char *prog)
  1621. #else
  1622. char *find_executable(prog)
  1623. X    char *prog;
  1624. #endif
  1625. {
  1626. X    return prog;    /* non-UNIX flavor always returns its argument */
  1627. }
  1628. #endif
  1629. SHAR_EOF
  1630. chmod 0644 pcalutil.c ||
  1631. echo 'restore of pcalutil.c failed'
  1632. Wc_c="`wc -c < 'pcalutil.c'`"
  1633. test 16402 -eq "$Wc_c" ||
  1634.     echo 'pcalutil.c: original size 16402, current size' "$Wc_c"
  1635. fi
  1636. # ============= protos.h ==============
  1637. if test -f 'protos.h' -a X"$1" != X"-c"; then
  1638.     echo 'x - skipping protos.h (File already exists)'
  1639. else
  1640. echo 'x - extracting protos.h (Text)'
  1641. sed 's/^X//' << 'SHAR_EOF' > 'protos.h' &&
  1642. /*
  1643. X * protos.h - ANSI-style function prototypes for Pcal sources
  1644. X *
  1645. X * Revision history:
  1646. X *
  1647. X *    4.02    AWR    06/07/91    added find_executable()
  1648. X *
  1649. X *    4.0    AWR    03/01/91    use <stdlib.h> where possible
  1650. X *
  1651. X *        AWR    02/19/91    adapted from Bill Hogsett's source
  1652. X *
  1653. X */
  1654. X
  1655. X
  1656. /*
  1657. X * Prototypes for functions defined in exprpars.c:
  1658. X */
  1659. int parse_expr(char *pbuf);
  1660. X
  1661. X
  1662. /*
  1663. X * Prototypes for functions defined in moonphas.c:
  1664. X */
  1665. double    calc_phase(int month, int day, int year);
  1666. double    find_phase(int month, int day, int year, int *pquarter);
  1667. char    *find_moonfile(int year);
  1668. int    read_moonfile(int year);
  1669. X
  1670. X
  1671. /*
  1672. X * Prototypes for functions defined in pcal.c:
  1673. X */
  1674. FILE    *alt_fopen(char *fullpath, char *name, char *pathlist[], char *access);
  1675. char    *color_msg(void);
  1676. int    get_args(char **argv, int curr_pass, char *where);
  1677. FLAG_USAGE *get_flag(char flag);
  1678. int    main(int argc, char **argv);
  1679. void    set_color(char *day, int col);
  1680. void    usage(FILE *fp, int fullmsg);
  1681. X
  1682. X
  1683. /*
  1684. X * Prototypes for functions defined in pcalutil.c:
  1685. X */
  1686. char    *alloc(int size);
  1687. int    calc_day(int ord, int wkd, int mm);
  1688. int    calc_weekday(int mm, int dd, int yy);
  1689. int    calc_year_day(int ord, int wkd, DATE *pdate);
  1690. int    ci_strcmp(register char *s1, register char *s2);
  1691. int    ci_strncmp(register char *s1, register char *s2, int n);
  1692. void    copy_text(char *pbuf, char **ptext);
  1693. char    *find_executable(char *prog);
  1694. int    getline(FILE *fp, int *pline);
  1695. int    is_valid(register int m, register int d, register int y);
  1696. int    loadwords(void);
  1697. char    *mk_filespec(char *filespec, char *path, char *name);
  1698. char    *mk_path(char *path, char *filespec);
  1699. void    normalize(DATE *pd);
  1700. int    split_date(char *pstr, int *pn1, int *pn2, int *pn3);
  1701. char    *trnlog(char *logname);
  1702. X
  1703. X
  1704. /*
  1705. X * Prototypes for functions defined in readfile.c:
  1706. X */
  1707. void    cleanup(void);
  1708. void    clear_syms(void);
  1709. int    date_type(char *cp, int *pn, int *pv);
  1710. int    do_define(char *sym);
  1711. int    do_ifdef(char *expr);
  1712. int    do_ifndef(char *expr);
  1713. int    do_include(char *path, char *name);
  1714. int    do_undef(char *sym);
  1715. int    enter_day_info(int m, int d, int y, int text_type, char **pword);
  1716. int    find_sym(char *sym);
  1717. year_info *find_year(int year, int insert);
  1718. int    get_keywd(char *cp);
  1719. int    get_month(char *cp, int numeric_ok, int year_ok);
  1720. int    get_ordinal(char *cp, int *pval);
  1721. int    get_prep(char *cp);
  1722. int    get_token(char *token);
  1723. int    get_weekday(char *cp, int wild_ok);
  1724. int    is_anyday(int mm, int dd, int yy);
  1725. int    is_holiday(int mm, int dd, int yy);
  1726. int    is_weekday(int mm, int dd, int yy);
  1727. int    is_workday(int mm, int dd, int yy);
  1728. int    not_holiday(int mm, int dd, int yy);
  1729. int    not_weekday(int mm, int dd, int yy);
  1730. int    not_workday(int mm, int dd, int yy);
  1731. int    parse(char **pword, char *filename);
  1732. int    parse_date(char **pword, int *ptype, char ***pptext);
  1733. int    parse_ord(int ord, int val, char **pword);
  1734. int    parse_rel(int wkd, char **pword, int *ptype, char ***pptext);
  1735. void    read_datefile(FILE *fp, char *filename);
  1736. X
  1737. X
  1738. /*
  1739. X * Prototypes for functions defined in writefil.c:
  1740. X */
  1741. void    def_footstring(char *p, char c);
  1742. void    find_daytext(int month, int year, int is_holiday);
  1743. void    find_holidays(int month, int year);
  1744. void    print_julian_info(int month, int year);
  1745. void    print_month(int month, int year);
  1746. void    print_moon_info(int month, int year);
  1747. void    print_text(char *p);
  1748. char    *print_word(char *p);
  1749. void    write_psfile(int month, int year, int nmonths);
  1750. X
  1751. X
  1752. /*
  1753. X * Prototypes for miscellaneous library routines (if not already included
  1754. X * via <stdlib.h> - cf. pcaldefs.h):
  1755. X */
  1756. #ifndef STDLIB
  1757. extern int    atoi(char *);
  1758. extern char    *calloc(unsigned int, unsigned int);
  1759. extern char    *getenv(char *);
  1760. #endif
  1761. SHAR_EOF
  1762. chmod 0666 protos.h ||
  1763. echo 'restore of protos.h failed'
  1764. Wc_c="`wc -c < 'protos.h'`"
  1765. test 3511 -eq "$Wc_c" ||
  1766.     echo 'protos.h: original size 3511, current size' "$Wc_c"
  1767. fi
  1768. true || echo 'restore of readfile.c failed'
  1769. echo End of part 5, continue with part 6
  1770. exit 0
  1771.