home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume33
/
remind
/
part06
< prev
next >
Wrap
Text File
|
1992-11-11
|
45KB
|
1,489 lines
Newsgroups: comp.sources.misc
From: dfs@doe.carleton.ca (David F. Skoll)
Subject: v33i063: remind - A replacement for calendar, Part06/12
Message-ID: <1992Nov10.041917.1064@sparky.imd.sterling.com>
X-Md4-Signature: 44ec5de29413cf93f680f62e5958684d
Date: Tue, 10 Nov 1992 04:19:17 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: dfs@doe.carleton.ca (David F. Skoll)
Posting-number: Volume 33, Issue 63
Archive-name: remind/part06
Environment: UNIX, MS-DOS
Supersedes: remind: Volume 17, Issue 3-6
#!/bin/sh
# This is part 06 of Remind 03.00.00
if touch 2>&1 | fgrep 'amc' > /dev/null
then TOUCH=touch
else TOUCH=true
fi
# ============= funcs.c ==============
if test X"$1" != X"-c" -a -f 'funcs.c'; then
echo "File already exists: skipping 'funcs.c'"
else
echo "x - extracting funcs.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > funcs.c &&
X/***************************************************************/
X/* */
X/* FUNCS.C */
X/* */
X/* This file contains the built-in functions used in */
X/* expressions. */
X/* */
X/* This file is part of REMIND. */
X/* Copyright (C) 1991 by David F. Skoll. */
X/* */
X/***************************************************************/
X#include <stdio.h>
X#include "config.h"
X#ifdef HAVE_STDLIB_H
X#include <stdlib.h>
X#endif
X#ifdef HAVE_MALLOC_H
X#include <malloc.h>
X#endif
X#include <string.h>
X#include <ctype.h>
X#ifdef UNIX
X#ifdef HAVE_UNISTD
X#include <unistd.h>
X#else
X#include <sys/file.h>
X#endif
X#endif
X/* May have to change previous line to <sys/file.h> for some unixes */
X#ifdef __MSDOS__
X#include <io.h>
X#define R_OK 4
X#define W_OK 2
X#define X_OK 1
X#endif
X#ifndef R_OK
X#define R_OK 4
X#define W_OK 2
X#define X_OK 1
X#endif
X#include "types.h"
X#include "globals.h"
X#include "protos.h"
X#include "err.h"
X#include "expr.h"
X#include "version.h"
X
X/* Function prototypes */
XPRIVATE int FAbs ARGS ((void));
XPRIVATE int FAccess ARGS ((void));
XPRIVATE int FAsc ARGS ((void));
XPRIVATE int FBaseyr ARGS ((void));
XPRIVATE int FChar ARGS ((void));
XPRIVATE int FChoose ARGS ((void));
XPRIVATE int FCoerce ARGS ((void));
XPRIVATE int FDate ARGS ((void));
XPRIVATE int FDay ARGS ((void));
XPRIVATE int FDaysinmon ARGS ((void));
XPRIVATE int FDefined ARGS ((void));
XPRIVATE int FFilename ARGS ((void));
XPRIVATE int FGetenv ARGS ((void));
XPRIVATE int FHour ARGS ((void));
XPRIVATE int FIif ARGS ((void));
XPRIVATE int FIndex ARGS ((void));
XPRIVATE int FIsomitted ARGS ((void));
XPRIVATE int FMax ARGS ((void));
XPRIVATE int FMin ARGS ((void));
XPRIVATE int FMinute ARGS ((void));
XPRIVATE int FMon ARGS ((void));
XPRIVATE int FMonnum ARGS ((void));
XPRIVATE int FOrd ARGS ((void));
XPRIVATE int FOstype ARGS ((void));
XPRIVATE int FPlural ARGS ((void));
XPRIVATE int FSgn ARGS ((void));
XPRIVATE int FShell ARGS ((void));
XPRIVATE int FStrlen ARGS ((void));
XPRIVATE int FSubstr ARGS ((void));
XPRIVATE int FTime ARGS ((void));
XPRIVATE int FTrigdate ARGS ((void));
XPRIVATE int FTrigtime ARGS ((void));
XPRIVATE int FTrigvalid ARGS ((void));
XPRIVATE int FTypeof ARGS ((void));
XPRIVATE int FUpper ARGS ((void));
XPRIVATE int FValue ARGS ((void));
XPRIVATE int FVersion ARGS ((void));
XPRIVATE int FWkday ARGS ((void));
XPRIVATE int FWkdaynum ARGS ((void));
XPRIVATE int FYear ARGS ((void));
XPRIVATE int FIsleap ARGS ((void));
XPRIVATE int FLower ARGS ((void));
XPRIVATE int FNow ARGS ((void));
XPRIVATE int FRealtoday ARGS ((void));
XPRIVATE int FToday ARGS ((void));
XPRIVATE int FTrigger ARGS ((void));
XPRIVATE int CheckArgs ARGS ((Operator *f, int nargs));
XPRIVATE int CleanUpAfterFunc ARGS ((void));
X
X#ifdef __MSDOS__
XPRIVATE FILE *popen ARGS((char *cmd, char *mode));
XPRIVATE int pclose ARGS((FILE *fp));
X#endif
X
X/* "Overload" the struct Operator definition */
X#define NO_MAX 127
X#define MINARGS prec
X#define MAXARGS type
X
X/* Sigh - we use a global var. to hold the number of args supplied to
X function being called */
Xstatic int Nargs;
X
X/* Use a global var. to hold function return value */
Xstatic Value RetVal;
X
X/* Temp string buffer */
Xstatic char Buffer[32];
X
X/* We need access to the value stack */
Xextern Value ValStack[];
Xextern int ValStackPtr;
X
X/* Macro for accessing arguments from the value stack - args are numbered
X from 0 to (Nargs - 1) */
X#define ARG(x) (ValStack[ValStackPtr - Nargs + (x)])
X
X/* Macro for copying a value while destroying original copy */
X#define DCOPYVAL(x, y) ( (x) = (y), (y).type = ERR_TYPE )
X
X/* Convenience macros */
X#define UPPER(c) ( ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'A' : (c) )
X#define LOWER(c) ( ((c) >= 'A' && (c) <= 'Z') ? (c) + 'a' - 'A' : (c) )
X
X/* The array holding the built-in functions. */
XOperator Func[] = {
X/* Name minargs maxargs func */
X
X { "abs", 1, 1, FAbs },
X { "access", 2, 2, FAccess },
X { "asc", 1, 1, FAsc },
X { "baseyr", 0, 0, FBaseyr },
X { "char", 1, NO_MAX, FChar },
X { "choose", 2, NO_MAX, FChoose },
X { "coerce", 2, 2, FCoerce },
X { "date", 3, 3, FDate },
X { "day", 1, 1, FDay },
X { "daysinmon", 2, 2, FDaysinmon },
X { "defined", 1, 1, FDefined },
X { "filename", 0, 0, FFilename },
X { "getenv", 1, 1, FGetenv },
X { "hour", 1, 1, FHour },
X { "iif", 3, 3, FIif },
X { "index", 2, 3, FIndex },
X { "isleap", 1, 1, FIsleap },
X { "isomitted", 1, 1, FIsomitted },
X { "lower", 1, 1, FLower },
X { "max", 1, NO_MAX, FMax },
X { "min", 1, NO_MAX, FMin },
X { "minute", 1, 1, FMinute },
X { "mon", 1, 1, FMon },
X { "monnum", 1, 1, FMonnum },
X { "now", 0, 0, FNow },
X { "ord", 1, 1, FOrd },
X { "ostype", 0, 0, FOstype },
X { "plural", 1, 3, FPlural },
X { "realtoday", 0, 0, FRealtoday },
X { "sgn", 1, 1, FSgn },
X { "shell", 1, 1, FShell },
X { "strlen", 1, 1, FStrlen },
X { "substr", 2, 3, FSubstr },
X { "time", 2, 2, FTime },
X { "today", 0, 0, FToday },
X { "trigdate", 0, 0, FTrigdate },
X { "trigger", 1, 1, FTrigger },
X { "trigtime", 0, 0, FTrigtime },
X { "trigvalid", 0, 0, FTrigvalid },
X { "typeof", 1, 1, FTypeof },
X { "upper", 1, 1, FUpper },
X { "value", 1, 2, FValue },
X { "version", 0, 0, FVersion },
X { "wkday", 1, 1, FWkday },
X { "wkdaynum", 1, 1, FWkdaynum },
X { "year", 1, 1, FYear }
X};
X
X/* Need a variable here - Func[] array not really visible to outside. */
Xint NumFuncs = sizeof(Func) / sizeof(Operator) ;
X
X/***************************************************************/
X/* */
X/* CallFunc */
X/* */
X/* Call a function given a pointer to it, and the number */
X/* of arguments supplied. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPUBLIC int CallFunc(Operator *f, int nargs)
X#else
Xint CallFunc(f, nargs)
XOperator *f;
Xint nargs;
X#endif
X{
X register int r = CheckArgs(f, nargs);
X int i;
X
X Nargs = nargs;
X
X RetVal.type = ERR_TYPE;
X if (DebugFlag & DB_PRTEXPR) {
X fprintf(ErrFp, "%s(", f->name);
X for (i=0; i<nargs; i++) {
X PrintValue(&ARG(i), ErrFp);
X if (i<nargs-1) fprintf(ErrFp, ", ");
X }
X fprintf(ErrFp, ") => ");
X if (r) {
X fprintf(ErrFp, "%s\n", ErrMsg[r]);
X return r;
X }
X }
X if (r) {
X Eprint("%s(): %s", f->name, ErrMsg[r]);
X return r;
X }
X
X r = (*(f->func))();
X if (r) {
X DestroyValue(&RetVal);
X if (DebugFlag & DB_PRTEXPR)
X fprintf(ErrFp, "%s\n", ErrMsg[r]);
X else
X Eprint("%s(): %s", f->name, ErrMsg[r]);
X return r;
X }
X if (DebugFlag & DB_PRTEXPR) {
X PrintValue(&RetVal, ErrFp);
X fprintf(ErrFp, "\n");
X }
X r = CleanUpAfterFunc();
X return r;
X}
X
X/***************************************************************/
X/* */
X/* CheckArgs */
X/* */
X/* Check that the right number of args have been supplied */
X/* for a function. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int CheckArgs(Operator *f, int nargs)
X#else
Xstatic int CheckArgs(f, nargs)
XOperator *f;
Xint nargs;
X#endif
X{
X if (nargs < f->MINARGS) return E_2FEW_ARGS;
X if (nargs > f->MAXARGS && f->MAXARGS != NO_MAX) return E_2MANY_ARGS;
X return OK;
X}
X/***************************************************************/
X/* */
X/* CleanUpAfterFunc */
X/* */
X/* Clean up the stack after a function call - remove */
X/* args and push the new value. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int CleanUpAfterFunc(void)
X#else
Xstatic int CleanUpAfterFunc()
X#endif
X{
X Value v;
X int i, r;
X
X for (i=0; i<Nargs; i++) {
X r = PopValStack(&v);
X if (r) return r;
X DestroyValue(&v);
X }
X PushValStack(&RetVal);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* RetStrVal */
X/* */
X/* Return a string value from a function. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int RetStrVal(const char *s)
X#else
Xstatic int RetStrVal(s)
Xchar *s;
X#endif
X{
X RetVal.type = STR_TYPE;
X if (!s) {
X RetVal.v.str = (char *) malloc(1);
X if (RetVal.v.str) *RetVal.v.str = 0;
X } else
X RetVal.v.str = StrDup(s);
X
X if (!RetVal.v.str) {
X RetVal.type = ERR_TYPE;
X return E_NO_MEM;
X }
X return OK;
X}
X
X
X/***************************************************************/
X/* */
X/* FStrlen - string length */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FStrlen(void)
X#else
Xstatic int FStrlen()
X#endif
X{
X Value *v = &ARG(0);
X if (v->type != STR_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X RetVal.v.val = strlen(v->v.str);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FBaseyr - system base year */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FBaseyr(void)
X#else
Xstatic int FBaseyr()
X#endif
X{
X RetVal.type = INT_TYPE;
X RetVal.v.val = BASE;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FDate - make a date from year, month, day. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FDate(void)
X#else
Xstatic int FDate()
X#endif
X{
X int y, m, d;
X if (ARG(0).type != INT_TYPE ||
X ARG(1).type != INT_TYPE ||
X ARG(2).type != INT_TYPE) return E_BAD_TYPE;
X y = ARG(0).v.val;
X m = ARG(1).v.val - 1;
X d = ARG(2).v.val;
X
X if (y < BASE || y > BASE+YR_RANGE || m < 0 || m > 11 || d < 1 ||
X d > DaysInMonth(m, y)) return E_BAD_DATE;
X
X RetVal.type = DATE_TYPE;
X RetVal.v.val = Julian(y, m, d);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FCoerce - type coercion function. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FCoerce(void)
X#else
Xstatic int FCoerce()
X#endif
X{
X char *s;
X
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X s = ARG(0).v.str;
X
X /* Copy the value of ARG(1) into RetVal, and make ARG(1) invalid so
X it won't be destroyed */
X DCOPYVAL(RetVal, ARG(1));
X
X if (StriEq(s, "int")) return DoCoerce(INT_TYPE, &RetVal);
X else if (StriEq(s, "date")) return DoCoerce(DATE_TYPE, &RetVal);
X else if (StriEq(s, "time")) return DoCoerce(TIM_TYPE, &RetVal);
X else if (StriEq(s, "string")) return DoCoerce(STR_TYPE, &RetVal);
X else return E_CANT_COERCE;
X}
X
X/***************************************************************/
X/* */
X/* FMax - select maximum from a list of args. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FMax(void)
X#else
Xstatic int FMax()
X#endif
X{
X Value *maxptr;
X int i;
X char type;
X
X maxptr = &ARG(0);
X type = maxptr->type;
X
X for (i=1; i<Nargs; i++) {
X if (ARG(i).type != type) return E_BAD_TYPE;
X if (type != STR_TYPE) {
X if (ARG(i).v.val > maxptr->v.val) maxptr=&ARG(i);
X } else {
X if (strcmp(ARG(i).v.str, maxptr->v.str) > 0) maxptr=&ARG(i);
X }
X }
X DCOPYVAL(RetVal, *maxptr);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FMin - select minimum from a list of args. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FMin(void)
X#else
Xstatic int FMin()
X#endif
X{
X Value *minptr;
X int i;
X char type;
X
X minptr = &ARG(0);
X type = minptr->type;
X
X for (i=1; i<Nargs; i++) {
X if (ARG(i).type != type) return E_BAD_TYPE;
X if (type != STR_TYPE) {
X if (ARG(i).v.val < minptr->v.val) minptr=&ARG(i);
X } else {
X if (strcmp(ARG(i).v.str, minptr->v.str) < 0) minptr=&ARG(i);
X }
X }
X DCOPYVAL(RetVal, *minptr);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FAsc - ASCII value of first char of string */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FAsc(void)
X#else
Xstatic int FAsc()
X#endif
X{
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X RetVal.v.val = *(ARG(0).v.str);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FChar - build a string from ASCII values */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FChar(void)
X#else
Xstatic int FChar()
X#endif
X{
X
X int i, len;
X
X/* Special case of one arg - if given ascii value 0, create empty string */
X if (Nargs == 1) {
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X if (ARG(0).v.val < 0) return E_2LOW;
X if (ARG(0).v.val > 255) return E_2HIGH;
X len = ARG(0).v.val ? 2 : 1;
X RetVal.v.str = (char *) malloc(len);
X if (!RetVal.v.str) return E_NO_MEM;
X RetVal.type = STR_TYPE;
X *(RetVal.v.str) = ARG(0).v.val;
X if (len>1) *(RetVal.v.str + 1) = 0;
X return OK;
X }
X
X RetVal.v.str = (char *) malloc(Nargs + 1);
X if (!RetVal.v.str) return E_NO_MEM;
X RetVal.type = STR_TYPE;
X for (i=0; i<Nargs; i++) {
X if (ARG(i).type != INT_TYPE) return E_BAD_TYPE;
X if (ARG(i).v.val < 1) return E_2LOW;
X if (ARG(i).v.val > 255) return E_2HIGH;
X *(RetVal.v.str + i) = ARG(i).v.val;
X }
X *(RetVal.v.str + Nargs) = 0;
X return OK;
X}
X/***************************************************************/
X/* */
X/* Functions for extracting the components of a date. */
X/* */
X/* FDay - get day of month */
X/* FMonnum - get month (1-12) */
X/* FYear - get year */
X/* FWkdaynum - get weekday num (0 = Sun) */
X/* FWkday - get weekday (string) */
X/* FMon - get month (string) */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FDay(void)
X#else
Xstatic int FDay()
X#endif
X{
X int y, m, d;
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X FromJulian(ARG(0).v.val, &y, &m, &d);
X RetVal.type = INT_TYPE;
X RetVal.v.val = d;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FMonnum(void)
X#else
Xstatic int FMonnum()
X#endif
X{
X int y, m, d;
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X FromJulian(ARG(0).v.val, &y, &m, &d);
X RetVal.type = INT_TYPE;
X RetVal.v.val = m+1;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FYear(void)
X#else
Xstatic int FYear()
X#endif
X{
X int y, m, d;
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X FromJulian(ARG(0).v.val, &y, &m, &d);
X RetVal.type = INT_TYPE;
X RetVal.v.val = y;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FWkdaynum(void)
X#else
Xstatic int FWkdaynum()
X#endif
X{
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X
X /* Correct so that 0 = Sunday */
X RetVal.v.val = (ARG(0).v.val+1) % 7;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FWkday(void)
X#else
Xstatic int FWkday()
X#endif
X{
X char *s;
X
X if (ARG(0).type != DATE_TYPE && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X if (ARG(0).type == INT_TYPE) {
X if (ARG(0).v.val < 0) return E_2LOW;
X if (ARG(0).v.val > 6) return E_2HIGH;
X /* Convert 0=Sun to 0=Mon */
X ARG(0).v.val--;
X if (ARG(0).v.val < 0) ARG(0).v.val = 6;
X s = DayName[ARG(0).v.val];
X } else s = DayName[ARG(0).v.val % 7];
X return RetStrVal(s);
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FMon(void)
X#else
Xstatic int FMon()
X#endif
X{
X char *s;
X int y, m, d;
X
X if (ARG(0).type != DATE_TYPE && ARG(0).type != INT_TYPE)
X return E_BAD_TYPE;
X if (ARG(0).type == INT_TYPE) {
X m = ARG(0).v.val - 1;
X if (m < 0) return E_2LOW;
X if (m > 11) return E_2HIGH;
X } else FromJulian(ARG(0).v.val, &y, &m, &d);
X s = MonthName[m];
X return RetStrVal(s);
X}
X
X/***************************************************************/
X/* */
X/* FHour - extract hour from a time */
X/* FMinute - extract minute from a time */
X/* FTime - create a time from hour and minute */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FHour(void)
X#else
Xstatic int FHour()
X#endif
X{
X if (ARG(0).type != TIM_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X RetVal.v.val = ARG(0).v.val / 60;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FMinute(void)
X#else
Xstatic int FMinute()
X#endif
X{
X if (ARG(0).type != TIM_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X RetVal.v.val = ARG(0).v.val % 60;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FTime(void)
X#else
Xstatic int FTime()
X#endif
X{
X int h, m;
X
X if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
X
X h = ARG(0).v.val;
X m = ARG(1).v.val;
X if (h<0 || m<0) return E_2LOW;
X if (h>23 || m>59) return E_2HIGH;
X RetVal.type = TIM_TYPE;
X RetVal.v.val = h*60 + m;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FAbs - absolute value */
X/* FSgn - signum function */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FAbs(void)
X#else
Xstatic int FAbs()
X#endif
X{
X int v;
X
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X v = ARG(0).v.val;
X RetVal.type = INT_TYPE;
X RetVal.v.val = (v < 0) ? (-v) : v;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FSgn(void)
X#else
Xstatic int FSgn()
X#endif
X{
X int v;
X
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X v = ARG(0).v.val;
X RetVal.type = INT_TYPE;
X if (v>0) RetVal.v.val = 1;
X else if (v<0) RetVal.v.val = -1;
X else RetVal.v.val = 0;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FOrd - returns a string containing ordinal number. */
X/* */
X/* EG - ord(2) == "2nd", etc. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FOrd(void)
X#else
Xstatic int FOrd()
X#endif
X{
X int t, u, v;
X char *s;
X
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X
X v = ARG(0).v.val;
X t = v % 100;
X if (t < 0) t = -t;
X u = t % 10;
X s = "th";
X if (u == 1 && t != 11) s = "st";
X if (u == 2 && t != 12) s = "nd";
X if (u == 3 && t != 13) s = "rd";
X sprintf(Buffer, "%d%s", v, s);
X return RetStrVal(Buffer);
X}
X
X/***************************************************************/
X/* */
X/* FPlural - pluralization function */
X/* */
X/* plural(n) --> "" or "s" */
X/* plural(n, str) --> "str" or "strs" */
X/* plural(n, str1, str2) --> "str1" or "str2" */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FPlural(void)
X#else
Xstatic int FPlural()
X#endif
X{
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X
X switch(Nargs) {
X case 1:
X if (ARG(0).v.val == 1) return RetStrVal("");
X else return RetStrVal("s");
X
X case 2:
X if (ARG(1).type != STR_TYPE) return E_BAD_TYPE;
X if (ARG(0).v.val == 1) {
X DCOPYVAL(RetVal, ARG(1));
X return OK;
X }
X RetVal.type = STR_TYPE;
X RetVal.v.str = (char *) malloc(strlen(ARG(1).v.str)+2);
X if (!RetVal.v.str) {
X RetVal.type = ERR_TYPE;
X return E_NO_MEM;
X }
X strcpy(RetVal.v.str, ARG(1).v.str);
X strcat(RetVal.v.str, "s");
X return OK;
X
X default:
X if (ARG(1).type != STR_TYPE || ARG(2).type != STR_TYPE)
X return E_BAD_TYPE;
X if (ARG(0).v.val == 1) DCOPYVAL(RetVal, ARG(1));
X else DCOPYVAL(RetVal, ARG(2));
X return OK;
X }
X}
X
X/***************************************************************/
X/* */
X/* FChoose */
X/* Choose the nth value from a list of value. If n<1, choose */
X/* first. If n>N, choose Nth value. Indexes always start */
X/* from 1. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FChoose(void)
X#else
Xstatic int FChoose()
X#endif
X{
X int v;
X
X if (ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X v = ARG(0).v.val;
X if (v < 1) v = 1;
X if (v > Nargs-1) v = Nargs-1;
X DCOPYVAL(RetVal, ARG(v));
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FVersion - version of Remind */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FVersion(void)
X#else
Xstatic int FVersion()
X#endif
X{
X return RetStrVal(VERSION);
X}
X
X/***************************************************************/
X/* */
X/* FOstype - the type of operating system (UNIX or MSDOS) */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FOstype(void)
X#else
Xstatic int FOstype()
X#endif
X{
X#ifdef UNIX
X return RetStrVal("UNIX");
X#else
X return RetStrVal("MSDOS");
X#endif
X}
X
X/***************************************************************/
X/* */
X/* FUpper - convert string to upper-case */
X/* FLower - convert string to lower-case */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FUpper(void)
X#else
Xstatic int FUpper()
X#endif
X{
X char *s;
X
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X DCOPYVAL(RetVal, ARG(0));
X s = RetVal.v.str;
X while (*s) { *s = UPPER(*s); s++; }
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FLower(void)
X#else
Xstatic int FLower()
X#endif
X{
X char *s;
X
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X DCOPYVAL(RetVal, ARG(0));
X s = RetVal.v.str;
X while (*s) { *s = LOWER(*s); s++; }
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FToday - return the system's notion of "today" */
X/* Frealtoday - return today's date as read from OS. */
X/* FNow - return the system time */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FToday(void)
X#else
Xstatic int FToday()
X#endif
X{
X RetVal.type = DATE_TYPE;
X RetVal.v.val = JulianToday;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FRealtoday(void)
X#else
Xstatic int FRealtoday()
X#endif
X{
X RetVal.type = DATE_TYPE;
X RetVal.v.val = RealToday;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FNow(void)
X#else
Xstatic int FNow()
X#endif
X{
X RetVal.type = TIM_TYPE;
X RetVal.v.val = (int) ( SystemTime() / 60L );
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FGetenv - get the value of an environment variable. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FGetenv(void)
X#else
Xstatic int FGetenv()
X#endif
X{
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X return RetStrVal(getenv(ARG(0).v.str));
X}
X
X/***************************************************************/
X/* */
X/* FValue */
X/* */
X/* Get the value of a variable. If a second arg is supplied, */
X/* it is returned if variable is undefined. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FValue(void)
X#else
Xstatic int FValue()
X#endif
X{
X Var *v;
X
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X switch(Nargs) {
X case 1:
X return GetVarValue(ARG(0).v.str, &RetVal, NULL);
X
X case 2:
X v = FindVar(ARG(0).v.str, 0);
X if (!v) {
X DCOPYVAL(RetVal, ARG(1));
X return OK;
X } else {
X return CopyValue(&RetVal, &v->v);
X }
X }
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FDefined */
X/* */
X/* Return 1 if a variable is defined, 0 if it is not. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FDefined(void)
X#else
Xstatic int FDefined()
X#endif
X{
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X
X RetVal.type = INT_TYPE;
X
X if (FindVar(ARG(0).v.str, 0))
X RetVal.v.val = 1;
X else
X RetVal.v.val = 0;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FTrigdate and FTrigtime */
X/* */
X/* Date and time of last trigger. These are stored in global */
X/* vars. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FTrigdate(void)
X#else
Xstatic int FTrigdate()
X#endif
X{
X RetVal.type = DATE_TYPE;
X RetVal.v.val = LastTriggerDate;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FTrigvalid(void)
X#else
Xstatic int FTrigvalid()
X#endif
X{
X RetVal.type = INT_TYPE;
X RetVal.v.val = LastTrigValid;
X return OK;
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int FTrigtime(void)
X#else
Xstatic int FTrigtime()
X#endif
X{
X RetVal.type = TIM_TYPE;
X RetVal.v.val = LastTriggerTime;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FDaysinmon */
X/* */
X/* Returns the number of days in mon,yr */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FDaysinmon(void)
X#else
Xstatic int FDaysinmon()
X#endif
X{
X if (ARG(0).type != INT_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
X
X if (ARG(0).v.val > 12 || ARG(0).v.val < 1 ||
X ARG(1).v.val < BASE || ARG(1).v.val > BASE+YR_RANGE)
X return E_DOMAIN_ERR;
X
X RetVal.type = INT_TYPE;
X RetVal.v.val = DaysInMonth(ARG(0).v.val-1, ARG(1).v.val);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FIsleap */
X/* */
X/* Return 1 if year is a leap year, zero otherwise. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FIsleap(void)
X#else
Xstatic int FIsleap()
X#endif
X{
X int y, m, d;
X
X if (ARG(0).type != INT_TYPE && ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X
X /* If it's a date, extract the year */
X if (ARG(0).type == DATE_TYPE)
X FromJulian(ARG(0).v.val, &y, &m, &d);
X else
X y = ARG(0).v.val;
X
X RetVal.type = INT_TYPE;
X RetVal.v.val = IsLeapYear(y);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FTrigger */
X/* */
X/* Put out a date in a format suitable for triggering. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FTrigger(void)
X#else
Xstatic int FTrigger()
X#endif
X{
X int y, m, d;
X char buf[40];
X
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X
X FromJulian(ARG(0).v.val, &y, &m, &d);
X sprintf(buf, "%d %s %d", d, MonthName[m], y);
X return RetStrVal(buf);
X}
X
X/***************************************************************/
X/* */
X/* FShell */
X/* */
X/* The shell function. */
X/* */
X/* If run is disabled, will not be executed. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FShell(void)
X#else
Xstatic int FShell()
X#endif
X{
X char buf[SHELLSIZE+1];
X int ch, len;
X FILE *fp;
X char *s;
X
X if (RunDisabled) return E_RUN_DISABLED;
X if (ARG(0).type != STR_TYPE) return E_BAD_TYPE;
X s = buf;
X len = 0;
X fp = popen(ARG(0).v.str, "r");
X if (!fp) return E_IO_ERR;
X while (len < SHELLSIZE) {
X ch = getc(fp);
X if (ch == EOF) {
X break;
X }
X if (isspace(ch)) *s++ = ' ';
X else *s++ = ch;
X len++;
X }
X *s = 0;
X
X /* Delete trailing newline (converted to space) */
X if (s > buf && *(s-1) == ' ') *(s-1) = 0;
X#ifdef __MSDOS__
X if (s-1 > buf && *(s-2) == ' ') *(s-2) = 0;
X#endif
X pclose(fp);
X return RetStrVal(buf);
X}
X
X/***************************************************************/
X/* */
X/* FIsomitted */
X/* */
X/* Is a date omitted? */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FIsomitted(void)
X#else
Xstatic int FIsomitted()
X#endif
X{
X if (ARG(0).type != DATE_TYPE) return E_BAD_TYPE;
X RetVal.type = INT_TYPE;
X RetVal.v.val = IsOmitted(ARG(0).v.val, 0);
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FSubstr */
X/* */
X/* The substr function. We destroy the value on the stack. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FSubstr(void)
X#else
Xstatic int FSubstr()
X#endif
X{
X char *s, *t;
X int start, end;
X
X if (ARG(0).type != STR_TYPE || ARG(1).type != INT_TYPE) return E_BAD_TYPE;
X if (Nargs == 3 && ARG(2).type != INT_TYPE) return E_BAD_TYPE;
X
X s = ARG(0).v.str;
X start = 1;
X while (start < ARG(1).v.val) {
X if (!*s) break;
X s++;
X start++;
X }
X if (Nargs == 2 || !*s) return RetStrVal(s);
X end = start;
X t = s;
X while (end <= ARG(2).v.val) {
X if (!*s) break;
X s++;
X end++;
X }
X *s = 0;
X return RetStrVal(t);
X}
X
X/***************************************************************/
X/* */
X/* FIndex */
X/* */
X/* The index of one string embedded in another. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FIndex(void)
X#else
Xstatic int FIndex()
X#endif
X{
X char *s;
X int start;
X
X if (ARG(0).type != STR_TYPE || ARG(1).type != STR_TYPE ||
X (Nargs == 3 && ARG(2).type != INT_TYPE)) return E_BAD_TYPE;
X
X s = ARG(0).v.str;
X
X/* If 3 args, bump up the start */
X if (Nargs == 3) {
X start = 1;
X while (start < ARG(2).v.val) {
X if (!*s) break;
X s++;
X start++;
X }
X }
X
X/* Find the string */
X s = strstr(s, ARG(1).v.str);
X RetVal.type = INT_TYPE;
X if (!s) {
X RetVal.v.val = 0;
X return OK;
X }
X RetVal.v.val = (s - ARG(0).v.str) + 1;
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FIif */
X/* */
X/* The IIF function. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FIif(void)
X#else
Xstatic int FIif()
X#endif
X{
X int istrue;
X
X if (ARG(0).type != STR_TYPE && ARG(0).type != INT_TYPE) return E_BAD_TYPE;
X
X if (ARG(0).type == INT_TYPE)
X istrue = ARG(0).v.val;
X else
X istrue = *(ARG(0).v.str);
X
X if (istrue) DCOPYVAL(RetVal, ARG(1));
X else DCOPYVAL(RetVal, ARG(2));
X
X return OK;
X}
X
X/***************************************************************/
X/* */
X/* FFilename */
X/* */
X/* Return name of current file */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FFilename(void)
X#else
Xstatic int FFilename()
X#endif
X{
X return RetStrVal(FileName);
X}
X
X/***************************************************************/
X/* */
X/* FAccess */
X/* */
X/* The UNIX access() system call. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FAccess(void)
X#else
Xstatic int FAccess()
X#endif
X{
X int amode;
X char *s;
X
X if (ARG(0).type != STR_TYPE ||
X (ARG(1).type != INT_TYPE && ARG(1).type != STR_TYPE)) return E_BAD_TYPE;
X
X if (ARG(1).type == INT_TYPE) amode = ARG(1).v.val;
X else {
X amode = 0;
X s = ARG(1).v.str;
X while (*s) {
X switch(*s++) {
X case 'r':
X case 'R': amode |= R_OK; break;
X case 'w':
X case 'W': amode |= W_OK; break;
X case 'x':
X case 'X': amode |= X_OK; break;
X }
X }
X }
X RetVal.type = INT_TYPE;
X RetVal.v.val = access(ARG(0).v.str, amode);
X return OK;
X}
X
X#ifdef __MSDOS__
X/***************************************************************/
X/* */
X/* popen and pclose */
X/* */
X/* These are some rather brain-dead kludges for MSDOS. */
X/* They are just sufficient for the shell() function, and */
X/* should NOT be viewed as general-purpose replacements */
X/* for the UNIX system calls. */
X/* */
X/***************************************************************/
X#ifdef __TURBOC__
X#pragma argsused
X#endif
X
Xstatic char *TmpFile;
X#ifdef HAVE_PROTOS
XPRIVATE FILE *popen(char *cmd, char *mode)
X#else
Xstatic FILE *popen(cmd, mode)
Xchar *cmd, *mode
X#endif
X{
X char *s;
X
X TmpFile = tmpnam(NULL);
X if (!TmpFile) return NULL;
X s = (char *) malloc(strlen(cmd) + 3 + strlen(TmpFile) + 1);
X if (!s) return NULL;
X strcpy(s, cmd);
X strcat(s, " > ");
X strcat(s, TmpFile);
X system(s);
X free(s);
X return fopen(TmpFile, "r");
X}
X
X#ifdef HAVE_PROTOS
XPRIVATE int pclose(FILE *fp)
X#else
Xstatic int pclose(fp)
XFILE *fp;
X#endif
X{
X unlink(TmpFile);
X return fclose(fp);
X}
X
X#endif
X
X/***************************************************************/
X/* */
X/* FTypeof */
X/* */
X/* Implement the typeof() function. */
X/* */
X/***************************************************************/
X#ifdef HAVE_PROTOS
XPRIVATE int FTypeof(void)
X#else
Xstatic int FTypeof()
X#endif
X{
X switch(ARG(0).type) {
X case INT_TYPE: return RetStrVal("INT");
X case DATE_TYPE: return RetStrVal("DATE");
X case TIM_TYPE: return RetStrVal("TIME");
X case STR_TYPE: return RetStrVal("STRING");
X default: return RetStrVal("ERR");
X }
X}
SHAR_EOF
$TOUCH -am 1109142392 funcs.c &&
chmod 0600 funcs.c ||
echo "restore of funcs.c failed"
set `wc -c funcs.c`;Wc_c=$1
if test "$Wc_c" != "41381"; then
echo original size 41381, current size $Wc_c
fi
fi
# ============= globals.c ==============
if test X"$1" != X"-c" -a -f 'globals.c'; then
echo "File already exists: skipping 'globals.c'"
else
echo "x - extracting globals.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > globals.c &&
X/***************************************************************/
X/* */
X/* GLOBALS.C */
X/* */
X/* This file simply instantiates all of the global variables. */
X/* */
X/* It does this by #defining MK_GLOBALS and #including */
X/* globals.h and err.h */
X/* */
X/* This file is part of REMIND. */
X/* Copyright (C) 1992 by David F. Skoll. */
X/* */
X/***************************************************************/
X#include "config.h"
X#include <stdio.h> /* For defintion of FILE - sigh! */
X#include "types.h"
X#define MK_GLOBALS
X#include "globals.h"
X#include "err.h"
SHAR_EOF
$TOUCH -am 1109141292 globals.c &&
chmod 0600 globals.c ||
echo "restore of globals.c failed"
set `wc -c globals.c`;Wc_c=$1
if test "$Wc_c" != "1011"; then
echo original size 1011, current size $Wc_c
fi
fi
echo "End of part 6, continue with part 7"
exit 0
exit 0 # Just in case...