home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume33 / remind / part06 < prev    next >
Text File  |  1992-11-11  |  45KB  |  1,489 lines

  1. Newsgroups: comp.sources.misc
  2. From: dfs@doe.carleton.ca (David F. Skoll)
  3. Subject:  v33i063:  remind - A replacement for calendar, Part06/12
  4. Message-ID: <1992Nov10.041917.1064@sparky.imd.sterling.com>
  5. X-Md4-Signature: 44ec5de29413cf93f680f62e5958684d
  6. Date: Tue, 10 Nov 1992 04:19:17 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
  10. Posting-number: Volume 33, Issue 63
  11. Archive-name: remind/part06
  12. Environment: UNIX, MS-DOS
  13. Supersedes: remind: Volume 17, Issue 3-6
  14.  
  15. #!/bin/sh
  16. # This is part 06 of Remind 03.00.00
  17. if touch 2>&1 | fgrep 'amc' > /dev/null
  18.  then TOUCH=touch
  19.  else TOUCH=true
  20. fi
  21. # ============= funcs.c ==============
  22. if test X"$1" != X"-c" -a -f 'funcs.c'; then
  23.     echo "File already exists: skipping 'funcs.c'"
  24. else
  25. echo "x - extracting funcs.c (Text)"
  26. sed 's/^X//' << 'SHAR_EOF' > funcs.c &&
  27. X/***************************************************************/
  28. X/*                                                             */
  29. X/*  FUNCS.C                                                    */
  30. X/*                                                             */
  31. X/*  This file contains the built-in functions used in          */
  32. X/*  expressions.                                               */
  33. X/*                                                             */
  34. X/*  This file is part of REMIND.                               */
  35. X/*  Copyright (C) 1991 by David F. Skoll.                      */
  36. X/*                                                             */
  37. X/***************************************************************/
  38. X#include <stdio.h>
  39. X#include "config.h"
  40. X#ifdef HAVE_STDLIB_H
  41. X#include <stdlib.h>
  42. X#endif
  43. X#ifdef HAVE_MALLOC_H
  44. X#include <malloc.h>
  45. X#endif
  46. X#include <string.h>
  47. X#include <ctype.h>
  48. X#ifdef UNIX
  49. X#ifdef HAVE_UNISTD
  50. X#include <unistd.h>
  51. X#else
  52. X#include <sys/file.h>
  53. X#endif
  54. X#endif
  55. X/* May have to change previous line to <sys/file.h> for some unixes */
  56. X#ifdef __MSDOS__
  57. X#include <io.h>
  58. X#define R_OK 4
  59. X#define W_OK 2
  60. X#define X_OK 1
  61. X#endif
  62. X#ifndef R_OK
  63. X#define R_OK 4
  64. X#define W_OK 2
  65. X#define X_OK 1
  66. X#endif
  67. X#include "types.h"
  68. X#include "globals.h"
  69. X#include "protos.h"
  70. X#include "err.h"
  71. X#include "expr.h"
  72. X#include "version.h"
  73. X
  74. X/* Function prototypes */
  75. XPRIVATE    int    FAbs        ARGS ((void));
  76. XPRIVATE    int    FAccess        ARGS ((void));
  77. XPRIVATE    int    FAsc        ARGS ((void));
  78. XPRIVATE    int    FBaseyr        ARGS ((void));
  79. XPRIVATE    int    FChar        ARGS ((void));
  80. XPRIVATE    int    FChoose        ARGS ((void));
  81. XPRIVATE    int    FCoerce        ARGS ((void));
  82. XPRIVATE    int    FDate        ARGS ((void));
  83. XPRIVATE    int    FDay        ARGS ((void));
  84. XPRIVATE    int    FDaysinmon    ARGS ((void));
  85. XPRIVATE    int    FDefined    ARGS ((void));
  86. XPRIVATE    int    FFilename    ARGS ((void));
  87. XPRIVATE    int    FGetenv        ARGS ((void));
  88. XPRIVATE    int    FHour        ARGS ((void));
  89. XPRIVATE    int    FIif        ARGS ((void));
  90. XPRIVATE    int    FIndex        ARGS ((void));
  91. XPRIVATE    int    FIsomitted    ARGS ((void));
  92. XPRIVATE    int    FMax        ARGS ((void));
  93. XPRIVATE    int    FMin        ARGS ((void));
  94. XPRIVATE    int    FMinute        ARGS ((void));
  95. XPRIVATE    int    FMon        ARGS ((void));
  96. XPRIVATE    int    FMonnum        ARGS ((void));
  97. XPRIVATE    int    FOrd        ARGS ((void));
  98. XPRIVATE    int    FOstype     ARGS ((void));
  99. XPRIVATE    int    FPlural        ARGS ((void));
  100. XPRIVATE    int    FSgn        ARGS ((void));
  101. XPRIVATE    int    FShell        ARGS ((void));
  102. XPRIVATE    int    FStrlen        ARGS ((void));
  103. XPRIVATE    int    FSubstr        ARGS ((void));
  104. XPRIVATE    int    FTime        ARGS ((void));
  105. XPRIVATE    int    FTrigdate    ARGS ((void));
  106. XPRIVATE    int    FTrigtime    ARGS ((void));
  107. XPRIVATE    int    FTrigvalid    ARGS ((void));
  108. XPRIVATE    int    FTypeof        ARGS ((void));
  109. XPRIVATE    int    FUpper        ARGS ((void));
  110. XPRIVATE    int    FValue        ARGS ((void));
  111. XPRIVATE    int    FVersion    ARGS ((void));
  112. XPRIVATE    int    FWkday        ARGS ((void));
  113. XPRIVATE    int    FWkdaynum    ARGS ((void));
  114. XPRIVATE    int    FYear        ARGS ((void));
  115. XPRIVATE int    FIsleap         ARGS ((void));
  116. XPRIVATE int    FLower          ARGS ((void));
  117. XPRIVATE int    FNow            ARGS ((void));
  118. XPRIVATE int    FRealtoday      ARGS ((void));
  119. XPRIVATE int    FToday          ARGS ((void));
  120. XPRIVATE int    FTrigger        ARGS ((void));
  121. XPRIVATE int    CheckArgs       ARGS ((Operator *f, int nargs));
  122. XPRIVATE int    CleanUpAfterFunc ARGS ((void));
  123. X     
  124. X#ifdef __MSDOS__
  125. XPRIVATE FILE *popen  ARGS((char *cmd, char *mode));
  126. XPRIVATE int   pclose ARGS((FILE *fp));
  127. X#endif
  128. X
  129. X/* "Overload" the struct Operator definition */
  130. X#define NO_MAX 127
  131. X#define MINARGS prec
  132. X#define MAXARGS type
  133. X
  134. X/* Sigh - we use a global var. to hold the number of args supplied to
  135. X   function being called */
  136. Xstatic int Nargs;
  137. X
  138. X/* Use a global var. to hold function return value */
  139. Xstatic Value RetVal;
  140. X
  141. X/* Temp string buffer */
  142. Xstatic char Buffer[32];
  143. X
  144. X/* We need access to the value stack */
  145. Xextern Value ValStack[];
  146. Xextern int ValStackPtr;
  147. X
  148. X/* Macro for accessing arguments from the value stack - args are numbered
  149. X   from 0 to (Nargs - 1) */
  150. X#define ARG(x) (ValStack[ValStackPtr - Nargs + (x)])
  151. X
  152. X/* Macro for copying a value while destroying original copy */
  153. X#define DCOPYVAL(x, y) ( (x) = (y), (y).type = ERR_TYPE )
  154. X
  155. X/* Convenience macros */
  156. X#define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
  157. X#define LOWER(c) ( ((c) >= 'A' && (c) <= 'Z') ? (c) + 'a' - 'A' : (c) )
  158. X
  159. X/* The array holding the built-in functions. */
  160. XOperator Func[] = {
  161. X/*    Name        minargs maxargs    func   */
  162. X
  163. X    {   "abs",        1,    1,    FAbs    },
  164. X    {   "access",       2,      2,      FAccess },
  165. X    {   "asc",        1,    1,    FAsc    },
  166. X    {   "baseyr",    0,    0,    FBaseyr    },
  167. X    {   "char",        1,    NO_MAX,    FChar    },
  168. X    {   "choose",    2,    NO_MAX, FChoose },
  169. X    {   "coerce",    2,    2,    FCoerce },
  170. X    {   "date",        3,    3,    FDate    },
  171. X    {   "day",        1,    1,    FDay    },
  172. X    {   "daysinmon",    2,    2,    FDaysinmon },
  173. X    {   "defined",    1,    1,    FDefined },
  174. X    {   "filename",    0,    0,    FFilename },
  175. X    {   "getenv",    1,    1,    FGetenv },
  176. X    {   "hour",        1,    1,    FHour    },
  177. X    {   "iif",        3,    3,    FIif    },
  178. X    {   "index",    2,    3,    FIndex     },
  179. X    {   "isleap",    1,    1,    FIsleap },
  180. X    {   "isomitted",    1,    1,    FIsomitted },
  181. X    {   "lower",    1,    1,    FLower    },
  182. X    {   "max",        1,    NO_MAX,    FMax    },
  183. X    {   "min",        1,    NO_MAX, FMin    },
  184. X    {   "minute",    1,    1,    FMinute },
  185. X    {   "mon",        1,    1,    FMon    },
  186. X    {   "monnum",    1,    1,    FMonnum },
  187. X    {   "now",        0,    0,    FNow    },
  188. X    {   "ord",        1,    1,    FOrd    },
  189. X    {   "ostype",       0,      0,      FOstype },
  190. X    {   "plural",    1,    3,    FPlural },
  191. X    {   "realtoday",    0,      0,      FRealtoday },
  192. X    {   "sgn",        1,    1,    FSgn    },
  193. X    {   "shell",    1,    1,    FShell    },
  194. X    {   "strlen",    1,    1,    FStrlen    },
  195. X    {   "substr",    2,    3,    FSubstr    },
  196. X    {   "time",        2,    2,    FTime    },
  197. X    {   "today",    0,    0,    FToday    },
  198. X    {   "trigdate",    0,    0,    FTrigdate },
  199. X    {   "trigger",    1,    1,    FTrigger },
  200. X    {   "trigtime",    0,    0,    FTrigtime },
  201. X    {   "trigvalid",    0,    0,    FTrigvalid },
  202. X    {   "typeof",       1,      1,      FTypeof },
  203. X    {   "upper",    1,    1,    FUpper    },
  204. X    {   "value",    1,    2,    FValue    },
  205. X    {   "version",      0,      0,      FVersion },
  206. X    {   "wkday",    1,    1,    FWkday    },
  207. X    {   "wkdaynum",    1,    1,    FWkdaynum },
  208. X    {   "year",        1,    1,    FYear    }
  209. X};
  210. X
  211. X/* Need a variable here - Func[] array not really visible to outside. */
  212. Xint NumFuncs = sizeof(Func) / sizeof(Operator) ;
  213. X     
  214. X/***************************************************************/
  215. X/*                                                             */
  216. X/*  CallFunc                                                   */
  217. X/*                                                             */
  218. X/*  Call a function given a pointer to it, and the number      */
  219. X/*  of arguments supplied.                                     */
  220. X/*                                                             */
  221. X/***************************************************************/
  222. X#ifdef HAVE_PROTOS
  223. XPUBLIC int CallFunc(Operator *f, int nargs)
  224. X#else
  225. Xint CallFunc(f, nargs)
  226. XOperator *f;
  227. Xint nargs;
  228. X#endif
  229. X{
  230. X   register int r = CheckArgs(f, nargs);
  231. X   int i;
  232. X
  233. X   Nargs = nargs;
  234. X
  235. X   RetVal.type = ERR_TYPE;
  236. X   if (DebugFlag & DB_PRTEXPR) {
  237. X      fprintf(ErrFp, "%s(", f->name);
  238. X      for (i=0; i<nargs; i++) {
  239. X     PrintValue(&ARG(i), ErrFp);
  240. X     if (i<nargs-1) fprintf(ErrFp, ", ");
  241. X      }
  242. X      fprintf(ErrFp, ") => ");
  243. X      if (r) {
  244. X     fprintf(ErrFp, "%s\n", ErrMsg[r]);
  245. X     return r;
  246. X      }
  247. X   }
  248. X   if (r) {
  249. X      Eprint("%s(): %s", f->name, ErrMsg[r]);
  250. X      return r;
  251. X   }
  252. X
  253. X   r = (*(f->func))();
  254. X   if (r) {
  255. X      DestroyValue(&RetVal);
  256. X      if (DebugFlag & DB_PRTEXPR)
  257. X     fprintf(ErrFp, "%s\n", ErrMsg[r]);
  258. X      else
  259. X     Eprint("%s(): %s", f->name, ErrMsg[r]);
  260. X      return r;
  261. X   }
  262. X   if (DebugFlag & DB_PRTEXPR) {
  263. X      PrintValue(&RetVal, ErrFp);
  264. X      fprintf(ErrFp, "\n");
  265. X   }
  266. X   r = CleanUpAfterFunc();
  267. X   return r;
  268. X}
  269. X
  270. X/***************************************************************/
  271. X/*                                                             */
  272. X/*  CheckArgs                                                  */
  273. X/*                                                             */
  274. X/*  Check that the right number of args have been supplied     */
  275. X/*  for a function.                                            */
  276. X/*                                                             */
  277. X/***************************************************************/
  278. X#ifdef HAVE_PROTOS
  279. XPRIVATE int CheckArgs(Operator *f, int nargs)
  280. X#else
  281. Xstatic int CheckArgs(f, nargs)
  282. XOperator *f;
  283. Xint nargs;
  284. X#endif
  285. X{
  286. X   if (nargs < f->MINARGS) return E_2FEW_ARGS;
  287. X   if (nargs > f->MAXARGS && f->MAXARGS != NO_MAX) return E_2MANY_ARGS;
  288. X   return OK;
  289. X}
  290. X/***************************************************************/
  291. X/*                                                             */
  292. X/*  CleanUpAfterFunc                                           */
  293. X/*                                                             */
  294. X/*  Clean up the stack after a function call - remove          */
  295. X/*  args and push the new value.                               */
  296. X/*                                                             */
  297. X/***************************************************************/
  298. X#ifdef HAVE_PROTOS
  299. XPRIVATE int CleanUpAfterFunc(void)
  300. X#else
  301. Xstatic int CleanUpAfterFunc()
  302. X#endif
  303. X{
  304. X   Value v;
  305. X   int i, r;
  306. X
  307. X   for (i=0; i<Nargs; i++) {
  308. X      r = PopValStack(&v);
  309. X      if (r) return r;
  310. X      DestroyValue(&v);
  311. X   }
  312. X   PushValStack(&RetVal);
  313. X   return OK;
  314. X}
  315. X
  316. X/***************************************************************/
  317. X/*                                                             */
  318. X/*  RetStrVal                                                  */
  319. X/*                                                             */
  320. X/*  Return a string value from a function.                     */
  321. X/*                                                             */
  322. X/***************************************************************/
  323. X#ifdef HAVE_PROTOS
  324. XPRIVATE int RetStrVal(const char *s)
  325. X#else
  326. Xstatic int RetStrVal(s)
  327. Xchar *s;
  328. X#endif
  329. X{
  330. X   RetVal.type = STR_TYPE;
  331. X   if (!s) {
  332. X      RetVal.v.str = (char *) malloc(1);
  333. X      if (RetVal.v.str) *RetVal.v.str = 0;
  334. X   } else
  335. X      RetVal.v.str = StrDup(s);
  336. X
  337. X   if (!RetVal.v.str) {
  338. X      RetVal.type = ERR_TYPE;
  339. X      return E_NO_MEM;
  340. X   }
  341. X   return OK;
  342. X}
  343. X
  344. X
  345. X/***************************************************************/
  346. X/*                                                             */
  347. X/*  FStrlen - string length                                    */
  348. X/*                                                             */
  349. X/***************************************************************/
  350. X#ifdef HAVE_PROTOS
  351. XPRIVATE int FStrlen(void)
  352. X#else
  353. Xstatic int FStrlen()
  354. X#endif
  355. X{
  356. X   Value *v = &ARG(0);
  357. X   if (v->type != STR_TYPE) return E_BAD_TYPE;
  358. X   RetVal.type = INT_TYPE;
  359. X   RetVal.v.val = strlen(v->v.str);
  360. X   return OK;
  361. X}
  362. X
  363. X/***************************************************************/
  364. X/*                                                             */
  365. X/*  FBaseyr - system base year                                 */
  366. X/*                                                             */
  367. X/***************************************************************/
  368. X#ifdef HAVE_PROTOS
  369. XPRIVATE int FBaseyr(void)
  370. X#else
  371. Xstatic int FBaseyr()
  372. X#endif
  373. X{
  374. X   RetVal.type = INT_TYPE;
  375. X   RetVal.v.val = BASE;
  376. X   return OK;
  377. X}
  378. X
  379. X/***************************************************************/
  380. X/*                                                             */
  381. X/*  FDate - make a date from year, month, day.                 */
  382. X/*                                                             */
  383. X/***************************************************************/
  384. X#ifdef HAVE_PROTOS
  385. XPRIVATE int FDate(void)
  386. X#else
  387. Xstatic int FDate()
  388. X#endif
  389. X{
  390. X   int y, m, d;
  391. X   if (ARG(0).type != INT_TYPE ||
  392. X       ARG(1).type != INT_TYPE ||
  393. X       ARG(2).type != INT_TYPE) return E_BAD_TYPE;
  394. X   y = ARG(0).v.val;
  395. X   m = ARG(1).v.val - 1;
  396. X   d = ARG(2).v.val;
  397. X
  398. X   if (y < BASE || y > BASE+YR_RANGE || m < 0 || m > 11 || d < 1 ||
  399. X       d > DaysInMonth(m, y)) return E_BAD_DATE;
  400. X
  401. X   RetVal.type = DATE_TYPE;
  402. X   RetVal.v.val = Julian(y, m, d);
  403. X   return OK;
  404. X}
  405. X
  406. X/***************************************************************/
  407. X/*                                                             */
  408. X/*  FCoerce - type coercion function.                          */
  409. X/*                                                             */
  410. X/***************************************************************/
  411. X#ifdef HAVE_PROTOS
  412. XPRIVATE int FCoerce(void)
  413. X#else
  414. Xstatic int FCoerce()
  415. X#endif
  416. X{
  417. X   char *s;
  418. X
  419. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  420. X   s = ARG(0).v.str;
  421. X
  422. X   /* Copy the value of ARG(1) into RetVal, and make ARG(1) invalid so
  423. X      it won't be destroyed */
  424. X   DCOPYVAL(RetVal, ARG(1));
  425. X
  426. X   if (StriEq(s, "int")) return DoCoerce(INT_TYPE, &RetVal);
  427. X   else if (StriEq(s, "date")) return DoCoerce(DATE_TYPE, &RetVal);
  428. X   else if (StriEq(s, "time")) return DoCoerce(TIM_TYPE, &RetVal);
  429. X   else if (StriEq(s, "string")) return DoCoerce(STR_TYPE, &RetVal);
  430. X   else return E_CANT_COERCE;
  431. X}
  432. X
  433. X/***************************************************************/
  434. X/*                                                             */
  435. X/*  FMax - select maximum from a list of args.                 */
  436. X/*                                                             */
  437. X/***************************************************************/
  438. X#ifdef HAVE_PROTOS
  439. XPRIVATE int FMax(void)
  440. X#else
  441. Xstatic int FMax()
  442. X#endif
  443. X{
  444. X   Value *maxptr;
  445. X   int i;
  446. X   char type;
  447. X
  448. X   maxptr = &ARG(0);
  449. X   type = maxptr->type;
  450. X
  451. X   for (i=1; i<Nargs; i++) {
  452. X      if (ARG(i).type != type) return E_BAD_TYPE;
  453. X      if (type != STR_TYPE) {
  454. X     if (ARG(i).v.val > maxptr->v.val) maxptr=&ARG(i);
  455. X      } else {
  456. X     if (strcmp(ARG(i).v.str, maxptr->v.str) > 0) maxptr=&ARG(i);
  457. X      }
  458. X   }
  459. X   DCOPYVAL(RetVal, *maxptr);
  460. X   return OK;
  461. X}
  462. X
  463. X/***************************************************************/
  464. X/*                                                             */
  465. X/*  FMin - select minimum from a list of args.                 */
  466. X/*                                                             */
  467. X/***************************************************************/
  468. X#ifdef HAVE_PROTOS
  469. XPRIVATE int FMin(void)
  470. X#else
  471. Xstatic int FMin()
  472. X#endif
  473. X{
  474. X   Value *minptr;
  475. X   int i;
  476. X   char type;
  477. X
  478. X   minptr = &ARG(0);
  479. X   type = minptr->type;
  480. X
  481. X   for (i=1; i<Nargs; i++) {
  482. X      if (ARG(i).type != type) return E_BAD_TYPE;
  483. X      if (type != STR_TYPE) {
  484. X     if (ARG(i).v.val < minptr->v.val) minptr=&ARG(i);
  485. X      } else {
  486. X     if (strcmp(ARG(i).v.str, minptr->v.str) < 0) minptr=&ARG(i);
  487. X      }
  488. X   }
  489. X   DCOPYVAL(RetVal, *minptr);
  490. X   return OK;
  491. X}
  492. X
  493. X/***************************************************************/
  494. X/*                                                             */
  495. X/*  FAsc - ASCII value of first char of string                 */
  496. X/*                                                             */
  497. X/***************************************************************/
  498. X#ifdef HAVE_PROTOS
  499. XPRIVATE int FAsc(void)
  500. X#else
  501. Xstatic int FAsc()
  502. X#endif
  503. X{
  504. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  505. X   RetVal.type = INT_TYPE;
  506. X   RetVal.v.val = *(ARG(0).v.str);
  507. X   return OK;
  508. X}
  509. X
  510. X/***************************************************************/
  511. X/*                                                             */
  512. X/*  FChar - build a string from ASCII values                   */
  513. X/*                                                             */
  514. X/***************************************************************/
  515. X#ifdef HAVE_PROTOS
  516. XPRIVATE int FChar(void)
  517. X#else
  518. Xstatic int FChar()
  519. X#endif
  520. X{
  521. X
  522. X   int i, len;
  523. X
  524. X/* Special case of one arg - if given ascii value 0, create empty string */
  525. X   if (Nargs == 1) {
  526. X      if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  527. X      if (ARG(0).v.val < 0) return E_2LOW;
  528. X      if (ARG(0).v.val > 255) return E_2HIGH;
  529. X      len = ARG(0).v.val ? 2 : 1;
  530. X      RetVal.v.str = (char *) malloc(len);
  531. X      if (!RetVal.v.str) return E_NO_MEM;
  532. X      RetVal.type = STR_TYPE;
  533. X      *(RetVal.v.str) = ARG(0).v.val;
  534. X      if (len>1) *(RetVal.v.str + 1) = 0;
  535. X      return OK;
  536. X   }
  537. X
  538. X   RetVal.v.str = (char *) malloc(Nargs + 1);
  539. X   if (!RetVal.v.str) return E_NO_MEM;
  540. X   RetVal.type = STR_TYPE;
  541. X   for (i=0; i<Nargs; i++) {
  542. X     if (ARG(i).type != INT_TYPE) return E_BAD_TYPE;
  543. X     if (ARG(i).v.val < 1) return E_2LOW;
  544. X     if (ARG(i).v.val > 255) return E_2HIGH;
  545. X     *(RetVal.v.str + i) = ARG(i).v.val;
  546. X   }
  547. X   *(RetVal.v.str + Nargs) = 0;
  548. X   return OK;
  549. X}
  550. X/***************************************************************/
  551. X/*                                                             */
  552. X/*  Functions for extracting the components of a date.         */
  553. X/*                                                             */
  554. X/*  FDay - get day of month                                    */
  555. X/*  FMonnum - get month (1-12)                                 */
  556. X/*  FYear - get year                                           */
  557. X/*  FWkdaynum - get weekday num (0 = Sun)                      */
  558. X/*  FWkday - get weekday (string)                              */
  559. X/*  FMon - get month (string)                                  */
  560. X/*                                                             */
  561. X/***************************************************************/
  562. X#ifdef HAVE_PROTOS
  563. XPRIVATE int FDay(void)
  564. X#else
  565. Xstatic int FDay()
  566. X#endif
  567. X{
  568. X   int y, m, d;
  569. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  570. X   FromJulian(ARG(0).v.val, &y, &m, &d);
  571. X   RetVal.type = INT_TYPE;
  572. X   RetVal.v.val = d;
  573. X   return OK;
  574. X}
  575. X
  576. X#ifdef HAVE_PROTOS
  577. XPRIVATE int FMonnum(void)
  578. X#else
  579. Xstatic int FMonnum()
  580. X#endif
  581. X{
  582. X   int y, m, d;
  583. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  584. X   FromJulian(ARG(0).v.val, &y, &m, &d);
  585. X   RetVal.type = INT_TYPE;
  586. X   RetVal.v.val = m+1;
  587. X   return OK;
  588. X}
  589. X
  590. X#ifdef HAVE_PROTOS
  591. XPRIVATE int FYear(void)
  592. X#else
  593. Xstatic int FYear()
  594. X#endif
  595. X{
  596. X   int y, m, d;
  597. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  598. X   FromJulian(ARG(0).v.val, &y, &m, &d);
  599. X   RetVal.type = INT_TYPE;
  600. X   RetVal.v.val = y;
  601. X   return OK;
  602. X}
  603. X
  604. X#ifdef HAVE_PROTOS
  605. XPRIVATE int FWkdaynum(void)
  606. X#else
  607. Xstatic int FWkdaynum()
  608. X#endif
  609. X{
  610. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  611. X   RetVal.type = INT_TYPE;
  612. X
  613. X   /* Correct so that 0 = Sunday */
  614. X   RetVal.v.val = (ARG(0).v.val+1) % 7;
  615. X   return OK;
  616. X}
  617. X
  618. X#ifdef HAVE_PROTOS
  619. XPRIVATE int FWkday(void)
  620. X#else
  621. Xstatic int FWkday()
  622. X#endif
  623. X{
  624. X   char *s;
  625. X
  626. X   if (ARG(0).type != DATE_TYPE && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  627. X   if (ARG(0).type == INT_TYPE) {
  628. X      if (ARG(0).v.val < 0) return E_2LOW;
  629. X      if (ARG(0).v.val > 6) return E_2HIGH;
  630. X      /* Convert 0=Sun to 0=Mon */
  631. X      ARG(0).v.val--;
  632. X      if (ARG(0).v.val < 0) ARG(0).v.val = 6;
  633. X      s = DayName[ARG(0).v.val];
  634. X   } else s = DayName[ARG(0).v.val % 7];
  635. X   return RetStrVal(s);
  636. X}
  637. X
  638. X#ifdef HAVE_PROTOS
  639. XPRIVATE int FMon(void)
  640. X#else
  641. Xstatic int FMon()
  642. X#endif
  643. X{
  644. X   char *s;
  645. X   int y, m, d;
  646. X
  647. X   if (ARG(0).type != DATE_TYPE && ARG(0).type != INT_TYPE)
  648. X      return E_BAD_TYPE;
  649. X   if (ARG(0).type == INT_TYPE) {
  650. X      m = ARG(0).v.val - 1;
  651. X      if (m < 0) return E_2LOW;
  652. X      if (m > 11) return E_2HIGH;
  653. X   } else FromJulian(ARG(0).v.val, &y, &m, &d);
  654. X   s = MonthName[m];
  655. X   return RetStrVal(s);
  656. X}
  657. X
  658. X/***************************************************************/
  659. X/*                                                             */
  660. X/*  FHour - extract hour from a time                           */
  661. X/*  FMinute - extract minute from a time                       */
  662. X/*  FTime - create a time from hour and minute                 */
  663. X/*                                                             */
  664. X/***************************************************************/
  665. X#ifdef HAVE_PROTOS
  666. XPRIVATE int FHour(void)
  667. X#else
  668. Xstatic int FHour()
  669. X#endif
  670. X{
  671. X   if (ARG(0).type != TIM_TYPE) return E_BAD_TYPE;
  672. X   RetVal.type = INT_TYPE;
  673. X   RetVal.v.val = ARG(0).v.val / 60;
  674. X   return OK;
  675. X}
  676. X
  677. X#ifdef HAVE_PROTOS
  678. XPRIVATE int FMinute(void)
  679. X#else
  680. Xstatic int FMinute()
  681. X#endif
  682. X{
  683. X   if (ARG(0).type != TIM_TYPE) return E_BAD_TYPE;
  684. X   RetVal.type = INT_TYPE;
  685. X   RetVal.v.val = ARG(0).v.val % 60;
  686. X   return OK;
  687. X}
  688. X
  689. X#ifdef HAVE_PROTOS
  690. XPRIVATE int FTime(void)
  691. X#else
  692. Xstatic int FTime()
  693. X#endif
  694. X{
  695. X   int h, m;
  696. X
  697. X   if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
  698. X
  699. X   h = ARG(0).v.val;
  700. X   m = ARG(1).v.val;
  701. X   if (h<0 || m<0) return E_2LOW;
  702. X   if (h>23 || m>59) return E_2HIGH;
  703. X   RetVal.type = TIM_TYPE;
  704. X   RetVal.v.val = h*60 + m;
  705. X   return OK;
  706. X}
  707. X
  708. X/***************************************************************/
  709. X/*                                                             */
  710. X/*  FAbs - absolute value                                      */
  711. X/*  FSgn - signum function                                     */
  712. X/*                                                             */
  713. X/***************************************************************/
  714. X#ifdef HAVE_PROTOS
  715. XPRIVATE int FAbs(void)
  716. X#else
  717. Xstatic int FAbs()
  718. X#endif
  719. X{
  720. X   int v;
  721. X
  722. X   if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  723. X   v = ARG(0).v.val;
  724. X   RetVal.type = INT_TYPE;
  725. X   RetVal.v.val = (v < 0) ? (-v) : v;
  726. X   return OK;
  727. X}
  728. X
  729. X#ifdef HAVE_PROTOS
  730. XPRIVATE int FSgn(void)
  731. X#else
  732. Xstatic int FSgn()
  733. X#endif
  734. X{
  735. X   int v;
  736. X
  737. X   if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  738. X   v = ARG(0).v.val;
  739. X   RetVal.type = INT_TYPE;
  740. X   if (v>0) RetVal.v.val = 1;
  741. X   else if (v<0) RetVal.v.val = -1;
  742. X   else RetVal.v.val = 0;
  743. X   return OK;
  744. X}
  745. X
  746. X/***************************************************************/
  747. X/*                                                             */
  748. X/*  FOrd - returns a string containing ordinal number.         */
  749. X/*                                                             */
  750. X/*  EG - ord(2) == "2nd", etc.                                 */
  751. X/*                                                             */
  752. X/***************************************************************/
  753. X#ifdef HAVE_PROTOS
  754. XPRIVATE int FOrd(void)
  755. X#else
  756. Xstatic int FOrd()
  757. X#endif
  758. X{
  759. X   int t, u, v;
  760. X   char *s;
  761. X
  762. X   if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  763. X
  764. X   v = ARG(0).v.val;
  765. X   t = v % 100;
  766. X   if (t < 0) t = -t;
  767. X   u = t % 10;
  768. X   s = "th";
  769. X   if (u == 1 && t != 11) s = "st";
  770. X   if (u == 2 && t != 12) s = "nd";
  771. X   if (u == 3 && t != 13) s = "rd";
  772. X   sprintf(Buffer, "%d%s", v, s);
  773. X   return RetStrVal(Buffer);
  774. X}
  775. X
  776. X/***************************************************************/
  777. X/*                                                             */
  778. X/*  FPlural - pluralization function                           */
  779. X/*                                                             */
  780. X/*  plural(n) -->  "" or "s"                                   */
  781. X/*  plural(n, str) --> "str" or "strs"                         */
  782. X/*  plural(n, str1, str2) --> "str1" or "str2"                 */
  783. X/*                                                             */
  784. X/***************************************************************/
  785. X#ifdef HAVE_PROTOS
  786. XPRIVATE int FPlural(void)
  787. X#else
  788. Xstatic int FPlural()
  789. X#endif
  790. X{
  791. X   if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  792. X
  793. X   switch(Nargs) {
  794. X      case 1:
  795. X     if (ARG(0).v.val == 1) return RetStrVal("");
  796. X     else return RetStrVal("s");
  797. X
  798. X      case 2:
  799. X     if (ARG(1).type != STR_TYPE) return E_BAD_TYPE;
  800. X     if (ARG(0).v.val == 1) {
  801. X        DCOPYVAL(RetVal, ARG(1));
  802. X        return OK;
  803. X     }
  804. X     RetVal.type = STR_TYPE;
  805. X     RetVal.v.str = (char *) malloc(strlen(ARG(1).v.str)+2);
  806. X     if (!RetVal.v.str) {
  807. X        RetVal.type = ERR_TYPE;
  808. X        return E_NO_MEM;
  809. X     }
  810. X     strcpy(RetVal.v.str, ARG(1).v.str);
  811. X     strcat(RetVal.v.str, "s");
  812. X     return OK;
  813. X
  814. X      default:
  815. X     if (ARG(1).type != STR_TYPE || ARG(2).type != STR_TYPE)
  816. X        return E_BAD_TYPE;
  817. X     if (ARG(0).v.val == 1) DCOPYVAL(RetVal, ARG(1));
  818. X     else DCOPYVAL(RetVal, ARG(2));
  819. X     return OK;
  820. X   }
  821. X}
  822. X
  823. X/***************************************************************/
  824. X/*                                                             */
  825. X/*  FChoose                                                    */
  826. X/*  Choose the nth value from a list of value.  If n<1, choose */
  827. X/*  first.  If n>N, choose Nth value.  Indexes always start    */
  828. X/*  from 1.                                                    */
  829. X/*                                                             */
  830. X/***************************************************************/
  831. X#ifdef HAVE_PROTOS
  832. XPRIVATE int FChoose(void)
  833. X#else
  834. Xstatic int FChoose()
  835. X#endif
  836. X{
  837. X   int v;
  838. X
  839. X   if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  840. X   v = ARG(0).v.val;
  841. X   if (v < 1) v = 1;
  842. X   if (v > Nargs-1) v = Nargs-1;
  843. X   DCOPYVAL(RetVal, ARG(v));
  844. X   return OK;
  845. X}
  846. X
  847. X/***************************************************************/
  848. X/*                                                             */
  849. X/*  FVersion - version of Remind                               */
  850. X/*                                                             */
  851. X/***************************************************************/
  852. X#ifdef HAVE_PROTOS
  853. XPRIVATE int FVersion(void)
  854. X#else
  855. Xstatic int FVersion()
  856. X#endif
  857. X{
  858. X   return RetStrVal(VERSION);
  859. X}
  860. X
  861. X/***************************************************************/
  862. X/*                                                             */
  863. X/*  FOstype - the type of operating system (UNIX or MSDOS)     */
  864. X/*                                                             */
  865. X/***************************************************************/
  866. X#ifdef HAVE_PROTOS
  867. XPRIVATE int FOstype(void)
  868. X#else
  869. Xstatic int FOstype()
  870. X#endif
  871. X{
  872. X#ifdef UNIX
  873. X   return RetStrVal("UNIX");
  874. X#else
  875. X   return RetStrVal("MSDOS");
  876. X#endif  
  877. X}
  878. X
  879. X/***************************************************************/
  880. X/*                                                             */
  881. X/*  FUpper - convert string to upper-case                      */
  882. X/*  FLower - convert string to lower-case                      */
  883. X/*                                                             */
  884. X/***************************************************************/
  885. X#ifdef HAVE_PROTOS
  886. XPRIVATE int FUpper(void)
  887. X#else
  888. Xstatic int FUpper()
  889. X#endif
  890. X{
  891. X   char *s;
  892. X
  893. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  894. X   DCOPYVAL(RetVal, ARG(0));
  895. X   s = RetVal.v.str;
  896. X   while (*s) { *s = UPPER(*s); s++; }
  897. X   return OK;
  898. X}
  899. X
  900. X#ifdef HAVE_PROTOS
  901. XPRIVATE int FLower(void)
  902. X#else
  903. Xstatic int FLower()
  904. X#endif
  905. X{
  906. X   char *s;
  907. X
  908. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  909. X   DCOPYVAL(RetVal, ARG(0));
  910. X   s = RetVal.v.str;
  911. X   while (*s) { *s = LOWER(*s); s++; }
  912. X   return OK;
  913. X}
  914. X
  915. X/***************************************************************/
  916. X/*                                                             */
  917. X/*  FToday - return the system's notion of "today"             */
  918. X/*  Frealtoday - return today's date as read from OS.          */
  919. X/*  FNow - return the system time                              */
  920. X/*                                                             */
  921. X/***************************************************************/
  922. X#ifdef HAVE_PROTOS
  923. XPRIVATE int FToday(void)
  924. X#else
  925. Xstatic int FToday()
  926. X#endif
  927. X{
  928. X   RetVal.type = DATE_TYPE;
  929. X   RetVal.v.val = JulianToday;
  930. X   return OK;
  931. X}
  932. X
  933. X#ifdef HAVE_PROTOS
  934. XPRIVATE int FRealtoday(void)
  935. X#else
  936. Xstatic int FRealtoday()
  937. X#endif
  938. X{
  939. X   RetVal.type = DATE_TYPE;
  940. X   RetVal.v.val = RealToday;
  941. X   return OK;
  942. X}
  943. X
  944. X#ifdef HAVE_PROTOS
  945. XPRIVATE int FNow(void)
  946. X#else
  947. Xstatic int FNow()
  948. X#endif
  949. X{
  950. X   RetVal.type = TIM_TYPE;
  951. X   RetVal.v.val = (int) ( SystemTime() / 60L );
  952. X   return OK;
  953. X}
  954. X
  955. X/***************************************************************/
  956. X/*                                                             */
  957. X/*  FGetenv - get the value of an environment variable.        */
  958. X/*                                                             */
  959. X/***************************************************************/
  960. X#ifdef HAVE_PROTOS
  961. XPRIVATE int FGetenv(void)
  962. X#else
  963. Xstatic int FGetenv()
  964. X#endif
  965. X{
  966. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  967. X   return RetStrVal(getenv(ARG(0).v.str));
  968. X}
  969. X     
  970. X/***************************************************************/
  971. X/*                                                             */
  972. X/*  FValue                                                     */
  973. X/*                                                             */
  974. X/*  Get the value of a variable.  If a second arg is supplied, */
  975. X/*  it is returned if variable is undefined.                   */
  976. X/*                                                             */
  977. X/***************************************************************/
  978. X#ifdef HAVE_PROTOS
  979. XPRIVATE int FValue(void)
  980. X#else
  981. Xstatic int FValue()
  982. X#endif
  983. X{
  984. X   Var *v;
  985. X
  986. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  987. X   switch(Nargs) {
  988. X      case 1:
  989. X     return GetVarValue(ARG(0).v.str, &RetVal, NULL);
  990. X
  991. X      case 2:
  992. X         v = FindVar(ARG(0).v.str, 0);
  993. X     if (!v) {
  994. X        DCOPYVAL(RetVal, ARG(1));
  995. X        return OK;
  996. X     } else {
  997. X        return CopyValue(&RetVal, &v->v);
  998. X     }
  999. X   }
  1000. X   return OK;
  1001. X}
  1002. X
  1003. X/***************************************************************/
  1004. X/*                                                             */
  1005. X/*  FDefined                                                   */
  1006. X/*                                                             */
  1007. X/*  Return 1 if a variable is defined, 0 if it is not.         */
  1008. X/*                                                             */
  1009. X/***************************************************************/
  1010. X#ifdef HAVE_PROTOS
  1011. XPRIVATE int FDefined(void)
  1012. X#else
  1013. Xstatic int FDefined()
  1014. X#endif
  1015. X{
  1016. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  1017. X
  1018. X   RetVal.type = INT_TYPE;
  1019. X
  1020. X   if (FindVar(ARG(0).v.str, 0))
  1021. X      RetVal.v.val = 1;
  1022. X   else
  1023. X      RetVal.v.val = 0;
  1024. X   return OK;
  1025. X}
  1026. X
  1027. X/***************************************************************/
  1028. X/*                                                             */
  1029. X/*  FTrigdate and FTrigtime                                    */
  1030. X/*                                                             */
  1031. X/*  Date and time of last trigger.  These are stored in global */
  1032. X/*  vars.                                                      */
  1033. X/*                                                             */
  1034. X/***************************************************************/
  1035. X#ifdef HAVE_PROTOS
  1036. XPRIVATE int FTrigdate(void)
  1037. X#else
  1038. Xstatic int FTrigdate()
  1039. X#endif
  1040. X{
  1041. X   RetVal.type = DATE_TYPE;
  1042. X   RetVal.v.val = LastTriggerDate;
  1043. X   return OK;
  1044. X}
  1045. X
  1046. X#ifdef HAVE_PROTOS
  1047. XPRIVATE int FTrigvalid(void)
  1048. X#else
  1049. Xstatic int FTrigvalid()
  1050. X#endif
  1051. X{
  1052. X   RetVal.type = INT_TYPE;
  1053. X   RetVal.v.val = LastTrigValid;
  1054. X   return OK;
  1055. X}
  1056. X
  1057. X#ifdef HAVE_PROTOS
  1058. XPRIVATE int FTrigtime(void)
  1059. X#else
  1060. Xstatic int FTrigtime()
  1061. X#endif
  1062. X{
  1063. X   RetVal.type = TIM_TYPE;
  1064. X   RetVal.v.val = LastTriggerTime;
  1065. X   return OK;
  1066. X}
  1067. X
  1068. X/***************************************************************/
  1069. X/*                                                             */
  1070. X/*  FDaysinmon                                                 */
  1071. X/*                                                             */
  1072. X/*  Returns the number of days in mon,yr                       */
  1073. X/*                                                             */
  1074. X/***************************************************************/
  1075. X#ifdef HAVE_PROTOS
  1076. XPRIVATE int FDaysinmon(void)
  1077. X#else
  1078. Xstatic int FDaysinmon()
  1079. X#endif
  1080. X{
  1081. X   if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
  1082. X
  1083. X   if (ARG(0).v.val > 12 || ARG(0).v.val < 1 ||
  1084. X       ARG(1).v.val < BASE || ARG(1).v.val > BASE+YR_RANGE)
  1085. X          return E_DOMAIN_ERR;
  1086. X
  1087. X   RetVal.type = INT_TYPE;
  1088. X   RetVal.v.val = DaysInMonth(ARG(0).v.val-1, ARG(1).v.val);
  1089. X   return OK;
  1090. X}
  1091. X
  1092. X/***************************************************************/
  1093. X/*                                                             */
  1094. X/*  FIsleap                                                    */
  1095. X/*                                                             */
  1096. X/*  Return 1 if year is a leap year, zero otherwise.           */
  1097. X/*                                                             */
  1098. X/***************************************************************/
  1099. X#ifdef HAVE_PROTOS
  1100. XPRIVATE int FIsleap(void)
  1101. X#else
  1102. Xstatic int FIsleap()
  1103. X#endif
  1104. X{
  1105. X   int y, m, d;
  1106. X
  1107. X   if (ARG(0).type != INT_TYPE && ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  1108. X
  1109. X   /* If it's a date, extract the year */
  1110. X   if (ARG(0).type == DATE_TYPE)
  1111. X      FromJulian(ARG(0).v.val, &y, &m, &d);
  1112. X   else
  1113. X      y = ARG(0).v.val;
  1114. X
  1115. X   RetVal.type = INT_TYPE;
  1116. X   RetVal.v.val = IsLeapYear(y);
  1117. X   return OK;
  1118. X}
  1119. X
  1120. X/***************************************************************/
  1121. X/*                                                             */
  1122. X/*  FTrigger                                                   */
  1123. X/*                                                             */
  1124. X/*  Put out a date in a format suitable for triggering.        */
  1125. X/*                                                             */
  1126. X/***************************************************************/
  1127. X#ifdef HAVE_PROTOS
  1128. XPRIVATE int FTrigger(void)
  1129. X#else
  1130. Xstatic int FTrigger()
  1131. X#endif
  1132. X{
  1133. X   int y, m, d;
  1134. X   char buf[40];
  1135. X
  1136. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  1137. X
  1138. X   FromJulian(ARG(0).v.val, &y, &m, &d);
  1139. X   sprintf(buf, "%d %s %d", d, MonthName[m], y);
  1140. X   return RetStrVal(buf);
  1141. X}
  1142. X
  1143. X/***************************************************************/
  1144. X/*                                                             */
  1145. X/*  FShell                                                     */
  1146. X/*                                                             */
  1147. X/*  The shell function.                                        */
  1148. X/*                                                             */
  1149. X/*  If run is disabled, will not be executed.                  */
  1150. X/*                                                             */
  1151. X/***************************************************************/
  1152. X#ifdef HAVE_PROTOS
  1153. XPRIVATE int FShell(void)
  1154. X#else
  1155. Xstatic int FShell()
  1156. X#endif
  1157. X{
  1158. X   char buf[SHELLSIZE+1];
  1159. X   int ch, len;
  1160. X   FILE *fp;
  1161. X   char *s;
  1162. X
  1163. X   if (RunDisabled) return E_RUN_DISABLED;
  1164. X   if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
  1165. X   s = buf;
  1166. X   len = 0;
  1167. X   fp = popen(ARG(0).v.str, "r");
  1168. X   if (!fp) return E_IO_ERR;
  1169. X   while (len < SHELLSIZE) {
  1170. X      ch = getc(fp);
  1171. X      if (ch == EOF) {
  1172. X     break;
  1173. X      }
  1174. X      if (isspace(ch)) *s++ = ' ';
  1175. X      else            *s++ = ch;
  1176. X      len++;
  1177. X   }
  1178. X   *s = 0;
  1179. X
  1180. X   /* Delete trailing newline (converted to space) */
  1181. X   if (s > buf && *(s-1) == ' ') *(s-1) = 0;
  1182. X#ifdef __MSDOS__
  1183. X   if (s-1 > buf && *(s-2) == ' ') *(s-2) = 0;
  1184. X#endif
  1185. X   pclose(fp);
  1186. X   return RetStrVal(buf);
  1187. X}
  1188. X
  1189. X/***************************************************************/
  1190. X/*                                                             */
  1191. X/*  FIsomitted                                                 */
  1192. X/*                                                             */
  1193. X/*  Is a date omitted?                                         */
  1194. X/*                                                             */
  1195. X/***************************************************************/
  1196. X#ifdef HAVE_PROTOS
  1197. XPRIVATE int FIsomitted(void)
  1198. X#else
  1199. Xstatic int FIsomitted()
  1200. X#endif
  1201. X{
  1202. X   if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
  1203. X   RetVal.type = INT_TYPE;
  1204. X   RetVal.v.val = IsOmitted(ARG(0).v.val, 0);
  1205. X   return OK;
  1206. X}
  1207. X
  1208. X/***************************************************************/
  1209. X/*                                                             */
  1210. X/*  FSubstr                                                    */
  1211. X/*                                                             */
  1212. X/*  The substr function.  We destroy the value on the stack.   */
  1213. X/*                                                             */
  1214. X/***************************************************************/
  1215. X#ifdef HAVE_PROTOS
  1216. XPRIVATE int FSubstr(void)
  1217. X#else
  1218. Xstatic int FSubstr()
  1219. X#endif
  1220. X{
  1221. X   char *s, *t;
  1222. X   int start, end;
  1223. X
  1224. X   if (ARG(0).type != STR_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
  1225. X   if (Nargs == 3 && ARG(2).type != INT_TYPE) return E_BAD_TYPE;
  1226. X
  1227. X   s = ARG(0).v.str;
  1228. X   start = 1;
  1229. X   while (start < ARG(1).v.val) {
  1230. X      if (!*s) break;
  1231. X      s++;
  1232. X      start++;
  1233. X   }
  1234. X   if (Nargs == 2 || !*s) return RetStrVal(s);
  1235. X   end = start;
  1236. X   t = s;
  1237. X   while (end <= ARG(2).v.val) {
  1238. X      if (!*s) break;
  1239. X      s++;
  1240. X      end++;
  1241. X   }
  1242. X   *s = 0;
  1243. X   return RetStrVal(t);
  1244. X}
  1245. X
  1246. X/***************************************************************/
  1247. X/*                                                             */
  1248. X/*  FIndex                                                     */
  1249. X/*                                                             */
  1250. X/*  The index of one string embedded in another.               */
  1251. X/*                                                             */
  1252. X/***************************************************************/
  1253. X#ifdef HAVE_PROTOS
  1254. XPRIVATE int FIndex(void)
  1255. X#else
  1256. Xstatic int FIndex()
  1257. X#endif
  1258. X{
  1259. X   char *s;
  1260. X   int start;
  1261. X
  1262. X   if (ARG(0).type != STR_TYPE || ARG(1).type != STR_TYPE ||
  1263. X       (Nargs == 3 && ARG(2).type != INT_TYPE)) return E_BAD_TYPE;
  1264. X
  1265. X   s = ARG(0).v.str;
  1266. X
  1267. X/* If 3 args, bump up the start */
  1268. X   if (Nargs == 3) {
  1269. X      start = 1;
  1270. X      while (start < ARG(2).v.val) {
  1271. X         if (!*s) break;
  1272. X     s++;
  1273. X     start++;
  1274. X      }
  1275. X  }
  1276. X
  1277. X/* Find the string */
  1278. X   s = strstr(s, ARG(1).v.str);
  1279. X   RetVal.type = INT_TYPE;
  1280. X   if (!s) {
  1281. X      RetVal.v.val = 0;
  1282. X      return OK;
  1283. X   }
  1284. X   RetVal.v.val = (s - ARG(0).v.str) + 1;
  1285. X   return OK;
  1286. X}
  1287. X
  1288. X/***************************************************************/
  1289. X/*                                                             */
  1290. X/*  FIif                                                       */
  1291. X/*                                                             */
  1292. X/*  The IIF function.                                          */
  1293. X/*                                                             */
  1294. X/***************************************************************/
  1295. X#ifdef HAVE_PROTOS
  1296. XPRIVATE int FIif(void)
  1297. X#else
  1298. Xstatic int FIif()
  1299. X#endif
  1300. X{
  1301. X   int istrue;
  1302. X
  1303. X   if (ARG(0).type != STR_TYPE && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
  1304. X
  1305. X   if (ARG(0).type == INT_TYPE)
  1306. X      istrue = ARG(0).v.val;
  1307. X   else
  1308. X      istrue = *(ARG(0).v.str);
  1309. X
  1310. X   if (istrue) DCOPYVAL(RetVal, ARG(1));
  1311. X   else        DCOPYVAL(RetVal, ARG(2));
  1312. X
  1313. X   return OK;
  1314. X}
  1315. X
  1316. X/***************************************************************/
  1317. X/*                                                             */
  1318. X/*  FFilename                                                  */
  1319. X/*                                                             */
  1320. X/*  Return name of current file                                */
  1321. X/*                                                             */
  1322. X/***************************************************************/
  1323. X#ifdef HAVE_PROTOS
  1324. XPRIVATE int FFilename(void)
  1325. X#else
  1326. Xstatic int FFilename()
  1327. X#endif
  1328. X{
  1329. X   return RetStrVal(FileName);
  1330. X}
  1331. X
  1332. X/***************************************************************/
  1333. X/*                                                             */
  1334. X/*  FAccess                                                    */
  1335. X/*                                                             */
  1336. X/*  The UNIX access() system call.                             */
  1337. X/*                                                             */
  1338. X/***************************************************************/
  1339. X#ifdef HAVE_PROTOS
  1340. XPRIVATE int FAccess(void)
  1341. X#else
  1342. Xstatic int FAccess()
  1343. X#endif
  1344. X{
  1345. X   int amode;
  1346. X   char *s;
  1347. X  
  1348. X   if (ARG(0).type != STR_TYPE || 
  1349. X       (ARG(1).type != INT_TYPE && ARG(1).type != STR_TYPE)) return E_BAD_TYPE;
  1350. X
  1351. X   if (ARG(1).type == INT_TYPE) amode = ARG(1).v.val;
  1352. X   else {
  1353. X      amode = 0;
  1354. X      s = ARG(1).v.str;
  1355. X      while (*s) {
  1356. X         switch(*s++) {
  1357. X        case 'r':
  1358. X        case 'R': amode |= R_OK; break;
  1359. X        case 'w':
  1360. X        case 'W': amode |= W_OK; break;
  1361. X        case 'x':
  1362. X        case 'X': amode |= X_OK; break;
  1363. X         }
  1364. X      }
  1365. X   } 
  1366. X   RetVal.type = INT_TYPE;
  1367. X   RetVal.v.val = access(ARG(0).v.str, amode);
  1368. X   return OK;
  1369. X}
  1370. X
  1371. X#ifdef __MSDOS__
  1372. X/***************************************************************/
  1373. X/*                                                             */
  1374. X/*  popen and pclose                                           */
  1375. X/*                                                             */
  1376. X/*  These are some rather brain-dead kludges for MSDOS.        */
  1377. X/*  They are just sufficient for the shell() function, and     */
  1378. X/*  should NOT be viewed as general-purpose replacements       */
  1379. X/*  for the UNIX system calls.                                 */
  1380. X/*                                                             */
  1381. X/***************************************************************/
  1382. X#ifdef __TURBOC__
  1383. X#pragma argsused
  1384. X#endif
  1385. X
  1386. Xstatic char *TmpFile;
  1387. X#ifdef HAVE_PROTOS
  1388. XPRIVATE FILE *popen(char *cmd, char *mode)
  1389. X#else
  1390. Xstatic FILE *popen(cmd, mode)
  1391. Xchar *cmd, *mode
  1392. X#endif
  1393. X{
  1394. X   char *s;
  1395. X
  1396. X   TmpFile = tmpnam(NULL);
  1397. X   if (!TmpFile) return NULL;
  1398. X   s = (char *) malloc(strlen(cmd) + 3 + strlen(TmpFile) + 1);
  1399. X   if (!s) return NULL;
  1400. X   strcpy(s, cmd);
  1401. X   strcat(s, " > ");
  1402. X   strcat(s, TmpFile);
  1403. X   system(s);
  1404. X   free(s);
  1405. X   return fopen(TmpFile, "r");
  1406. X}
  1407. X
  1408. X#ifdef HAVE_PROTOS
  1409. XPRIVATE int pclose(FILE *fp)
  1410. X#else
  1411. Xstatic int pclose(fp)
  1412. XFILE *fp;
  1413. X#endif
  1414. X{
  1415. X   unlink(TmpFile);
  1416. X   return fclose(fp);
  1417. X}
  1418. X
  1419. X#endif
  1420. X
  1421. X/***************************************************************/
  1422. X/*                                                             */
  1423. X/*  FTypeof                                                    */
  1424. X/*                                                             */
  1425. X/*  Implement the typeof() function.                           */
  1426. X/*                                                             */
  1427. X/***************************************************************/
  1428. X#ifdef HAVE_PROTOS
  1429. XPRIVATE int FTypeof(void)
  1430. X#else
  1431. Xstatic int FTypeof()
  1432. X#endif
  1433. X{
  1434. X   switch(ARG(0).type) {
  1435. X      case INT_TYPE:  return RetStrVal("INT");
  1436. X      case DATE_TYPE: return RetStrVal("DATE");
  1437. X      case TIM_TYPE:  return RetStrVal("TIME");
  1438. X      case STR_TYPE:  return RetStrVal("STRING");
  1439. X      default:        return RetStrVal("ERR");
  1440. X   }
  1441. X}
  1442. SHAR_EOF
  1443. $TOUCH -am 1109142392 funcs.c &&
  1444. chmod 0600 funcs.c ||
  1445. echo "restore of funcs.c failed"
  1446. set `wc -c funcs.c`;Wc_c=$1
  1447. if test "$Wc_c" != "41381"; then
  1448.     echo original size 41381, current size $Wc_c
  1449. fi
  1450. fi
  1451. # ============= globals.c ==============
  1452. if test X"$1" != X"-c" -a -f 'globals.c'; then
  1453.     echo "File already exists: skipping 'globals.c'"
  1454. else
  1455. echo "x - extracting globals.c (Text)"
  1456. sed 's/^X//' << 'SHAR_EOF' > globals.c &&
  1457. X/***************************************************************/
  1458. X/*                                                             */
  1459. X/*  GLOBALS.C                                                  */
  1460. X/*                                                             */
  1461. X/*  This file simply instantiates all of the global variables. */
  1462. X/*                                                             */
  1463. X/*  It does this by #defining MK_GLOBALS and #including        */
  1464. X/*  globals.h and err.h                                        */
  1465. X/*                                                             */
  1466. X/*  This file is part of REMIND.                               */
  1467. X/*  Copyright (C) 1992 by David F. Skoll.                      */
  1468. X/*                                                             */
  1469. X/***************************************************************/
  1470. X#include "config.h"
  1471. X#include <stdio.h>   /* For defintion of FILE - sigh! */
  1472. X#include "types.h"
  1473. X#define MK_GLOBALS
  1474. X#include "globals.h"
  1475. X#include "err.h"
  1476. SHAR_EOF
  1477. $TOUCH -am 1109141292 globals.c &&
  1478. chmod 0600 globals.c ||
  1479. echo "restore of globals.c failed"
  1480. set `wc -c globals.c`;Wc_c=$1
  1481. if test "$Wc_c" != "1011"; then
  1482.     echo original size 1011, current size $Wc_c
  1483. fi
  1484. fi
  1485. echo "End of part 6, continue with part 7"
  1486. exit 0
  1487.  
  1488. exit 0 # Just in case...
  1489.