home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / sources / misc / 4068 < prev    next >
Encoding:
Text File  |  1992-11-09  |  44.6 KB  |  1,495 lines

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