Initial checkin

This commit is contained in:
dfs
1996-03-27 03:25:46 +00:00
commit 1b189e0cb5
72 changed files with 27259 additions and 0 deletions

103
COPYRIGHT Normal file
View File

@@ -0,0 +1,103 @@
$Id: COPYRIGHT,v 1.1 1996-03-27 03:25:46 dfs Exp $
THE REMIND COPYRIGHT
1. REMIND refers to the entire set of files and documentation in the
REMIND package.
2. REMIND is Copyright 1992-1996 by David Skoll,
except where noted in individual files.
3. You may use REMIND for free, and may freely distribute it, providing
you do not charge the recipients to whom you distribute REMIND.
4. This means that if you distribute REMIND:
- You may not charge more than cost for distribution media.
- If you run a BBS or network service, you cannot charge more than
the regular access fee for REMIND. That is, REMIND must be accessible
at the basic BBS access rate, with no surcharge.
- You may not charge users support fees for REMIND.
- No other fees may be levied for REMIND.
- You cannot use REMIND to solicit donations.
5. You may modify REMIND. However, you must clearly indicate such
modifications when you distribute REMIND, and must tell the recipients
of the modified version that it is modified. Place that notice in the
WHATSNEW.xx file.
6. You may incorporate parts of REMIND into your own programs,
providing you do not sell these programs. You must clearly indicate
that the parts of REMIND you have incorporated are Copyright 1992-1996
by David Skoll. These programs can be distributed according to the terms
of paragraphs 3 and 4.
7. I will attempt to support REMIND as much as possible. However,
REMIND is supplied on an "as-is" basis with no warranty. You use it
at your own risk. I am not responsible for any damages caused by the
use or misuse of REMIND.
8. If you wish to contribute ideas or money to help the production of
software like REMIND, you can reply to the address shown at the end of
this file. Note that you are under no obligation to send me money.
If you don't donate, you have full rights to use REMIND just as if you
had donated. If you do donate, you get a big thank-you, but no
special rights. However, you will have helped support the production
of software like REMIND. Should you wish to donate, the suggested
amount is $18.00 (Canadian)
If you wish to incorporate Remind into a commercial product, or to
charge support fees for products incorporating Remind, contact
me for licensing arrangements.
ACKNOWLEDGEMENTS:
I would like to thank the following people:
Bill Aten <netagw!bill@uunet.UU.NET> for providing remind-all.sh
Bradley D. Keister <keister@poincare.phys.cmu.edu>, Rhys Weatherly
rhys@batserver.cs.uq.OZ.AU> and Anthony Cheng for initially providing
the Turbo C compiler support.
Dennis Cottel <dennis@peanuts.nosc.mil> for providing the patch to
produce calendars by weeks as well as by months.
Bill Silvert <bill%biomel@cs.dal.ca> and Dennis Cottel
<dennis@peanuts.nosc.mil> for suggesting many of the new features in
REMIND.
Dave Wolfe <dwolfe@pffft.sps.mot.com> and Raphael Manfredi
<ram@eiffel.com> for noticing bugs and sending me fixes.
Dave Rickel and George M. Sipe for sample reminders and holidays.
Michael Salmon for ISO encoding of PostScript output.
Darrel Hankerson for helping me provide some OS/2 support. Sorry
it's not complete, Darrel!
Phillipp Slusallek for suggesting the -k option.
Amos Shapir, David W. Tamkin and Frank Yellin for help with the Hebrew
calendar.
All of the language translators whose names are listed in lang.h
Timo Salmi, Keith Petersen, Bill Davidsen and Kent Landfield for
maintaining the uwasa and SIMTEL archives, and comp.binaries.ibm.pc
and comp.sources.misc in the face of a flurry of updates to REMIND.
All others who have corresponded with me to report bugs, express
appreciation or suggest features - too many people to list here.
Finally, all those who donated money to support the production of
REMIND. Your donations were gratefully appreciated.
--
David F. Skoll <dfs@doe.carleton.ca>
986 Eiffel Avenue
Ottawa, Ontario K2C 0J2
CANADA
Tel. (613) 225-8687

72
MANIFEST.DOS Normal file
View File

@@ -0,0 +1,72 @@
calendar.c
config.h
copyrigh
danish.h
defs.rem
dorem.c
dosubst.c
dutch.h
english.h
err.h
expr.c
expr.h
files.c
finnish.h
french.h
funcs.c
german.h
globals.c
globals.h
hbcal.c
init.c
kall
kall.1
lang.h
lnk.bcc
lnk.msc
lnk.tc
main.c
makefile
makefile.bcc
makefile.msc
makefile.os2
makefile.tc
manifest.dos
manifest.unx
moon.c
norwgian.h
omit.c
os2func.c
polish.h
protos.h
queue.c
readme.bcc
readme.dos
readme.os2
readme.uni
rem
rem.1
rem2ps.1
rem2ps.c
rem2ps.h
remind-a.csh
remind-a.sh
remind.1
remind.def
sort.c
test-rem
test-rem.bat
test-rem.cmd
test.cmp
test.rem
test1.cmp
test2.cmp
token.c
trigger.c
tstlang.rem
types.h
userfns.c
utils.c
var.c
version.h
whatsnew.30

72
MANIFEST.UNX Normal file
View File

@@ -0,0 +1,72 @@
COPYRIGHT
MANIFEST.DOS
MANIFEST.UNX
Makefile
README.BCC
README.DOS
README.OS2
README.UNIX
WHATSNEW.30
calendar.c
config.h
danish.h
defs.rem
dorem.c
dosubst.c
dutch.h
english.h
err.h
expr.c
expr.h
files.c
finnish.h
french.h
funcs.c
german.h
globals.c
globals.h
hbcal.c
init.c
kall
kall.1
lang.h
lnk.bcc
lnk.msc
lnk.tc
main.c
makefile.bcc
makefile.msc
makefile.os2
makefile.tc
moon.c
norwgian.h
omit.c
os2func.c
polish.h
protos.h
queue.c
rem
rem.1
rem2ps.1
rem2ps.c
rem2ps.h
remind-all.csh
remind-all.sh
remind.1
remind.def
sort.c
test-rem
test-rem.bat
test-rem.cmd
test.cmp
test.rem
test1.cmp
test2.cmp
token.c
trigger.c
tstlang.rem
types.h
userfns.c
utils.c
var.c
version.h

210
Makefile Normal file
View File

@@ -0,0 +1,210 @@
# Makefile for REMIND
# $Id: Makefile,v 1.1 1996-03-27 03:25:48 dfs Exp $
#-----------------------------------------------------------------------------
# THINGS FOR YOU TO EDIT START BELOW
#-----------------------------------------------------------------------------
# Uncomment the next line if you are running on a SYSV system
SYSV= -DSYSV
# Uncomment the next line if you are running under UNIX (including SYSV!)
UNIX= -DUNIX
# Uncomment the next lines if you want to use gcc instead of default compiler
# NOTE: Tempting as it may be, if you use 'cc' for the C compiler, do not
# use 'ld' for the linker. It will probably work much better if you use
# LD= cc rather than LD= ld.
CC= gcc
LD= gcc
# Put any additional flags for the C compiler or linker here - if you
# are not using gcc, you probably want to remove '-ansi'.
CFLAGS= -O -ansi
CDEFS=
LDFLAGS=
#### INSTALLATION LOCATIONS ####
# Note that I use 'cp' rather than 'install' for improved portability.
#
# BINDIR: Where should the Remind executable be installed?
BINDIR= /usr/local/bin
# SCRIPTDIR: Where should the kall and rem shell scripts be installed?
SCRIPTDIR= /usr/local/bin
# MANDIR: Where should the man pages be installed?
MANDIR= /usr/local/man
# MANSECT: Which man section should the man pages go into?
MANSECT= 1
# EXEMODE: What file protection mode should be used for the executables?
EXEMODE= 755
# MANMODE: What file protection mode should be used for the man pages?
MANMODE= 644
# OWNER, GROUP: What owner and group to use for executables,
# scripts and man pages?
OWNER=bin
GROUP=bin
#-----------------------------------------------------------------------------
# YOU SHOULDN'T EDIT ANYTHING BELOW HERE. You may want to change some things
# in config.h; then, you should be able to type 'make'.
#-----------------------------------------------------------------------------
VERSION= 03.00.13
MATHLIB= -lm
HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
lang.h english.h german.h dutch.h finnish.h french.h norwgian.h \
danish.h polish.h
STDHDRS= config.h types.h protos.h globals.h err.h lang.h
LANGHDRS= english.h german.h dutch.h finnish.h french.h norwgian.h danish.h \
polish.h
SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c hbcal.c \
init.c main.c moon.c omit.c sort.c queue.c token.c trigger.c userfns.c \
utils.c var.c
MANIFEST= README.UNIX README.DOS COPYRIGHT $(HDRS) $(SRCS) Makefile rem rem.1 \
remind.1 remind-all.csh remind-all.sh test.rem test-rem test.cmp makefile.tc \
makefile.msc lnk.msc lnk.tc MANIFEST.UNX MANIFEST.DOS WHATSNEW.30 kall kall.1 \
defs.rem README.OS2 makefile.os2 rem2ps.c rem2ps.h remind.def rem2ps.1 \
tstlang.rem README.BCC lnk.bcc makefile.bcc os2func.c \
test-rem.bat test-rem.cmd test1.cmp test2.cmp
OBJS= $(SRCS:.c=.o)
all: remind rem2ps
.c.o:
$(CC) $(UNIX) $(SYSV) -c $(CFLAGS) $(CDEFS) $*.c
rem2ps: rem2ps.o
$(LD) $(LDFLAGS) -o rem2ps rem2ps.o
remind: $(OBJS)
$(LD) $(LDFLAGS) -o remind $(OBJS) $(MATHLIB)
clean:
rm -f *.o *~ core *.bak
clobber:
rm -f *.o *~ remind rem2ps test.out core *.bak
test: remind
sh test-rem
rem2ps.o: rem2ps.c rem2ps.h lang.h config.h
calendar.o: calendar.c $(STDHDRS) expr.h
dorem.o: dorem.c $(STDHDRS) expr.h
dosubst.o: dosubst.c $(STDHDRS) $(LANGHDRS)
expr.o: expr.c $(STDHDRS) expr.h
files.o: files.c $(STDHDRS)
funcs.o: funcs.c $(STDHDRS) expr.h version.h
globals.o: globals.c config.h types.h globals.h err.h lang.h $(LANGHDRS)
hbcal.o: hbcal.c $(STDHDRS)
init.o: init.c $(STDHDRS) expr.h version.h lang.h $(LANGHDRS)
main.o: main.c $(STDHDRS) expr.h
moon.o: moon.c $(STDHDRS)
omit.o: omit.c $(STDHDRS)
sort.o: sort.c $(STDHDRS)
queue.o: queue.c $(STDHDRS)
token.o: token.c $(STDHDRS)
trigger.o: trigger.c $(STDHDRS) expr.h
userfns.o: userfns.c $(STDHDRS) expr.h
utils.o: utils.c $(STDHDRS)
var.o: var.c $(STDHDRS) expr.h
tarZ:
tar cvf remind-3.0.13.tar $(MANIFEST)
compress -v remind-3.0.13.tar
shar:
shar -x -n"Remind $(VERSION)" -l45 -o./Shar $(MANIFEST)
todos:
mcopy -tn $(MANIFEST) a:
fromdos:
mcopy -tn 'a:*' .
-mv -f copyrigh COPYRIGHT
-mv -f makefile Makefile
-mv -f readme.os2 README.OS2
-mv -f readme.dos README.DOS
-mv -f readme.bcc README.BCC
-mv -f readme.uni README.UNIX
-mv -f remind-a.csh remind-all.csh
-mv -f remind-a.sh remind-all.sh
-mv -f manifest.dos MANIFEST.DOS
-mv -f manifest.unx MANIFEST.UNX
-mv -f whatsnew.30 WHATSNEW.30
-chmod u+x test-rem
backup:
cp $(MANIFEST) ../backup
transmit:
sz -a -e $(MANIFEST)
install: install-bin install-scripts install-man
install-bin: remind rem2ps
cp remind $(BINDIR)/remind
-chmod $(EXEMODE) $(BINDIR)/remind
-chown $(OWNER) $(BINDIR)/remind
-chgrp $(GROUP) $(BINDIR)/remind
cp rem2ps $(BINDIR)/rem2ps
-chmod $(EXEMODE) $(BINDIR)/rem2ps
-chown $(OWNER) $(BINDIR)/rem2ps
-chgrp $(GROUP) $(BINDIR)/rem2ps
install-scripts:
cp kall $(SCRIPTDIR)/kall
-chmod $(EXEMODE) $(SCRIPTDIR)/kall
-chown $(OWNER) $(SCRIPTDIR)/kall
-chgrp $(GROUP) $(SCRIPTDIR)/kall
cp rem $(SCRIPTDIR)/rem
-chmod $(EXEMODE) $(SCRIPTDIR)/rem
-chown $(OWNER) $(SCRIPTDIR)/rem
-chgrp $(GROUP) $(SCRIPTDIR)/rem
install-man:
cp remind.1 $(MANDIR)/man$(MANSECT)/remind.$(MANSECT)
-chmod $(MANMODE) $(MANDIR)/man$(MANSECT)/remind.$(MANSECT)
-chown $(OWNER) $(MANDIR)/man$(MANSECT)/remind.$(MANSECT)
-chgrp $(GROUP) $(MANDIR)/man$(MANSECT)/remind.$(MANSECT)
cp rem.1 $(MANDIR)/man$(MANSECT)/rem.$(MANSECT)
-chmod $(MANMODE) $(MANDIR)/man$(MANSECT)/rem.$(MANSECT)
-chown $(OWNER) $(MANDIR)/man$(MANSECT)/rem.$(MANSECT)
-chgrp $(GROUP) $(MANDIR)/man$(MANSECT)/rem.$(MANSECT)
cp kall.1 $(MANDIR)/man$(MANSECT)/kall.$(MANSECT)
-chmod $(MANMODE) $(MANDIR)/man$(MANSECT)/kall.$(MANSECT)
-chown $(OWNER) $(MANDIR)/man$(MANSECT)/kall.$(MANSECT)
-chgrp $(GROUP) $(MANDIR)/man$(MANSECT)/kall.$(MANSECT)
cp rem2ps.1 $(MANDIR)/man$(MANSECT)/rem2ps.$(MANSECT)
-chmod $(MANMODE) $(MANDIR)/man$(MANSECT)/rem2ps.$(MANSECT)
-chown $(OWNER) $(MANDIR)/man$(MANSECT)/rem2ps.$(MANSECT)
-chgrp $(GROUP) $(MANDIR)/man$(MANSECT)/rem2ps.$(MANSECT)
release:
-mkdir RELEASE
-rm -f RELEASE/*
mkpatch ../prev . patch.13 Shar "Remind-3.0/Patch-13/part"
mv Shar* RELEASE
rm -f patch.13*
for i in *.1; do nroff -man $$i | sed -e 's/_//g' > `basename $$i .1`.man; done
mv *.man RELEASE
for i in *.1; do groff -man -Tps $$i > `basename $$i .1`.ps; done
mv *.ps RELEASE
# Meant for debugging - don't invoke this target unless you know what
# you're doing!
majortest:
for comp in "cc" "gcc -Wall -pedantic -ansi" ; do for lang in 1 2 3 4 5 0 ; do for def in ISOLATIN1 IBMEXTENDED FOOBARBAZ ; do echo $$def $$lang ; $(MAKE) clobber ; $(MAKE) "CDEFS=-DLANG=$$lang -D$$def=1" CFLAGS=-O "CC=$$comp" "LD=$$comp" ; done ; done ; done

65
README.BCC Normal file
View File

@@ -0,0 +1,65 @@
$Id: README.BCC,v 1.1 1996-03-27 03:25:48 dfs Exp $
REMIND version 3.0 for Borland C++
1 - Read the file COPYRIGHT. (This may be called COPYRIGH on your
MS-DOS system.)
2 - You must use the Borland C++ OS/2 or MSDOS/Windows compiler.
3 - Examine the file config.h and adjust parameters as needed
4 - Examine the file makefile.bcc and adjust parameters as needed.
5 - Type:
make -f makefile.bcc
This will make 'remind.exe' and 'rem2ps.exe' in the ..\os2-ex or ..\msdos-ex
directories.
The file "defs.rem" has some sample Remind definitions and commands,
as well as U.S. and Jewish holidays.
NOTE that I do not have access to an OS/2 system, so support for this
system may not be as good as I'd like.
OS/2 support is courtesy of Russ Herman <rwh@gov.on.ca>, Norman Walsh
<norm@ora.com>, and Darrel Hankerson <hankedr@mail.auburn.edu>.
However, if you have problems, please contact me.
OTHER LANGUAGE SUPPORT
Remind has support for languages other than English. See the file
"lang.h" for details. The language support may vary - you can change
only the substitution filter, or you can translate all of the usage
instructions and error messages as well. See "french.h" for an
example of the latter.
If you add support for a non-English language, Remind will accept both the
English and non-English names of months and weekdays in an input script.
However, you should not rely on this feature if you want to write portable
Remind scripts.
At a minimum, you should support month and day names in the foreign
language, and should modify the substitution filter appropriately.
If you are truly diligent, you can translate usage and error messages
too.
Take a look at the files "english.h" and "german.h" if you want to add
support for your favourite language. If you do add another language
to Remind, please let me know! Here are the basic guidelines:
- Your language file should be called "lxxx.h", where lxxx is the first 8
characters of the ENGLISH name of your language.
- You should define L_LANGNAME to be the full English name of your language,
with the first letter capitalized and the rest lower-case.
--
David F. Skoll <dfs@doe.carleton.ca>
986 Eiffel Avenue
Ottawa, Ontario K2C 0J2
CANADA
Tel. (613) 225-8687

59
README.DOS Normal file
View File

@@ -0,0 +1,59 @@
$Id: README.DOS,v 1.1 1996-03-27 03:25:49 dfs Exp $
REMIND version 3.0 for MS-DOS
REMIND is a sophisticated alarm/calendar program. Details are given
in the man page, "remind.1".
1 - Read the file COPYRIGHT. (This may be called COPYRIGH on your
MS-DOS system.)
2 - Examine the file config.h and adjust parameters as needed
3 - If you are using Turbo C to compile Remind, type:
make -fmakefile.tc
If you are using Microsoft C to compile Remind, type:
make makefile.msc
This will create REMIND.EXE, which is ready to be executed.
The file "defs.rem" has some sample Remind definitions and commands,
as well as U.S. and Jewish holidays.
OTHER LANGUAGE SUPPORT
Remind has support for languages other than English. See the file
"lang.h" for details. The language support may vary - you can change
only the substitution filter, or you can translate all of the usage
instructions and error messages as well. See "french.h" for an example.
If you add support for a non-English language, Remind will accept both the
English and non-English names of months and weekdays in an input script.
However, you should not rely on this feature if you want to write portable
Remind scripts.
At a minimum, you should support month and day names in the foreign
language, and should modify the substitution filter appropriately.
If you are truly diligent, you can translate usage and error messages
too.
Take a look at the files "english.h" and "german.h" if you want to add
support for your favourite language. If you do add another language
to Remind, please let me know! Here are the basic guidelines:
- Your language file should be called "lxxx.h", where lxxx is the first 8
characters of the ENGLISH name of your language.
- You should define L_LANGNAME to be the full English name of your language,
with the first letter capitalized and the rest lower-case.
--
David F. Skoll <dfs@doe.carleton.ca>
986 Eiffel Avenue
Ottawa, Ontario K2C 0J2
CANADA
Tel. (613) 225-8687

137
README.OS2 Normal file
View File

@@ -0,0 +1,137 @@
$Id: README.OS2,v 1.1 1996-03-27 03:25:49 dfs Exp $
REMIND version 3.0 for OS/2
This file contains instructions for compiling Remind under OS/2 with
Eberhard Mattes' emx/gcc compiler and with the Microsoft C compiler.
There are a number of targets in Makefile.os2, including OS/2-only
versions and bound versions (programs which run under OS/2 and DOS).
Note that there is also support for OS/2 using the Borland C
compiler--see the file README.BCC for details.
REMIND is a sophisticated alarm/calendar program. Details are given
in the man page, "remind.1".
1 - Read the file COPYRIGHT. (This may be called COPYRIGH on your
MS-DOS system.)
2 - To compile Remind for OS/2, you must use the Microsoft C compiler
or emx/gcc. You must also have a decent version of 'make', such
as dmake or GNU make.
3 - Examine the file config.h and adjust parameters as needed
4 - Examine the file Makefile.os2 and adjust parameters as needed.
5 - Type:
make -f Makefile.os2
to see a list of targets. For example,
make -f Makefile.os2 emx
will build a 32-bit emx version which runs under OS/2 2.x and DOS.
The file "defs.rem" has some sample Remind definitions and commands,
as well as U.S. and Jewish holidays.
NOTE that I do not have access to an OS/2 system, so support for this
system may not be as good as I'd like.
OS/2 support is courtesy of Russ Herman <rwh@gov.on.ca>, Norman Walsh
<norm@ora.com>, and Darrel Hankerson <hankedr@mail.auburn.edu>.
However, if you have problems, please contact me.
OTHER LANGUAGE SUPPORT
Remind has support for languages other than English. See the file
"lang.h" for details. The language support may vary - you can change
only the substitution filter, or you can translate all of the usage
instructions and error messages as well. See "french.h" for an
example of the latter.
If you add support for a non-English language, Remind will accept both the
English and non-English names of months and weekdays in an input script.
However, you should not rely on this feature if you want to write portable
Remind scripts.
At a minimum, you should support month and day names in the foreign
language, and should modify the substitution filter appropriately.
If you are truly diligent, you can translate usage and error messages
too.
Take a look at the files "english.h" and "german.h" if you want to add
support for your favourite language. If you do add another language
to Remind, please let me know! Here are the basic guidelines:
- Your language file should be called "lxxx.h", where lxxx is the first 8
characters of the ENGLISH name of your language.
- You should define L_LANGNAME to be the full English name of your language,
with the first letter capitalized and the rest lower-case.
RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
1. POPUP REMINDERS
If you define the symbol OS2_POPUP in the OS/2 Makefile, you get
"full-screen popups" (as implemented by Russ Herman) for all MSG-
and MSF-type reminders. You may or may not like this feature.
One way of implementing popup reminders is to get the program
"pmpopup.exe" from ftp-os2.cdrom.com, and using Remind with the
'-k' option as follows from C:\STARTUP.CMD:
start /pm /inv /n remind "-kstart pmpopup %%s" remfile
Alternatively, if you have the Vrexx package, you can use this
procedure suggested by Norman Walsh:
Start remind like this in C:\STARTUP.CMD:
start /pm /inv /n \bin\remind -faz "-kstart popupmsg %%s" .reminders
The popups are done by POPUPMSG.CMD which looks like this:
-------------- Cut Here ---------- Cut Here ---------- Cut Here --------
/* PopUpMsg */
'@echo off'
parse arg theargs
if theargs = "" then
theargs = "Empty message"
call RxFuncAdd 'VInit', 'VREXX', 'VINIT'
initcode = VInit()
if initcode = 'ERROR' then signal CLEANUP
signal on failure name CLEANUP
signal on halt name CLEANUP
signal on syntax name CLEANUP
/* example VMsgBox call */
msg.0 = 1
msg.1 = theargs
call VDialogPos 50, 50
call VMsgBox 'Popup Message', msg, 1
/* end of CMD file */
CLEANUP:
call VExit
exit
-------------- Cut Here ---------- Cut Here ---------- Cut Here --------
--
David F. Skoll <dfs@doe.carleton.ca>
986 Eiffel Avenue
Ottawa, Ontario K2C 0J2
CANADA
Tel. (613) 225-8687

139
README.UNIX Normal file
View File

@@ -0,0 +1,139 @@
$Id: README.UNIX,v 1.1 1996-03-27 03:25:49 dfs Exp $
REMIND version 3.0 for UNIX
REMIND is a sophisticated alarm/calendar program. Details are given
in the man page, "remind.1".
1 - Read the file COPYRIGHT.
2- Before compiling the software, check to see if it includes patches.
These are files called patch.xx. If there are patches, apply them all
by typing:
cat patch.* | patch
3 - Examine the Makefile and change any parameters which need to be
changed for your system. As it stands, the Makefile is set up for a
BSD system.
4 - Examine the file config.h and adjust parameters as needed
5 - Examine lang.h and choose the language you want Remind to use.
6 - Type 'make'
7 - Type 'sh test-rem' or 'make test' to run the acceptance test. Note
that the test script works only for the English version of Remind.
8 - Type 'make install' to install Remind, kall, rem and the man
pages.
Two shell scripts, "remind-all.csh" and "remind-all.sh" are provided.
These allow automatic mailing of reminders to all users who create a
$HOME/.reminders file. These two scripts are equivalent; one is a
"sh" script and the other is a "csh" script. Pick the one you want to
use, and follow the instructions in the opening comments of the
script.
*** NOTE *** Please be aware that "remind-all.csh" and "remind-all.sh"
have been changed since version 03.00.05 of Remind. If you install
the new remind executable, make sure you switch over to the new
"remind-all" scripts.
A shell script called "rem" is provided for those who like to have
'remind' assume a default reminders file. A man page for this script
is provided. You should examine the script to ensure that the defaults
are correct.
Many people have asked me why I supply the "rem" script instead of
having Remind assume a default file. The answer is: That's how I like
it! My personal preference is for a program which normally takes
parameters to display usage information when invoked with no
parameters. I like that behaviour so I can quickly get an idea of
what a program does without poring through the man page. And I think
I'll keep Remind that way. Sorry to all who dislike it. :-)
A shell script called "kall" is provided so you can kill your background
remind processes when you log out. See the man page. Note that kall
depends on the output of "ps", and may not be portable.
The file "defs.rem" has some sample Remind definitions and commands,
as well as U.S. and Jewish holidays.
OTHER LANGUAGE SUPPORT
Remind has support for languages other than English. See the file
"lang.h" for details. The language support may vary - you can change
only the substitution filter, or you can translate all of the usage
instructions and error messages as well. See "french.h" for an
example of the latter.
If you add support for a non-English language, Remind will accept both the
English and non-English names of months and weekdays in an input script.
However, you should not rely on this feature if you want to write portable
Remind scripts.
At a minimum, you should support month and day names in the foreign
language, and should modify the substitution filter appropriately.
If you are truly diligent, you can translate usage and error messages
too.
Take a look at the files "english.h" and "german.h" if you want to add
support for your favourite language. If you do add another language
to Remind, please let me know! Here are the basic guidelines:
- Your language file should be called "lxxx.h", where lxxx is the first 8
characters of the ENGLISH name of your language.
- Your language file should define L_LANGNAME to be the full English
name of your language, with the first letter capitalized and the rest
lower-case.
RELEASE NOTES -- miscellaneous info that couldn't go anywhere else!
1. POPUP REMINDERS
If you're running under X-Windows and you have the TCL tools,
you can create simple pop-up reminders by creating the following
TCL script called 'popup'. It pops a message on to the screen and
waits for you to press the 'OK' button. If you don't press the OK button
within 15 seconds, it exits anyway. To use it, you can use the '-k' option
for Remind as follows:
remind "-kpopup '%s'&" .reminders
Or use the following in your Remind script:
REM AT 17:00 RUN popup 'Time to go home.' &
This TCL script is a slightly modified version of one submitted by
Norman Walsh. TCL is available via FTP at ftp.uu.net in /languages/tcl.
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
#!/usr/local/bin/wish -f
wm withdraw .
if { [ llength $argv ] == 1 } {
eval set msg $argv
} else {
eval set msg [ list $argv ]
}
after 15000 { destroy . ; exit }
tk_dialog .d { Message } $msg warning 0 { OK }
destroy .
exit
-------------- Cut Here ---------- Cut Here ---------- Cut Here -------------
--
David F. Skoll <dfs@doe.carleton.ca>
986 Eiffel Avenue
Ottawa, Ontario K2C 0J2
CANADA
Tel. (613) 225-8687

613
WHATSNEW.30 Normal file
View File

@@ -0,0 +1,613 @@
CHANGES TO REMIND
* Version 3.0 Patch 13
+ MINOR ENHANCEMENTS
- Added extra parameters to the "psmoon" built-in function so you
can annotate the PostScript moon icons.
- Added a command-line "time" argument to Remind for testing Remind
scripts with specific system times. Also added the realnow() function
which has the same relationship to now() as realtoday() has to today().
(See the man page!)
- Modified Rem2PS so it prints progress messages to stderr if
'-v' command-line argument is used.
- In the top of the 'finnish.h' file, added a note about
Mikko Silvonen's file of Finnish holidays.
+ BUG FIXES
- Fixed a bug in rem2ps which sometimes caused incorrect PostScript if
the -e and -m options were used. Thanks to Michael Neuhauser for
reporting the bug and providing a fix.
- Made the '-k' option escape shell characters in the message to make it
safer.
- Fixed a segmentation violation which resulted if not all
PUSH-OMIT-CONTEXTs were balanced by POP-OMIT-CONTEXTs.
- Removed the prototype for DestroyValue, which is now a macro. I'm
amazed that very few compilers complained about this one!
- Updated the copyright notices everywhere.
* Version 3.0 Patch 12
+ MINOR ENHANCEMENTS
- Added support for the Danish language, courtesy of Mogens Lynnerup.
- Added support for the Polish language, courtesy of Jerzy Sobczyk.
- Made the Makefile more portable, thanks to Jim Budler.
- Removed some compiler warnings under Linux, thanks to Francois Pinard.
- Tidied the man page a bit; added a small bibliography.
+ BUG FIXES
- Fixed a problem with the '-k' option which resulted in a newline being
placed after the message text. This was giving sh(1) heartburn...
* Version 3.0 Patch 11
+ MINOR ENHANCEMENTS
- Added release notes to README.UNIX and README.OS2 describing one
way to make pop-up alarms under X-Windows and Presentation Manager.
- Added the $DefaultPrio system variable
- Improved OS/2 support, thanks to Darrel Hankerson, Russ Herman
and Norman Walsh.
- Made the pushing and popping of operators and operands during
expression evaluation in-line code instead of function calls. Did the
same for DestroyValue. I'm not sure if this was a good idea -- on the
Sparc using gcc, this slowed things down... go figure.
+ BUG FIXES
- Fixed a potential memory leak in the char() function.
- Made the TRIGGER() built-in function return its answer in English even
for the foreign-language versions -- this was required for compilers which
are not 8-bit clean, and for languages with accented letters.
- Made expression evaluation slightly faster by eliminating some unnecessary
copying of string values.
- Corrected some non-portable definitions of the macro UPPER(c)
- Fixed typos in french.h
* Version 3.0 Patch 10
+ MAJOR ENHANCEMENT
- OS/2 support is now much better, thanks to Russ Herman. The Borland
C compiler under OS/2 and MS-DOS is supported.
+ MINOR ENHANCEMENTS
- Added the SCHED keyword for precise control of scheduling of timed
reminders -- it's really quite nifty!
- Modified the trigger() function to take up to three arguments -- in
addition to a date, you can specify a time and a flag specifying that
the trigger should be converted from UTC to local time.
- Added $SortByDate, $SortByTime and $SortByPrio system variables.
- Added test suites for MS-DOS and OS/2, courtesy of Russ Herman.
- In PostScript output, the month and year are output in the %%Page: comments.
Makes it nicer to view multi-month calendars with previewers (eg,
GhostView.)
- Added the PRIORITY keyword for more control of sort order of reminders.
Based on a suggestion by George M. Sipe.
- Added the msgprefix() and msgsuffix() evaluations around MSG-type
reminders for doing fancy things with reminders of different priorities.
Also added calprefix() and calsuffix() for doing the same thing in
calendar mode.
- Enabled the -g option during calendar mode as well as regular mode.
+ BUG FIXES
- Fixed minor bugs in the LocalToUTC and UTCToLocal functions.
- "remind -c -de file" used to cause a segmentation violation. Whoops...
- Some files which should have included <string.h> didn't include it - these
are now fixed.
- Fixed the moondate() and moontime() functions, which used to be incorrect
after November 1994.
- Fixed the Finnish language support which was missing a few newlines.
* Version 3.0 Patch 9
+ NOTES
- Remind is now too big to compile under the "small" model in
MS-DOS. You must recompile everything under the "medium" model.
+ MAJOR ENHANCEMENTS
- Functions moonphase(), moondate() and moontime() were added for dealing
with phases of the moon. The code was snarfed from "moontool" by
John Walker - see the file "moon.c" for detailed acknowledgement. Also
added psmoon() for putting little moon symbols on the PostScript calendar.
+ MINOR ENHANCEMENTS
- Added some more examples to defs.rem - notably, support for ANSI
terminal color-changing escape sequences, thanks to Gail Gurman.
- Modified both Remind and Rem2PS so that calendars can start on Sunday or
Monday, depending on your preference. Unfortunately, the command-line
options are different -- for Remind, it's '-m' and for Rem2PS it's '-n'
because '-m' was already in use. Based on a suggestion by John Plate
and a patch sent by Mikko Silvonen.
- The Finnish language support is better - now, all usage and error
messages are in Finnish. In addition, the Finnish language module
supports the IBM extended character set as well as ISOLATIN1.
Thanks to Mikko Silvonen.
- Modified Rem2PS to allow more control over the placement of the small
calendars, thanks to a suggestion by Frank Vance. Also added option
to control the calendar title (e.g., "September 1993") independently
of day-of-week headings.
- Added the psshade() function to make it easier to shade PostScript
calendars.
- Allowed a repeat parameter '*num' to be supplied on command line so
a 'preview' of many days' worth of reminders can be obtained easily.
- Added the $Location system variable.
- Allowed an expression to be supplied to EXIT to return an exit
status.
- Added the FLUSH command.
+ BUG FIXES
- Fixed the MSF-type reminder to fill paragraphs more intelligently.
It puts double spaces after '!', '.' and '?', and can handle quotes,
brackets, etc. after periods, etc. These characters can be specified
with the $EndSent and $EndSentIg system variables. Also modified it
so that newlines in the body start new paragraphs, rather than being
swallowed as white-space.
* Version 3.0 Patch 8
+ MAJOR ENHANCEMENTS
- Changed the code to more fully support foreign languages - error
messages and usage instructions can now be changed. All changes can
be localized in the appropriate language.h files.
- Added support for the French language, courtesy of Laurent Duperval.
Note that the French support is more complete than for other languages -
French usage instructions and error messages are supported.
- Added support for the Norwegian language, courtesy of Trygve Randen.
+ MINOR ENHANCEMENTS
- Added code for the functions timelocal() and timegm(), courtesy of
Lucio de Re. This is for those very few machines whose libraries
include neither those functions nor mktime().
- Added the filedate() function.
- Allowed the filename to be specified as "-" to cause Remind to take
its input from the standard input stream.
- Added the "MSF" keyword to cause reminders to be formatted automatically.
This keyword paragraph-fills reminder text following user specifications.
Based on a suggestion by Ken McGlothlen.
- Added the "-e" option to Rem2PS, allowing the PostScript calendar
to fill the entire page. Thanks to Arthur G. Yaffe.
+ BUG FIXES
- Corrected the Hebrew holidays Tzom Gedalia, Tzom Tevet, Ta'anit
Esther, Tzom Tamuz and Tisha B'Av so they won't occur on Saturday.
Corrections made following the algorithm in "Calendrical Calculations"
by Nachum Dershowitz and Edward M. Reingold.
- Changed the dutch.h language file as suggested by Erik-Jan Vens. Made
month and day names lower-case; corrected the spelling of oktober.
- Changed HashVal in var.c to use unsigned arithmetic - it's conceivable
that a machine with signed chars could cause problems otherwise.
- Changed the LONG_* macros in config.h to LON_* to avoid conflicts
with names defined by ANSI C. Thanks to David W. Sanderson.
- Allowed the built-in function char() to accept numbers in the
range [-128, 255] (but not 0) so that char(asc(s)) works even
on machines with signed char types.
* Version 3.0 Patch 7
+ MAJOR ENHANCEMENTS
- Added "system variables" to allow the user more control over
Remind operation, and to allow queries about the command-line
options from within a reminder script. They allow for specification
of longitude and latitude for use by sunrise/sunset calculations.
- Added sunrise(), sunset(), isdst() and minsfromutc() functions -
these are needed to support sunrise and sunset calculations.
+ MINOR ENHANCEMENTS
- Allowed the MSG, RUN, CAL, PS and PSF keywords to be used in the
same reminder as the SATISFY keyword. This makes many complex
reminders more compact.
- Added the filedir() function to enable Remind's include to emulate
CPP's #include more closely.
- Allowed non-root users to use the "-u" option. It only affects
the "SHELL", "HOME", "USER" and "LOGNAME" environment variables -
it doesn't change the effective uid and gid when run by non-root.
- Added built-in function "easterdate" to calculate date of Easter
Sunday - function courtesy of Michael Salmon.
- Improved the Jewish holiday reminders in "defs.rem" to give advance
notice of holidays.
- Allowed the "simple calendar" option (-s) to specify a number of
weeks as well as a number of months, in the same fashion as the
-c option. Thanks to Dave Rickel.
+ BUG FIXES
- Corrected the behaviour of "hebdate" for jahrzeits; added an additional
parameter to specify the behaviour of dates in Adar during leap years.
- Changed kall so that "kall sh" doesn't commit suicide - patch courtesy
of Michael Salmon.
* Version 3.0 Patch 6
+ MINOR ENHANCEMENTS
- Added the PS- and PSFILE-type reminders - these allow you to include
arbitrary PostScript code in your PostScript calendars. Useful for
shading, drawing graphics on calendars, etc. Use with care, though!
- Added the "-ivar=val" option to initialize variables from the command
line. Changed the remind-all.* shell scripts to predefine the variable
"remind_all".
+ BUG FIXES
- Fixed a bug in the hebmon(), hebday() and hebyear() functions - there
was an off-by-one error. Sorry!
- Fixed a bug in the hebdate() function which resulted in infinite loops
for dates after about 2075
- Fixed a bug in the -u option which sometimes caused a core dump
(embarrassed grin!) The fix is due to Tina Hoeltig. Thanks, Tina!
* Version 3.0 Patch 5
+ MAJOR ENHANCEMENTS:
- Added support for the Hebrew calendar - can now specify Jewish holidays
easily. Thanks to Amos Shapir for explaining the Hebrew calendar, and
to Danny Sadinoff, from whose HEBCAL program I got some inspiration.
Also thanks to David W. Tamkin and Frank Yellin for explaining the rules
for jahrzeits.
+ MINOR ENHANCEMENTS:
- Allowed the default page size used by Rem2PS to be selected in config.h
- Edited the defs.rem file to contain Jewish holidays. Cleaned up some
of the examples and improved the layout - thanks to George M. Sipe.
- Modified the IIF function to be more general
- Updated finnish.h to support the ISO 8859-1 character set, courtesy
of Mikko Silvonen.
- Changed the date conversion routines to greatly speed up conversion from
Julian to yyyy/mm/dd form.
+ BUG FIXES:
- Fixed a bug in which Remind complained incorrectly about a missing quote
in the command SET foo ""
- Fixed bugs in dosubst.c which caused the %o, %1 and %@ substitutions
to be incorrect
- Fixed a bug in the man page - thanks to Ed Oskiewicz.
* Version 3.0 Patch 4
- Added the -g option - this sorts reminders by date/time before
issuing them. (You can see I'm running out of letters to
name options!) This feature was suggested by George M. Sipe,
Paul D. Smith, and Francois Pinard.
- Added the "args()" and "dosubst()" built-in functions - see the
man page for details.
- Added more support for the ISO 8859-1 character set, and
modified the german.h file to take advantage of this, thanks
to Robert Joop.
- Allowed any character to be used as date and time separator
characters (not just "/-:.")
- Added support for the Dutch and Finnish languages, thanks to
Willem Kasdorp and Mikko Silvonen. (Anyone care to contribute
French? Italian? Spanish?)
- Made Remind issue a warning if you try to redefine a built-in
function. This warning is disabled in 'Hush' mode.
- Added the SCANFROM clause to the REM command. This allows reasonably
safe moveable OMITs such as the Labour Day example in the manual.
- Added more examples to the defs.rem file, and cleaned up some old
examples. Note that there are now safe moveable holidays for most
U.S. holidays provided in the defs.rem file.
- Added the '-k' option, which allows MSG-type reminders to be passed
to any system command. (Idea and patch courtesy of Philipp Slusallek.)
- Allowed selection of ':' or '.' as time separator characters at
compile-time.
- Edited the COPYRIGHT file to clarify the rules. Please read them.
- Removed hard-coding of "am" and "pm" and placed them in language-specific
header files as #defines L_AM and L_PM
- Fixed a bug in the FindToken() routine which had, through sheer luck,
never been activated until the SCANFROM clause was added!
- Fixed the UNTIL clause to check for a valid expiry date.
- Removed identifiers in the C source beginning with "_" to conform
to ANSI practice.
- Fixed a bug in the -u option which resulted in environment variables
SHELL and USER not being set correctly. Also made -u set the LOGNAME
environment variable.
- Fixed a couple of typos in the man page; added LDFLAGS to the
Makefile. (Thanks to Dave Wolfe.)
- Put my new mailing address in the README files.
* Version 3.0 Patch 3
- Corrected bugs in Remind and Rem2PS. No new features added. You
should NOT use patch level 2 - either stick to 3.0.1 or upgrade to
3.0.3.
* Version 3.0 Patch 2
- Added the -u option to Remind so that root can run it as any user.
This simplifies the remind-all scripts, and makes them more efficient.
If you are worried that this option is a security hole, you can
disable it in config.h
- Changed the RUN command so that RUN OFF can be used anywhere, even
though RUN ON only works in the top-level file. This eases the
management of global files which may want to switch RUN OFF.
- Added ISO encoding (ISO 8859-1) to the PostScript output, courtesy of
Michael Salmon. This can be selected with the '-i' option in rem2ps.
- Added support for the '-' date separator as well as the '/' separator.
- Added support for languages other than English. Note that this support
is not complete - error messages are still in English. The idea and
German translation came from Wolfgang Thronicke.
- Changed the -w option to include the "padding" and "spacing" options.
NOTE INCOMPATIBILITY: In the previous patch level, creating a weekly
calendar using the -c+n option left no blank lines between the day
number and the first reminder entry. This has been changed so that one
blank line is left. To revert to the old behaviour, use the "-w,,0"
option.
- Added the -o option to Rem2ps. This allows you to specify the margins
when producing a PostScript calendar.
- Updated the copyright notices in all the files. :-)
- Added 'make clobber' and 'make test' targets to the Unix makefile.
- Corrected typos in WHATSNEW.30 and remind.1 man page. Thanks to
Dave Wolfe <dwolfe@pffft.sps.mot.com>
- Changed Remind so that supplying the -a option causes timed reminders
not to be placed into the calendar in calendar mode.
* Version 3.0 Patch 1
- Wrote the Rem2ps program to produce PostScript calendars
- Added an 'install' target to the Makefile
- Fixed a bug which allowed the shell() function to execute in timed
reminders which were queued with RUN disabled.
- Added support for OS/2, courtesy of DARREL HANKERSON
<HANK@DUCVAX.AUBURN.EDU>
- In expressions, can now specify literal dates as 'yyyy/mm/dd' rather than
using the date() function.
- Fixed all the source files to include "config.h" first.
- Changed the way triggers are calculated so that trigger dates are
always valid if year, month and day are specified, and there is no
UNTIL clause. See MAN page section "DETAILS ABOUT TRIGVALID()."
- Defined _POSIX_SOURCE so Remind will compile on SGI workstations (and
be more portable... I hope.)
- Fixed some rather brain-dead definitions of UPPER and LOWER, as pointed
out by <rsalz@osf.org>
- Added more details to the Man page concerning how triggers are computed,
and added warnings about computing OMIT dates.
- Added the file defs.rem which contains examples of useful definitions and
triggers.
- Changed the script test-rem to be a sh script instead of csh for improved
portability.
- Fixed up the README.* files to reflect the changes.
- Re-formatted the WHATSNEW.30 file.
* Version 3.0
- Total rewrite from previous versions
- Added variables, expressions, flow-control statements, daemon mode
- Added "expression pasting"
- Added CAL-type reminders
- Added the SATISFY clause
- Improved debugging of reminder scripts
- Took out the "purge" option - it is in general too dificult to tell when
a reminder has expired for good, so now it's up to you to do this
by hand.
- Fixed a lurking bug in trigger date calculation which, amazingly, had not
been caught in the couple of years that Remind has been out!
* Version 2.3 Patch 5
- Added the "c+n" option for printing a calendar by
weeks instead of months, courtesy Dennis Cottel (dennis@peanuts.nosc.mil).
* Version 2.3 Patch 4
- Made the init.c file nicer. Made the Makefile
prettier. Added "make test", "make tar" and "make shar" Makefile targets.
* Version 2.3 Patch 3
- Added a command-line option for Remind to process
queued reminders in the foreground. This makes automatic termination
of Remind processes from within X-Windows and Sunview easier.
* Version 2.3 Patch 2
- Fixed up a problem with timed reminders which resulted
in cursor not starting from left side of screen on some systems.
- Fixed the SIGINT handler for SYSV systems - this was interrupting the
sleep(2) system call.
- Closed stdin and stdout if remind was part of a pipe - this prevents other
sections of the pipe from hanging as remind puts itself in the background.
- Added the "-h" (Hush mode) option
- Added the "%#" and "%@" modifiers for the current time.
- Made the Makefile more portable
* Version 2.3 Patch 1
- Added the "-t" command-line option to get Remind
to trigger all non-expired reminders.
- Added Turbo C support courtesy of Rhys Weatherly
- Added the "RUN ON" and "RUN OFF" commands for a secure interface with
the Elm mail system.
- Added the "rem" shell script for running Remind with a default script.
- Added manual pages for "kall" and "rem".
* Version 2.3
- Added the UNTIL keyword for forcing reminders to expire.
- Added the "++" form of 'back' and the "--" form of 'delta' for
ignoring OMIT information.
- Added the CLEAR-OMIT-CONTEXT, PUSH-OMIT-CONTEXT and POP-OMIT-CONTEXT
keywords for isolating personal or peculiar reminders from the global
OMIT context.
- Speeded up the parsing of tokens.
- Changed the source to recognize and exploit ANSI-C compilers which
accept function prototypes.
- Added the "-n" option to output the next occurrence of each reminder
in SimpleCalendar format
- Modified the calendar and SimpleCalendar formats so that the % escape
substitutions ARE performed.
* Version 2.2 - Patch 5
- Added the BEFORE, AFTER and SKIP tokens to make the
handling of holidays more sensible. Also corrected a few more bugs.
* Version 2.2 - Patch 3
- Added the MSG or RUN tokens in an OMIT command; also
allowed RUN-type reminders to be explicitly included in the calendar by
using the %" escape sequence.
* Version 2.2
- Added the AT keyword, the timed reminders daemon, and the
calendar facility.
* Version 2.1
- Added the "repeat" token for repeating reminders with a period
other than 7 days. Also fixed some bugs from version 2.0
* Version 2.0
- first public release. Included advanced date specifications,
character substitution, and the RUN keyword.
* Version 1.0
- never publicly released.

924
calendar.c Normal file
View File

@@ -0,0 +1,924 @@
/***************************************************************/
/* */
/* CALENDAR.C */
/* */
/* The code for generating a calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: calendar.c,v 1.1 1996-03-27 03:25:50 dfs Exp $";
#include "config.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include "types.h"
#include "protos.h"
#include "expr.h"
#include "globals.h"
#include "err.h"
/* Data structures used by the calendar */
typedef struct cal_entry {
struct cal_entry *next;
char *text;
char *pos;
int time;
int priority;
} CalEntry;
/* Global variables */
static CalEntry *CalColumn[7];
static CalEntry *CalPs[7];
static int ColSpaces;
PRIVATE void SortCol ARGS((CalEntry **col));
PRIVATE void DoCalendarOneWeek ARGS ((void));
PRIVATE void DoCalendarOneMonth ARGS ((void));
PRIVATE int WriteCalendarRow ARGS ((void));
PRIVATE void PrintLeft ARGS ((char *s, int width, char pad));
PRIVATE void PrintCentered ARGS ((char *s, int width, char pad));
PRIVATE int WriteOneCalLine ARGS ((void));
PRIVATE int WriteOneColLine ARGS ((int col));
PRIVATE void GenerateCalEntries ARGS ((int col));
PRIVATE void WriteCalHeader ARGS ((void));
PRIVATE void WriteCalTrailer ARGS ((void));
PRIVATE int DoCalRem ARGS ((ParsePtr p, int col));
PRIVATE void WriteSimpleEntries ARGS ((int col, int jul));
PRIVATE void WriteSolidCalLine ARGS ((void));
PRIVATE void WriteIntermediateCalLine ARGS ((void));
PRIVATE void WriteCalDays ARGS ((void));
/***************************************************************/
/* */
/* ProduceCalendar */
/* */
/* Main loop for generating a calendar. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void ProduceCalendar(void)
#else
void ProduceCalendar()
#endif
{
int y, m, d;
ShouldCache = 1;
ColSpaces = (CalWidth - 9) / 7;
CalWidth = 7*ColSpaces + 8;
if (CalMonths) {
FromJulian(JulianToday, &y, &m, &d);
JulianToday = Julian(y, m, 1);
while (CalMonths--)
DoCalendarOneMonth();
return;
} else {
if (MondayFirst) JulianToday -= (JulianToday%7);
else JulianToday -= ((JulianToday+1)%7);
if (!DoSimpleCalendar) {
WriteIntermediateCalLine();
WriteCalDays();
WriteIntermediateCalLine();
}
while (CalWeeks--)
DoCalendarOneWeek();
return;
}
}
/***************************************************************/
/* */
/* DoCalendarOneWeek */
/* */
/* Write a calendar for a single week */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DoCalendarOneWeek(void)
#else
static void DoCalendarOneWeek()
#endif
{
int y, m, d, done, i, l, wd;
char buf[81];
int LinesWritten = 0;
int OrigJul = JulianToday;
/* Fill in the column entries */
for (i=0; i<7; i++) {
GenerateCalEntries(i);
JulianToday++;
}
/* Output the entries */
/* If it's "Simple Calendar" format, do it simply... */
if (DoSimpleCalendar) {
if (MondayFirst) wd = JulianToday % 7;
else wd = (JulianToday + 1) % 7;
for (i=0; i<7; i++) {
WriteSimpleEntries(i, OrigJul+i-wd);
}
return;
}
/* Here come the first few lines... */
putchar('|');
for (i=0; i<7; i++) {
FromJulian(OrigJul+i, &y, &m, &d);
sprintf(buf, "%d %c%c%c ", d, MonthName[m][0], MonthName[m][1],
MonthName[m][2]);
if (OrigJul+i == RealToday)
PrintLeft(buf, ColSpaces, '*');
else
PrintLeft(buf, ColSpaces, ' ');
putchar('|');
}
putchar('\n');
for (l=0; l<CalPad; l++) {
putchar('|');
for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' ');
putchar('|');
}
putchar('\n');
}
/* Write the body lines */
done = 0;
while (!done) {
done = WriteOneCalLine();
LinesWritten++;
}
/* Write any blank lines required */
while (LinesWritten++ < CalLines) {
putchar('|');
for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' ');
putchar('|');
}
putchar('\n');
}
/* Write the final line */
WriteIntermediateCalLine();
}
/***************************************************************/
/* */
/* DoCalendarOneMonth */
/* */
/* Produce a calendar for the current month. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DoCalendarOneMonth(void)
#else
static void DoCalendarOneMonth()
#endif
{
int y, m, d, mm, yy;
if (!DoSimpleCalendar) WriteCalHeader();
if (PsCal) {
FromJulian(JulianToday, &y, &m, &d);
printf("%s\n", PSBEGIN);
printf("%s %d %d %d\n",
MonthName[m], y, DaysInMonth(m, y), (JulianToday+1) % 7);
mm = m-1;
if (mm<0) {
mm = 11; yy = y-1;
} else yy=y;
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
mm = m+1;
if (mm>11) {
mm = 0; yy = y+1;
} else yy=y;
printf("%s %d\n", MonthName[mm], DaysInMonth(mm,yy));
}
while (WriteCalendarRow()) continue;
if (PsCal) printf("%s\n", PSEND);
if (!DoSimpleCalendar) WriteCalTrailer();
}
/***************************************************************/
/* */
/* WriteCalendarRow */
/* */
/* Write one row of the calendar */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int WriteCalendarRow(void)
#else
static int WriteCalendarRow()
#endif
{
int y, m, d, wd, i, l;
int done;
char buf[81];
int OrigJul = JulianToday;
int LinesWritten = 0;
/* Get the date of the first day */
FromJulian(JulianToday, &y, &m, &d);
if (!MondayFirst) wd = (JulianToday + 1) % 7;
else wd = JulianToday % 7;
/* Fill in the column entries */
for (i=wd; i<7; i++) {
if (d+i-wd > DaysInMonth(m, y)) break;
GenerateCalEntries(i);
JulianToday++;
}
/* Output the entries */
/* If it's "Simple Calendar" format, do it simply... */
if (DoSimpleCalendar) {
for (i=wd; i<7 && d+i-wd<=DaysInMonth(m, y); i++) {
WriteSimpleEntries(i, OrigJul+i-wd);
}
return (d+7-wd <= DaysInMonth(m, y));
}
/* Here come the first few lines... */
putchar('|');
for (i=0; i<7; i++) {
if (i < wd || d+i-wd>DaysInMonth(m, y))
PrintLeft("", ColSpaces, ' ');
else {
sprintf(buf, "%d", d+i-wd);
PrintLeft(buf, ColSpaces, ' ');
}
putchar('|');
}
putchar('\n');
for (l=0; l<CalPad; l++) {
putchar('|');
for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' ');
putchar('|');
}
putchar('\n');
}
/* Write the body lines */
done = 0;
while (!done) {
done = WriteOneCalLine();
LinesWritten++;
}
/* Write any blank lines required */
while (LinesWritten++ < CalLines) {
putchar('|');
for (i=0; i<7; i++) {
PrintLeft("", ColSpaces, ' ');
putchar('|');
}
putchar('\n');
}
WriteIntermediateCalLine();
/* Return non-zero if we have not yet finished */
return (d+7-wd <= DaysInMonth(m, y));
}
/***************************************************************/
/* */
/* PrintLeft */
/* */
/* Left-justify a piece of text. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void PrintLeft(char *s, int width, char pad)
#else
static void PrintLeft(s, width, pad)
char *s;
int width;
char pad;
#endif
{
int len = strlen(s);
printf("%s", s);
while (len++ < width) putchar(pad);
}
/***************************************************************/
/* */
/* PrintCentered */
/* */
/* Center a piec of text */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void PrintCentered(char *s, int width, char pad)
#else
static void PrintCentered(s, width, pad)
char *s;
int width;
char pad;
#endif
{
int len = strlen(s);
int d = (width - len) / 2;
int i;
for (i=0; i<d; i++) putchar(pad);
for (i=0; i<width; i++) {
if (*s) putchar(*s++); else break;
}
for (i=d+len; i<width; i++) putchar(pad);
}
/***************************************************************/
/* */
/* WriteOneCalLine */
/* */
/* Write a single line. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int WriteOneCalLine(void)
#else
static int WriteOneCalLine()
#endif
{
int done = 1, i;
putchar('|');
for (i=0; i<7; i++) {
if (CalColumn[i]) {
if (WriteOneColLine(i)) done = 0;
} else {
PrintCentered("", ColSpaces, ' ');
}
putchar('|');
}
putchar('\n');
return done;
}
/***************************************************************/
/* */
/* WriteOneColLine */
/* */
/* Write a single line for a specified column. Return 1 if */
/* the column still has entries; 0 otherwise. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int WriteOneColLine(int col)
#else
static int WriteOneColLine(col)
int col;
#endif
{
CalEntry *e = CalColumn[col];
char *s;
char *space;
int numwritten = 0;
/* Print as many characters as possible within the column */
space = NULL;
s = e->pos;
/* If we're at the end, and there's another entry, do a blank line and move
to next entry. */
if (!*s && e->next) {
PrintLeft("", ColSpaces, ' ');
CalColumn[col] = e->next;
free(e->text);
free(e);
return 1;
}
/* Find the last space char within the column. */
while (s - e->pos <= ColSpaces) {
if (!*s) {space = s; break;}
if (*s == ' ') space = s;
s++;
}
/* If we couldn't find a space char, print what we have. */
if (!space) {
for (s = e->pos; s - e->pos < ColSpaces; s++) {
if (!*s) break;
numwritten++;
putchar(*s);
}
e->pos = s;
} else {
/* We found a space - print everything before it. */
for (s = e->pos; s<space; s++) {
if (!*s) break;
numwritten++;
putchar(*s);
}
}
/* Flesh out the rest of the column */
while(numwritten++ < ColSpaces) putchar(' ');
/* Skip any spaces before next word */
while (*s == ' ') s++;
/* If done, free memory if no next entry. */
if (!*s && !e->next) {
CalColumn[col] = e->next;
free(e->text);
free(e);
} else {
e->pos = s;
}
if (CalColumn[col]) return 1; else return 0;
}
/***************************************************************/
/* */
/* GenerateCalEntries */
/* */
/* Generate the calendar entries for the ith column */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void GenerateCalEntries(int col)
#else
static void GenerateCalEntries(col)
int col;
#endif
{
int r;
Token tok;
char *s;
Parser p;
/* Do some initialization first... */
ClearGlobalOmits();
DestroyOmitContexts();
DestroyVars(0);
NumTriggered = 0;
r=OpenFile(InitialFile);
if (r) {
fprintf(ErrFp, "%s %s: %s\n", ErrMsg[E_ERR_READING], InitialFile, ErrMsg[r]);
exit(1);
}
while(1) {
r = ReadLine();
if (r == E_EOF) return;
if (r) {
Eprint("%s: %s", ErrMsg[E_ERR_READING], ErrMsg[r]);
exit(1);
}
s = FindInitialToken(&tok, CurLine);
/* Should we ignore it? */
if (NumIfs &&
tok.type != T_If &&
tok.type != T_Else &&
tok.type != T_EndIf &&
tok.type != T_IfTrig &&
ShouldIgnoreLine())
{
/* DO NOTHING */
}
else {
/* Create a parser to parse the line */
CreateParser(s, &p);
switch(tok.type) {
case T_Empty:
case T_Comment:
break;
case T_ErrMsg: r=DoErrMsg(&p); break;
case T_Rem: r=DoCalRem(&p, col); break;
case T_If: r=DoIf(&p); break;
case T_IfTrig: r=DoIfTrig(&p); break;
case T_Else: r=DoElse(&p); break;
case T_EndIf: r=DoEndif(&p); break;
case T_Include: r=DoInclude(&p); break;
case T_Exit: DoExit(&p); break;
case T_Set: r=DoSet(&p); break;
case T_Fset: r=DoFset(&p); break;
case T_UnSet: r=DoUnset(&p); break;
case T_Clr: r=DoClear(&p); break;
case T_Flush: r=DoFlush(&p); break;
case T_Debug: break; /* IGNORE DEBUG CMD */
case T_Dumpvars: break; /* IGNORE DUMPVARS CMD */
case T_Banner: break; /* IGNORE BANNER CMD */
case T_Omit: r=DoOmit(&p);
if (r == E_PARSE_AS_REM) {
DestroyParser(&p);
CreateParser(s, &p);
r=DoCalRem(&p, col);
}
break;
case T_Pop: r=PopOmitContext(&p); break;
case T_Push: r=PushOmitContext(&p); break;
case T_Preserve: r=DoPreserve(&p); break;
case T_RemType: if (tok.val == RUN_TYPE) {
r=DoRun(&p);
break;
} else {
CreateParser(CurLine, &p);
r=DoCalRem(&p, col);
break;
}
/* If we don't recognize the command, do a REM by default */
/* Note: Since the parser hasn't been used yet, we don't */
/* need to destroy it here. */
default: CreateParser(CurLine, &p);
r=DoCalRem(&p, col);
break;
}
if (r && (!Hush || r != E_RUN_DISABLED)) Eprint("%s", ErrMsg[r]);
/* Destroy the parser - free up resources it may be tying up */
DestroyParser(&p);
}
}
}
/***************************************************************/
/* */
/* WriteCalHeader */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void WriteCalHeader(void)
#else
static void WriteCalHeader()
#endif
{
char buf[80];
int y, m, d;
FromJulian(JulianToday, &y, &m, &d);
sprintf(buf, "%s %d", MonthName[m], y);
WriteSolidCalLine();
putchar('|');
PrintCentered(buf, CalWidth-2, ' ');
putchar('|');
putchar('\n');
WriteIntermediateCalLine();
WriteCalDays();
WriteIntermediateCalLine();
}
/***************************************************************/
/* */
/* WriteCalTrailer */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void WriteCalTrailer(void)
#else
static void WriteCalTrailer()
#endif
{
putchar('\f');
}
/***************************************************************/
/* */
/* DoCalRem */
/* */
/* Do the REM command in the context of a calendar. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int DoCalRem(ParsePtr p, int col)
#else
static int DoCalRem(p, col)
ParsePtr p;
int col;
#endif
{
Trigger trig;
TimeTrig tim;
Value v;
int r;
int jul;
CalEntry *CurCol = CalColumn[col];
CalEntry *CurPs = CalPs[col];
CalEntry *e;
char *s, *s2;
static char buf[TOKSIZE];
static char obuf[LINELEN];
Token tok;
/* Parse the trigger date and time */
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
/* Don't include timed reminders in calendar if -a option supplied. */
#ifdef HAVE_QUEUED
if (DontIssueAts && tim.ttime != NO_TIME) return OK;
#endif
if (trig.typ == NO_TYPE) return E_EOLN;
if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, &tim, p);
if (r) return r;
r=ParseToken(p, buf);
if (r) return r;
FindToken(buf, &tok);
if (tok.type == T_Empty || tok.type == T_Comment) return OK;
if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR;
trig.typ = tok.val;
jul = LastTriggerDate;
if (!LastTrigValid) return OK;
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
if (r) return r;
}
if (!PsCal && (trig.typ == PS_TYPE || trig.typ == PSF_TYPE)) return OK;
/* Remove any "at" times from PS or PSFILE reminders */
if (trig.typ == PS_TYPE || trig.typ == PSF_TYPE) tim.ttime = NO_TIME;
/* If trigger date == today, add it to the current entry */
if (jul == JulianToday) {
NumTriggered++;
s = obuf;
*s = 0;
if (DoSimpleCalendar || tim.ttime != NO_TIME)
s += strlen(SimpleTime(tim.ttime, s));
if (trig.typ != PS_TYPE && trig.typ != PSF_TYPE &&
UserFuncExists("calprefix")==1) {
sprintf(buf, "calprefix(%d)", trig.priority);
s2 = buf;
r = EvalExpr(&s2, &v);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
strcat(s, v.v.str);
s += strlen(s);
}
DestroyValue(v);
}
}
if ( (r=DoSubst(p, s, &trig, &tim, jul, CAL_MODE)) ) return r;
if (!*s) return OK;
if (trig.typ != PS_TYPE && trig.typ != PSF_TYPE &&
UserFuncExists("calsuffix")==1) {
sprintf(buf, "calsuffix(%d)", trig.priority);
s2 = buf;
r = EvalExpr(&s2, &v);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
strcat(s, v.v.str);
s += strlen(s);
}
DestroyValue(v);
}
}
s = obuf;
if (!DoSimpleCalendar) while (isspace(*s)) s++;
e = NEW(CalEntry);
if (!e) return E_NO_MEM;
e->text = StrDup(s);
if (!e->text) {
free(e);
return E_NO_MEM;
}
e->priority = trig.priority;
if (trig.typ == PS_TYPE || trig.typ == PSF_TYPE) {
e->pos = (trig.typ == PS_TYPE) ? "P" : "F";
e->time = NO_TIME;
e->next = CurPs;
CalPs[col] = e;
SortCol(&CalPs[col]);
} else {
e->pos = e->text;
e->time = tim.ttime;
e->next = CurCol;
CalColumn[col] = e;
SortCol(&CalColumn[col]);
}
}
return OK;
}
/***************************************************************/
/* */
/* WriteSimpleEntries */
/* */
/* Write entries in 'simple calendar' format. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void WriteSimpleEntries(int col, int jul)
#else
static void WriteSimpleEntries(col, jul)
int col, jul;
#endif
{
CalEntry *e = CalPs[col];
CalEntry *n;
int y, m, d;
/* Do all the PostScript entries first, if any */
FromJulian(jul, &y, &m, &d);
while(e) {
printf("%c%c%c%c%c%02d%c%02d ", *(e->pos), *(e->pos),
*(e->pos), *(e->pos), DATESEP,
m+1, DATESEP, d);
printf("%s\n", e->text);
free(e->text);
n = e->next;
free(e);
e = n;
}
CalPs[col] = NULL;
e = CalColumn[col];
while(e) {
printf("%04d%c%02d%c%02d ", y, DATESEP, m+1, DATESEP, d);
printf("%s\n", e->text);
free(e->text);
n = e->next;
free(e);
e = n;
}
CalColumn[col] = NULL;
}
/***************************************************************/
/* */
/* Various functions for writing different types of lines. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void WriteSolidCalLine(void)
#else
static void WriteSolidCalLine()
#endif
{
putchar('+');
PrintCentered("", CalWidth-2, '-');
putchar('+');
putchar('\n');
}
#ifdef HAVE_PROTOS
PRIVATE void WriteIntermediateCalLine(void)
#else
static void WriteIntermediateCalLine()
#endif
{
int i;
putchar('+');
for (i=0; i<7; i++) {
PrintCentered("", ColSpaces, '-');
putchar('+');
}
putchar('\n');
}
#ifdef HAVE_PROTOS
PRIVATE void WriteCalDays(void)
#else
static void WriteCalDays()
#endif
{
int i;
putchar('|');
for (i=0; i<7; i++) {
if (!MondayFirst)
PrintCentered(DayName[(i+6)%7], ColSpaces, ' ');
else
PrintCentered(DayName[i%7], ColSpaces, ' ');
putchar('|');
}
putchar('\n');
}
/***************************************************************/
/* */
/* SimpleTime */
/* */
/* Format the time according to simple time format. */
/* If out is NULL, result placed in internal static buffer. */
/* A trailing space is always added. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *SimpleTime(int tim, char *out)
#else
char *SimpleTime(tim, out)
int tim;
char *out;
#endif
{
static buf[9];
int h, min, hh;
if (!out) out = (char *) buf;
*out = 0;
switch(ScFormat) {
case SC_AMPM:
if (tim == NO_TIME) sprintf(out, " ");
else {
h = tim / 60;
min = tim % 60;
if (h == 0) hh=12;
else if (h > 12) hh=h-12;
else hh=h;
sprintf(out, "%2d%c%02d%s ", hh, TIMESEP, min, (h>=12) ? L_PM : L_AM);
}
break;
case SC_MIL:
if (tim == NO_TIME) sprintf(out, " ");
else {
h = tim / 60;
min = tim % 60;
sprintf(out, "%02d%c%02d ", h, TIMESEP, min);
}
break;
}
return out;
}
/***************************************************************/
/* */
/* SortCol */
/* */
/* Sort the calendar entries in a column by time and priority */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void SortCol(CalEntry **col)
#else
static void SortCol(col)
CalEntry **col;
#endif
{
CalEntry *cur, *prev, *next;
cur = *col;
prev = NULL;
/* Note that we use <= comparison rather than > comparison to preserve the
file order of reminders which have the same time and priority */
while (cur->next &&
CompareRems(0, cur->time, cur->priority,
0, cur->next->time, cur->next->priority,
SortByDate, SortByTime, SortByPrio) <= 0) {
next = cur->next;
/* Swap cur and next */
if (!prev) {
*col = next;
cur->next = next->next;
next->next = cur;
prev = next;
} else {
prev->next = next;
cur->next = next->next;
next->next = cur;
prev = next;
}
}
}

263
config.h Normal file
View File

@@ -0,0 +1,263 @@
/***************************************************************/
/* */
/* CONFIG.H */
/* */
/* Contains various configuration parameters for Remind. */
/* You may have to edit this file to tweak parameters or take */
/* care of certain system dependencies. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: config.h,v 1.1 1996-03-27 03:25:50 dfs Exp $ */
/*---------------------------------------------------------------------*/
/* LAT_DEG, LAT_MIN and LAT_SEC: Latitude of your location */
/* LON_DEG, LON_MIN and LON_SEC: Longitude of your location */
/* LOCATION: A string identifying your location. */
/* For latitude, north is positive, south is negative. */
/* For longitude, west is positive, east is negative. */
/* NOTE: For negative numbers, all three of DEG, MIN, SEC should be */
/* negative. To indicate -20deg22'33" use */
/* DEG=-20, MIN=-22 and SEC=-33. */
/* The default values are initially set to Ottawa, Ontario, Canada. */
/*---------------------------------------------------------------------*/
#define LAT_DEG 45
#define LAT_MIN 24
#define LAT_SEC 0
#define LON_DEG 75
#define LON_MIN 39
#define LON_SEC 0
#define LOCATION "Ottawa"
/*---------------------------------------------------------------------*/
/* HAVE_MKTIME: Define this if your C library includes the mktime() */
/* function. Otherwise, will attempt to use the Unix */
/* style time manipulations. */
/*---------------------------------------------------------------------*/
#define HAVE_MKTIME 1
/*---------------------------------------------------------------------*/
/* NEED_TIMEGM: If your C library does not have mktime() and it ALSO */
/* does not have timelocal() or timegm(), uncomment the */
/* next line. If HAVE_MKTIME is defined, NEED_TIMEGM is */
/* ignored. Very few systems should require NEED_TIMEGM. */
/*---------------------------------------------------------------------*/
/* #define NEED_TIMEGM 1 */
/*---------------------------------------------------------------------*/
/* DEFAULT_PAGE: The default page size to use for Rem2PS. */
/* The Letter version is appropriate for North America; the A4 version */
/* is appropriate for Europe. */
/*---------------------------------------------------------------------*/
#define DEFAULT_PAGE {"Letter", 612, 792}
/* #define DEFAULT_PAGE {"A4", 595, 842} */
/*---------------------------------------------------------------------*/
/* DATESEP: The default date separator. North American usage is '/'; */
/* others may prefer '-'. */
/*---------------------------------------------------------------------*/
#define DATESEP '/'
/* #define DATESEP '-' */
/*---------------------------------------------------------------------*/
/* TIMESEP: The default time separator. North American usage is ':'; */
/* others may prefer '.'. */
/*---------------------------------------------------------------------*/
#define TIMESEP ':'
/* #define TIMESEP '.' */
/*---------------------------------------------------------------------*/
/* ISOLATIN1: uncomment the following line if your system uses the */
/* ISO 8859-1 character set instead of ASCII. */
/*---------------------------------------------------------------------*/
/* #define ISOLATIN1 1 */
/*---------------------------------------------------------------------*/
/* IBMEXTENDED: uncomment the following line if you want to use the */
/* IBM extended character set. NOT ALL LANGUAGE MODULES SUPPORT THIS. */
/* Note that at most one of ISOLATIN1 or IBMEXTENDED should be */
/* defined; if both are defined, the results are unspecified. */
/*---------------------------------------------------------------------*/
/* #define IBMEXTENDED 1 */
/*---------------------------------------------------------------------*/
/* WANT_U_OPTION: Comment out the next define to permanently disable */
/* the -u option. If you do this, however, remind-all.[c]sh will not */
/* work. */
/*---------------------------------------------------------------------*/
#define WANT_U_OPTION 1
/*---------------------------------------------------------------------*/
/* WANT_SHELL_ESCAPING: Define this if you want special shell */
/* characters to be escaped with a backslash for the -k option. */
/*---------------------------------------------------------------------*/
#if defined(UNIX)
#define WANT_SHELL_ESCAPING 1
#endif
/*---------------------------------------------------------------------*/
/* STRSTR: If your system does not have the "strstr" function, */
/* uncomment the following line. */
/*---------------------------------------------------------------------*/
/* #define NO_STRSTR 1 */
/*---------------------------------------------------------------------*/
/* STDLIB: If you don't have the <stdlib.h> header file, comment the */
/* following line. */
/*---------------------------------------------------------------------*/
#define HAVE_STDLIB_H 1
/*---------------------------------------------------------------------*/
/* MALLOC: If you do not have the <malloc.h> header file, */
/* comment out the next 3 lines. */
/*---------------------------------------------------------------------*/
#ifdef UNIX
#define HAVE_MALLOC_H 1
#endif
/*---------------------------------------------------------------------*/
/* BASE: The base year for date calculation. NOTE! January 1 of the */
/* base year MUST be a Monday, else Remind will not work! */
/* IMPORTANT NOTE: The Hebrew date routines depend on BASE */
/* being set to 1990. If you change it, you'll have to add the */
/* number of days between 1 Jan <NEWBASE> and 1 Jan 1990 to the */
/* manifest constant CORRECTION in hbcal.c. Also, the year */
/* folding mechanism in main.c depends on BASE<2001. */
/*---------------------------------------------------------------------*/
#define BASE 1990
/*---------------------------------------------------------------------*/
/* YR_RANGE: The range of years allowed. Computers with 16-bit */
/* integers can handle about 89 years worth of reminders; if */
/* you use 32-bit integers, you can handle over 5 867 000 */
/* years. Note that YR_RANGE is set to 88 rather than 89 */
/* because we can range up to the last day of the 88th year. */
/*---------------------------------------------------------------------*/
#define YR_RANGE 88
/*---------------------------------------------------------------------*/
/* VAR_NAME_LEN: The maximum length of variable names. Don't make it */
/* any less than 12. */
/*---------------------------------------------------------------------*/
#define VAR_NAME_LEN 12
/*---------------------------------------------------------------------*/
/* MAX_PRT_LEN: The maximum number of characters to print when */
/* displaying a string value for debugging purposes. */
/*---------------------------------------------------------------------*/
#define MAX_PRT_LEN 40
/*---------------------------------------------------------------------*/
/* LINELEN: The maximum length of an input line */
/*---------------------------------------------------------------------*/
#define LINELEN 512
/*---------------------------------------------------------------------*/
/* OP_STACK_SIZE: The size of the operator stack for expr. parsing */
/*---------------------------------------------------------------------*/
#define OP_STACK_SIZE 30
/*---------------------------------------------------------------------*/
/* VAL_STACK_SIZE: The size of the operand stack for expr. parsing */
/*---------------------------------------------------------------------*/
#define VAL_STACK_SIZE 30
/*---------------------------------------------------------------------*/
/* INCLUDE_NEST: How many nested INCLUDES do we handle? */
/*---------------------------------------------------------------------*/
#define INCLUDE_NEST 8
/*---------------------------------------------------------------------*/
/* IF_NEST: How many nested IFs do we handle? Maximum is the number */
/* of bits in an int, divided by two. Beware! */
/*---------------------------------------------------------------------*/
#define IF_NEST (4*sizeof(unsigned int))
/*---------------------------------------------------------------------*/
/* Do we handle queued reminders? */
/*---------------------------------------------------------------------*/
#if defined(UNIX) || defined(__OS2__)
#define HAVE_QUEUED 1
#endif
/*---------------------------------------------------------------------*/
/* Does our C compiler have prototypes? Override this test if you */
/* are using a non-ANSI compiler that nevertheless has prototypes. */
/*---------------------------------------------------------------------*/
#if defined(__STDC__) || defined(__TURBOC__) || defined(__BORLANDC__)
#define HAVE_PROTOS 1
#endif
/*---------------------------------------------------------------------*/
/* Do we use the <stdarg.h> scheme for functions with variable number */
/* of parameters? If not, the <varargs.h> scheme is assumed. */
/*---------------------------------------------------------------------*/
#if defined(__STDC__) || defined(__TURBOC__) || defined(__BORLANDC__)
#define HAVE_STDARG 1
#endif
/*---------------------------------------------------------------------*/
/* Does the function argument to the signal() function take an INT */
/* argument? If yes, uncomment the next line. If you get it wrong, */
/* the only bad side effect is a compiler warning, so don't worry too */
/* much about it. */
/*---------------------------------------------------------------------*/
/* #define SIGHANDLER_INT_ARG 1 */
/*---------------------------------------------------------------------*/
/* Do we have the <unistd.h> header? If not, use sys/files.h */
/*---------------------------------------------------------------------*/
#ifdef UNIX
#define HAVE_UNISTD 1
#endif
/*---------------------------------------------------------------------*/
/* How many attempts to resolve a weird date spec? */
/*---------------------------------------------------------------------*/
#define TRIG_ATTEMPTS 25
/*---------------------------------------------------------------------*/
/* How many global omits of the form YYYY MM DD do we handle? */
/*---------------------------------------------------------------------*/
#define MAX_FULL_OMITS 75
/*---------------------------------------------------------------------*/
/* How many global omits of the form MM DD do we handle? */
/*---------------------------------------------------------------------*/
#define MAX_PARTIAL_OMITS 75
/*---------------------------------------------------------------------*/
/* The size of statically-allocated buffers for tokens. */
/*---------------------------------------------------------------------*/
#define TOKSIZE 128
/*---------------------------------------------------------------------*/
/* The size of the buffer for the shell() function. */
/*---------------------------------------------------------------------*/
#define SHELLSIZE 512
/*---------------------------------------------------------------------*/
/* A newline - some systems need "\n\r" */
/*---------------------------------------------------------------------*/
#define NL "\n"
/*---------------------------------------------------------------------*/
/* Minimum number of linefeeds in each calendar "box" */
/*---------------------------------------------------------------------*/
#define CAL_LINES 5
/*---------------------------------------------------------------------*/
/* Don't change the next definitions */
/*---------------------------------------------------------------------*/
#define PUBLIC
#define PRIVATE static
#ifdef UNIX
#define _POSIX_SOURCE
#endif
#define PSBEGIN "# rem2ps begin"
#define PSEND "# rem2ps end"

116
danish.h Normal file
View File

@@ -0,0 +1,116 @@
/***************************************************************/
/* */
/* DANISH.H */
/* */
/* Support for the Danish language. */
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1996 by David F. Skoll */
/* This file is Copyright (C) 1993 by Mogens Lynnerup. */
/* */
/***************************************************************/
/* $Id: danish.h,v 1.1 1996-03-27 03:25:51 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "Danish"
/* Day names */
#ifdef ISOLATIN1
# define L_SUNDAY "S\370ndag"
#else
# define L_SUNDAY "Soendag"
#endif
#define L_MONDAY "Mandag"
#define L_TUESDAY "Tirsdag"
#define L_WEDNESDAY "Onsdag"
#define L_THURSDAY "Torsdag"
#define L_FRIDAY "Fredag"
#ifdef ISOLATIN1
# define L_SATURDAY "L\370rdag"
#else
# define L_SATURDAY "Loerdag"
#endif
/* Day initials - first letter only */
#define L_DAYINIT "SMTOTFL"
/* Month names */
#define L_JAN "Januar"
#define L_FEB "Februar"
#define L_MAR "Mars"
#define L_APR "April"
#define L_MAY "Maj"
#define L_JUN "Juni"
#define L_JUL "Juli"
#define L_AUG "August"
#define L_SEP "September"
#define L_OCT "Oktober"
#define L_NOV "November"
#define L_DEC "December"
/* Today and tomorrow */
#define L_TODAY "i dag"
#define L_TOMORROW "i morgen"
/* The default banner */
#ifdef ISOLATIN1
# define L_BANNER "P\345mindelse for %w, %d. %m, %y%o:"
#else
# define L_BANNER "Paamindelse for %w, %d. %m, %y%o:"
#endif
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "siden"
#define L_FROMNOW "fra nu"
/* "in %d days' time" */
#define L_INXDAYS "om %d dage"
/* "on" as in "on date..." */
#ifdef ISOLATIN1
# define L_ON "p\345"
#else
# define L_ON "paa"
#endif
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL "e"
/* Minutes, hours, at, etc */
#define L_NOW "nu"
#define L_AT "kl."
#define L_MINUTE "minut"
#define L_HOUR "time"
#define L_IS "er"
#define L_WAS "var"
#define L_AND "og"
/* What to add to make "hour" plural */
#define L_HPLU "r"
/* What to add to make "minute" plural */
#define L_MPLU "ter"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " om natten" : " om formiddagen" : (hour > 17) ? " om aftenen" : " om eftermiddagen";
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
#define L_E_OVER sprintf(s, "den %02d%c%02d%c%04d", d, DATESEP, m+1, DATESEP, y);
#define L_F_OVER sprintf(s, "den %02d%c%02d%c%04d", m+1, DATESEP, d, DATESEP, y);
#define L_G_OVER sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
#define L_H_OVER sprintf(s, "den %02d%c%02d", d, DATESEP, m+1);
#define L_I_OVER sprintf(s, "den %02d%c%02d", m+1, DATESEP, d);
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER
#endif /* L_IN_DOSUBST */

629
defs.rem Normal file
View File

@@ -0,0 +1,629 @@
#############################################################################
# #
# DEFS.REM #
# #
# This file is a reminder script, which contains a few handy definitions. #
# Cut and paste as desired! Also, near the end, there are a bunch of #
# holiday definitions for the U.S. #
# #
# Some examples provided by George M. Sipe <gsipe@pyratl.ga.pyramid.com> #
# #
# U.S. holidays provided by Dave Rickel <drickel@sjc.mentorg.com> #
# #
# Use your text editor to search for: #
# "#USHOLS" for U.S. holidays #
# "#JHOLS" for Jewish holidays #
# "#PSSTUFF" for nifty PostScript examples #
# "#COLORS" for examples of ANSI color escape sequences. #
# #
# This file is part of REMIND. #
# Copyright (C) 1992-1996 by David F. Skoll #
# #
#############################################################################
#
# $Id: defs.rem,v 1.1 1996-03-27 03:25:51 dfs Exp $
#
RUN OFF
################################################
# Ensure required version of remind is used... #
################################################
IF version() < "03.00.10"
ERRMSG This file requires at least version 03.00.10 of Remind.%
ERRMSG This version is version [version()].
EXIT
ENDIF
######################################
# Symbolic constants for weekdays... #
######################################
SET Sunday 0
SET Monday 1
SET Tuesday 2
SET Wednesday 3
SET Thursday 4
SET Friday 5
SET Saturday 6
SET Sun 0
SET Mon 1
SET Tue 2
SET Wed 3
SET Thu 4
SET Fri 5
SET Sat 6
#########################################
# Symbolic constants for month names... #
#########################################
SET Jan 1
SET Feb 2
SET Mar 3
SET Apr 4
SET May 5
SET Jun 6
SET Jul 7
SET Aug 8
SET Sep 9
SET Oct 10
SET Nov 11
SET Dec 12
SET January 1
SET February 2
SET March 3
SET April 4
SET May 5
SET June 6
SET July 7
SET August 8
SET September 9
SET October 10
SET November 11
SET December 12
###########################################################
# Other symbolic constants and functions for "pasting"... #
###########################################################
SET Quote CHAR(34)
# Handy constants/function for specifing week of month...
SET Week_1 1
SET Week_2 8
SET Week_3 15
SET Week_4 22
FSET _last(mo) "1 " + MON((mo%12)+1)+" --7"
# Shorthand for commonly used expression...
FSET _trig() TRIGGER(TRIGDATE())
# Handy function to provide SCANFROM dates...
FSET _back(days) TRIGGER(TODAY()-days)
###########################################################
# On MS-DOS systems, the standard C library functions are #
# not reliable for computing offsets from local time to #
# UTC. The following provides a work-around for the #
# sunrise() and sunset() functions. Note, however, that #
# if Daylight Savings Time is in effect for today(), the #
# sun functions return times in DST even for dates on #
# which DST is not in effect; the converse can also occur.#
# #
# Change the timezone to your timezone - the default is #
# for EST which is 5 hours (300 minutes) behind UTC. #
# The code is correct for places in which Daylight Savings#
# Time begins on the last Sunday in April and ends on the #
# last Sunday in October. #
###########################################################
IF OSTYPE() == "MSDOS"
# Eastern Standard Time
SET TimeZone -300
# Use --8 rather than --7 because we want the last day BEFORE
# the time switch occurs.
REM Sun 1 May --8 SATISFY 1
SET BegDst TRIGDATE()
REM Sun 1 Nov --8 SATISFY 1
SET EndDst TRIGDATE()
SET $CalcUTC 0
# Check out the following IF statement and figure out why it works!
IF EndDst < BegDst
# Daylight Savings Time
SET $MinsFromUTC TimeZone+60
ELSE
# Standard Time
SET $MinsFromUTC TimeZone
ENDIF
ENDIF
###########################################################
# Function which returns a string in "am/pm" format based #
# on the time. For example, set a am_pm(NOW())... #
###########################################################
FSET _am_pm(tm) IIF(tm<01:00, tm+12*60+"am", \
tm<12:00, tm+"am", \
tm<13:00, tm+"pm", \
tm-12*60+"pm")
#################################################################
# Function which removes a single leading zero from a string... #
#################################################################
FSET _no_lz(s) IIF(SUBSTR(s, 1, 1)=="0", SUBSTR(s, 2), s)
############################################################
# Function to calculate number of years since a given year #
# or number of months since a given month and year... #
############################################################
FSET _yr_num(yr) ORD(YEAR(TRIGDATE()) - yr)
FSET _mo_num(mo, yr) ORD(12 * (YEAR(TRIGDATE()) - yr) + \
MONNUM(TRIGDATE()) - mo)
# Here's an example of how to use them:
REM 1 Nov ++12 MSG %"Dean's [_yr_num(1984)] birthday%" is %b.
REM 1 MSG Dean's [_mo_num(11, 1984)] 'monthly' anniversary
###########################################################
# Function to send mail via elm's "fastmail" (by GMS!)... #
###########################################################
#FSET _mail(from, subj) "mailx -s " + \
# Quote + from + " : " + subj + Quote \
# GETENV("LOGNAME") + " < /dev/null 1>&0"
FSET _mail(from, subj) "fastmail -f " + \
Quote + from + Quote + \
" -s " + Quote + subj + Quote + \
" /dev/null " + GETENV("LOGNAME")
#############################################################################
# Here's a tricky problem: The 4th of July is a holiday in the U.S.
# However, if it falls on a Saturday, the previous Friday is a holiday.
# If it falls on a Sunday, the next Monday is a holiday. Here's how
# to do it. NOTE that the following procedure makes the OMIT context
# dependent upon the current date. SInce it only depends on the current
# year, which is not likely to change while producing a calendar, we
# are fairly safe. However, reminders with huge DELTA or BACK components
# may not operate as expected. In general, any time you make OMIT
# dependent upon the current date, it's tricky and results may not be
# what you expect. You should try to make sure that the OMIT context
# "near" any current reminders will not change during a calendar run.
# The SCANFROM clause should help make these OMITs very safe.
############################################################################
# Calculate the weekday of the holiday.
REM 4 July SCANFROM [_back(7)] SATISFY 1
IF WKDAYNUM(TRIGDATE()) == Sat
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
OMIT [TRIGGER(TRIGDATE()-1)] MSG Independence day (observed)
ELSE
IF WKDAYNUM(TRIGDATE()) == Sun
REM [TRIGGER(TRIGDATE())] MSG Independence day (actual)
OMIT [TRIGGER(TRIGDATE()+1)] MSG Independence day (observed)
ELSE
OMIT [TRIGGER(TRIGDATE())] MSG Independence day
ENDIF
ENDIF
############################################################################
# #
# A meeting on the first Monday of every month which is moved to the #
# second Monday in the event of a holiday. #
# #
############################################################################
# First, the normal meeting. However, the SKIP keyword means this
# one won't be triggered if the first Monday is a holiday
REM Mon 1 SKIP MSG Meeting
# Now, calculate the "potential" delayed meeting
REM Mon 8 SATISFY 1
# But only actually trigger the delayed meeting if the previous
# Monday was a holiday
IF ISOMITTED(TRIGDATE()-7)
REM [TRIGGER(TRIGDATE())] MSG Delayed meeting
ENDIF
############################################################################
# #
# A very complicated reminder sent in by a Remind user. #
# This person gets paid every two weeks, starting from 8 January 1993. #
# If a pay date occurs before the twelfth of a month, then that #
# he pays his mortgage on that pay date. Otherwise, he pays the mortgage #
# on the previous pay date. Furthermore, he has to schedule his #
# mortgage payment six days before it is due. He wants to be reminded #
# a further four days before the scheduling deadline. He also #
# wants to be mailed a notice two weeks before the scheduling deadline. #
# #
# Here's the solution - if you can follow this, consider yourself a #
# Remind programmer extraordinaire! #
# #
############################################################################
# A function to determine whether or not a pay-date is a mortgage-date.
FSET _IsMortDate(x) DAY(x) < 12 || (DAY(x+14) >= 12 && DAY(x+14) <= 14)
# Paydays - for reference
REM 8 Jan 1993 *14 MSG Payday
# Calculate the mortgage payment six days ahead of time. Note that this
# is done "implicitly" by subtracting 6 from the starting date - we start
# on 2 Jan rather than 8 Jan. We add 6 to TRIGDATE() in _IsMortDate to
# compensate.
REM 2 Jan 1993 *14 ++4 SATISFY [_IsMortDate(TRIGDATE()+6)] \
MSG %"Schedule mortgage payment%" for %a.
# Now the mail reminder two weeks before the payment date - because two
# weeks before a payment date is also a payment date, no pre-compensation
# in the starting date of 8 Jan is necessary - convince yourself of this!
# This uses the _mail() function defined earlier.
REM ONCE 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE()+14)] \
RUN [_mail("Decatur Federal", \
"Pay mortgage by the " + ORD(DAY(TRIGDATE()+14)))]
# Make an entry on the calendar when the mortgage should be paid
REM 8 Jan 1993 *14 SATISFY [_IsMortDate(TRIGDATE())] \
CAL Mortgage payment
##########################################################################
# #
# On our UNIX system, I run a program which queries the university #
# library and creates a file called ".booksdue". This file is #
# a REMIND script to tell me when my library books are due. Here's #
# an example from my reminder file - it shows the use of filedate(). #
# When the .booksdue file is at least 7 days old, I create a new version #
# by querying the library computer. Note the use of realtoday() rather #
# than today. #
# #
##########################################################################
IF !$RunOff && !$CalMode && !$SimpleCal
IF REALTODAY()-FILEDATE("/home/dfs/.booksdue") >= 7
REM RUN /home/dfs/bilge/library/getbooks
ENDIF
ENDIF
#PSSTUFF
##########################################################################
# #
# This portion of the file contains some cute examples of the new #
# PS-type reminders. You need a PostScript printer or viewer to #
# appreciate these. To use them, pipe the output of remind -p into the #
# rem2ps program. #
# #
##########################################################################
# Convenient to stick all the PostScript code in a string var - makes
# reminders easier to understand and faster. The variable "shade" will
# contain PostScript code to shade in a particular box on the calendar.
SET shade psshade(95)
# The following reminder will shade the Saturday and Sunday calendar
# entries.
REM Sat Sun PS [shade]
# The following will fill in the Hebrew dates on the calendar. For this
# example, I recommend that you use the -sd 10 option for Rem2PS.
REM PS Border Border moveto \
/DayFont findfont DaySize scalefont setfont \
([hebday(today())] [hebmon(today())]) show
# Fill in the phases of the moon on the PostScript calendar
[trigger(moondate(0))] PS [psmoon(0)]
[trigger(moondate(1))] PS [psmoon(1)]
[trigger(moondate(2))] PS [psmoon(2)]
[trigger(moondate(3))] PS [psmoon(3)]
# The following example puts sunrise and sunset times in PostScript in the
# calendar - the sizes are hard-coded, however, and work best in landscape.
REM PS Border Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \
(Sunrise: [sunrise(trigdate())] Sunset: [sunset(trigdate())]) show
# The next one puts the day number (1-366) and days left in the year at the
# bottom of the post-script calendar. Again, the hard-coded sizes work best
# in landscape.
FSET _DayOfYear(x) x-(date(year(x),1,1) - 1)
REM PS BoxWidth 3 mul 4 div Border 5 sub moveto \
/SmallFont findfont 4 scalefont setfont \
([_DayOfYear(today())]([365+isleap(today())-_DayOfYear(today())])) show
#USHOLS
#############################################################################
# #
# The following holidays were provided by Dave Rickel #
# Modified by D. Skoll to give safe OMITs for moveable holidays #
# #
#############################################################################
SET SaveTrig $NumTrig
SET easter EASTERDATE(YEAR(TODAY()))
REM [TRIGGER(easter-46)] MSG %"Ash Wednesday%"
REM [TRIGGER(easter-7)] MSG %"Palm Sunday%"
OMIT [TRIGGER(easter-2)] MSG %"Good Friday%"
OMIT [TRIGGER(easter)] MSG %"Easter%" Sunday
REM [TRIGGER(easter+39)] MSG %"Ascension Day%"
REM [TRIGGER(easter+49)] MSG %"Pentecost%"
# Some holidays are omitted, some are not. You may want to change
# which ones are omitted - use the general forms shown below.
# You'll need the _back() function and the Week_n variables defined
# way up in the file.
OMIT Jan 1 MSG %"New Year's%" Day
REM Mon Jan [Week_3] MSG Martin Luther King - %"MLK Day%"
REM Feb 2 MSG %"Ground Hog Day%"
REM Feb 14 MSG %"Valentine's%" Day
REM Mon Feb [Week_3] SCANFROM [_back(7)] SATISFY 1
OMIT [_trig()] MSG %"President's Day%"
REM Mar 17 MSG %"St. Patrick's%" Day
REM Sun Apr 1 ++2 MSG Daylight Savings Time - %"DST starts%" %b
REM Apr 1 MSG %"April Fool's%" Day
REM Mon Tue Wed Thu Fri Sat 15 Apr MSG %"Income tax%" due
REM May 5 MSG %"Cinco de Mayo%"
REM Sat May [Week_1] MSG %"Kentucky Derby%"
REM Sun May [Week_2] MSG %"Mother's Day%"
REM Sat May [Week_3] MSG %"Armed Forces Day%"
REM Mon [_last(May)] SCANFROM [_back(7)] SATISFY 1
OMIT [_trig()] MSG %"Memorial Day%"
REM Jun 14 MSG %"Flag Day%"
REM Sun Jun [Week_3] MSG %"Father's Day%"
REM Mon Sep [Week_1] SCANFROM [_back(7)] SATISFY 1
OMIT [_trig()] MSG %"Labor Day%"
REM Mon Oct [Week_2] MSG %"Columbus Day%"
REM Nov 11 MSG %"Veterans Day%"
REM Sun [_last(Oct)] MSG Daylight Savings Time - %"DST over%"
REM Oct 30 MSG %"Mischief Night%"
REM Oct 31 MSG %"Halloween%"
REM Tue Nov 2 SCANFROM [_back(7)] \
SATISFY [(YEAR(TRIGDATE()) % 4) == 0] \
MSG %"Election%" Day
REM Thu Nov [Week_4] SCANFROM [_back(7)] SATISFY 1
OMIT [_trig()] MSG %"Thanksgiving%" Day
REM Fri Nov [Week_4+1] SCANFROM [_back(7)] SATISFY 1
OMIT [_trig()] MSG %"Thanksgiving%" (cont.)
OMIT Dec 24 MSG %"Christmas Eve%"
OMIT Dec 25 MSG %"Christmas%" Day
##########################################################################
# #
# The next block uses the shade variable defined in PSSTUFF above. #
# If any US holidays were triggered above, shade in the calendar #
# entry in PostScript. This is not quite correct, as it blots out the #
# other PostScript stuff above. I was too lazy to do it properly :-) #
# #
##########################################################################
if $NumTrig > SaveTrig
REM PS [shade]
endif
# Seasons (valid from 1992 to 2000)...
REM Mar 20 MSG %"Spring%" begins
REM Jun [IIF(YEAR(TODAY())%4, 21, 20)] MSG %"Summer%" begins
REM Sep [CHOOSE(YEAR(TODAY())-1991, 22,22,23,23,22,22,22,23,22)] \
MSG %"Fall%" begins
REM Dec [IIF((YEAR(TODAY())+1)%4, 21, 22)] MSG %"Winter%" begins
#JHOLS
##########################################################################
# #
# This portion of the file contains reminders for Jewish holidays. The #
# dates were obtained from "The First Jewish Catalog" by Richard Siegel #
# and Michael and Sharon Strassfeld, published by the Jewish Publication #
# Society of America. The Reform version of the calendar was guessed #
# at by David Skoll based on experience. There is probably no standard #
# Reform position on many of the holidays, so you may have to adjust #
# the file as required. #
# #
# Additional corrections were made from the paper "Calendrical #
# Calculations" by Nachum Dershowitz and Edward M. Reingold. Any #
# further corrections are welcome. #
# #
##########################################################################
# Here are some general functions that you might find nice to use
# _hstr: Returns a string which is the full Hebrew date of its argument.
# Example: hstr('1994/02/02') returns "21 Shvat 5754"
FSET _hstr(x) HEBDAY(x) + " " + HEBMON(x) + " " + HEBYEAR(x)
# _hyrlen: Return the length of the specified Hebrew year
# Example: _hyrlen(5754) returns 355
FSET _hyrlen(x) HEBDATE(1, "Tishrey", x+1) - HEBDATE(1, "Tishrey", x)
# --- HERE ARE THE JEWISH HOLIDAYS ---
# Set the variable InIsrael to 1 if you live in Israel. Otherwise,
# you get the Diaspora versions of Jewish holidays
SET InIsrael 0
# Set the variable Reform to 1 if you want the Reform version of the
# Jewish calendar. Otherwise, you get the traditional version
SET Reform 0
# Convenient function definition to save typing
FSET _h(x, y) TRIGGER(HEBDATE(x,y))
FSET _h2(x, y) HEBDATE(x, y, TODAY()-7)
FSET _PastSat(x, y) TRIGGER(IIF(WKDAYNUM(_h2(x,y))!=6, _h2(x,y), _h2(x,y)+1))
# Default values in case InIsrael and Reform are not set
SET InIsrael VALUE("InIsrael", 0)
SET Reform VALUE("Reform", 0)
[_h(1, "Tishrey")] ++4 MSG %"Rosh Hashana 1%" is %b.
# No RH-2 or Tzom Gedalia in Reform
IF !Reform
[_h(2, "Tishrey")] ++4 MSG %"Rosh Hashana 2%" is %b.
[_PastSat(3, "Tishrey")] ++4 MSG %"Tzom Gedalia%" is %b.
ENDIF
[_h(10, "Tishrey")] ++4 MSG %"Yom Kippur%" is %b.
[_h(15, "Tishrey")] ++4 MSG %"Sukkot 1%" is %b.
IF !InIsrael
[_h(16, "Tishrey")] MSG %"Sukkot 2%"
ENDIF
[_h(21, "Tishrey")] ++4 MSG %"Hashana Rabba%" is %b.
[_h(22, "Tishrey")] ++4 MSG %"Shemini Atzeret%" is %b.
IF InIsrael
[_h(22, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
ELSE
[_h(23, "Tishrey")] ++4 MSG %"Simchat Torah%" is %b.
ENDIF
# Because Kislev can change length, we must be more careful about Chanukah
FSET _chan(x) TRIGGER(HEBDATE(24, "Kislev", today()-9)+x)
[_chan(1)] ++4 MSG %"Chanukah 1%" is %b.
[_chan(2)] MSG %"Chanukah 2%"
[_chan(3)] MSG %"Chanukah 3%"
[_chan(4)] MSG %"Chanukah 4%"
[_chan(5)] MSG %"Chanukah 5%"
[_chan(6)] MSG %"Chanukah 6%"
[_chan(7)] MSG %"Chanukah 7%"
[_chan(8)] MSG %"Chanukah 8%"
# Not sure about Reform's position on the next one.
IF !Reform
# 10 Tevet will never be a Saturday, so whether or not to
# move it is moot. (Thanks to Art Werschulz.)
[_h(10, "Tevet")] MSG %"Tzom Tevet%" is %b.
ENDIF
[_h(15, "Shvat")] ++4 MSG %"Tu B'Shvat%" is %b.
[_h(15, "Adar A")] ++4 MSG %"Purim Katan%" is %b.
# If Purim is on Sunday, then Fast of Esther is 11 Adar.
IF WKDAYNUM(_h2(13, "Adar")) != 6
REM [TRIGGER(_h2(13, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
ELSE
REM [TRIGGER(_h2(11, "Adar"))] ++4 MSG %"Fast of Esther%" is %b.
ENDIF
[_h(14, "Adar")] ++4 MSG %"Purim%" is %b.
[_h(15, "Nisan")] ++4 MSG %"Pesach%" is %b.
IF !InIsrael
[_h(16, "Nisan")] MSG %"Pesach 2%"
ENDIF
[_h(21, "Nisan")] MSG %"Pesach 7%"
IF !InIsrael && !Reform
[_h(22, "Nisan")] MSG %"Pesach 8%"
ENDIF
[_h(27, "Nisan")] ++4 MSG %"Yom HaShoah%" is %b.
[_h(4, "Iyar")] ++4 MSG %"Yom HaZikaron%" is %b.
[_h(5, "Iyar")] ++4 MSG %"Yom Ha'atzmaut%" is %b.
# Not sure about Reform's position on Lag B'Omer
IF !Reform
[_h(18, "Iyar")] ++4 MSG %"Lag B'Omer%" is %b.
ENDIF
[_h(28, "Iyar")] ++4 MSG %"Yom Yerushalayim%" is %b.
[_h(6, "Sivan")] ++4 MSG %"Shavuot%" is %b.
IF !InIsrael && !Reform
[_h(7, "Sivan")] MSG %"Shavuot 2%"
ENDIF
# Fairly sure Reform Jews don't observe the next two
IF !Reform
# Tzom Tamuz and Tish'a B'Av are moved to Sunday if they normally
# fall on a Saturday
[_PastSat(17, "Tamuz")] ++4 MSG %"Tzom Tammuz%" is %b.
[_PastSat(9, "Av")] ++4 MSG %"Tish'a B'Av%" is %b.
ENDIF
# Counting the omer - do the whole spiel, i.e:
# "This is the xth day of the omer, being y weeks and z days of the omer."
# Nice Remind programming example here!
SET ostart HEBDATE(16, "Nisan", TODAY()-50)
IF ostart <= TODAY() && (TODAY() - ostart < 49)
SET odays TODAY()-ostart+1
IF odays < 7
MSG %"%"Today is the [ORD(odays)] day of the Omer.
ELSE
IF !(odays % 7)
MSG %"%"Today is the [ORD(odays)] day of the Omer, being [odays / 7] [PLURAL(odays/7, "week")] of the Omer.
ELSE
MSG %"%"Today is the [ORD(odays)] day of the Omer, being [odays/7] [PLURAL(odays/7, "week")] and [odays%7] [PLURAL(odays%7, "day")] of the Omer.
ENDIF
ENDIF
CAL [ORD(odays)] of Omer
ENDIF
### Candle lighting and Havdalah. You should probably add candle lighting
### for other holidays besides Shabbat. These just create calendar entries
### for Friday and Saturday. Note: You must set your latitude, longitude
### and possibly time zone for these to work properly!
REM Friday CAL Candle lighting at [sunset(trigdate())-18]
REM Saturday CAL Havdalah at [sunset(trigdate())+42]
#COLORS
##########################################################################
# #
# This contains sample ANSI escape sequences for coloring messages. #
# It should work on an IBM PC with the ANSI.SYS driver, and on #
# other terminals which use the ANSI sequences. #
# #
# This information was provided by Gail Gurman.
# #
##########################################################################
# Colors - use Nrm to reset to normal text.
SET Esc CHAR(27)
SET Nrm Esc + "[0m"
SET Blk Esc + "[0;30m"
SET Red Esc + "[0;31m"
SET Grn Esc + "[0;32m"
SET Ylw Esc + "[0;33m"
SET Blu Esc + "[0;34m"
SET Mag Esc + "[0;35m"
SET Cyn Esc + "[0;36m"
SET Wht Esc + "[0;37m"
SET Gry Esc + "[30;1m"
SET BrRed Esc + "[31;1m"
SET BrGrn Esc + "[32;1m"
SET BrYlw Esc + "[33;1m"
SET BrBlu Esc + "[34;1m"
SET BrMag Esc + "[35;1m"
SET BrCyn Esc + "[36;1m"
SET BrWht Esc + "[37;1m"
# Examples
REM MSG A [Blu]blue[Nrm] reminder.
REM MSG [Red]%"A red reminder%" safe to use in the calendar mode.[Nrm]
# Here is an example of how to use msgprefix() and msgsuffix(). These
# will highlight priority-0 reminders in bright red,
# priority-2500 in red, and priority-7500 in blue. All others
# will be in the normal colors
FSET msgprefix(x) iif(x==0, BrRed, x==2500, Red, x==7500, Blu, Nrm)
# Don't forget to return to normal color set at the end of reminder!
FSET msgsuffix(x) Nrm
# The next examples are great for putting right at the end of the reminder
# file. They make queued reminders more eye-catching when they pop up.
FSET msgprefix(x) char(13,10,13,10)+"******************"+char(13,10,13,10)
FSET msgsuffix(x) char(13,10)+"******************"+char(13,10,13,10)

797
dorem.c Normal file
View File

@@ -0,0 +1,797 @@
/***************************************************************/
/* */
/* DOREM.C */
/* */
/* Contains routines for parsing reminders and evaluating */
/* triggers. Also contains routines for parsing OMIT */
/* commands. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: dorem.c,v 1.1 1996-03-27 03:25:52 dfs Exp $";
#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
PRIVATE int ParseTimeTrig ARGS ((ParsePtr s, TimeTrig *tim));
PRIVATE int ParseLocalOmit ARGS ((ParsePtr s, Trigger *t));
PRIVATE int ParseScanFrom ARGS ((ParsePtr s, Trigger *t));
PRIVATE int ParsePriority ARGS ((ParsePtr s, Trigger *t));
PRIVATE int ParseUntil ARGS ((ParsePtr s, Trigger *t));
/***************************************************************/
/* */
/* DoRem */
/* */
/* Do the REM command. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoRem(ParsePtr p)
#else
int DoRem(p)
ParsePtr p;
#endif
{
Trigger trig;
TimeTrig tim;
int r;
int jul;
char buf[TOKSIZE];
Token tok;
/* Parse the trigger date and time */
if ( (r=ParseRem(p, &trig, &tim)) ) return r;
if (trig.typ == NO_TYPE) return E_EOLN;
if (trig.typ == SAT_TYPE) {
r=DoSatRemind(&trig, &tim, p);
if (r) return r;
r=ParseToken(p, buf);
if (r) return r;
FindToken(buf, &tok);
if (tok.type == T_Empty || tok.type == T_Comment) return OK;
if (tok.type != T_RemType || tok.val == SAT_TYPE) return E_PARSE_ERR;
trig.typ = tok.val;
jul = LastTriggerDate;
if (!LastTrigValid) return OK;
} else {
/* Calculate the trigger date */
jul = ComputeTrigger(trig.scanfrom, &trig, &r);
if (r) return r;
}
/* Queue the reminder, if necessary */
#ifdef HAVE_QUEUED
if (jul == JulianToday &&
!(!IgnoreOnce &&
trig.once != NO_ONCE &&
FileAccessDate == JulianToday))
QueueReminder(p, trig.typ, &tim, trig.sched);
/* If we're in daemon mode, do nothing over here */
if (Daemon) return OK;
#endif
if (ShouldTriggerReminder(&trig, &tim, jul)) {
#ifdef OS2_POPUP
if ( (r=TriggerReminder(p, &trig, &tim, jul, 0)) ) {
#else
if ( (r=TriggerReminder(p, &trig, &tim, jul)) ) {
#endif
return r;
}
}
return OK;
}
/***************************************************************/
/* */
/* ParseRem */
/* */
/* Given a parse pointer, parse line and fill in a */
/* trigger structure. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ParseRem(ParsePtr s, Trigger *trig, TimeTrig *tim)
#else
int ParseRem(s, trig, tim)
ParsePtr s;
Trigger *trig;
TimeTrig *tim;
#endif
{
register int r;
Token tok;
trig->y = NO_YR;
trig->m = NO_MON;
trig->d = NO_DAY;
trig->wd = NO_WD;
trig->back = NO_BACK;
trig->delta = NO_DELTA;
trig->until = NO_UNTIL;
trig->rep = NO_REP;
trig->localomit = NO_WD;
trig->skip = NO_SKIP;
trig->once = NO_ONCE;
trig->typ = NO_TYPE;
trig->scanfrom = NO_DATE;
trig->priority = DefaultPrio;
trig->sched[0] = 0;
tim->ttime = NO_TIME;
tim->delta = NO_DELTA;
tim->rep = NO_REP;
while(1) {
/* Read space-delimited string */
r = ParseToken(s, TokBuffer);
if (r) return r;
/* Figure out what we've got */
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_WkDay:
if (trig->wd & (1 << tok.val)) return E_WD_TWICE;
trig->wd |= (1 << tok.val);
break;
case T_Month:
if (trig->m != NO_MON) return E_MON_TWICE;
trig->m = tok.val;
break;
case T_Skip:
if (trig->skip != NO_SKIP) return E_SKIP_ERR;
trig->skip = tok.val;
break;
case T_Priority:
r=ParsePriority(s, trig);
if (r) return r;
break;
case T_At:
r=ParseTimeTrig(s, tim);
if (r) return r;
break;
case T_Scanfrom:
r=ParseScanFrom(s, trig);
if (r) return r;
break;
case T_RemType:
trig->typ = tok.val;
if (s->isnested) return E_CANT_NEST_RTYPE;
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
return OK;
case T_Until:
r=ParseUntil(s, trig);
if (r) return r;
break;
case T_Year:
if (trig->y != NO_YR) return E_YR_TWICE;
trig->y = tok.val;
break;
case T_Day:
if (trig->d != NO_DAY) return E_DAY_TWICE;
trig->d = tok.val;
break;
case T_Rep:
if (trig->rep != NO_REP) return E_REP_TWICE;
trig->rep = tok.val;
break;
case T_Delta:
if (trig->delta != NO_DELTA) return E_DELTA_TWICE;
trig->delta = tok.val;
break;
case T_Back:
if (trig->back != NO_BACK) return E_BACK_TWICE;
trig->back = tok.val;
break;
case T_Once:
if (trig->once != NO_ONCE) return E_ONCE_TWICE;
trig->once = ONCE_ONCE;
break;
case T_Omit:
r = ParseLocalOmit(s, trig);
if (r) return r;
break;
case T_Empty:
if (trig->scanfrom == NO_DATE) trig->scanfrom = JulianToday;
return OK;
case T_Sched:
r=ParseToken(s, TokBuffer);
if(r) return r;
StrnCpy(trig->sched, TokBuffer, VAR_NAME_LEN);
break;
default:
Eprint("%s: %s", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer);
return E_UNKNOWN_TOKEN;
}
}
}
/***************************************************************/
/* */
/* ParseTimeTrig - parse the AT part of a timed reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseTimeTrig(ParsePtr s, TimeTrig *tim)
#else
static int ParseTimeTrig(s, tim)
ParsePtr s;
TimeTrig *tim;
#endif
{
Token tok;
int r;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_Time:
tim->ttime = tok.val;
break;
case T_Delta:
tim->delta = (tok.val > 0) ? tok.val : -tok.val;
break;
case T_Rep:
tim->rep = tok.val;
break;
default:
if (tim->ttime == NO_TIME) return E_EXPECT_TIME;
/* Save in global variable */
LastTriggerTime = tim->ttime;
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* ParseLocalOmit - parse the local OMIT portion of a */
/* reminder. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseLocalOmit(ParsePtr s, Trigger *t)
#else
static int ParseLocalOmit(s, t)
ParsePtr s;
Trigger *t;
#endif
{
Token tok;
int r;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_WkDay:
t->localomit |= (1 << tok.val);
break;
default:
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* ParseUntil - parse the UNTIL portion of a reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseUntil(ParsePtr s, Trigger *t)
#else
static int ParseUntil(s, t)
ParsePtr s;
Trigger *t;
#endif
{
int y = NO_YR,
m = NO_MON,
d = NO_DAY;
Token tok;
int r;
if (t->until != NO_UNTIL) return E_UNTIL_TWICE;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_Year:
if (y != NO_YR) {
Eprint("UNTIL: %s", ErrMsg[E_YR_TWICE]);
return E_YR_TWICE;
}
y = tok.val;
break;
case T_Month:
if (m != NO_MON) {
Eprint("UNTIL: %s", ErrMsg[E_MON_TWICE]);
return E_MON_TWICE;
}
m = tok.val;
break;
case T_Day:
if (d != NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE;
}
d = tok.val;
break;
default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("UNTIL: %s", ErrMsg[E_INCOMPLETE]);
return E_INCOMPLETE;
}
if (!DateOK(y, m, d)) return E_BAD_DATE;
t->until = Julian(y, m, d);
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* ParseScanFrom - parse the SCANFROM portion of a reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParseScanFrom(ParsePtr s, Trigger *t)
#else
static int ParseScanFrom(s, t)
ParsePtr s;
Trigger *t;
#endif
{
int y = NO_YR,
m = NO_MON,
d = NO_DAY;
Token tok;
int r;
if (t->scanfrom != NO_DATE) return E_SCAN_TWICE;
while(1) {
r = ParseToken(s, TokBuffer);
if (r) return r;
FindToken(TokBuffer, &tok);
switch(tok.type) {
case T_Year:
if (y != NO_YR) {
Eprint("SCANFROM: %s", ErrMsg[E_YR_TWICE]);
return E_YR_TWICE;
}
y = tok.val;
break;
case T_Month:
if (m != NO_MON) {
Eprint("SCANFROM: %s", ErrMsg[E_MON_TWICE]);
return E_MON_TWICE;
}
m = tok.val;
break;
case T_Day:
if (d != NO_DAY) {
Eprint("SCANFROM: %s", ErrMsg[E_DAY_TWICE]);
return E_DAY_TWICE;
}
d = tok.val;
break;
default:
if (y == NO_YR || m == NO_MON || d == NO_DAY) {
Eprint("SCANFROM: %s", ErrMsg[E_INCOMPLETE]);
return E_INCOMPLETE;
}
if (!DateOK(y, m, d)) return E_BAD_DATE;
t->scanfrom = Julian(y, m, d);
PushToken(TokBuffer);
return OK;
}
}
}
/***************************************************************/
/* */
/* TriggerReminder */
/* */
/* Trigger the reminder if it's a RUN or MSG type. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
#ifdef OS2_POPUP
PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul,
int AsPopUp)
#else /* ! OS2_POPUP */
PUBLIC int TriggerReminder(ParsePtr p, Trigger *t, TimeTrig *tim, int jul)
#endif /* OS2_POPUP */
#else /* ! HAVE_PROTOS */
#ifdef OS2_POPUP
int TriggerReminder(p, t, tim, jul, AsPopUp)
ParsePtr p;
Trigger *t;
TimeTrig *tim;
int jul;
int AsPopUp;
#else /* ! OS2_POPUP */
int TriggerReminder(p, t, tim, jul)
ParsePtr p;
Trigger *t;
TimeTrig *tim;
int jul;
#endif /* OS2_POPUP */
#endif /* HAVE_PROTOS */
{
int r, y, m, d;
char PrioExpr[25];
static char buf[LINELEN+TOKSIZE];
char *s, *s2;
Value v;
if (t->typ == RUN_TYPE && RunDisabled) return E_RUN_DISABLED;
if (t->typ == CAL_TYPE || t->typ == PS_TYPE || t->typ == PSF_TYPE)
return OK;
/* If it's a MSG-type reminder, and no -k option was used, issue the banner. */
if ((t->typ == MSG_TYPE || t->typ == MSF_TYPE)
&& !NumTriggered && !NextMode && !MsgCommand) {
if (!DoSubstFromString(Banner, SubstBuffer, JulianToday, NO_TIME) && *SubstBuffer)
#ifdef OS2_POPUP
if (AsPopUp)
PutlPopUp(SubstBuffer);
else
printf("%s\n", SubstBuffer);
#else
printf("%s\n", SubstBuffer);
#endif
}
/* If it's NextMode, process as a CAL-type entry, and issue simple-calendar
format. */
if (NextMode) {
if ( (r=DoSubst(p, SubstBuffer, t, tim, jul, CAL_MODE)) ) return r;
if (!*SubstBuffer) return OK;
FromJulian(jul, &y, &m, &d);
#ifdef OS2_POPUP
if (AsPopUp) {
sprintf(buf, "%04d%c%02d%c%02d %s", y, DATESEP, m+1, DATESEP, d,
SimpleTime(tim->ttime, NULL));
StartPopUp();
PutsPopUp(buf);
PutlPopUp(SubstBuffer);
}
else
printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d,
SimpleTime(tim->ttime, NULL),
SubstBuffer);
#else
printf("%04d%c%02d%c%02d %s%s\n", y, DATESEP, m+1, DATESEP, d,
SimpleTime(tim->ttime, NULL),
SubstBuffer);
#endif
return OK;
}
/* Put the substituted string into the SubstBuffer */
s2 = buf;
*s2 = 0;
if (UserFuncExists("msgprefix") == 1) {
sprintf(PrioExpr, "msgprefix(%d)", t->priority);
s = PrioExpr;
r = EvalExpr(&s, &v);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
sprintf(s2, "%s", v.v.str);
s2 += strlen(s2);
}
DestroyValue(v);
}
}
if ( (r=DoSubst(p, s2, t, tim, jul, NORMAL_MODE)) ) return r;
s2 += strlen(s2);
if (UserFuncExists("msgsuffix") == 1) {
sprintf(PrioExpr, "msgsuffix(%d)", t->priority);
s = PrioExpr;
r = EvalExpr(&s, &v);
if (!r) {
if (!DoCoerce(STR_TYPE, &v)) {
sprintf(s2, "%s", v.v.str);
s2 += strlen(s2);
}
DestroyValue(v);
}
}
if ((!MsgCommand && t->typ == MSG_TYPE) || t->typ == MSF_TYPE) {
*s2++ = '\n';
}
*s2 = 0;
/* If we are sorting, just queue it up in the sort buffer */
if (SortByDate) {
if (InsertIntoSortBuffer(jul, tim->ttime, buf, t->typ, t->priority) == OK) {
NumTriggered++;
return OK;
}
}
/* If we didn't insert the reminder into the sort buffer, issue the
reminder now. */
switch(t->typ) {
case MSG_TYPE:
if (MsgCommand) {
DoMsgCommand(MsgCommand, buf);
} else {
#ifdef OS2_POPUP
if (AsPopUp)
PutlPopUp(buf);
else
printf("%s", buf);
#else
printf("%s", buf);
#endif
}
break;
case MSF_TYPE:
#ifdef OS2_POPUP
if (AsPopUp) {
StartPopUp();
FillParagraph(buf, 1);
EndPopUp();
} else {
FillParagraph(buf, 0);
}
#else
FillParagraph(buf);
#endif
break;
case RUN_TYPE:
system(buf);
break;
default: /* Unknown/illegal type? */
return E_SWERR;
}
NumTriggered++;
return OK;
}
/***************************************************************/
/* */
/* ShouldTriggerReminder */
/* */
/* Return 1 if we should trigger a reminder, based on today's */
/* date and the trigger. Return 0 if reminder should not be */
/* triggered. */
/* */
/***************************************************************/
#ifdef __TURBOC__
#pragma argsused
#endif
#ifdef HAVE_PROTOS
PUBLIC int ShouldTriggerReminder(Trigger *t, TimeTrig *tim, int jul)
#else
int ShouldTriggerReminder(t, tim, jul)
Trigger *t;
TimeTrig *tim;
int jul;
#endif
{
int r;
/* Handle the ONCE modifier in the reminder. */
if (!IgnoreOnce && t->once !=NO_ONCE && FileAccessDate == JulianToday)
return 0;
if (jul < JulianToday) return 0;
/* Don't trigger timed reminders if DontIssueAts is true, and if the
reminder is for today */
#ifdef HAVE_QUEUED
if (jul == JulianToday && DontIssueAts && tim->ttime != NO_TIME) return 0;
#endif
/* Don't trigger "old" timed reminders */
/*** REMOVED...
if (jul == JulianToday &&
tim->ttime != NO_TIME &&
tim->ttime < SystemTime(0) / 60) return 0;
*** ...UNTIL HERE */
/* If "infinite delta" option is chosen, always trigger future reminders */
if (InfiniteDelta || NextMode) return 1;
/* Move back by delta days, if any */
if (t->delta != NO_DELTA) {
if (t->delta < 0)
jul = jul + t->delta;
else {
r = t->delta;
while(r && jul > JulianToday) {
jul--;
if (!IsOmitted(jul, t->localomit)) r--;
}
}
}
/* Should we trigger the reminder? */
return (jul <= JulianToday);
}
/***************************************************************/
/* */
/* DoSatRemind */
/* */
/* Do the "satisfying..." remind calculation. */
/* */
/***************************************************************/
#ifdef __TURBOC__
#pragma argsused
#endif
#ifdef HAVE_PROTOS
PUBLIC int DoSatRemind(Trigger *trig, TimeTrig *tim, ParsePtr p)
#else
int DoSatRemind(trig, tim, p)
Trigger *trig;
TimeTrig *tim;
ParsePtr p;
#endif
{
int iter, jul, r;
Value v;
char *s, *t;
t = p->pos;
iter = 0;
jul = trig->scanfrom;
while (iter++ < MaxSatIter) {
jul = ComputeTrigger(jul, trig, &r);
if (r) {
if (r == E_CANT_TRIG) return OK; else return r;
}
s = p->pos;
r = EvaluateExpr(p, &v);
t = p->pos;
if (r) return r;
if (v.type != INT_TYPE && v.type != STR_TYPE) return E_BAD_TYPE;
if (v.type == INT_TYPE && v.v.val) return OK;
if (v.type == STR_TYPE && *v.v.str) return OK;
p->pos = s;
jul++;
}
p->pos = t;
LastTrigValid = 0;
return OK;
}
/***************************************************************/
/* */
/* ParsePriority - parse the PRIORITY portion of a reminder */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ParsePriority(ParsePtr s, Trigger *t)
#else
static int ParsePriority(s, t)
ParsePtr s;
Trigger *t;
#endif
{
int p, r;
char *u;
r = ParseToken(s, TokBuffer);
if(r) return r;
u = TokBuffer;
if (!isdigit(*u)) return E_EXPECTING_NUMBER;
p = 0;
while (isdigit(*u)) {
p = p*10 + *u - '0';
u++;
}
if (*u) return E_EXPECTING_NUMBER;
/* Tricky! The only way p can be < 0 is if overflow occurred; thus,
E2HIGH is indeed the appropriate error message. */
if (p<0 || p>9999) return E_2HIGH;
t->priority = p;
return OK;
}
/***************************************************************/
/* */
/* DoMsgCommand */
/* */
/* Execute the '-k' command, escaping shell chars in message. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DoMsgCommand(char *cmd, char *msg)
#else
void DoMsgCommand(cmd, msg)
char *cmd;
char *msg;
#endif
{
#ifdef WANT_SHELL_ESCAPING
char buf[2*LINELEN+TOKSIZE];
char *s, *t;
/* Escape shell characters in msg INCLUDING WHITESPACE! */
for (t=buf, s=msg; *s; s++) {
if (isspace(*s) || strchr("\"'!$%^&*()|<>[]{}`~;?\\", *s)) *t++ = '\\';
*t++ = *s;
}
*t = 0;
/* Use SubstBuffer -- not too safe, since no check for overflow... */
sprintf(SubstBuffer, cmd, buf);
#else
sprintf(SubstBuffer, cmd, msg);
#endif /* WANT_SHELL_ESCAPING */
system(SubstBuffer);
}

661
dosubst.c Normal file
View File

@@ -0,0 +1,661 @@
/***************************************************************/
/* */
/* DOSUBST.C */
/* */
/* This performs all the "%" substitution functions when */
/* reminders are triggered. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: dosubst.c,v 1.1 1996-03-27 03:25:52 dfs Exp $";
#define L_IN_DOSUBST
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#define UPPER(c) (islower(c) ? toupper(c) : c)
#define ABS(x) ( (x) < 0 ? -(x) : (x) )
#ifndef NL
#define NL "\n"
#endif
static char TODAY[] = L_TODAY;
static char TOMORROW[] = L_TOMORROW;
/***************************************************************/
/* */
/* DoSubst */
/* */
/* Process the % escapes in the reminder. If */
/* mode==NORMAL_MODE, ignore the %" sequence. If */
/* mode==CAL_MODE, process the %" sequence. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoSubst(ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode)
#else
int DoSubst(p, out, t, tt, jul, mode)
ParsePtr p;
char *out;
Trigger *t;
TimeTrig *tt;
int jul, mode;
#endif
{
int diff = jul - JulianToday;
int curtime = SystemTime(0) / 60;
int err, done;
int c;
int d, m, y;
int tim = tt->ttime;
int h, min, hh, ch, cmin, chh;
char *pm, *cpm;
int tdiff, adiff, mdiff, hdiff;
char *mplu, *hplu, *when, *plu;
int has_quote = 0;
char *s = out;
char *os;
FromJulian(jul, &y, &m, &d);
if (tim == NO_TIME) tim = curtime;
tdiff = tim - curtime;
adiff = ABS(tdiff);
mdiff = adiff % 60;
hdiff = adiff / 60;
mplu = (mdiff == 1 ? "" : L_MPLU);
hplu = (hdiff == 1 ? "" : L_HPLU);
when = (tdiff < 0 ? L_AGO : L_FROMNOW);
h = tim / 60;
min = tim % 60;
#ifdef L_AMPM_OVERRIDE
L_AMPM_OVERRIDE (pm, h)
#else
pm = (h < 12) ? L_AM : L_PM;
#endif
hh = (h == 12) ? 12 : h % 12;
ch = curtime / 60;
cmin = curtime % 60;
#ifdef L_AMPM_OVERRIDE
L_AMPM_OVERRIDE (cpm, ch)
#else
cpm = (ch < 12) ? L_AM : L_PM;
#endif
chh = (ch == 12) ? 12 : ch % 12;
#ifdef L_ORDINAL_OVERRIDE
L_ORDINAL_OVERRIDE
#else
switch(d) {
case 1:
case 21:
case 31: plu = "st"; break;
case 2:
case 22: plu = "nd"; break;
case 3:
case 23: plu = "rd"; break;
default: plu = "th"; break;
}
#endif
while(1) {
c = ParseChar(p, &err, 0);
if (err) return err;
if (c == '\n') continue;
if (!c) {
if (mode != CAL_MODE && t->typ != RUN_TYPE && !MsgCommand)
*s++ = '\n';
*s++ = 0;
break;
}
if (c != '%') {
*s++ = c;
continue;
}
c = ParseChar(p, &err, 0);
if (err) return err;
if (!c) {
*s++ = 0;
break;
}
os = s;
done = 0;
if (diff <= 1) {
switch(UPPER(c)) {
#ifndef L_NOTOMORROW_A
case 'A':
#endif
#ifndef L_NOTOMORROW_B
case 'B':
#endif
#ifndef L_NOTOMORROW_C
case 'C':
#endif
#ifndef L_NOTOMORROW_E
case 'E':
#endif
#ifndef L_NOTOMORROW_F
case 'F':
#endif
#ifndef L_NOTOMORROW_G
case 'G':
#endif
#ifndef L_NOTOMORROW_H
case 'H':
#endif
#ifndef L_NOTOMORROW_I
case 'I':
#endif
#ifndef L_NOTOMORROW_J
case 'J':
#endif
#ifndef L_NOTOMORROW_K
case 'K':
#endif
#ifndef L_NOTOMORROW_L
case 'L':
#endif
#ifndef L_NOTOMORROW_U
case 'U':
#endif
#ifndef L_NOTOMORROW_V
case 'V':
#endif
sprintf(s, "%s", (diff ? TOMORROW : TODAY));
s += strlen(s);
done = 1;
break;
default: done = 0;
}
}
if (!done) switch(UPPER(c)) {
case 'A':
#ifdef L_A_OVER
L_A_OVER
#else
sprintf(s, "%s %s, %d %s, %d", L_ON, DayName[jul%7], d,
MonthName[m], y);
#endif
s += strlen(s);
break;
case 'B':
#ifdef L_B_OVER
L_B_OVER
#else
sprintf(s, L_INXDAYS, diff);
#endif
s += strlen(s);
break;
case 'C':
#ifdef L_C_OVER
L_C_OVER
#else
sprintf(s, "%s %s", L_ON, DayName[jul%7]);
#endif
s += strlen(s);
break;
case 'D':
#ifdef L_D_OVER
L_D_OVER
#else
sprintf(s, "%d", d);
#endif
s += strlen(s);
break;
case 'E':
#ifdef L_E_OVER
L_E_OVER
#else
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, d, DATESEP,
m+1, DATESEP, y);
#endif
s += strlen(s);
break;
case 'F':
#ifdef L_F_OVER
L_F_OVER
#else
sprintf(s, "%s %02d%c%02d%c%04d", L_ON, m+1, DATESEP, d, DATESEP, y);
#endif
s += strlen(s);
break;
case 'G':
#ifdef L_G_OVER
L_G_OVER
#else
sprintf(s, "%s %s, %d %s", L_ON, DayName[jul%7], d, MonthName[m]);
#endif
s += strlen(s);
break;
case 'H':
#ifdef L_H_OVER
L_H_OVER
#else
sprintf(s, "%s %02d%c%02d", L_ON, d, DATESEP, m+1);
#endif
s += strlen(s);
break;
case 'I':
#ifdef L_I_OVER
L_I_OVER
#else
sprintf(s, "%s %02d%c%02d", L_ON, m+1, DATESEP, d);
#endif
s += strlen(s);
break;
case 'J':
#ifdef L_J_OVER
L_J_OVER
#else
sprintf(s, "%s %s, %s %d%s, %d", L_ON, DayName[jul%7],
MonthName[m], d, plu, y);
#endif
s += strlen(s);
break;
case 'K':
#ifdef L_K_OVER
L_K_OVER
#else
sprintf(s, "%s %s, %s %d%s", L_ON, DayName[jul%7],
MonthName[m], d, plu);
#endif
s += strlen(s);
break;
case 'L':
#ifdef L_L_OVER
L_L_OVER
#else
sprintf(s, "%s %04d%c%02d%c%02d", L_ON, y, DATESEP, m+1, DATESEP, d);
#endif
s += strlen(s);
break;
case 'M':
#ifdef L_M_OVER
L_M_OVER
#else
sprintf(s, "%s", MonthName[m]);
#endif
s += strlen(s);
break;
case 'N':
#ifdef L_N_OVER
L_N_OVER
#else
sprintf(s, "%d", m+1);
#endif
s += strlen(s);
break;
case 'O':
#ifdef L_O_OVER
L_O_OVER
#else
if (RealToday == JulianToday) sprintf(s, " (%s)", L_TODAY);
else *s = 0;
#endif
s += strlen(s);
break;
case 'P':
#ifdef L_P_OVER
L_P_OVER
#else
sprintf(s, (diff == 1 ? "" : L_PLURAL));
#endif
s += strlen(s);
break;
case 'Q':
#ifdef L_Q_OVER
L_Q_OVER
#else
sprintf(s, (diff == 1 ? "'s" : "s'"));
#endif
s += strlen(s);
break;
case 'R':
#ifdef L_R_OVER
L_R_OVER
#else
sprintf(s, "%02d", d);
#endif
s += strlen(s);
break;
case 'S':
#ifdef L_S_OVER
L_S_OVER
#else
sprintf(s, plu);
#endif
s += strlen(s);
break;
case 'T':
#ifdef L_T_OVER
L_T_OVER
#else
sprintf(s, "%02d", m+1);
#endif
s += strlen(s);
break;
case 'U':
#ifdef L_U_OVER
L_U_OVER
#else
sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], d,
plu, MonthName[m], y);
#endif
s += strlen(s);
break;
case 'V':
#ifdef L_V_OVER
L_V_OVER
#else
sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], d, plu,
MonthName[m]);
#endif
s += strlen(s);
break;
case 'W':
#ifdef L_W_OVER
L_W_OVER
#else
sprintf(s, DayName[jul%7]);
#endif
s += strlen(s);
break;
case 'X':
#ifdef L_X_OVER
L_X_OVER
#else
sprintf(s, "%d", diff);
#endif
s += strlen(s);
break;
case 'Y':
#ifdef L_Y_OVER
L_Y_OVER
#else
sprintf(s, "%d", y);
#endif
s += strlen(s);
break;
case 'Z':
#ifdef L_Z_OVER
L_Z_OVER
#else
sprintf(s, "%d", y % 100);
#endif
s += strlen(s);
break;
case '1':
#ifdef L_1_OVER
L_1_OVER
#else
if (tdiff == 0)
sprintf(s, L_NOW);
else if (hdiff == 0)
sprintf(s, "%d %s%s %s", mdiff, L_MINUTE, mplu, when);
else if (mdiff == 0)
sprintf(s, "%d %s%s %s", hdiff, L_HOUR, hplu, when);
else
sprintf(s, "%d %s%s %s %d %s%s %s", hdiff, L_HOUR, hplu,
L_AND, mdiff, L_MINUTE, mplu, when);
#endif
s += strlen(s);
break;
case '2':
#ifdef L_2_OVER
L_2_OVER
#else
sprintf(s, "%s %d%c%02d%s", L_AT, hh, TIMESEP, min, pm);
#endif
s += strlen(s);
break;
case '3':
#ifdef L_3_OVER
L_3_OVER
#else
sprintf(s, "%s %02d%c%02d", L_AT, h, TIMESEP, min);
#endif
s += strlen(s);
break;
case '4':
#ifdef L_4_OVER
L_4_OVER
#else
sprintf(s, "%d", tdiff);
#endif
s += strlen(s);
break;
case '5':
#ifdef L_5_OVER
L_5_OVER
#else
sprintf(s, "%d", adiff);
#endif
s += strlen(s);
break;
case '6':
#ifdef L_6_OVER
L_6_OVER
#else
sprintf(s, when);
#endif
s += strlen(s);
break;
case '7':
#ifdef L_7_OVER
L_7_OVER
#else
sprintf(s, "%d", hdiff);
#endif
s += strlen(s);
break;
case '8':
#ifdef L_8_OVER
L_8_OVER
#else
sprintf(s, "%d", mdiff);
#endif
s += strlen(s);
break;
case '9':
#ifdef L_9_OVER
L_9_OVER
#else
sprintf(s, mplu);
#endif
s += strlen(s);
break;
case '0':
#ifdef L_0_OVER
L_0_OVER
#else
sprintf(s, hplu);
#endif
s += strlen(s);
break;
case '!':
#ifdef L_BANG_OVER
L_BANG_OVER
#else
sprintf(s, (tdiff >= 0 ? L_IS : L_WAS));
#endif
s += strlen(s);
break;
case '@':
#ifdef L_AT_OVER
L_AT_OVER
#else
sprintf(s, "%d%c%02d%s", chh, TIMESEP, cmin, cpm);
#endif
s += strlen(s);
break;
case '#':
#ifdef L_HASH_OVER
L_HASH_OVER
#else
sprintf(s, "%02d%c%02d", ch, TIMESEP, cmin);
#endif
s += strlen(s);
break;
case '_':
if (mode != CAL_MODE && !MsgCommand)
sprintf(s, "%s", NL);
else
sprintf(s, " ");
s += strlen(s);
break;
case QUOTE_MARKER:
/* Swallow any QUOTE_MARKERs which may somehow creep in... */
break;
case '"':
*s++ = QUOTE_MARKER;
has_quote = 1;
break;
default:
*s++ = c;
}
if (isupper(c)) *os = UPPER(*os);
}
/* We're outside the big while loop. The only way to get here is for c to
be null. Now we go through and delete %" sequences, if it's the
NORMAL_MODE, or retain only things within a %" sequence if it's the
CAL_MODE. */
/* If there are NO quotes, then: If CAL_MODE && RUN_TYPE, we don't want the
reminder in the calendar. Zero the output buffer and quit. */
if (!has_quote) {
if (mode == CAL_MODE && t->typ == RUN_TYPE) *out = 0;
return OK;
}
/* There ARE quotes. If in CAL_MODE, delete everything before first quote
and after second quote. If in NORMAL_MODE, delete the %" sequences. */
s = out;
os = out;
if (mode == NORMAL_MODE) {
while (*s) {
if (*s != QUOTE_MARKER) *os++ = *s;
s++;
}
*os = 0;
} else {
/* Skip past the quote marker */
while (*s && (*s != QUOTE_MARKER)) s++;
/* Security check... actually, *s must == QUOTE_MARKER at this point, but
it doesn't hurt to make it a bit robust. */
if (*s) s++;
/* Copy the output until the next QUOTE_MARKER */
while (*s && (*s != QUOTE_MARKER)) *os++ = *s++;
*os = 0;
}
return OK;
}
/***************************************************************/
/* */
/* DoSubstFromString */
/* */
/* DoSubst consumes input from a parser. This function */
/* consumes characters from a string. It also provides */
/* default triggers and a mode of NORMAL_MODE. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoSubstFromString(char *source, char *dest, int jul, int tim)
#else
int DoSubstFromString(source, dest, jul, tim)
char *source;
char *dest;
int jul;
int tim;
#endif
{
Trigger tempTrig;
TimeTrig tempTime;
Parser tempP;
int r;
if (jul == NO_DATE) jul=JulianToday;
if (tim == NO_TIME) tim=SystemTime(0)/60;
CreateParser(source, &tempP);
tempP.allownested = 0;
tempTrig.typ = MSG_TYPE;
tempTime.ttime = tim;
r = DoSubst(&tempP, dest, &tempTrig, &tempTime, jul, NORMAL_MODE);
DestroyParser(&tempP);
return r;
}

110
dutch.h Normal file
View File

@@ -0,0 +1,110 @@
/***************************************************************/
/* */
/* DUTCH.H */
/* */
/* Support for the DUTCH language. */
/* */
/* Author: Willem Kasdorp */
/* */
/* Modified slightly by David Skoll */
/* */
/* Further corrections by Erik-Jan Vens */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: dutch.h,v 1.1 1996-03-27 03:25:53 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "Dutch"
/* Day names */
#define L_SUNDAY "zondag"
#define L_MONDAY "maandag"
#define L_TUESDAY "dinsdag"
#define L_WEDNESDAY "woensdag"
#define L_THURSDAY "donderdag"
#define L_FRIDAY "vrijdag"
#define L_SATURDAY "zaterdag"
/* Day initials - first letter only */
#define L_DAYINIT "zmdwdvz"
/* Month names */
#define L_JAN "januari"
#define L_FEB "februari"
#define L_MAR "maart"
#define L_APR "april"
#define L_MAY "mei"
#define L_JUN "juni"
#define L_JUL "juli"
#define L_AUG "augustus"
#define L_SEP "september"
#define L_OCT "oktober"
#define L_NOV "november"
#define L_DEC "december"
/* Today and tomorrow */
#define L_TODAY "vandaag"
#define L_TOMORROW "morgen"
/* The default banner */
#define L_BANNER "Herinneringen voor %w, %d%s %m, %y%o:"
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "geleden"
#define L_FROMNOW "vanaf nu"
/* "in %d days' time" */
#define L_INXDAYS "over %d dagen"
/* "on" as in "on date..." */
#define L_ON "op"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix. (Indeed..., wkasdo) */
#define L_PLURAL "s"
/* Minutes, hours, at, etc */
#define L_NOW "nu"
#define L_AT "op"
#define L_MINUTE "minuut"
#define L_HOUR "uur"
#define L_IS "is"
#define L_WAS "was"
#define L_AND "en"
/* What to add to make "hour" plural (should result in uren, not uuren (wkasdo) */
#define L_HPLU "en"
/* What to add to make "minute" plural (should be minuten, not minuuten) */
#define L_MPLU "en"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
/* Willem - I fixed the uren/uuren problem here */
#define L_1_OVER \
if (tdiff == 0) \
sprintf(s, L_NOW); \
else if (hdiff == 0) \
sprintf(s, "%d %s %s", mdiff, \
(mdiff == 1 ? "minuut" : "minuten"), when); \
else if (mdiff == 0) \
sprintf(s, "%d %s %s", hdiff, \
(mdiff == 1 ? "uur" : "uren"), when); \
else sprintf(s, "%d %s %s %d %s %s", hdiff, \
(hdiff == 1 ? "uur" : "uren"), \
L_AND, mdiff, \
(mdiff == 1 ? "minuut" : "minuten"), \
when);
#endif /* L_IN_DOSUBST */

87
english.h Normal file
View File

@@ -0,0 +1,87 @@
/***************************************************************/
/* */
/* ENGLISH.H */
/* */
/* Support for the English language. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: english.h,v 1.1 1996-03-27 03:25:53 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "English"
/* Day names */
#define L_SUNDAY "Sunday"
#define L_MONDAY "Monday"
#define L_TUESDAY "Tuesday"
#define L_WEDNESDAY "Wednesday"
#define L_THURSDAY "Thursday"
#define L_FRIDAY "Friday"
#define L_SATURDAY "Saturday"
/* Day initials - first letter only */
#define L_DAYINIT "SMTWTFS"
/* Month names */
#define L_JAN "January"
#define L_FEB "February"
#define L_MAR "March"
#define L_APR "April"
#define L_MAY "May"
#define L_JUN "June"
#define L_JUL "July"
#define L_AUG "August"
#define L_SEP "September"
#define L_OCT "October"
#define L_NOV "November"
#define L_DEC "December"
/* Today and tomorrow */
#define L_TODAY "today"
#define L_TOMORROW "tomorrow"
/* The default banner */
#define L_BANNER "Reminders for %w, %d%s %m, %y%o:"
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "ago"
#define L_FROMNOW "from now"
/* "in %d days' time" */
#define L_INXDAYS "in %d days' time"
/* "on" as in "on date..." */
#define L_ON "on"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL "s"
/* Minutes, hours, at, etc */
#define L_NOW "now"
#define L_AT "at"
#define L_MINUTE "minute"
#define L_HOUR "hour"
#define L_IS "is"
#define L_WAS "was"
#define L_AND "and"
/* What to add to make "hour" plural */
#define L_HPLU "s"
/* What to add to make "minute" plural */
#define L_MPLU "s"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#endif /* L_IN_DOSUBST */

234
err.h Normal file
View File

@@ -0,0 +1,234 @@
/***************************************************************/
/* */
/* ERR.H */
/* */
/* Error definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: err.h,v 1.1 1996-03-27 03:25:53 dfs Exp $ */
/* Note that not all of the "errors" are really errors - some are just
messages for information purposes. Constants beginning with M_ should
never be returned as error indicators - they should only be used to
index the ErrMsg array. */
#define OK 0
#define E_MISS_END 1
#define E_MISS_QUOTE 2
#define E_OP_STK_OVER 3
#define E_VA_STK_OVER 4
#define E_MISS_RIGHT_PAREN 5
#define E_UNDEF_FUNC 6
#define E_ILLEGAL_CHAR 7
#define E_EXPECTING_BINOP 8
#define E_NO_MEM 9
#define E_BAD_NUMBER 10
#define E_OP_STK_UNDER 11
#define E_VA_STK_UNDER 12
#define E_CANT_COERCE 13
#define E_BAD_TYPE 14
#define E_DATE_OVER 15
#define E_STACK_ERR 16
#define E_DIV_ZERO 17
#define E_NOSUCH_VAR 18
#define E_EOLN 19
#define E_EOF 20
#define E_IO_ERR 21
#define E_LINE_2_LONG 22
#define E_SWERR 23
#define E_BAD_DATE 24
#define E_2FEW_ARGS 25
#define E_2MANY_ARGS 26
#define E_BAD_TIME 27
#define E_2HIGH 28
#define E_2LOW 29
#define E_CANT_OPEN 30
#define E_NESTED_INCLUDE 31
#define E_PARSE_ERR 32
#define E_CANT_TRIG 33
#define E_NESTED_IF 34
#define E_ELSE_NO_IF 35
#define E_ENDIF_NO_IF 36
#define E_2MANY_LOCALOMIT 37
#define E_EXTRANEOUS_TOKEN 38
#define E_POP_NO_PUSH 39
#define E_RUN_DISABLED 40
#define E_DOMAIN_ERR 41
#define E_BAD_ID 42
#define E_RECURSIVE 43
#define E_PARSE_AS_REM 44 /* Not really an error - just returned by
DoOmit to indicate line should be executed
as a REM statement, also. */
#define E_CANT_MODIFY 45
#define E_MKTIME_PROBLEM 46
#define E_REDEF_FUNC 47
#define E_CANTNEST_FDEF 48
#define E_REP_FULSPEC 49
#define E_YR_TWICE 50
#define E_MON_TWICE 51
#define E_DAY_TWICE 52
#define E_UNKNOWN_TOKEN 53
#define E_SPEC_MON_DAY 54
#define E_2MANY_PART 55
#define E_2MANY_FULL 56
#define E_PUSH_NOPOP 57
#define E_ERR_READING 58
#define E_EXPECTING_EOL 59
#define E_BAD_HEBDATE 60
#define E_IIF_ODD 61
#define E_MISS_ENDIF 62
#define E_EXPECT_COMMA 63
#define E_WD_TWICE 64
#define E_SKIP_ERR 65
#define E_CANT_NEST_RTYPE 66
#define E_REP_TWICE 67
#define E_DELTA_TWICE 68
#define E_BACK_TWICE 69
#define E_ONCE_TWICE 70
#define E_EXPECT_TIME 71
#define E_UNTIL_TWICE 72
#define E_INCOMPLETE 73
#define E_SCAN_TWICE 74
#define E_VAR 75
#define E_VAL 76
#define E_UNDEF 77
#define E_ENTER_FUN 78
#define E_LEAVE_FUN 79
#define E_EXPIRED 80
#define E_CANTFORK 81
#define E_CANTACCESS 82
#define M_BAD_SYS_DATE 83
#define M_BAD_DB_FLAG 84
#define M_BAD_OPTION 85
#define M_BAD_USER 86
#define M_NO_CHG_GID 87
#define M_NO_CHG_UID 88
#define M_NOMEM_ENV 89
#define E_MISS_EQ 90
#define E_MISS_VAR 91
#define E_MISS_EXPR 92
#define M_CANTSET_ACCESS 93
#define M_I_OPTION 94
#define E_NOREMINDERS 95
#define M_QUEUED 96
#define E_EXPECTING_NUMBER 97
#ifdef MK_GLOBALS
#undef EXTERN
#define EXTERN
#else
#undef EXTERN
#define EXTERN extern
#endif
#ifndef L_ERR_OVERRIDE
EXTERN char *ErrMsg[]
#ifdef MK_GLOBALS
= {
"Ok",
"Missing ']'",
"Missing quote",
"Expression too complex - too many operators",
"Expression too complex - too many operands",
"Missing ')'",
"Undefined function",
"Illegal character",
"Expecting binary operator",
"Out of memory",
"Ill-formed number",
"Op stack underflow - internal error",
"Va stack underflow - internal error",
"Can't coerce",
"Type mismatch",
"Date overflow",
"Stack error - internal error",
"Division by zero",
"Undefined variable",
"Unexpected end of line",
"Unexpected end of file",
"I/O error",
"Line too long",
"Internal error",
"Bad date specification",
"Not enough arguments",
"Too many arguments",
"Ill-formed time",
"Number too high",
"Number too low",
"Can't open file",
"INCLUDE nested too deeply",
"Parse error",
"Can't compute trigger",
"Too many nested IFs",
"ELSE with no matching IF",
"ENDIF with no matching IF",
"Can't OMIT every weekday",
"Extraneous token(s) on line",
"POP-OMIT-CONTEXT without matching PUSH-OMIT-CONTEXT",
"RUN disabled",
"Domain error",
"Invalid identifier",
"Recursive function call detected",
"",
"Cannot modify system variable",
"C library function can't represent date/time",
"Attempt to redefine built-in function",
"Can't nest function definition in expression",
"Must fully specify date to use repeat factor",
"Year specified twice",
"Month specified twice",
"Day specified twice",
"Unknown token",
"Must specify month and day in OMIT command",
"Too many partial OMITs",
"Too many full OMITs",
"Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
"Error reading file",
"Expecting end-of-line",
"Invalid Hebrew date",
"IIF needs odd number of arguments",
"Warning: Missing ENDIF",
"Expecting comma",
"Weekday specified twice",
"Only use one of BEFORE, AFTER or SKIP",
"Can't nest MSG, MSF, RUN, etc. in expression",
"Repeat value specified twice",
"Delta value specified twice",
"Back value specified twice",
"ONCE keyword used twice. (Hah.)",
"Expecting time after AT",
"UNTIL keyword used twice",
"Incomplete date specification",
"SCANFROM keyword used twice",
"Variable",
"Value",
"*UNDEFINED*",
"Entering UserFN",
"Leaving UserFN",
"Expired",
"fork() failed - can't do queued reminders",
"Can't access file",
"Illegal system date: Year is less than %d\n",
"Unknown debug flag '%c'\n",
"Unknown option '%c'\n",
"Unknown user '%s'\n",
"Could not change gid to %d\n",
"Could not change uid to %d\n",
"Out of memory for environment\n",
"Missing '=' sign",
"Missing variable name",
"Missing expression",
"Can't reset access date of %s\n",
"Remind: '-i' option: %s\n",
"No reminders.",
"%d reminder(s) queued for later today.\n",
"Expecting number"
}
#endif /* MK_GLOBALS */
;
#endif /* L_ERR_OVERRIDE */

1209
expr.c Normal file

File diff suppressed because it is too large Load Diff

55
expr.h Normal file
View File

@@ -0,0 +1,55 @@
/***************************************************************/
/* */
/* EXPR.H */
/* */
/* Contains a few definitions used by expression evaluator. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: expr.h,v 1.1 1996-03-27 03:25:54 dfs Exp $ */
/* Define the types of values */
#define ERR_TYPE 0
#define INT_TYPE 1
#define TIM_TYPE 2
#define DATE_TYPE 3
#define STR_TYPE 4
/* Define stuff for parsing expressions */
#define BEG_OF_EXPR '['
#define END_OF_EXPR ']'
#define COMMA ','
#define UN_OP 0 /* Unary operator */
#define BIN_OP 1 /* Binary Operator */
#define FUNC 2 /* Function */
/* Make the pushing and popping of values and operators in-line code
for speed. BEWARE: These macros invoke return if an error happens ! */
#define PushOpStack(op) \
if (OpStackPtr >= OP_STACK_SIZE) \
return E_OP_STK_OVER; \
else \
OpStack[OpStackPtr++] = (op)
#define PopOpStack(op) \
if (OpStackPtr <= 0) \
return E_OP_STK_UNDER; \
else \
(op) = OpStack[--OpStackPtr]
#define PushValStack(val) \
if (ValStackPtr >= VAL_STACK_SIZE) \
return E_VA_STK_OVER; \
else \
ValStack[ValStackPtr++] = (val)
#define PopValStack(val) \
if (ValStackPtr <= 0) \
return E_VA_STK_UNDER; \
else \
(val) = ValStack[--ValStackPtr]

558
files.c Normal file
View File

@@ -0,0 +1,558 @@
/***************************************************************/
/* */
/* FILES.C */
/* */
/* Controls the opening and closing of files, etc. Also */
/* handles caching of lines and reading of lines from */
/* files. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: files.c,v 1.1 1996-03-27 03:25:55 dfs Exp $";
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#if defined(__MSDOS__)
#include <io.h>
#endif
#ifdef __MSC__
#include <dos.h>
#endif
#include "types.h"
#include "protos.h"
#include "globals.h"
#include "err.h"
/* Convenient macro for closing files */
#define FCLOSE(fp) (((fp)&&((fp)!=stdin)) ? (fclose(fp),(fp)=NULL) : ((fp)=NULL))
/* Define the structures needed by the file caching system */
typedef struct cache {
struct cache *next;
char *text;
int LineNo;
} CachedLine;
typedef struct cheader {
struct cheader *next;
char *filename;
CachedLine *cache;
} CachedFile;
/* Define the structures needed by the INCLUDE file system */
typedef struct {
char *filename;
int LineNo;
unsigned int IfFlags;
int NumIfs;
long offset;
CachedLine *CLine;
} IncludeStruct;
static CachedFile *CachedFiles = (CachedFile *) NULL;
static CachedLine *CLine = (CachedLine *) NULL;
static FILE *fp;
static IncludeStruct IStack[INCLUDE_NEST];
static int IStackPtr = 0;
PRIVATE int ReadLineFromFile ARGS ((void));
PRIVATE int CacheFile ARGS ((const char *fname));
PRIVATE void DestroyCache ARGS ((CachedFile *cf));
/***************************************************************/
/* */
/* ReadLine */
/* */
/* Read a line from the file or cache. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ReadLine(void)
#else
int ReadLine()
#endif
{
int r;
/* If we're at the end of a file, pop */
while (!CLine && !fp) {
r = PopFile();
if (r) return r;
}
/* If it's cached, read line from the cache */
if (CLine) {
CurLine = CLine->text;
LineNo = CLine->LineNo;
CLine = CLine->next;
FreshLine = 1;
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
return OK;
}
/* Not cached. Read from the file. */
return ReadLineFromFile();
}
/***************************************************************/
/* */
/* ReadLineFromFile */
/* */
/* Read a line from the file pointed to by fp. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int ReadLineFromFile(void)
#else
static ReadLineFromFile()
#endif
{
int l;
char *ptr;
char *tmp;
CurLine = LineBuffer;
*LineBuffer = (char) 0;
l = 0;
ptr = LineBuffer;
while(fp) {
tmp=fgets(ptr, LINELEN-l, fp);
LineNo++;
if (ferror(fp)) return E_IO_ERR;
if (feof(fp) || !tmp) {
FCLOSE(fp);
}
l = strlen(LineBuffer);
if (l && (LineBuffer[l-1] == '\n')) LineBuffer[--l] = '\0';
if (l && (LineBuffer[l-1] == '\\')) {
l--;
ptr = LineBuffer+l;
if (l >= LINELEN-1) return E_LINE_2_LONG;
continue;
}
FreshLine = 1;
if (DebugFlag & DB_ECHO_LINE) OutputLine(ErrFp);
return OK;
}
return OK;
}
/***************************************************************/
/* */
/* OpenFile */
/* */
/* Open a file for reading. If it's in the cache, set */
/* CLine. Otherwise, open it on disk and set fp. If */
/* ShouldCache is 1, cache the file */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int OpenFile(const char *fname)
#else
int OpenFile(fname)
char *fname;
#endif
{
CachedFile *h = CachedFiles;
int r;
/* If it's in the cache, get it from there. */
while (h) {
if (!strcmp(fname, h->filename)) {
CLine = h->cache;
STRSET(FileName, fname);
LineNo = 0;
if (FileName) return OK; else return E_NO_MEM;
}
h = h->next;
}
/* If it's a dash, then it's stdin */
if (!strcmp(fname, "-")) {
fp = stdin;
} else {
fp = fopen(fname, "r");
}
if (!fp) return E_CANT_OPEN;
CLine = NULL;
if (ShouldCache) {
LineNo = 0;
r = CacheFile(fname);
if (r == OK) {
fp = NULL;
CLine = CachedFiles->cache;
} else {
if (strcmp(fname, "-"))
fp = fopen(fname, "r");
else
fp = stdin;
if (!fp) return E_CANT_OPEN;
}
}
STRSET(FileName, fname);
LineNo = 0;
if (FileName) return OK; else return E_NO_MEM;
}
/***************************************************************/
/* */
/* CacheFile */
/* */
/* Cache a file in memory. If we fail, set ShouldCache to 0 */
/* Returns an indication of success or failure. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int CacheFile(const char *fname)
#else
static int CacheFile(fname)
char *fname;
#endif
{
int r;
CachedFile *cf;
CachedLine *cl;
char *s;
cl = NULL;
/* Create a file header */
cf = NEW(CachedFile);
cf->cache = NULL;
if (!cf) { ShouldCache = 0; FCLOSE(fp); return E_NO_MEM; }
cf->filename = StrDup(fname);
if (!cf->filename) {
ShouldCache = 0;
FCLOSE(fp);
free(cf);
return E_NO_MEM;
}
/* Read the file */
while(fp) {
r = ReadLineFromFile();
if (r) {
DestroyCache(cf);
ShouldCache = 0;
FCLOSE(fp);
return r;
}
/* Skip blank chars */
s = LineBuffer;
while (isspace(*s)) s++;
if (*s && *s!=';' && *s!='#') {
/* Add the line to the cache */
if (!cl) {
cf->cache = NEW(CachedLine);
if (!cf->cache) {
DestroyCache(cf);
ShouldCache = 0;
FCLOSE(fp);
return E_NO_MEM;
}
cl = cf->cache;
} else {
cl->next = NEW(CachedLine);
if (!cl->next) {
DestroyCache(cf);
ShouldCache = 0;
FCLOSE(fp);
return E_NO_MEM;
}
cl = cl->next;
}
cl->next = NULL;
cl->LineNo = LineNo;
cl->text = StrDup(s);
if (!cl->text) {
DestroyCache(cf);
ShouldCache = 0;
FCLOSE(fp);
return E_NO_MEM;
}
}
}
/* Put the cached file at the head of the queue */
cf->next = CachedFiles;
CachedFiles = cf;
return OK;
}
/***************************************************************/
/* */
/* PopFile - we've reached the end. Pop up to the previous */
/* file, or return E_EOF */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PopFile(void)
#else
int PopFile()
#endif
{
IncludeStruct *i;
if (!Hush && NumIfs) Eprint("%s", ErrMsg[E_MISS_ENDIF]);
if (!IStackPtr) return E_EOF;
IStackPtr--;
i = &IStack[IStackPtr];
LineNo = i->LineNo;
IfFlags = i->IfFlags;
NumIfs = i->NumIfs;
CLine = i->CLine;
fp = NULL;
STRSET(FileName, i->filename);
if (!CLine && (i->offset != -1L)) {
/* We must open the file, then seek to specified position */
if (strcmp(i->filename, "-"))
fp = fopen(i->filename, "r");
else
fp = stdin;
if (!fp) return E_CANT_OPEN;
if (fp != stdin)
(void) fseek(fp, i->offset, 0); /* Trust that it works... */
}
free(i->filename);
return OK;
}
/***************************************************************/
/* */
/* DoInclude */
/* */
/* The INCLUDE command. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoInclude(ParsePtr p)
#else
int DoInclude(p)
ParsePtr p;
#endif
{
char tok[TOKSIZE];
int r, e;
if ( (r=ParseToken(p, tok)) ) return r;
e = VerifyEoln(p);
if (e) Eprint("%s", ErrMsg[e]);
if ( (r=IncludeFile(tok)) ) return r;
NumIfs = 0;
IfFlags = 0;
return OK;
}
/***************************************************************/
/* */
/* IncludeFile */
/* */
/* Process the INCLUDE command - actually do the file */
/* inclusion. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int IncludeFile(const char *fname)
#else
int IncludeFile(fname)
char *fname;
#endif
{
IncludeStruct *i;
int r;
if (IStackPtr+1 >= INCLUDE_NEST) return E_NESTED_INCLUDE;
i = &IStack[IStackPtr];
i->filename = StrDup(FileName);
if (!i->filename) return E_NO_MEM;
i->LineNo = LineNo;
i->NumIfs = NumIfs;
i->IfFlags = IfFlags;
i->CLine = CLine;
i->offset = -1L;
if (fp) {
i->offset = ftell(fp);
FCLOSE(fp);
}
IStackPtr++;
/* Try to open the new file */
if (!OpenFile(fname)) {
return OK;
}
/* Ugh! We failed! */
if ( (r=PopFile()) ) return r;
Eprint("%s: %s", ErrMsg[E_CANT_OPEN], fname);
return E_CANT_OPEN;
}
/***************************************************************/
/* */
/* GetAccessDate - get the access date of a file. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetAccessDate(char *file)
#else
int GetAccessDate(file)
char *file;
#endif
{
struct stat statbuf;
struct tm *t1;
if (stat(file, &statbuf)) return -1;
#ifdef __TURBOC__
t1 = localtime( (time_t *) &(statbuf.st_atime) );
#else
t1 = localtime(&(statbuf.st_atime));
#endif
if (t1->tm_year + 1900 < BASE)
return 0;
else
return Julian(t1->tm_year+1900, t1->tm_mon, t1->tm_mday);
}
/***************************************************************/
/* */
/* SetAccessDate */
/* */
/* Used only by DOS to set access date after we close the */
/* file. Not needed for UNIX. */
/* */
/***************************************************************/
#if defined(__MSDOS__)
/*
* WARNING WARNING WARNING WARNING
* In the version of Turbo C which I have, there is a bug in the
* stdio.h file. The following lines correct the bug. YOU MAY
* HAVE TO REMOVE THESE LINES FOR LATER VERSIONS OF TURBOC
*/
#ifdef __TURBOC__
#ifndef fileno
#define fileno(f) ((f)->fd)
#endif
#endif
#ifdef HAVE_PROTOS
PUBLIC int SetAccessDate(char *fname, int jul)
#else
int SetAccessDate(fname, jul)
char *fname;
int jul;
#endif
{
#ifdef __TURBOC__
int y, m, d;
struct ftime ft;
FILE *f;
FromJulian(jul, &y, &m, &d);
ft.ft_tsec = 0;
ft.ft_min = 0;
ft.ft_hour = 12; /* Arbitrarily set time to noon. */
ft.ft_day = (unsigned int) d;
ft.ft_month = (unsigned int) m+1;
ft.ft_year = (unsigned int) (y - 1980);
f = fopen(fname, "r");
if (!f || setftime(fileno(f) , &ft)) {
#else /* Must be MSC */
if (utime(fname, (struct utimbuf *) NULL)) {
#endif
fprintf(ErrFp, ErrMsg[M_CANTSET_ACCESS], fname);
#ifdef __TURBOC__
if (f) FCLOSE(f);
#endif
return -1;
}
#ifdef __TURBOC__
FCLOSE(f);
#endif
return 0;
}
#endif /* __MSDOS__ */
/***************************************************************/
/* */
/* DestroyCache */
/* */
/* Free all the memory used by a cached file. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DestroyCache(CachedFile *cf)
#else
static void DestroyCache(cf)
CachedFile *cf;
#endif
{
CachedLine *cl, *cnext;
CachedFile *temp;
if (cf->filename) free(cf->filename);
cl = cf->cache;
while (cl) {
if (cl->text) free (cl->text);
cnext = cl->next;
free(cl);
cl = cnext;
}
if (CachedFiles == cf) CachedFiles = cf->next;
else {
temp = CachedFiles;
while(temp) {
if (temp->next == cf) {
temp->next = cf->next;
break;
}
temp = temp->next;
}
}
free(cf);
}
/***************************************************************/
/* */
/* TopLevel */
/* */
/* Returns 1 if current file is top level, 0 otherwise. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int TopLevel(void)
#else
int TopLevel()
#endif
{
return !IStackPtr;
}

617
finnish.h Normal file
View File

@@ -0,0 +1,617 @@
/***************************************************************/
/* */
/* FINNISH.H */
/* */
/* Support for the Finnish language. */
/* */
/* Author: Mikko Silvonen <Mikko.Silvonen@Helsinki.FI> */
/* */
/* Finnish holidays and name days for Remind are available */
/* at ftp.funet.fi (pub/unix/misc/remind-fin*). */
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993, 1994 by Mikko Silvonen. */
/* REMIND is Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: finnish.h,v 1.1 1996-03-27 03:25:55 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "Finnish"
/* Day names */
#define L_SUNDAY "sunnuntai"
#define L_MONDAY "maanantai"
#define L_TUESDAY "tiistai"
#define L_WEDNESDAY "keskiviikko"
#define L_THURSDAY "torstai"
#define L_FRIDAY "perjantai"
#define L_SATURDAY "lauantai"
/* Day initials - first letter only */
#define L_DAYINIT "SMTKTPL"
/* Month names */
#define L_JAN "tammikuu"
#define L_FEB "helmikuu"
#define L_MAR "maaliskuu"
#define L_APR "huhtikuu"
#define L_MAY "toukokuu"
#if defined(ISOLATIN1)
#define L_JUN "kes\xE4kuu"
#define L_JUL "hein\xE4kuu"
#elif defined(IBMEXTENDED)
#define L_JUN "kes\x84kuu"
#define L_JUL "hein\x84kuu"
#else
#define L_JUN "kes{kuu"
#define L_JUL "hein{kuu"
#endif
#define L_AUG "elokuu"
#define L_SEP "syyskuu"
#define L_OCT "lokakuu"
#define L_NOV "marraskuu"
#define L_DEC "joulukuu"
/* Today and tomorrow */
#if defined(ISOLATIN1)
#define L_TODAY "t\xE4n\xE4\xE4n"
#elif defined(IBMEXTENDED)
#define L_TODAY "t\x84n\x84\x84n"
#else
#define L_TODAY "t{n{{n"
#endif
#define L_TOMORROW "huomenna"
/* The default banner */
#define L_BANNER "Viestit %wna, %d. %mta %y%o:"
/* "am" and "pm" */
#define L_AM "ap"
#define L_PM "ip"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "sitten"
#define L_FROMNOW "kuluttua"
/* "in %d days' time" */
#if defined(ISOLATIN1)
#define L_INXDAYS "%d p\xE4iv\xE4n kuluttua"
#elif defined(IBMEXTENDED)
#define L_INXDAYS "%d p\x84iv\x84n kuluttua"
#else
#define L_INXDAYS "%d p{iv{n kuluttua"
#endif
/* "on" as in "on date...", but in Finnish it is a case ending;
L_PARTIT is the partitive ending appended to -kuu and -tai */
#define L_ON "na"
#define L_PARTIT "ta"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
/* The partitive ending of "day" */
#if defined(ISOLATIN1)
#define L_PLURAL "\xE4"
#elif defined(IBMEXTENDED)
#define L_PLURAL "\x84"
#else
#define L_PLURAL "{"
#endif
/* Minutes, hours, at, etc */
#define L_NOW "nyt"
#define L_AT "klo"
#define L_MINUTE "minuutti"
#define L_HOUR "tunti"
#define L_IS "on"
#define L_WAS "oli"
#define L_AND "ja"
/* What to add to make "hour" plural (or actually partitive) */
#define L_HPLU "a"
/* What to add to make "minute" plural (or actually partitive) */
#define L_MPLU "a"
/* Genitive form of "hour" */
#define L_HGEN "tunnin"
/* Genitive form of "minute" */
#define L_MGEN "minuutin"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#if defined(ISOLATIN1)
#define L_ORDINAL_OVERRIDE switch(d) { \
case 1: plu = ":sen\xE4"; break; \
case 2: plu = ":sena"; break; \
default: \
switch(d%10) { \
case 2: \
case 3: \
case 6: \
case 8: plu = ":ntena"; break; \
default: plu = ":nten\xE4"; break; \
} \
}
#elif defined(IBMEXTENDED)
#define L_ORDINAL_OVERRIDE switch(d) { \
case 1: plu = ":sen\x84"; break; \
case 2: plu = ":sena"; break; \
default: \
switch(d%10) { \
case 2: \
case 3: \
case 6: \
case 8: plu = ":ntena"; break; \
default: plu = ":nten\x84"; break; \
} \
}
#else
#define L_ORDINAL_OVERRIDE switch(d) { \
case 1: plu = ":sen{"; break; \
case 2: plu = ":sena"; break; \
default: \
switch(d%10) { \
case 2: \
case 3: \
case 6: \
case 8: plu = ":ntena"; break; \
default: plu = ":nten{"; break; \
} \
}
#endif
#define L_A_OVER sprintf(s, "%s%s, %d. %s%s %d", DayName[jul%7], L_ON, d, \
MonthName[m], L_PARTIT, y);
#define L_C_OVER sprintf(s, "%s%s", DayName[jul%7], L_ON);
#define L_E_OVER sprintf(s, "%02d%c%02d%c%04d", d, DATESEP, m+1, DATESEP, \
y);
#define L_F_OVER sprintf(s, "%02d%c%02d%c%04d", m+1, DATESEP, d, DATESEP, y);
#define L_G_OVER sprintf(s, "%s%s, %d. %s%s", DayName[jul%7], L_ON, d, \
MonthName[m], L_PARTIT);
#define L_H_OVER sprintf(s, "%02d%c%02d", d, DATESEP, m+1);
#define L_I_OVER sprintf(s, "%02d%c%02d", m+1, DATESEP, d);
#define L_J_OVER sprintf(s, "%s%s, %sn %d%s %d", DayName[jul%7], L_ON, \
MonthName[m], d, plu, y);
#define L_K_OVER sprintf(s, "%s%s, %sn %d%s", DayName[jul%7], L_ON, \
MonthName[m], d, plu);
#define L_L_OVER sprintf(s, "%04d%c%02d%c%02d", y, DATESEP, m+1, DATESEP, d);
#define L_Q_OVER sprintf(s, "n");
#define L_U_OVER sprintf(s, "%s%s, %d%s %s%s %d", DayName[jul%7], L_ON, \
d, plu, MonthName[m], L_PARTIT, y);
#define L_V_OVER sprintf(s, "%s%s, %d%s %s%s", DayName[jul%7], L_ON, d, \
plu, MonthName[m], L_PARTIT);
#define L_1_OVER if (tdiff == 0) \
sprintf(s, L_NOW); \
else { \
if (hdiff != 0) { \
if (tdiff < 0) \
sprintf(s, "%d %s%s ", hdiff, L_HOUR, hplu); \
else \
sprintf(s, "%d %s ", hdiff, L_HGEN); \
s += strlen(s); \
} \
if (mdiff != 0) { \
if (tdiff < 0) \
sprintf(s, "%d %s%s ", mdiff, L_MINUTE, \
mplu); \
else \
sprintf(s, "%d %s ", mdiff, L_MGEN); \
s += strlen(s); \
} \
sprintf(s, when); \
}
#endif /* L_IN_DOSUBST */
/* The next ones are used only when MK_GLOBALS is set */
#ifdef MK_GLOBALS
#define L_ERR_OVERRIDE 1
EXTERN char *ErrMsg[] =
{
#if defined(ISOLATIN1)
"Ok",
"Puuttuva ']'",
"Puuttuva lainausmerkki",
"Liian monimutkainen lauseke - liikaa operaattoreita",
"Liian monimutkainen lauseke - liikaa operandeja",
"Puuttuva ')'",
"M\xE4\xE4rittelem\xE4t\xF6n funktio",
"Virheellinen merkki",
"Kaksipaikkainen operaattori puuttuu",
"Muisti loppui",
"Virheellinen luku",
"Operaattoripino tyhj\xE4 - sis\xE4inen virhe",
"Muuttujapino tyhj\xE4 - sis\xE4inen virhe",
"Tyyppimuunnos ei onnistu",
"Virheellinen tyyppi",
"Liian suuri p\xE4iv\xE4ys",
"Pinovirhe - sis\xE4inen virhe",
"Jako nollalla",
"M\xE4\xE4rittelem\xE4t\xF6n funktio",
"Odottamaton rivin loppu",
"Odottamaton tiedoston loppu",
"Sy\xF6tt\xF6- tai tulostusvirhe",
"Liian pitk\xE4 rivi",
"Sis\xE4inen virhe",
"Virheellinen p\xE4iv\xE4ys",
"Liian v\xE4h\xE4n argumentteja",
"Liian paljon argumentteja",
"Virheellinen aika",
"Liian suuri luku",
"Liian pieni luku",
"Tiedoston avaus ei onnistu",
"Liian monta sis\xE4kk\xE4ist\xE4 INCLUDEa",
"J\xE4sennysvirhe",
"Laukaisuhetken laskenta ei onnistu",
"Liian monta sis\xE4kk\xE4ist\xE4 IF-lausetta",
"ELSE ilman IF-lausetta",
"ENDIF ilman IF-lausetta",
"Kaikkia viikonp\xE4ivi\xE4 ei voi j\xE4tt\xE4\xE4 pois",
"Ylim\xE4\xE4r\xE4isi\xE4 merkkej\xE4 rivill\xE4",
"POP-OMIT-CONTEXT ilman PUSH-OMIT-CONTEXTia",
"RUN-lauseen k\xE4ytt\xF6 estetty",
"Arvoaluevirhe",
"Virheellinen tunniste",
"Rekursiivinen funktiokutsu havaittu",
"",
"J\xE4rjestelm\xE4muuttujan muuttaminen ei onnistu",
"C-kirjastofunktio ei pysty esitt\xE4m\xE4\xE4n p\xE4iv\xE4yst\xE4 tai aikaa",
"Sis\xE4isen funktion m\xE4\xE4ritelm\xE4\xE4 yritettiin muuttaa",
"Lausekkeessa ei voi olla sis\xE4kk\xE4isi\xE4 funktiom\xE4\xE4ritelmi\xE4",
"P\xE4iv\xE4yksen t\xE4ytyy olla t\xE4ydellinen toistokertoimessa",
"Vuosi annettu kahdesti",
"Kuukausi annettu kahdesti",
"P\xE4iv\xE4 annettu kahdesti",
"Tuntematon sana tai merkki",
"OMIT-komennossa on annettava kuukausi ja p\xE4iv\xE4",
"Liian monta osittaista OMIT-komentoa",
"Liian monta t\xE4ydellist\xE4 OMIT-komentoa",
"Varoitus: PUSH-OMIT-CONTEXT ilman POP-OMIT-CONTEXTia",
"Virhe tiedoston luvussa",
"Pilkku puuttuu",
"Virheellinen juutalainen p\xE4iv\xE4ys",
"IIF vaatii parittoman m\xE4\xE4r\xE4n argumentteja",
"Varoitus: puuttuva ENDIF",
"Pilkku puuttuu",
"Viikonp\xE4iv\xE4 annettu kahdesti",
"K\xE4yt\xE4 vain yht\xE4 komennoista BEFORE, AFTER ja SKIP",
"Sis\xE4kk\xE4isi\xE4 MSG-, MSF- ja RUN-lauseita ei voi k\xE4ytt\xE4\xE4 lausekkeessa",
"Toistokerroin annettu kahdesti",
"Delta-arvo annettu kahdesti",
"Peruutusarvo annettu kahdesti",
"ONCE-avainsanaa k\xE4ytetty kahdesti. (Hah.)",
"AT-sanan per\xE4st\xE4 puuttuu aika",
"UNTIL-sanaa k\xE4ytetty kahdesti",
"Ep\xE4t\xE4ydellinen p\xE4iv\xE4ys",
"SCANFROM-sanaa k\xE4ytetty kahdesti",
"Muuttuja",
"Arvo",
"*M\xC4\xC4RITTELEM\xC4T\xD6N*",
"Siirryt\xE4\xE4n funktioon",
"Poistutaan funktiosta",
"Vanhentunut",
"fork() ep\xE4onnistui - jonomuistutukset eiv\xE4t toimi",
"Tiedoston avaus ei onnistu",
"Virheellinen j\xE4rjestelm\xE4p\xE4iv\xE4ys: vuosi on v\xE4hemm\xE4n kuin %d\n",
"Tuntematon virheenetsint\xE4tarkenne '%c'\n",
"Tuntematon tarkenne '%c'\n",
"Tuntematon k\xE4ytt\xE4j\xE4 '%s'\n",
"Ryhm\xE4numeron vaihto %d:ksi ei onnistunut\n",
"K\xE4ytt\xE4j\xE4numeron vaihto %d:ksi ei onnistunut\n",
"Muisti ei riit\xE4 ymp\xE4rist\xF6lle\n",
"Puuttuva '='-merkki",
"Puuttuva muuttujanimi",
"Puuttuva lauseke",
"P\xE4iv\xE4n asetus %s:ksi ei onnitus\n",
"Remind: tarkenne '-i': %s\n",
"Ei viestej\xE4.",
"%d viesti(\xE4) t\xE4m\xE4n p\xE4iv\xE4n jonossa.\n",
#elif defined(IBMEXTENDED)
"Ok",
"Puuttuva ']'",
"Puuttuva lainausmerkki",
"Liian monimutkainen lauseke - liikaa operaattoreita",
"Liian monimutkainen lauseke - liikaa operandeja",
"Puuttuva ')'",
"M\x84\x84rittelem\x84t\x94n funktio",
"Virheellinen merkki",
"Kaksipaikkainen operaattori puuttuu",
"Muisti loppui",
"Virheellinen luku",
"Operaattoripino tyhj\x84 - sis\x84inen virhe",
"Muuttujapino tyhj\x84 - sis\x84inen virhe",
"Tyyppimuunnos ei onnistu",
"Virheellinen tyyppi",
"Liian suuri p\x84iv\x84ys",
"Pinovirhe - sis\x84inen virhe",
"Jako nollalla",
"M\x84\x84rittelem\x84t\x94n funktio",
"Odottamaton rivin loppu",
"Odottamaton tiedoston loppu",
"Sy\x94tt\x94- tai tulostusvirhe",
"Liian pitk\x84 rivi",
"Sis\x84inen virhe",
"Virheellinen p\x84iv\x84ys",
"Liian v\x84h\x84n argumentteja",
"Liian paljon argumentteja",
"Virheellinen aika",
"Liian suuri luku",
"Liian pieni luku",
"Tiedoston avaus ei onnistu",
"Liian monta sis\x84kk\x84ist\x84 INCLUDEa",
"J\x84sennysvirhe",
"Laukaisuhetken laskenta ei onnistu",
"Liian monta sis\x84kk\x84ist\x84 IF-lausetta",
"ELSE ilman IF-lausetta",
"ENDIF ilman IF-lausetta",
"Kaikkia viikonp\x84ivi\x84 ei voi j\x84tt\x84\x84 pois",
"Ylim\x84\x84r\x84isi\x84 merkkej\x84 rivill\x84",
"POP-OMIT-CONTEXT ilman PUSH-OMIT-CONTEXTia",
"RUN-lauseen k\x84ytt\x94 estetty",
"Arvoaluevirhe",
"Virheellinen tunniste",
"Rekursiivinen funktiokutsu havaittu",
"",
"J\x84rjestelm\x84muuttujan muuttaminen ei onnistu",
"C-kirjastofunktio ei pysty esitt\x84m\x84\x84n p\x84iv\x84yst\x84 tai aikaa",
"Sis\x84isen funktion m\x84\x84ritelm\x84\x84 yritettiin muuttaa",
"Lausekkeessa ei voi olla sis\x84kk\x84isi\x84 funktiom\x84\x84ritelmi\x84",
"P\x84iv\x84yksen t\x84ytyy olla t\x84ydellinen toistokertoimessa",
"Vuosi annettu kahdesti",
"Kuukausi annettu kahdesti",
"P\x84iv\x84 annettu kahdesti",
"Tuntematon sana tai merkki",
"OMIT-komennossa on annettava kuukausi ja p\x84iv\x84",
"Liian monta osittaista OMIT-komentoa",
"Liian monta t\x84ydellist\x84 OMIT-komentoa",
"Varoitus: PUSH-OMIT-CONTEXT ilman POP-OMIT-CONTEXTia",
"Virhe tiedoston luvussa",
"Pilkku puuttuu",
"Virheellinen juutalainen p\x84iv\x84ys",
"IIF vaatii parittoman m\x84\x84r\x84n argumentteja",
"Varoitus: puuttuva ENDIF",
"Pilkku puuttuu",
"Viikonp\x84iv\x84 annettu kahdesti",
"K\x84yt\x84 vain yht\x84 komennoista BEFORE, AFTER ja SKIP",
"Sis\x84kk\x84isi\x84 MSG-, MSF- ja RUN-lauseita ei voi k\x84ytt\x84\x84 lausekkeessa",
"Toistokerroin annettu kahdesti",
"Delta-arvo annettu kahdesti",
"Peruutusarvo annettu kahdesti",
"ONCE-avainsanaa k\x84ytetty kahdesti. (Hah.)",
"AT-sanan per\x84st\x84 puuttuu aika",
"UNTIL-sanaa k\x84ytetty kahdesti",
"Ep\x84t\x84ydellinen p\x84iv\x84ys",
"SCANFROM-sanaa k\x84ytetty kahdesti",
"Muuttuja",
"Arvo",
"*M\x8E\x8ERITTELEM\x8ET\x99N*",
"Siirryt\x84\x84n funktioon",
"Poistutaan funktiosta",
"Vanhentunut",
"fork() ep\x84onnistui - jonomuistutukset eiv\x84t toimi",
"Tiedoston avaus ei onnistu",
"Virheellinen j\x84rjestelm\x84p\x84iv\x84ys: vuosi on v\x84hemm\x84n kuin %d\n",
"Tuntematon virheenetsint\x84tarkenne '%c'\n",
"Tuntematon tarkenne '%c'\n",
"Tuntematon k\x84ytt\x84j\x84 '%s'\n",
"Ryhm\x84numeron vaihto %d:ksi ei onnistunut\n",
"K\x84ytt\x84j\x84numeron vaihto %d:ksi ei onnistunut\n",
"Muisti ei riit\x84 ymp\x84rist\x94lle\n",
"Puuttuva '='-merkki",
"Puuttuva muuttujanimi",
"Puuttuva lauseke",
"P\x84iv\x84n asetus %s:ksi ei onnitus\n",
"Remind: tarkenne '-i': %s\n",
"Ei viestej\x84.",
"%d viesti(\x84) t\x84m\x84n p\x84iv\x84n jonossa.\n",
"Numero puuttuu"
#else
"Ok",
"Puuttuva ']'",
"Puuttuva lainausmerkki",
"Liian monimutkainen lauseke - liikaa operaattoreita",
"Liian monimutkainen lauseke - liikaa operandeja",
"Puuttuva ')'",
"M{{rittelem{t|n funktio",
"Virheellinen merkki",
"Kaksipaikkainen operaattori puuttuu",
"Muisti loppui",
"Virheellinen luku",
"Operaattoripino tyhj{ - sis{inen virhe",
"Muuttujapino tyhj{ - sis{inen virhe",
"Tyyppimuunnos ei onnistu",
"Virheellinen tyyppi",
"Liian suuri p{iv{ys",
"Pinovirhe - sis{inen virhe",
"Jako nollalla",
"M{{rittelem{t|n funktio",
"Odottamaton rivin loppu",
"Odottamaton tiedoston loppu",
"Sy|tt|- tai tulostusvirhe",
"Liian pitk{ rivi",
"Sis{inen virhe",
"Virheellinen p{iv{ys",
"Liian v{h{n argumentteja",
"Liian paljon argumentteja",
"Virheellinen aika",
"Liian suuri luku",
"Liian pieni luku",
"Tiedoston avaus ei onnistu",
"Liian monta sis{kk{ist{ INCLUDEa",
"J{sennysvirhe",
"Laukaisuhetken laskenta ei onnistu",
"Liian monta sis{kk{ist{ IF-lausetta",
"ELSE ilman IF-lausetta",
"ENDIF ilman IF-lausetta",
"Kaikkia viikonp{ivi{ ei voi j{tt{{ pois",
"Ylim{{r{isi{ merkkej{ rivill{",
"POP-OMIT-CONTEXT ilman PUSH-OMIT-CONTEXTia",
"RUN-lauseen k{ytt| estetty",
"Arvoaluevirhe",
"Virheellinen tunniste",
"Rekursiivinen funktiokutsu havaittu",
"",
"J{rjestelm{muuttujan muuttaminen ei onnistu",
"C-kirjastofunktio ei pysty esitt{m{{n p{iv{yst{ tai aikaa",
"Sis{isen funktion m{{ritelm{{ yritettiin muuttaa",
"Lausekkeessa ei voi olla sis{kk{isi{ funktiom{{ritelmi{",
"P{iv{yksen t{ytyy olla t{ydellinen toistokertoimessa",
"Vuosi annettu kahdesti",
"Kuukausi annettu kahdesti",
"P{iv{ annettu kahdesti",
"Tuntematon sana tai merkki",
"OMIT-komennossa on annettava kuukausi ja p{iv{",
"Liian monta osittaista OMIT-komentoa",
"Liian monta t{ydellist{ OMIT-komentoa",
"Varoitus: PUSH-OMIT-CONTEXT ilman POP-OMIT-CONTEXTia",
"Virhe tiedoston luvussa",
"Pilkku puuttuu",
"Virheellinen juutalainen p{iv{ys",
"IIF vaatii parittoman m{{r{n argumentteja",
"Varoitus: puuttuva ENDIF",
"Pilkku puuttuu",
"Viikonp{iv{ annettu kahdesti",
"K{yt{ vain yht{ komennoista BEFORE, AFTER ja SKIP",
"Sis{kk{isi{ MSG-, MSF- ja RUN-lauseita ei voi k{ytt{{ lausekkeessa",
"Toistokerroin annettu kahdesti",
"Delta-arvo annettu kahdesti",
"Peruutusarvo annettu kahdesti",
"ONCE-avainsanaa k{ytetty kahdesti. (Hah.)",
"AT-sanan per{st{ puuttuu aika",
"UNTIL-sanaa k{ytetty kahdesti",
"Ep{t{ydellinen p{iv{ys",
"SCANFROM-sanaa k{ytetty kahdesti",
"Muuttuja",
"Arvo",
"*M[[RITTELEM[T\\N*",
"Siirryt{{n funktioon",
"Poistutaan funktiosta",
"Vanhentunut",
"fork() ep{onnistui - jonomuistutukset eiv{t toimi",
"Tiedoston avaus ei onnistu",
"Virheellinen j{rjestelm{p{iv{ys: vuosi on v{hemm{n kuin %d\n",
"Tuntematon virheenetsint{tarkenne '%c'\n",
"Tuntematon tarkenne '%c'\n",
"Tuntematon k{ytt{j{ '%s'\n",
"Ryhm{numeron vaihto %d:ksi ei onnistunut\n",
"K{ytt{j{numeron vaihto %d:ksi ei onnistunut\n",
"Muisti ei riit{ ymp{rist|lle\n",
"Puuttuva '='-merkki",
"Puuttuva muuttujanimi",
"Puuttuva lauseke",
"P{iv{n asetus %s:ksi ei onnitus\n",
"Remind: tarkenne '-i': %s\n",
"Ei viestej{.",
"%d viesti({) t{m{n p{iv{n jonossa.\n",
"Numero puuttuu"
#endif
};
#endif /* MK_GLOBALS */
/* The following is only used in init.c */
#ifdef L_IN_INIT
#define L_USAGE_OVERRIDE 1
#ifdef HAVE_PROTOS
PUBLIC void Usage(void)
#else
void Usage()
#endif /* HAVE_PROTOS */
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1994 by David F. Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETAVERSIO <<<<\n");
#endif
#if defined(ISOLATIN1)
fprintf(ErrFp, "K\xE4ytt\xF6: remind [tarkenteet] tiedosto [p\xE4iv\xE4ys] [aika] [*toisto]\n");
fprintf(ErrFp, "Tarkenteet:\n");
fprintf(ErrFp, " -n Tulosta viestien seuraavat esiintymiskerrat yksink. muodossa\n");
fprintf(ErrFp, " -r Est\xE4 RUN-lauseiden k\xE4ytt\xF6\n");
fprintf(ErrFp, " -c[n] Tulosta n:n kuukauden kalenteri (oletus 1)\n");
fprintf(ErrFp, " -c+[n] Tulosta n:n viikon kalenteri (oletus 1)\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Aseta kalenterin leveys, tasaus ja v\xE4lit\n");
fprintf(ErrFp, " -s[+][n] Tulosta n:n kuukauden (viikon) 'yksink. kalenteri' (oletus 1)\n");
fprintf(ErrFp, " -p[n] Kuten -s, mutta tulosta rem2ps:lle sopivassa muodossa\n");
fprintf(ErrFp, " -v Laveat tulostukset\n");
fprintf(ErrFp, " -o \xC4l\xE4 noudata ONCE-lauseita\n");
fprintf(ErrFp, " -t Laukaise kaikki viestit deltan arvosta v\xE4litt\xE4m\xE4tt\xE4\n");
fprintf(ErrFp, " -h Suppeat tulostukset\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a \xC4l\xE4 laukaise viestej\xE4 heti - lis\xE4\xE4 ne jonoon\n");
fprintf(ErrFp, " -q \xC4l\xE4 lis\xE4\xE4 viestej\xE4 jonoon\n");
fprintf(ErrFp, " -f Laukaise viestit, pysy etualalla\n");
fprintf(ErrFp, " -z[n] K\xE4ynnisty demonina, her\xE4tys n:n (5:n) minuutin v\xE4lein\n");
#endif
fprintf(ErrFp, " -d... Virheenetsint\xE4: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n");
fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n");
fprintf(ErrFp, " -x[n] SATISFY-lauseen toistoraja (oletus 150)\n");
fprintf(ErrFp, " -kcmd Suorita 'cmd' MSG-tyyppisille viesteille\n");
fprintf(ErrFp, " -g[ddd] Lajittele viestit p\xE4iv\xE4yksen, ajan ja t\xE4rkeyden mukaan\n");
fprintf(ErrFp, " -ivar=val Alusta muuttuja var arvolla val ja s\xE4ilyt\xE4 var\n");
fprintf(ErrFp, " -m Aloita kalenteri maanantaista eik\xE4 sunnuntaista\n");
exit(1);
#elif defined(IBMEXTENDED)
fprintf(ErrFp, "K\x84ytt\x94: remind [tarkenteet] tiedosto [p\x84iv\x84ys] [aika] [*toisto]\n");
fprintf(ErrFp, "Tarkenteet:\n");
fprintf(ErrFp, " -n Tulosta viestien seuraavat esiintymiskerrat yksink. muodossa\n");
fprintf(ErrFp, " -r Est\x84 RUN-lauseiden k\x84ytt\x94\n");
fprintf(ErrFp, " -c[n] Tulosta n:n kuukauden kalenteri (oletus 1)\n");
fprintf(ErrFp, " -c+[n] Tulosta n:n viikon kalenteri (oletus 1)\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Aseta kalenterin leveys, tasaus ja v\x84lit\n");
fprintf(ErrFp, " -s[+][n] Tulosta n:n kuukauden (viikon) 'yksink. kalenteri' (oletus 1)\n");
fprintf(ErrFp, " -p[n] Kuten -s, mutta tulosta rem2ps:lle sopivassa muodossa\n");
fprintf(ErrFp, " -v Laveat tulostukset\n");
fprintf(ErrFp, " -o \x8El\x84 noudata ONCE-lauseita\n");
fprintf(ErrFp, " -t Laukaise kaikki viestit deltan arvosta v\x84litt\x84m\x84tt\x84\n");
fprintf(ErrFp, " -h Suppeat tulostukset\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a \x8El\x84 laukaise viestej\x84 heti - lis\x84\x84 ne jonoon\n");
fprintf(ErrFp, " -q \x8El\x84 lis\x84\x84 viestej\x84 jonoon\n");
fprintf(ErrFp, " -f Laukaise viestit, pysy etualalla\n");
fprintf(ErrFp, " -z[n] K\x84ynnisty demonina, her\x84tys n:n (5:n) minuutin v\x84lein\n");
#endif
fprintf(ErrFp, " -d... Virheenetsint\x84: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n");
fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n");
fprintf(ErrFp, " -x[n] SATISFY-lauseen toistoraja (oletus 150)\n");
fprintf(ErrFp, " -kcmd Suorita 'cmd' MSG-tyyppisille viesteille\n");
fprintf(ErrFp, " -g[ddd] Lajittele viestit p\x84iv\x84yksen, ajan ja t\x84rkeyden mukaan\n");
fprintf(ErrFp, " -ivar=val Alusta muuttuja var arvolla val ja s\x84ilyt\x84 var\n");
fprintf(ErrFp, " -m Aloita kalenteri maanantaista eik\x84 sunnuntaista\n");
exit(1);
#else
fprintf(ErrFp, "K{ytt|: remind [tarkenteet] tiedosto [p{iv{ys] [aika] [*toisto]\n");
fprintf(ErrFp, "Tarkenteet:\n");
fprintf(ErrFp, " -n Tulosta viestien seuraavat esiintymiskerrat yksink. muodossa\n");
fprintf(ErrFp, " -r Est{ RUN-lauseiden k{ytt|\n");
fprintf(ErrFp, " -c[n] Tulosta n:n kuukauden kalenteri (oletus 1)\n");
fprintf(ErrFp, " -c+[n] Tulosta n:n viikon kalenteri (oletus 1)\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Aseta kalenterin leveys, tasaus ja v{lit\n");
fprintf(ErrFp, " -s[+][n] Tulosta n:n kuukauden (viikon) 'yksink. kalenteri' (oletus 1)\n");
fprintf(ErrFp, " -p[n] Kuten -s, mutta tulosta rem2ps:lle sopivassa muodossa\n");
fprintf(ErrFp, " -v Laveat tulostukset\n");
fprintf(ErrFp, " -o [l{ noudata ONCE-lauseita\n");
fprintf(ErrFp, " -t Laukaise kaikki viestit deltan arvosta v{litt{m{tt{\n");
fprintf(ErrFp, " -h Suppeat tulostukset\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a [l{ laukaise viestej{ heti - lis{{ ne jonoon\n");
fprintf(ErrFp, " -q [l{ lis{{ viestej{ jonoon\n");
fprintf(ErrFp, " -f Laukaise viestit, pysy etualalla\n");
fprintf(ErrFp, " -z[n] K{ynnisty demonina, her{tys n:n (5:n) minuutin v{lein\n");
#endif
fprintf(ErrFp, " -d... Virheenetsint{: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Ohjaa virhetulostus stdout-vuohon\n");
fprintf(ErrFp, " -b[n] Ajan ilmaisu: 0=ap/ip, 1=24 tuntia, 2=ei aikoja\n");
fprintf(ErrFp, " -x[n] SATISFY-lauseen toistoraja (oletus 150)\n");
fprintf(ErrFp, " -kcmd Suorita 'cmd' MSG-tyyppisille viesteille\n");
fprintf(ErrFp, " -g[ddd] Lajittele viestit p{iv{yksen, ajan ja t{rkeyden mukaan\n");
fprintf(ErrFp, " -ivar=val Alusta muuttuja var arvolla val ja s{ilyt{ var\n");
fprintf(ErrFp, " -m Aloita kalenteri maanantaista eik{ sunnuntaista\n");
exit(1);
#endif
}
#endif /* L_IN_INIT */

426
french.h Normal file
View File

@@ -0,0 +1,426 @@
/***************************************************************/
/* */
/* FRENCH.H */
/* */
/* Support for the French language. */
/* */
/* Contributed by Laurent Duperval. */
/* */
/* This file is part of REMIND. */
/* */
/* REMIND is Copyright (C) 1992-1996 by David F. Skoll */
/* This file is Copyright (C) 1993 by Laurent Duperval and */
/* David F. Skoll. */
/* */
/***************************************************************/
/* $Id: french.h,v 1.1 1996-03-27 03:25:55 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "French"
/* Day names */
#define L_SUNDAY "dimanche"
#define L_MONDAY "lundi"
#define L_TUESDAY "mardi"
#define L_WEDNESDAY "mercredi"
#define L_THURSDAY "jeudi"
#define L_FRIDAY "vendredi"
#define L_SATURDAY "samedi"
/* Day initials - first letter only */
#define L_DAYINIT "dlmmjvs"
/* Month names */
#define L_JAN "janvier"
#ifdef ISOLATIN1
#define L_FEB "f\351vrier"
#else
#define L_FEB "fevrier"
#endif
#define L_MAR "mars"
#define L_APR "avril"
#define L_MAY "mai"
#define L_JUN "juin"
#define L_JUL "juillet"
#ifdef ISOLATIN1
#define L_AUG "ao\373t"
#else
#define L_AUG "aout"
#endif
#define L_SEP "septembre"
#define L_OCT "octobre"
#define L_NOV "novembre"
#ifdef ISOLATIN1
#define L_DEC "d\351cembre"
#else
#define L_DEC "decembre"
#endif
/* Today and tomorrow */
#define L_TODAY "aujourd'hui"
#define L_TOMORROW "demain"
/* The default banner */
#define L_BANNER "Rappels pour %w, %d%s %m, %y%o:"
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "il y a"
#define L_FROMNOW "dans"
/* "in %d days' time" */
#define L_INXDAYS "dans %d jours"
/* "on" as in "on date..." */
#define L_ON "le"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL "s"
/* Minutes, hours, at, etc */
#define L_NOW "maintenant"
#ifdef ISOLATIN1
#define L_AT "\340"
#else
#define L_AT "a"
#endif
#define L_MINUTE "minute"
#define L_HOUR "heure"
#define L_IS "est"
#ifdef ISOLATIN1
#define L_WAS "\351tait"
#else
#define L_WAS "etait"
#endif
#define L_AND "et"
/* What to add to make "hour" plural */
#define L_HPLU "s"
/* What to add to make "minute" plural */
#define L_MPLU "s"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#define L_ORDINAL_OVERRIDE \
switch(d) { \
case 1: plu = "er"; break; \
\
default: plu = ""; break; \
}
#define L_1_OVER \
if (tdiff == 0) \
sprintf(s, L_NOW); \
else if (tdiff < 0) { \
if (mdiff == 0) \
sprintf(s, "il y a %d heure%s", hdiff, hplu); \
else if (hdiff == 0) \
sprintf(s, "il y a %d minute%s", mdiff, mplu); \
else \
sprintf(s, "il y a %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
} else { \
if (mdiff == 0) \
sprintf(s, "dans %d heure%s", hdiff, hplu); \
else if (hdiff == 0) \
sprintf(s, "dans %d minute%s", mdiff, mplu); \
else \
sprintf(s, "dans %d heure%s et %d minute%s", hdiff, hplu, mdiff, mplu); \
}
#define L_J_OVER \
sprintf(s, "%s %s, %d%s %s, %d", L_ON, DayName[jul%7], \
d, plu, MonthName[m], y);
#define L_K_OVER \
sprintf(s, "%s %s, %d%s %s", L_ON, DayName[jul%7], \
d, plu, MonthName[m]);
#endif /* L_IN_DOSUBST */
/* The next ones are used only when MK_GLOBALS is set */
#ifdef MK_GLOBALS
#define L_ERR_OVERRIDE 1
EXTERN char *ErrMsg[] =
{
#ifdef ISOLATIN1
"Ok",
"']' manquant",
"Apostrophe manquant",
"Expression trop complexe - trop d'op\351rateurs",
"Expression trop complexe - trop d'op\351randes",
"')' manquante",
"Fonction non-d\351finie",
"Caract\350re ill\351gal",
"Op\351rateur binaire attendu",
"Manque de m\351moire",
"Nombre mal form\351",
"Erreur interne - 'underflow' de la pile d'op\351rateurs",
"Erreur interne - 'underflow' de la pile de variables",
"Impossible de convertir",
"Types non-\351quivalents",
"D\351bordement de date",
"Erreur interne - erreur de pile",
"Division par z\351ro",
"Variable non d\351finie",
"Fin de ligne non attendue",
"Fin de fichier non attendue",
"Erreur I/O",
"Ligne trop longue",
"Erreur interne",
"Mauvaise date sp\351cifi\351e",
"Pas assez d'arguments",
"Trop d'arguments",
"Heure mal form\351e",
"Nombre trop \351lev\351",
"Nombre trop bas",
"Impossible d'ouvrir le fichier",
"Trop d'INCLUDE imbriqu\351s",
"Erreur d'analyse",
"Impossible de calculer le d\351clenchement",
"Trop de IF imbriqu\351s",
"ELSE sans IF correspondant",
"ENDIF sans IF correspondant",
"Impossible d'omettre (OMIT) tous les jours",
"El\351ment(s) \351tranger(s) sur la ligne",
"POP-OMIT-CONTEXT sans PUSH-OMIT-CONTEXT correspondant",
"RUN d\351activ\351",
"Erreur de domaine",
"Identificateur invalide",
"Appel r\351cursif d\351tect\351",
"",
"Impossible de modifier une variable syst\350me",
"Fonction de la librairie C ne peut repr\351senter la date/l'heure",
"Tentative de red\351finition d'une fonction intrins\350que",
"Impossible d'imbriquer une d\351finition de fonction dans une expression",
"Pour utiliser le facteur de r\351p\351tition la date doit \352tre sp\351cifi\351e au complet",
"Ann\351e sp\351cifi\351e deux fois",
"Mois sp\351cifi\351 deux fois",
"Jour sp\351cifi\351 deux fois",
"El\351ment inconnu",
"Mois et jour doivent \352tre sp\351cifi\351s dans commande OMIT",
"Trop de OMITs partiels",
"Trop de OMITs complets",
"Attention: PUSH-OMIT-CONTEXT sans POP-OMIT-CONTEXT correspondant",
"Erreur \340 la lecture du fichier",
"Fin de ligne attendue",
"Date h\351breuse invalide",
"IIF demande nombre d'arguments impair",
"Attention: ENDIF manquant",
"Virgule attendue",
"Jour de la semaine sp\351cifi\351 deux fois",
"Utiliser un seul parmi BEFORE, AFTER ou SKIP",
"Impossible d'imbriquer MSG, MSF, RUN, etc. dans une expression",
"Valeur de r\351p\351tition sp\351cifi\351e deux fois",
"Valeur delta sp\351cifi\351e deux fois",
"Valeur de retour sp\351cifi\351e deux fois",
"Mot-cl\351 ONCE utilis\351 deux fois. (Hah.)",
"Heure attendue apr\350s AT",
"Mot-cl\351 UNTIL utilis\351 deux fois",
"Sp\351cification de date incompl\350te",
"Mot-cl\351 SCANFROM utilis\351 deux fois",
"Variable",
"Valeur",
"*NON-DEFINI*",
"Entr\351e dans UserFN",
"Sortie de UserFN",
"Expir\351",
"fork() \351chou\351 - impossible de faire les appels en queue",
"Impossible d'acc\351der au fichier",
"Date syst\350me ill\351gale: Ann\351e est inf\351rieure \340 %d\n",
"Option de d\351verminage inconnue '%c'\n",
"Option inconnue '%c'\n",
"Usager inconnu '%s'\n",
"Impossible de changer gid pour %d\n",
"Impossible de changer uid pour %d\n",
"Manque de m\351moire pour environnement\n",
"Signe '=' manquant",
"Nom de variable absent",
"Expression absente",
"Impossible de changer la date d'acc\350s de %s\n",
"Remind: '-i' option: %s\n",
"Pas de rappels.",
"%d rappel(s) en file pour aujourd'hui.\n",
"Nombre attendu"
#else /* ISOLATIN1 */
"Ok",
"']' manquant",
"Apostrophe manquant",
"Expression trop complexe - trop d'operateurs",
"Expression trop complexe - trop d'operandes",
"')' manquante",
"Fonction non-definie",
"Caractere illegal",
"Operateur binaire attendu",
"Manque de memoire",
"Nombre mal forme",
"Erreur interne - 'underflow' de la pile d'operateurs",
"Erreur interne - 'underflow' de la pile de variables",
"Impossible de convertir",
"Types non-equivalents",
"Debordement de date",
"Erreur interne - erreur de pile",
"Division par zero",
"Variable non definie",
"Fin de ligne non attendue",
"Fin de fichier non attendue",
"Erreur I/O",
"Ligne trop longue",
"Erreur interne",
"Mauvaise date specifiee",
"Pas assez d'arguments",
"Trop d'arguments",
"Heure mal formee",
"Nombre trop eleve",
"Nombre trop bas",
"Impossible d'ouvrir le fichier",
"Trop d'INCLUDE imbriques",
"erreur d'analyse",
"Impossible de calculer le declenchement",
"Trop de IF imbriques",
"ELSE sans IF correspondant",
"ENDIF sans IF correspondant",
"Impossible d'omettre (OMIT) tous les jours",
"Element(s) etranger(s) sur la ligne",
"POP-OMIT-CONTEXT sans PUSH-OMIT-CONTEXT correspondant",
"RUN desactive",
"Erreur de domaine",
"Identificateur invalide",
"Appel recursif detecte",
"",
"Impossible de modifier une variable systeme",
"Fonction de la librairie C ne peut representer la date/l'heure",
"Tentative de redefinition d'une fonction intrinseque",
"Impossible d'imbriquer une definition de fonction dans une expression",
"Pour utiliser le facteur de repetition la date doit etre specifiee au complet",
"Annee specifiee deux fois",
"Mois specifie deux fois",
"Jour specifie deux fois",
"Element inconnu",
"Mois et jour doivent etre specifies dans commande OMIT",
"Trop de OMITs partiels",
"Trop de OMITs complets",
"Attention: PUSH-OMIT-CONTEXT sans POP-OMIT-CONTEXT correspondant",
"Erreur a la lecture du fichier",
"Fin de ligne attendue",
"Date hebreuse invalide",
"IIF demande nombre d'arguments impair",
"Attention: ENDIF manquant",
"Virgule attendue",
"Jour de la semaine specifie deux fois",
"Utiliser un seul parmi BEFORE, AFTER ou SKIP",
"Impossible d'imbriquer MSG, MSF, RUN, etc. dans une expression",
"Valeur de repetition specifiee deux fois",
"Valeur delta specifiee deux fois",
"Valeur de retour specifiee deux fois",
"Mot-cle ONCE utilise deux fois. (Hah.)",
"Heure attendue apres AT",
"Mot-cle UNTIL utilise deux fois",
"Specification de date incomplete",
"Mot-cle SCANFROM utilise deux fois",
"Variable",
"Valeur",
"*NON-DEFINI*",
"Entree dans UserFN",
"Sortie de UserFN",
"Expire",
"fork() echoue - impossible de faire les appels en queue",
"Impossible d'acceder au fichier",
"Date systeme illegale: Annee est inferieure a %d\n",
"Option de deverminage inconnue '%c'\n",
"Option inconnue '%c'\n",
"Usager inconnu '%s'\n",
"Impossible de changer gid pour %d\n",
"Impossible de changer uid pour %d\n",
"Manque de memoire pour environnement\n",
"Signe '=' manquant",
"Nom de variable absent",
"Expression absente",
"Impossible de changer la date d'acces de %s\n",
"Remind: '-i' option: %s\n",
"Pas de rappels.",
"%d rappel(s) en file pour aujourd'hui.\n",
"Nombre attendu"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
/* The following is only used in init.c */
#ifdef L_IN_INIT
#define L_USAGE_OVERRIDE 1
#ifdef HAVE_PROTOS
PUBLIC void Usage(void)
#else
void Usage()
#endif /* HAVE_PROTOS */
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1996 by David F. Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
#ifdef ISOLATIN1
fprintf(ErrFp, "\nUtilisation: remind [options] fichier [date] [heure] [*r\351p\351tition]\n");
fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Afficher la prochaine occurence des rappels en format simple\n");
fprintf(ErrFp, " -r D\351sactiver les instructions RUN\n");
fprintf(ErrFp, " -c[n] Produire un calendrier pour n (d\351faut 1) mois\n");
fprintf(ErrFp, " -c+[n] Produire un calendrier pour n (d\351faut 1) semaines\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Sp\351cifier largeur, remplissage et espacement du calendrier\n");
fprintf(ErrFp, " -s[+][n] Produire un 'calendrier simple' pour n (1) mois (semaines)\n");
fprintf(ErrFp, " -p[n] Comme -s, mais avec entr\351e compatible avec rem2ps\n");
fprintf(ErrFp, " -v Mode verbeux\n");
fprintf(ErrFp, " -o Ignorer instructions ONCE\n");
fprintf(ErrFp, " -t D\351clencher tous les rappels peu importe le delta\n");
fprintf(ErrFp, " -h Mode silencieux\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a Ne pas d\351clencher les rappels minut\351s imm\351diatement - les mettre en file\n");
fprintf(ErrFp, " -q Ne pas mettre les rappels minut\351s en file\n");
fprintf(ErrFp, " -f D\351clencher les rappels minut\351s imm\351diatement en restant en avant-plan\n");
fprintf(ErrFp, " -z[n] Entrer en mode 'daemon', r\351veil chaque n (5) minutes\n");
#endif
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Envoyer les messages de stderr \340 stdout\n");
fprintf(ErrFp, " -b[n] Formats de l'heure pour le calendrier: 0=am/pm, 1=24hr, 2=aucun\n");
fprintf(ErrFp, " -x[n] Limite d'it\351rations pour la clause SATISFY (def=150)\n");
fprintf(ErrFp, " -kcmd Ex\351cuter 'cmd' pour les rappels de type MSG\n");
fprintf(ErrFp, " -g[ddd] Trier les rappels par date, heure et priorit\351 avant d'\351mettre\n");
fprintf(ErrFp, " -ivar=val Initialiser var \340 val et conserver var\n");
fprintf(ErrFp, " -m Commencer le calendrier avec lundi plut\364t que dimanche\n");
#else /* ISOLATIN1 */
fprintf(ErrFp, "\nUtilisation: remind [options] fichier [date] [heure] [*repetition]\n");
fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Afficher la prochaine occurence des rappels en format simple\n");
fprintf(ErrFp, " -r Desactiver les instructions RUN\n");
fprintf(ErrFp, " -c[n] Produire un calendrier pour n (defaut 1) mois\n");
fprintf(ErrFp, " -c+[n] Produire un calendrier pour n (defaut 1) semaines\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Specifier largeur, remplissage et espacement du calendrier\n");
fprintf(ErrFp, " -s[+][n] Produire un 'calendrier simple' pour n (1) mois (semaines)\n");
fprintf(ErrFp, " -p[n] Comme -s, mais avec entree compatible avec rem2ps\n");
fprintf(ErrFp, " -v Mode verbeux\n");
fprintf(ErrFp, " -o Ignorer instructions ONCE\n");
fprintf(ErrFp, " -t Declencher tous les rappels peu importe le delta\n");
fprintf(ErrFp, " -h Mode silencieux\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a Ne pas declencher les rappels minutes immediatement - les mettre en file\n");
fprintf(ErrFp, " -q Ne pas mettre les rappels minutes en file\n");
fprintf(ErrFp, " -f Declencher les rappels minutes immediatement en restant en avant-plan\n");
fprintf(ErrFp, " -z[n] Entrer en mode 'daemon', reveil chaque n (5) minutes\n");
#endif
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Envoyer les messages de stderr a stdout\n");
fprintf(ErrFp, " -b[n] Formats de l'heure pour le calendrier: 0=am/pm, 1=24hr, 2=aucun\n");
fprintf(ErrFp, " -x[n] Limite d'iterations pour la clause SATISFY (def=150)\n");
fprintf(ErrFp, " -kcmd Executer 'cmd' pour les rappels de type MSG\n");
fprintf(ErrFp, " -g[ddd] Trier les rappels par date, heure et priorite avant d'emettre\n");
fprintf(ErrFp, " -ivar=val Initialiser var a val et conserver var\n");
fprintf(ErrFp, " -m Commencer le calendrier avec lundi plutot que dimanche\n");
#endif /* ISOLATIN1 */
exit(1);
}
#endif /* L_IN_INIT */

2358
funcs.c Normal file

File diff suppressed because it is too large Load Diff

105
german.h Normal file
View File

@@ -0,0 +1,105 @@
/***************************************************************/
/* */
/* GERMAN.H */
/* */
/* Support for the German language. */
/* */
/* This file was derived from a patch submitted by Wolfgang */
/* Thronicke. I don't guarantee that there are no mistakes - */
/* I don't speak German. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: german.h,v 1.1 1996-03-27 03:25:56 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "German"
/* Day names */
#define L_SUNDAY "Sonntag"
#define L_MONDAY "Montag"
#define L_TUESDAY "Dienstag"
#define L_WEDNESDAY "Mittwoch"
#define L_THURSDAY "Donnerstag"
#define L_FRIDAY "Freitag"
#define L_SATURDAY "Samstag"
/* Day initials - first letter only */
#define L_DAYINIT "SMDMDFS"
/* Month names */
#define L_JAN "Januar"
#define L_FEB "Februar"
#ifdef ISOLATIN1
# define L_MAR "M\344rz"
#else
# define L_MAR "Maerz"
#endif
#define L_APR "April"
#define L_MAY "Mai"
#define L_JUN "Juni"
#define L_JUL "Juli"
#define L_AUG "August"
#define L_SEP "September"
#define L_OCT "Oktober"
#define L_NOV "November"
#define L_DEC "Dezember"
/* Today and tomorrow */
#define L_TODAY "heute"
#define L_TOMORROW "morgen"
/* The default banner */
#ifdef ISOLATIN1
# define L_BANNER "Termine f\374r %w, den %d. %m %y%o:"
#else
# define L_BANNER "Termine fuer %w, den %d. %m %y%o:"
#endif
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "vorher"
#define L_FROMNOW "von heute"
/* "in %d days' time" */
#define L_INXDAYS "in %d Tagen"
/* "on" as in "on date..." */
#define L_ON "am"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL "en"
/* Minutes, hours, at, etc */
#define L_NOW "jetzt"
#define L_AT "um"
#define L_MINUTE "Minute"
#define L_HOUR "Stunde"
#define L_IS "ist"
#define L_WAS "war"
#define L_AND "und"
/* What to add to make "hour" plural */
#define L_HPLU "n"
/* What to add to make "minute" plural */
#define L_MPLU "n"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#define L_AMPM_OVERRIDE(ampm, hour) ampm = (hour < 12) ? (hour<5) ? " nachts" : " vormittags" : (hour > 17) ? " abends" : " nachmittags";
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
#define L_G_OVER sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER
#endif /* L_IN_DOSUBST */

22
globals.c Normal file
View File

@@ -0,0 +1,22 @@
/***************************************************************/
/* */
/* GLOBALS.C */
/* */
/* This file simply instantiates all of the global variables. */
/* */
/* It does this by #defining MK_GLOBALS and #including */
/* globals.h and err.h */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: globals.c,v 1.1 1996-03-27 03:25:57 dfs Exp $";
#include "config.h"
#include <stdio.h> /* For defintion of FILE - sigh! */
#include "types.h"
#define MK_GLOBALS
#include "globals.h"
#include "err.h"

182
globals.h Normal file
View File

@@ -0,0 +1,182 @@
/***************************************************************/
/* */
/* GLOBALS.H */
/* */
/* This function contains declarations of global variables. */
/* They are instantiated in main.c by defining */
/* MK_GLOBALS. Also contains useful macro definitions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: globals.h,v 1.1 1996-03-27 03:25:57 dfs Exp $ */
#ifdef MK_GLOBALS
#undef EXTERN
#define EXTERN
#define INIT(var, val) var = val
#else
#undef EXTERN
#define EXTERN extern
#define INIT(var, val) var
#endif
#define DaysInYear(y) (((y) % 4) ? 365 : ((!((y) % 100) && ((y) % 400)) ? 365 : 366 ))
#define IsLeapYear(y) (((y) % 4) ? 0 : ((!((y) % 100) && ((y) % 400)) ? 0 : 1 ))
#define DaysInMonth(m, y) ((m) != 1 ? MonthDays[m] : 28 + IsLeapYear(y))
#define DestroyValue(x) (void) (((x).type == STR_TYPE && (x).v.str) ? (free((x).v.str),(x).type = ERR_TYPE) : 0)
EXTERN int JulianToday;
EXTERN int RealToday;
EXTERN int CurDay;
EXTERN int CurMon;
EXTERN int CurYear;
EXTERN int LineNo;
EXTERN int FreshLine;
EXTERN char LineBuffer[LINELEN];
EXTERN char SubstBuffer[LINELEN];
EXTERN char TokBuffer[TOKSIZE+1];
EXTERN INIT( char *MsgCommand, NULL);
EXTERN INIT( int ShowAllErrors, 0);
EXTERN INIT( int DebugFlag, 0);
EXTERN INIT( int DoCalendar, 0);
EXTERN INIT( int DoSimpleCalendar, 0);
EXTERN INIT( int MondayFirst, 0);
EXTERN INIT( int Iterations, 1);
EXTERN INIT( int PsCal, 0);
EXTERN INIT( int CalWidth, 80);
EXTERN INIT( int CalWeeks, 0);
EXTERN INIT( int CalMonths, 0);
EXTERN INIT( int Hush, 0);
EXTERN INIT( int NextMode, 0);
EXTERN INIT( int InfiniteDelta, 0);
EXTERN INIT( int RunDisabled, 0);
EXTERN INIT( int IgnoreOnce, 0);
EXTERN INIT( int SortByTime, 0);
EXTERN INIT( int SortByDate, 0);
EXTERN INIT( int SortByPrio, 0);
EXTERN INIT( int DefaultPrio, NO_PRIORITY);
EXTERN INIT( long SysTime, -1L);
EXTERN char *InitialFile;
EXTERN int FileAccessDate;
EXTERN INIT( int DontFork, 0);
EXTERN INIT( int DontQueue, 0);
EXTERN INIT( int NumQueued, 0);
EXTERN INIT( int DontIssueAts, 0);
EXTERN INIT( int Daemon, 0);
EXTERN INIT( int ScFormat, SC_AMPM);
EXTERN INIT( int MaxSatIter, 150);
EXTERN INIT( char *FileName, NULL);
EXTERN INIT( int UseStdin, 0);
EXTERN FILE *ErrFp;
EXTERN INIT( int NumIfs, 0);
EXTERN INIT( unsigned int IfFlags, 0);
EXTERN INIT( int LastTriggerDate, 0);
EXTERN INIT( int LastTrigValid, 0);
EXTERN INIT( int LastTriggerTime, 0);
EXTERN INIT( int ShouldCache, 0);
EXTERN char *CurLine;
EXTERN INIT( int NumTriggered, 0);
EXTERN int ArgC;
EXTERN char **ArgV;
EXTERN INIT( int CalLines, CAL_LINES);
EXTERN INIT( int CalPad, 1);
/* Latitude and longitude */
EXTERN INIT( int LatDeg, LAT_DEG);
EXTERN INIT( int LatMin, LAT_MIN);
EXTERN INIT( int LatSec, LAT_SEC);
EXTERN INIT( int LongDeg, LON_DEG);
EXTERN INIT( int LongMin, LON_MIN);
EXTERN INIT( int LongSec, LON_SEC);
EXTERN INIT( char *Location, LOCATION);
/* UTC calculation stuff */
EXTERN INIT( int MinsFromUTC, 0);
EXTERN INIT( int CalculateUTC, 1);
EXTERN INIT( int FoldYear, 0);
/* Parameters for formatting MSGF reminders */
EXTERN INIT( int FormWidth, 72);
EXTERN INIT( int FirstIndent, 0);
EXTERN INIT( int SubsIndent, 0);
EXTERN INIT( char *EndSent, ".?!");
EXTERN INIT( char *EndSentIg, "\"')]}>");
/* We need the language stuff here... */
#include "lang.h"
EXTERN INIT( char Banner[LINELEN], L_BANNER);
/* List of months */
EXTERN char *EnglishMonthName[]
#ifdef MK_GLOBALS
= {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"}
#endif
;
#if LANG == ENGLISH
#define MonthName EnglishMonthName
#else
EXTERN char *MonthName[]
#ifdef MK_GLOBALS
= {L_JAN, L_FEB, L_MAR, L_APR, L_MAY, L_JUN,
L_JUL, L_AUG, L_SEP, L_OCT, L_NOV, L_DEC}
#endif
;
#endif
EXTERN char *EnglishDayName[]
#ifdef MK_GLOBALS
= {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday", "Sunday"}
#endif
;
#if LANG == ENGLISH
#define DayName EnglishDayName
#else
EXTERN char *DayName[]
#ifdef MK_GLOBALS
= {L_MONDAY, L_TUESDAY, L_WEDNESDAY, L_THURSDAY, L_FRIDAY,
L_SATURDAY, L_SUNDAY}
#endif
;
#endif
EXTERN int MonthDays[]
#ifdef MK_GLOBALS
= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
#endif
;
/* The first day of each month expressed as number of days after Jan 1.
Second row is for leap years. */
EXTERN int MonthIndex[2][12]
#ifdef MK_GLOBALS
= {
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
}
#endif
;
#if defined(__OS2__)
#if defined(_MSC_VER) || defined(__EMX__)
#define OS2MODE (_osmode == OS2_MODE)
#define DOSMODE (_osmode == DOS_MODE)
#else
#define OS2MODE 1
#define DOSMODE 0
#endif
#endif

544
hbcal.c Normal file
View File

@@ -0,0 +1,544 @@
/***************************************************************/
/* */
/* HBCAL.C */
/* */
/* Support for the Hebrew calendar */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/* Derived from code written by Amos Shapir in 1978; revised */
/* 1985. */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: hbcal.c,v 1.1 1996-03-27 03:25:58 dfs Exp $";
#include <stdio.h> /* For FILE used by protos.h - sigh. */
#include "config.h"
#include "types.h"
#include "protos.h"
#include "globals.h"
#include "err.h"
#define HOUR 1080L
#define DAY (24L*HOUR)
#define WEEK (7L*DAY)
#define M(h,p) ((long)(h*HOUR+p))
#define MONTH (DAY+M(12,793))
/* Correction to convert base reference to 1990. NOTE: If you change
the value of BASE in config.h, this will NOT WORK! You'll have to
add the appropriate number of days to CORRECTION. */
#define CORRECTION 732774L
#define TISHREY 0
#define HESHVAN 1
#define KISLEV 2
#define TEVET 3
#define SHVAT 4
#define ADARA 5
#define ADARB 6
#define NISAN 7
#define IYAR 8
#define SIVAN 9
#define TAMUZ 10
#define AV 11
#define ELUL 12
#define ADAR 13
#define JAHR_NONE 0
#define JAHR_FORWARD 1
#define JAHR_BACKWARD 2
#define ADAR2ADARB 0
#define ADAR2ADARA 1
#define ADAR2BOTH 2
static char *HebMonthNames[] = {
"Tishrey", "Heshvan", "Kislev", "Tevet", "Shvat", "Adar A", "Adar B",
"Nisan", "Iyar", "Sivan", "Tamuz", "Av", "Elul", "Adar"};
static char MaxMonLen[] = {
30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29, 29};
static char HebIsLeap[] = {0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1};
/***************************************************************/
/* */
/* RoshHashana */
/* */
/* Return the Julian date for Rosh Hashana of specified */
/* Hebrew year. (ie, 5751, not 1990) */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int RoshHashana(int i)
#else
int RoshHashana(i)
int i;
#endif
{
long j;
j = DaysToHebYear(i-3744) - CORRECTION;
return (int) j; /* No overflow check... very trusting! */
}
/***************************************************************/
/* */
/* DaysToHebYear */
/* */
/* Return the number of days to RH of specified Hebrew year */
/* from new moon before Tishrey 1 5701. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC long DaysToHebYear(int y)
#else
long DaysToHebYear(y)
int y;
#endif
{
long m, nm, dw, s, l;
l = y*7+1; /* no. of leap months */
m = y*12+l/19; /* total no. of months */
nm = m*MONTH+M(1,779); /* molad at 197 cycles */
s = m*28+nm/DAY-2;
nm %= WEEK;
l %= 19L;
dw = nm/DAY;
nm %= DAY;
/* special cases of Molad Zaken */
if (nm >= 18*HOUR ||
(l < 12 && dw==3 && nm>=M(9,204)) ||
(l < 7 && dw==2 && nm>=M(15,589)))
s++,dw++;
/* ADU */
if(dw == 1 || dw == 4 || dw == 6)
s++;
return s;
}
/***************************************************************/
/* */
/* DaysInHebYear */
/* */
/* Return the number of days in the Hebrew year. */
/* */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DaysInHebYear(int y)
#else
int DaysInHebYear(y)
int y;
#endif
{
long thisyear, nextyear;
thisyear = DaysToHebYear(y-3744);
nextyear = DaysToHebYear(y-3743);
return (int) (nextyear - thisyear);
}
/***************************************************************/
/* */
/* DaysInHebMonths */
/* */
/* Return a pointer to an array giving lengths of months */
/* given the LENGTH of the Hebrew year. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *DaysInHebMonths(int ylen)
#else
char *DaysInHebMonths(ylen)
int ylen;
#endif
{
static char monlen[13] =
{30, 29, 30, 29, 30, 0, 29, 30, 29, 30, 29, 30, 29};
if (ylen > 355) {
monlen[ADARA] = 30;
ylen -= 30;
} else monlen[ADARA] = 0;
if (ylen == 353) monlen[KISLEV] = 29; else monlen[KISLEV] = 30;
if (ylen == 355) monlen[HESHVAN] = 30; else monlen[HESHVAN] = 29;
return monlen;
}
/***************************************************************/
/* */
/* HebToJul */
/* */
/* Convert a Hebrew date to Julian. */
/* Hebrew months range from 0-12, but Adar A has 0 length in */
/* non-leap-years. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int HebToJul(int hy, int hm, int hd)
#else
int HebToJul(hy, hm, hd)
int hy, hm, hd;
#endif
{
int ylen;
char *monlens;
int rh;
int m;
/* Do some range checking */
if (hy - 3761 < BASE || hy - 3760 > BASE+YR_RANGE) return -1;
ylen = DaysInHebYear(hy);
monlens = DaysInHebMonths(ylen);
/* Get the Rosh Hashana of the year */
rh = RoshHashana(hy);
/* Bump up to the appropriate month */
for (m=0; m<hm; m++) rh += monlens[m];
/* Add in appropriate number of days */
rh += hd - 1;
return rh;
}
/***************************************************************/
/* */
/* JulToHeb */
/* */
/* Convert a Julian date to Hebrew. */
/* Hebrew months range from 0-12, but Adar A has 0 length in */
/* non-leap-years. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void JulToHeb(int jul, int *hy, int *hm, int *hd)
#else
void JulToHeb(jul, hy, hm, hd)
int jul, *hy, *hm, *hd;
#endif
{
int y, m, d;
int rh;
int ylen;
char *monlen;
/* Get the common year */
FromJulian(jul, &y, &m, &d);
y += 3763; /* Over-estimate a bit to be on the safe side below... */
/* Find the RH just before desired date */
while ((rh=RoshHashana(y))>jul) y--;
/* Got the year - now find the month */
jul -= rh;
ylen = DaysInHebYear(y);
monlen = DaysInHebMonths(ylen);
m = 0;
while((jul >= monlen[m]) || !monlen[m]) {
jul -= monlen[m];
m++;
}
*hy = y;
*hm = m;
*hd = jul+1;
}
/***************************************************************/
/* */
/* HebNameToNum */
/* */
/* Convert a Hebrew month's name to its number, given the */
/* year. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int HebNameToNum(const char *mname)
#else
int HebNameToNum(mname)
char *mname;
#endif
{
int i;
int m=-1;
for (i=0; i<14; i++)
if (!StrCmpi(mname, HebMonthNames[i])) {
m = i;
break;
}
return m;
}
/***************************************************************/
/* */
/* HebMonthname */
/* */
/* Convert a Hebrew month's number to its name, given the */
/* year. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *HebMonthName(int m, int y)
#else
char *HebMonthName(m, y)
int m, y;
#endif
{
if (m != ADARA && m != ADARB) return HebMonthNames[m];
if (!HebIsLeap[(y-1)%19]) return HebMonthNames[ADAR];
else return HebMonthNames[m];
}
/***************************************************************/
/* */
/* GetValidHebDate */
/* */
/* Given the day of a month, a Hebrew month number, and a */
/* year, return a valid year number, month number, and day */
/* number. Returns 0 for success, non-0 for failure. */
/* If *dout is set to -1, then date is completely invalid. */
/* Otherwise, date is only invalid in specified year. */
/* */
/* Algorithm: */
/* - Convert references to Adar to Adar B. */
/* If jahr == 0 then */
/* - If no such date in current Hebrew year, return */
/* failure. */
/* else follow jahrzeit rules: */
/* - If jahr == 1: Convert 30 Kislev to 1 Tevet and */
/* 30 Heshvan to 1 Kislev if chaser. */
/* Convert 30 Adar A to 1 Nisan in nonleap */
/* This rule is NOT appropriate for a */
/* jahrzeit on 30 Adar A. Use rule 2 for */
/* that. However, I believe it is correct */
/* for smachot. */
/* - If jahr == 2: Convert 30 Kislev to 29 Kislev and */
/* 30 Heshvan to 29 Heshvan if chaser. */
/* Change 30 Adar A to 30 Shvat in nonleap */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetValidHebDate(int yin, int min, int din, int adarbehave,
int *mout, int *dout, int jahr)
#else
int GetValidHebDate(yin, min, din, adarbehave, mout, dout, jahr)
int yin, min, din, adarbehave, *mout, *dout, jahr;
#endif
{
char *monlen;
int ylen;
*mout = min;
*dout = din;
/* Do some error checking */
if (din < 1 || din > MaxMonLen[min] || min < 0 || min > 13) {
*dout = -1;
return E_BAD_HEBDATE;
}
ylen = DaysInHebYear(yin);
monlen = DaysInHebMonths(ylen);
/* Convert ADAR as necessary */
if (min == ADAR) {
switch(adarbehave) {
case ADAR2ADARA: if (monlen[ADARA]) *mout = min = ADARA;
else *mout = min = ADARB;
break;
case ADAR2ADARB: *mout = min = ADARB; break;
default:
Eprint("GetValidHebDate: Bad adarbehave value %d", adarbehave);
return E_SWERR;
}
}
if (din <= monlen[min]) return OK;
switch(jahr) {
case JAHR_NONE: return E_BAD_DATE;
case JAHR_FORWARD:
if (min == KISLEV) {
*mout = TEVET;
*dout = 1;
return OK;
} else if (min == HESHVAN) {
*mout = KISLEV;
*dout = 1;
return OK;
} else if (min == ADARA) {
if (din > 29) {
*dout = 1;
*mout = NISAN;
} else {
*dout = din;
*mout = ADARB;
}
return OK;
}
Eprint("GetValidHebDate: (1) software error! %d", jahr);
return E_SWERR;
case JAHR_BACKWARD:
if (min == KISLEV) {
*mout = KISLEV;
*dout = 29;
return OK;
} else if (min == HESHVAN) {
*mout = HESHVAN;
*dout = 29;
return OK;
} else if (min == ADARA) {
if (din > 29) {
*dout = 30;
*mout = SHVAT;
} else {
*mout = ADARB;
*dout = din;
}
return OK;
}
Eprint("GetValidHebDate: (2) software error! %d", jahr);
return E_SWERR;
default:
Eprint("GetValidHebDate: (3) software error! %d", jahr);
return E_SWERR;
}
}
/***************************************************************/
/* */
/* GetNextHebrewDate */
/* */
/* Get the next Hebrew date on or after specified date. */
/* */
/* Returns 0 for success, non-zero for failure. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetNextHebrewDate(int julstart, int hm, int hd,
int jahr, int adarbehave, int *ans)
#else
int GetNextHebrewDate(julstart, hm, hd, jahr, adarbehave, ans)
int julstart, hm, hd, jahr, adarbehave, *ans;
#endif
{
int r, yout, mout, dout, jul=1;
int adarflag = adarbehave;
/* I initialize jul above to stop gcc from complaining about
possible use of uninitialized variable. You can take it
out if the small inefficiency really bothers you. */
/* If adarbehave == ADAR2BOTH, set adarflag to ADAR2ADARA for now */
if (adarbehave == ADAR2BOTH) adarflag = ADAR2ADARA;
JulToHeb(julstart, &yout, &mout, &dout);
r = 1;
while(r) {
r = GetValidHebDate(yout, hm, hd, adarflag, &mout, &dout, jahr);
if (dout == -1) return r;
if (r) {
if (adarbehave == ADAR2BOTH && hm == ADAR) {
if (adarflag == ADAR2ADARA) {
adarflag = ADAR2ADARB;
} else {
adarflag = ADAR2ADARA;
yout++;
}
} else yout++;
continue;
}
jul = HebToJul(yout, mout, dout);
if (jul < 0) return E_DATE_OVER;
if (jul >= julstart) break;
else {
if (adarbehave == ADAR2BOTH && hm == ADAR) {
if (adarflag == ADAR2ADARA) {
adarflag = ADAR2ADARB;
} else {
adarflag = ADAR2ADARA;
yout++;
}
} else yout++;
r=1; /* Force loop to continue */
}
}
*ans = jul;
return OK;
}
/***************************************************************/
/* */
/* ComputeJahr */
/* */
/* Given a date of death, compute the value to use for jahr. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ComputeJahr(int y, int m, int d, int *ans)
#else
int ComputeJahr(y, m, d, ans)
int y, m, d, *ans;
#endif
{
char *monlen;
int len;
*ans = JAHR_NONE;
len = DaysInHebYear(y);
monlen = DaysInHebMonths(len);
/* Check for Adar A */
if (m == ADARA && monlen[m] == 0) {
Eprint("No Adar A in %d", y);
return E_BAD_HEBDATE;
}
if (d < 1 || d > MaxMonLen[m] || m < 0 || m > 13) {
return E_BAD_HEBDATE;
}
if (d > monlen[m]) {
Eprint("%d %s %d: %s", d, HebMonthNames[m], y, ErrMsg[E_BAD_HEBDATE]);
return E_BAD_HEBDATE;
}
/* If the jahrzeit was in Adar A, we always use JAHR_BACKWARD */
if (m == ADARA) {
*ans = JAHR_BACKWARD;
return OK;
}
/* Get lengths of months in year following jahrzeit */
len = DaysInHebYear(y+1);
monlen = DaysInHebMonths(len);
if (d > monlen[m]) *ans = JAHR_FORWARD;
else *ans = JAHR_BACKWARD;
return OK;
}

633
init.c Normal file
View File

@@ -0,0 +1,633 @@
/***************************************************************/
/* */
/* INIT.C */
/* */
/* Initialize remind; perform certain tasks between */
/* iterations in calendar mode; do certain checks after end */
/* in normal mode. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: init.c,v 1.1 1996-03-27 03:25:58 dfs Exp $";
#define L_IN_INIT 1
#include "config.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef UNIX
#include <sys/types.h>
#include <pwd.h>
#ifdef HAVE_UNISTD
#include <unistd.h>
#endif
#endif
#include <ctype.h>
#include "types.h"
#include "protos.h"
#include "expr.h"
#include "err.h"
#include "version.h"
#include "globals.h"
/***************************************************************
*
* Command line options recognized:
*
* -n = Output next trigger date of each reminder in
* simple calendar format.
* -r = Disallow RUN mode
* -c[n] = Produce a calendar for n months (default = 1)
* -w[n,n,n] = Specify output device width, padding and spacing
* -s[n] = Produce calendar in "simple calendar" format
* -p[n] = Produce calendar in format compatible with rem2ps
* -v = Verbose mode
* -o = Ignore ONCE directives
* -a = Don't issue timed reminders which will be queued
* -q = Don't queue timed reminders
* -t = Trigger all reminders (infinite delta)
* -h = Hush mode
* -f = Do not fork
* -dchars = Debugging mode: Chars are:
* e = Echo input lines
* x = Display expression evaluation
* t = Display trigger dates
* v = Dump variables at end
* l = Display entire line in error messages
* -e = Send messages normally sent to stderr to stdout instead
* -z[n] = Daemon mode waking up every n (def 5) minutes.
* -bn = Time format for cal (0, 1, or 2)
* -xn = Max. number of iterations for SATISFY
* -uname = Run as user 'name' - only valid when run by root. If run
* by non-root, changes environment but not effective uid.
* -kcmd = Run 'cmd' for MSG-type reminders instead of printing to stdout
* -iVAR=EXPR = Initialize and preserve VAR.
* -m = Start calendar with Monday instead of Sunday.
* A minus sign alone indicates to take input from stdin
*
**************************************************************/
/* For parsing an integer */
#define PARSENUM(var, s) \
var = 0; \
while (isdigit(*(s))) { \
var *= 10; \
var += *(s) - '0'; \
s++; \
}
#ifdef UNIX
PRIVATE void ChgUser ARGS((char *uname));
#endif
PRIVATE void InitializeVar ARGS ((char *str));
static char *BadDate = "Illegal date on command line\n";
/***************************************************************/
/* */
/* InitRemind */
/* */
/* Initialize the system - called only once at beginning! */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void InitRemind(int argc, char *argv[])
#else
void InitRemind(argc, argv)
int argc;
char *argv[];
#endif
{
char *arg;
int i;
int y, m, d, rep;
Token tok;
y = NO_YR;
m = NO_MON;
d = NO_DAY;
rep = NO_REP;
RealToday = SystemDate(&CurYear, &CurMon, &CurDay);
if (RealToday < 0) {
fprintf(ErrFp, ErrMsg[M_BAD_SYS_DATE], BASE);
exit(1);
}
JulianToday = RealToday;
FromJulian(JulianToday, &CurYear, &CurMon, &CurDay);
#if !defined(HAVE_QUEUED)
DontFork = 1;
DontQueue = 1;
NumQueued = 0;
DontIssueAts = 0;
Daemon = 0;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
DontFork = 1;
#elif defined(__OS2__) && defined (__MSDOS__)
if (DOSMODE)
DontFork = 1;
#endif
/* Parse the command-line options */
i = 1;
while (i < argc) {
arg = argv[i];
if (*arg != '-') break; /* Exit the loop if it's not an option */
i++;
arg++;
if (!*arg) {
UseStdin = 1;
IgnoreOnce = 1;
i--;
break;
}
while (*arg) {
switch(*arg++) {
case 'i':
case 'I':
InitializeVar(arg);
while(*arg) arg++;
break;
case 'n':
case 'N':
NextMode = 1;
#ifdef HAVE_QUEUED
DontQueue = 1;
Daemon = 0;
#endif
break;
case 'r':
case 'R':
RunDisabled = 1;
break;
case 'm':
case 'M':
MondayFirst = 1;
break;
case 'o':
case 'O':
IgnoreOnce = 1;
break;
case 't':
case 'T':
InfiniteDelta = 1;
break;
case 'e':
case 'E':
ErrFp = stdout;
break;
case 'h':
case 'H':
Hush = 1;
break;
case 'g':
case 'G':
SortByDate = SORT_ASCEND;
SortByTime = SORT_ASCEND;
SortByPrio = SORT_ASCEND;
if (*arg) {
if (*arg == 'D' || *arg == 'd')
SortByDate = SORT_DESCEND;
arg++;
}
if (*arg) {
if (*arg == 'D' || *arg == 'd')
SortByTime = SORT_DESCEND;
arg++;
}
if (*arg) {
if (*arg == 'D' || *arg == 'd')
SortByPrio = SORT_DESCEND;
arg++;
}
break;
#if defined(UNIX) && defined(WANT_U_OPTION)
case 'u':
case 'U':
ChgUser(arg);
while (*arg) arg++;
break;
#endif
#ifdef HAVE_QUEUED
case 'z':
case 'Z':
DontFork = 1;
PARSENUM(Daemon, arg);
if (Daemon<5) Daemon=5;
else if (Daemon>60) Daemon=60;
break;
case 'a':
case 'A':
DontIssueAts = 1;
break;
case 'q':
case 'Q':
DontQueue = 1;
break;
case 'f':
case 'F':
DontFork = 1;
break;
#endif
case 'c':
case 'C':
DoCalendar = 1;
if (*arg == '+') {
arg++;
PARSENUM(CalWeeks, arg);
if (!CalWeeks) CalWeeks = 1;
} else {
PARSENUM(CalMonths, arg);
if (!CalMonths) CalMonths = 1;
}
break;
case 's':
case 'S':
DoSimpleCalendar = 1;
if (*arg == '+') {
arg++;
PARSENUM(CalWeeks, arg);
if (!CalWeeks) CalWeeks = 1;
} else {
PARSENUM(CalMonths, arg);
if (!CalMonths) CalMonths = 1;
}
break;
case 'p':
case 'P':
DoSimpleCalendar = 1;
PsCal = 1;
PARSENUM(CalMonths, arg);
if (!CalMonths) CalMonths = 1;
break;
case 'w':
case 'W':
if (*arg != ',') {
PARSENUM(CalWidth, arg);
if (CalWidth < 80) CalWidth = 80;
}
if (*arg == ',') {
arg++;
if (*arg != ',') {
PARSENUM(CalLines, arg);
if (CalLines > 20) CalLines = 20;
}
if (*arg == ',') {
arg++;
PARSENUM(CalPad, arg);
if (CalPad > 20) CalPad = 20;
}
}
break;
case 'd':
case 'D':
while (*arg) {
switch(*arg++) {
case 'e': case 'E': DebugFlag |= DB_ECHO_LINE; break;
case 'x': case 'X': DebugFlag |= DB_PRTEXPR; break;
case 't': case 'T': DebugFlag |= DB_PRTTRIG; break;
case 'v': case 'V': DebugFlag |= DB_DUMP_VARS; break;
case 'l': case 'L': DebugFlag |= DB_PRTLINE; break;
default:
fprintf(ErrFp, ErrMsg[M_BAD_DB_FLAG], *(arg-1));
}
}
break;
case 'v':
case 'V':
DebugFlag |= DB_PRTLINE;
ShowAllErrors = 1;
break;
case 'b':
case 'B':
PARSENUM(ScFormat, arg);
if (ScFormat<0 || ScFormat>2) ScFormat=SC_AMPM;
break;
case 'x':
case 'X':
PARSENUM(MaxSatIter, arg);
if (MaxSatIter < 10) MaxSatIter=10;
break;
case 'k':
case 'K':
MsgCommand = arg;
while (*arg) arg++; /* Chew up remaining chars in this arg */
break;
default:
fprintf(ErrFp, ErrMsg[M_BAD_OPTION], *(arg-1));
}
}
}
/* Get the filename. */
if (i >= argc) {
Usage();
exit(1);
}
InitialFile = argv[i++];
/* Get the date, if any */
if (i < argc) {
while (i < argc) {
arg = argv[i++];
FindToken(arg, &tok);
switch (tok.type) {
case T_Time:
if (SysTime != -1L) Usage();
else {
SysTime = (long) tok.val * 60L;
#ifdef HAVE_QUEUED
DontQueue = 1;
Daemon = 0;
#endif
}
break;
case T_Month:
if (m != NO_MON) Usage();
else m = tok.val;
break;
case T_Day:
if (d != NO_DAY) Usage();
else d = tok.val;
break;
case T_Year:
if (y != NO_YR) Usage();
else y = tok.val;
break;
case T_Rep:
if (rep != NO_REP) Usage();
else rep = tok.val;
break;
default: Usage();
}
}
if (rep > 0) {
Iterations = rep;
DontQueue = 1;
Daemon = 0;
}
/* Must supply date in the form: day, mon, yr OR mon, yr */
if (m != NO_MON || y != NO_YR || d != NO_DAY) {
if (m == NO_MON || y == NO_YR) {
if (rep == NO_REP) Usage();
else if (m != NO_MON || y != NO_YR) Usage();
else {
m = CurMon;
y = CurYear;
if (d == NO_DAY) d = CurDay;
}
}
if (d == NO_DAY) d=1;
if (d > DaysInMonth(m, y)) {
fprintf(ErrFp, BadDate);
Usage();
}
JulianToday = Julian(y, m, d);
if (JulianToday == -1) {
fprintf(ErrFp, BadDate);
Usage();
}
CurYear = y;
CurMon = m;
CurDay = d;
if (JulianToday != RealToday) IgnoreOnce = 1;
}
}
/* Figure out the offset from UTC */
if (CalculateUTC)
(void) CalcMinsFromUTC(JulianToday, SystemTime(1)/60,
&MinsFromUTC, NULL);
}
/***************************************************************/
/* */
/* Usage */
/* */
/* Print the usage info. */
/* */
/***************************************************************/
#ifndef L_USAGE_OVERRIDE
#ifdef HAVE_PROTOS
PUBLIC void Usage(void)
#else
void Usage()
#endif /* HAVE_PROTOS */
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1996 by David F. Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
fprintf(ErrFp, "Usage: remind [options] filename [date] [time] [*rep]\n");
fprintf(ErrFp, "Options:\n");
fprintf(ErrFp, " -n Output next occurrence of reminders in simple format\n");
fprintf(ErrFp, " -r Disable RUN directives\n");
fprintf(ErrFp, " -c[n] Produce a calendar for n (default 1) months\n");
fprintf(ErrFp, " -c+[n] Produce a calendar for n (default 1) weeks\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Specify width, padding and spacing of calendar\n");
fprintf(ErrFp, " -s[+][n] Produce 'simple calendar' for n (1) months (weeks)\n");
fprintf(ErrFp, " -p[n] Same as -s, but input compatible with rem2ps\n");
fprintf(ErrFp, " -v Verbose mode\n");
fprintf(ErrFp, " -o Ignore ONCE directives\n");
fprintf(ErrFp, " -t Trigger all future reminders regardless of delta\n");
fprintf(ErrFp, " -h 'Hush' mode - be very quiet\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a Don't trigger timed reminders immediately - just queue them\n");
fprintf(ErrFp, " -q Don't queue timed reminders\n");
fprintf(ErrFp, " -f Trigger timed reminders by staying in foreground\n");
fprintf(ErrFp, " -z[n] Enter daemon mode, waking every n (5) minutes.\n");
#endif
fprintf(ErrFp, " -d... Debug: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Divert messages normally sent to stderr to stdout\n");
fprintf(ErrFp, " -b[n] Time format for cal: 0=am/pm, 1=24hr, 2=none\n");
fprintf(ErrFp, " -x[n] Iteration limit for SATISFY clause (def=150)\n");
fprintf(ErrFp, " -kcmd Run 'cmd' for MSG-type reminders\n");
fprintf(ErrFp, " -g[ddd] Sort reminders by date, time and priority before issuing\n");
fprintf(ErrFp, " -ivar=val Initialize var to val and preserve var\n");
fprintf(ErrFp, " -m Start calendar with Monday rather than Sunday\n");
exit(1);
}
#endif /* L_USAGE_OVERRIDE */
/***************************************************************/
/* */
/* ChgUser */
/* */
/* Run as a specified user. Can only be used if Remind is */
/* started by root. This changes the real and effective uid, */
/* the real and effective gid, and sets the HOME, SHELL and */
/* USER environment variables. */
/* */
/***************************************************************/
#if defined(UNIX) && defined(WANT_U_OPTION)
#ifdef HAVE_PROTOS
PRIVATE void ChgUser(char *user)
#else
static void ChgUser(user)
char *user;
#endif /* HAVE_PROTOS */
{
#ifdef SYSV
/* uid_t myuid; This seems to mess up on XENIX, so forget it... */
int myuid;
#else
int myuid;
#endif
struct passwd *pwent;
static char *home, *shell, *username, *logname;
myuid = getuid();
pwent = getpwnam(user);
if (!pwent) {
fprintf(ErrFp, ErrMsg[M_BAD_USER], user);
exit(1);
}
if (!myuid && setgid(pwent->pw_gid)) {
fprintf(ErrFp, ErrMsg[M_NO_CHG_GID], pwent->pw_gid);
exit(1);
}
if (!myuid && setuid(pwent->pw_uid)) {
fprintf(ErrFp, ErrMsg[M_NO_CHG_UID], pwent->pw_uid);
exit(1);
}
home = malloc(strlen(pwent->pw_dir) + 6);
if (!home) {
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
exit(1);
}
sprintf(home, "HOME=%s", pwent->pw_dir);
putenv(home);
shell = malloc(strlen(pwent->pw_shell) + 7);
if (!shell) {
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
exit(1);
}
sprintf(shell, "SHELL=%s", pwent->pw_shell);
putenv(shell);
if (pwent->pw_uid) {
username = malloc(strlen(pwent->pw_name) + 6);
if (!username) {
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
exit(1);
}
sprintf(username, "USER=%s", pwent->pw_name);
putenv(username);
logname= malloc(strlen(pwent->pw_name) + 9);
if (!logname) {
fprintf(ErrFp, ErrMsg[M_NOMEM_ENV]);
exit(1);
}
sprintf(logname, "LOGNAME=%s", pwent->pw_name);
putenv(logname);
}
}
#endif /* UNIX && WANT_U_OPTION */
/***************************************************************/
/* */
/* InitializeVar */
/* */
/* Initialize and preserve a variable */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void InitializeVar(char *str)
#else
static void InitializeVar(str)
char *str;
#endif
{
char *varname, *expr;
Value val;
int r;
/* Scan for an '=' sign */
varname = str;
while (*str && *str != '=') str++;
if (!*str) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EQ]);
return;
}
*str = 0;
if (!*varname) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_VAR]);
return;
}
expr = str+1;
if (!*expr) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[E_MISS_EXPR]);
return;
}
r=EvalExpr(&expr, &val);
if (r) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
return;
}
if (*varname == '$') {
r=SetSysVar(varname+1, &val);
if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
return;
}
r=SetVar(varname, &val);
if (r) {
fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
return;
}
r=PreserveVar(varname);
if (r) fprintf(ErrFp, ErrMsg[M_I_OPTION], ErrMsg[r]);
return;
}

42
kall Normal file
View File

@@ -0,0 +1,42 @@
#!/bin/sh
#
# $Id: kall,v 1.1 1996-03-27 03:25:59 dfs Exp $
#
# kall - kill all processes belonging to this user that match
# specified string.
signal=`echo $1 | grep '^\-.*'`
me=`basename $0`
if [ "$signal" != "" ]; then
shift
else
signal="-TERM"
fi
if [ "$1" = "" ]; then
echo "usage: $me [-signal] string [string...]"
echo " kills all of your processes where command name matches"
echo " any of the given strings."
exit
fi
msg="0"
while [ "$1" != "" ]; do
# NOTE: You may have to modify the next line, since PS is non-portable.
# The 'awk' command picks out the process IDs to pass them on to kill.
rprocs=`ps cx | awk '{if(prog == $NF && $1 != mypid) print $1}' prog=$1 mypid=$$ -`
if [ "$rprocs" != "" ]; then
msg="1"
echo -n "${me}: Sending $signal signal to $1 process(es)"
echo '...'
kill $signal $rprocs
fi
shift
done
if [ $msg = "1" ]; then
echo "${me}: Done."
fi

27
kall.1 Normal file
View File

@@ -0,0 +1,27 @@
.TH KALL 1 "26 February 1991"
.UC 4
.SH NAME
kall \- kill processes by command name
.SH SYNOPSIS
.B kall
[\-\fIsignal\fR] prog1 [prog2...]
.SH DESCRIPTION
.B Kall
sends the specified \fIsignal\fR (defaults to \fB-TERM\fR) to all processes
whose command name is specified on the command line. For example:
.PP
.nf
kall -HUP remind foobar
.fi
.PP
sends a \fBHUP\fR signal to all \fIremind\fR and \fIfoobar\fR programs.
Note that \fBkall\fR sends signals only to those processes owned by the
user invoking \fBkall\fR.
.SH AUTHOR
David F. Skoll
.SH BUGS
.B Kall
is a sh(1) script and depends on the behaviour of ps(1); thus, it is
not especially portable.
.SH SEE ALSO
remind, rem

64
lang.h Normal file
View File

@@ -0,0 +1,64 @@
/***************************************************************/
/* */
/* LANG.H */
/* */
/* Header file for language support for various languages. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: lang.h,v 1.1 1996-03-27 03:25:59 dfs Exp $ */
/* I'm chauvinistic and name each language with its English name... */
#define ENGLISH 0 /* original by David F. Skoll */
#define GERMAN 1 /* translated by Wolfgang Thronicke */
#define DUTCH 2 /* translated by Willem Kasdorp and Erik-Jan Vens */
#define FINNISH 3 /* translated by Mikko Silvonen */
#define FRENCH 4 /* translated by Laurent Duperval */
#define NORWEGIAN 5 /* translated by Trygve Randen */
#define DANISH 6 /* translated by Mogens Lynnerup */
#define POLISH 7 /* translated by Jerzy Sobczyk */
/* Add more languages here - but please e-mail dfs@doe.carleton.ca
to have your favorite language assigned a number. If you add a
language, please send me the header file, and permission to include
it in future releases of Remind. Note that you'll get no remuneration
for this service - just everlasting fame. :-)
Use the file tstlang.rem to test your new language file. */
/************************************************************************
* *
* Define the language you want to use here *
* *
************************************************************************/
#ifndef LANG /* Allow for definition on compiler command line */
#define LANG ENGLISH
#endif
/* Pick up the appropriate header file */
#if LANG == ENGLISH
#include "english.h"
#elif LANG == GERMAN
#include "german.h"
#elif LANG == DUTCH
#include "dutch.h"
#elif LANG == FINNISH
#include "finnish.h"
#elif LANG == FRENCH
#include "french.h"
#elif LANG == NORWEGIAN
#include "norwgian.h"
#elif LANG == DANISH
#include "danish.h"
#elif LANG == POLISH
#include "polish.h"
/* If no sensible language, choose English. I intended to use
the #error directive here, but some C compilers barf. */
#else
#include "english.h"
#endif

20
lnk.bcc Normal file
View File

@@ -0,0 +1,20 @@
calendar.obj
dorem.obj
dosubst.obj
expr.obj
files.obj
funcs.obj
globals.obj
hbcal.obj
init.obj
main.obj
moon.obj
omit.obj
os2func.obj
queue.obj
sort.obj
token.obj
trigger.obj
userfns.obj
utils.obj
var.obj

23
lnk.msc Normal file
View File

@@ -0,0 +1,23 @@
calendar.obj +
dorem.obj +
dosubst.obj +
expr.obj +
files.obj +
funcs.obj +
globals.obj +
hbcal.obj +
init.obj +
main.obj +
moon.obj +
omit.obj +
sort.obj +
token.obj +
trigger.obj +
userfns.obj +
utils.obj +
var.obj
remind.exe
nul

19
lnk.tc Normal file
View File

@@ -0,0 +1,19 @@
-eremind.exe
calendar.obj
dorem.obj
dosubst.obj
expr.obj
files.obj
funcs.obj
globals.obj
hbcal.obj
init.obj
main.obj
moon.obj
omit.obj
sort.obj
token.obj
trigger.obj
userfns.obj
utils.obj
var.obj

1550
main.c Normal file

File diff suppressed because it is too large Load Diff

107
makefile.bcc Normal file
View File

@@ -0,0 +1,107 @@
# Makefile for REMIND for Borland C++
# $Id: makefile.bcc,v 1.1 1996-03-27 03:26:01 dfs Exp $
VERSION= 03.00.13
MODEL=l
!if $d(__OS2__)
CFLAGS= -DOS2_POPUP -w-pia -O2
BINDIR= ..\OS2-EX
DELFLAG= /f
!else
CFLAGS= -w-pia -O2 -m$(MODEL)
BINDIR= ..\MSDOS-EX
DELFLAG=
!endif
HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
lang.h english.h german.h dutch.h finnish.h french.h norwgian.h \
danish.h polish.h
STDHDRS= config.h types.h protos.h globals.h err.h lang.h
LANGHDRS= english.h german.h dutch.h finnish.h french.h norwgian.h danish.h \
polish.h
SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
main.c omit.c sort.c token.c trigger.c userfns.c utils.c var.c hbcal.c \
queue.c moon.c os2func.c
OBJS=calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
globals.obj init.obj main.obj omit.obj sort.obj token.obj trigger.obj \
utils.obj userfns.obj var.obj hbcal.obj queue.obj moon.obj os2func.obj
MANIFEST= readme.uni readme.dos copyrigh $(HDRS) $(SRCS) makefile rem rem.1 \
remind.1 remind-a.csh remind-a.sh test.rem test-rem test.cmp makefile.tc \
makefile.msc lnk.msc lnk.tc manifest.dos manifest.unx whatsnew.30 kall kall.1 \
tstlang.rem defs.rem readme.os2 makefile.os2 rem2ps.c rem2ps.h remind.def \
rem2ps.1 makefile.bcc lnk.bcc test-rem.cmd test2.cmp
all: exes test-rem.cmd test-rem.bat
test-rem
clean:
-del $(DELFLAG) *.obj
-del $(DELFLAG) $(BINDIR)\*.exe
exes: $(BINDIR)\remind.exe $(BINDIR)\rem2ps.exe
..\os2-ex\remind.exe: $(OBJS)
bcc -e..\os2-ex\remind @lnk.bcc -lap;Toe
..\msdos-ex\remind.exe: $(OBJS)
bcc -e..\msdos-ex\remind -m$(MODEL) @lnk.bcc
..\os2-ex\rem2ps.exe: rem2ps.obj
bcc -e..\os2-ex\rem2ps rem2ps.obj -lap;Toe
..\msdos-ex\rem2ps.exe: rem2ps.obj
bcc -e..\msdos-ex\rem2ps -m$(MODEL) rem2ps.obj
.c.obj:
bcc $(CFLAGS) -c {$< }
rem2ps.obj: rem2ps.c rem2ps.h config.h lang.h
calendar.obj: calendar.c $(STDHDRS) expr.h
dorem.obj: dorem.c $(STDHDRS) expr.h
dosubst.obj: dosubst.c $(STDHDRS) $(LANGHDRS)
expr.obj: expr.c $(STDHDRS) expr.h
files.obj: files.c $(STDHDRS)
funcs.obj: funcs.c $(STDHDRS) expr.h version.h
globals.obj: globals.c config.h types.h globals.h err.h lang.h
init.obj: init.c $(STDHDRS) expr.h version.h
main.obj: main.c $(STDHDRS) expr.h
moon.obj: moon.c $(STDHDRS) expr.h
omit.obj: omit.c $(STDHDRS)
os2func.obj: os2func.c $(STDHDRS)
queue.obj: queue.c $(STDHDRS)
sort.obj: sort.c $(STDHDRS)
token.obj: token.c $(STDHDRS)
trigger.obj: trigger.c $(STDHDRS) expr.h
userfns.obj: userfns.c $(STDHDRS) expr.h
utils.obj: utils.c $(STDHDRS)
var.obj: var.c $(STDHDRS) expr.h
remind.zoo: $(MANIFEST)
zoo aI remind.zoo < manifest.dos

74
makefile.msc Normal file
View File

@@ -0,0 +1,74 @@
# Makefile for REMIND for Microsoft C for MSDOS
# $Id: makefile.msc,v 1.1 1996-03-27 03:26:01 dfs Exp $
OBJS= calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
globals.obj init.obj main.obj omit.obj token.obj trigger.obj userfns.obj \
utils.obj var.obj sort.obj hbcal.obj moon.obj
DEFINES= /D__MSDOS__ /D__MSC__
MODEL= /AM
calendar.obj: calendar.c
cl /c $(DEFINES) $(MODEL) /Focalendar.obj calendar.c
dorem.obj: dorem.c
cl /c $(DEFINES) $(MODEL) /Fodorem.obj dorem.c
dosubst.obj: dosubst.c
cl /c $(DEFINES) $(MODEL) /Fodosubst.obj dosubst.c
expr.obj: expr.c
cl /c $(DEFINES) $(MODEL) /Foexpr.obj expr.c
hbcal.obj: hbcal.c
cl /c $(DEFINES) $(MODEL) /Fohbcal.obj hbcal.c
sort.obj: sort.c
cl /c $(DEFINES) $(MODEL) /Fosort.obj sort.c
files.obj: files.c
cl /c $(DEFINES) $(MODEL) /Fofiles.obj files.c
funcs.obj: funcs.c
cl /c $(DEFINES) $(MODEL) /Fofuncs.obj funcs.c
globals.obj: globals.c
cl /c $(DEFINES) $(MODEL) /Foglobals.obj globals.c
init.obj: init.c
cl /c $(DEFINES) $(MODEL) /Foinit.obj init.c
main.obj: main.c
cl /c $(DEFINES) $(MODEL) /Fomain.obj main.c
moon.obj: moon.c
cl /c $(DEFINES) $(MODEL) /Fomoon.obj moon.c
omit.obj: omit.c
cl /c $(DEFINES) $(MODEL) /Foomit.obj omit.c
token.obj: token.c
cl /c $(DEFINES) $(MODEL) /Fotoken.obj token.c
trigger.obj: trigger.c
cl /c $(DEFINES) $(MODEL) /Fotrigger.obj trigger.c
userfns.obj: userfns.c
cl /c $(DEFINES) $(MODEL) /Fouserfns.obj userfns.c
utils.obj: utils.c
cl /c $(DEFINES) $(MODEL) /Foutils.obj utils.c
var.obj: var.c
cl /c $(DEFINES) $(MODEL) /Fovar.obj var.c
remind.exe: $(OBJS)
link /NOI @lnk.msc
rem2ps.obj: rem2ps.c
cl /c $(DEFINES) $(MODEL) /Forem2ps.obj rem2ps.c
rem2ps.exe: rem2ps.obj
link /NOI rem2ps,rem2ps.exe,,,

110
makefile.os2 Normal file
View File

@@ -0,0 +1,110 @@
# Makefile for REMIND
#
# $Id: makefile.os2,v 1.1 1996-03-27 03:26:02 dfs Exp $
#
# - for GNU gcc (emx 0.8g kit) [executables for OS/2 2.x or DOS (32-bit)]
# - for Microsoft C 6.00A [executables for OS/2 or MSDOS (16-bit)]
# To use, enter "make -f Makefile.os2" (this makefile depends on its
# name being "Makefile.os2").
#
# Tested with dmake 3.8 and GNU make 3.68 under OS/2
default:
@echo "Enter $(MAKE) -f Makefile.os2 target "
@echo " where 'target' is chosen from "
@echo " msc OS/2 exe [Microsoft C 6.00a] "
@echo " mscbnd OS/2 and DOS exe [Microsoft C 6.00a] "
@echo " emx OS/2 and DOS 32-bit exe [EMX/gcc] "
msc:
$(MAKE) -f Makefile.os2 all \
CC="cl -nologo -AM" O=".obj" \
CFLAGS="-D__STDC__ -D__OS2__" \
LFLAGS="-Lp" \
LFLAGS2="setargv.obj remind.def -link /NOE"
mscbnd:
$(MAKE) -f Makefile.os2 all \
CC="cl -nologo -AM" O=".obj" \
CFLAGS="-D__STDC__ -D__OS2__ -D__MSDOS__" \
LFLAGS="-Lp" LBIND="-Fb" \
LFLAGS2="setargv.obj remind.def -link /NOE" \
BIND="bind remind /n DOSMAKEPIPE DOSCWAIT VIOENDPOPUP VIOPOPUP"
emx:
$(MAKE) -f Makefile.os2 all \
CC="gcc -O -s" O=".o" \
CFLAGS="-D__OS2__ -D__MSDOS__" \
LFLAGS=""
# OS2_POPUP enables Russ Herman's popup reminders
#OS2_POPUP =
OS2_POPUP = -DOS2_POPUP
HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
lang.h english.h german.h dutch.h finnish.h french.h norwgian.h \
danish.h polish.h
STDHDRS= config.h types.h protos.h globals.h err.h lang.h
LANGHDRS= english.h german.h dutch.h finnish.h french.h norwgian.h danish.h \
polish.h
SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c hbcal.c \
init.c main.c moon.c omit.c sort.c queue.c token.c trigger.c userfns.c \
utils.c var.c os2func.c
MANIFEST= README.UNIX README.DOS COPYRIGHT $(HDRS) $(SRCS) Makefile rem rem.1 \
remind.1 remind-all.csh remind-all.sh test.rem test-rem test.cmp makefile.tc \
makefile.msc lnk.msc lnk.tc MANIFEST.UNX MANIFEST.DOS WHATSNEW.30 kall kall.1 \
defs.rem README.OS2 makefile.os2 rem2ps.c rem2ps.h remind.def rem2ps.1 \
tstlang.rem README.BCC lnk.bcc makefile.bcc os2func.c \
test-rem.bat test-rem.cmd test1.cmp test2.cmp
OBJS= $(SRCS:.c=$O)
all: remind.exe rem2ps.exe
.c$O:
$(CC) -c $(CFLAGS) $(OS2_POPUP) $*.c
rem2ps.exe: rem2ps$O
$(CC) $(LFLAGS) $(LBIND) -o $@ rem2ps$O $(LFLAGS2)
remind.exe: $(OBJS)
$(CC) $(LFLAGS) -o $@ $(OBJS) $(LFLAGS2)
$(BIND)
clean:
rm -f *.o *.obj *~ core *.bak
clobber:
rm -f *.o *.obj *~ remind.exe rem2ps.exe test.out core *.bak
test:
test-rem.cmd
rem2ps$O: rem2ps.c rem2ps.h lang.h config.h
calendar$O: calendar.c $(STDHDRS) expr.h
dorem$O: dorem.c $(STDHDRS) expr.h
dosubst$O: dosubst.c $(STDHDRS) $(LANGHDRS)
expr$O: expr.c $(STDHDRS) expr.h
files$O: files.c $(STDHDRS)
funcs$O: funcs.c $(STDHDRS) expr.h version.h
globals$O: globals.c config.h types.h globals.h err.h lang.h $(LANGHDRS)
hbcal$O: hbcal.c $(STDHDRS)
init$O: init.c $(STDHDRS) expr.h version.h $(LANGHDRS)
main$O: main.c $(STDHDRS) expr.h
moon$O: moon.c $(STDHDRS)
omit$O: omit.c $(STDHDRS)
sort$O: sort.c $(STDHDRS)
queue$O: queue.c $(STDHDRS)
token$O: token.c $(STDHDRS)
trigger$O: trigger.c $(STDHDRS) expr.h
userfns$O: userfns.c $(STDHDRS) expr.h
utils$O: utils.c $(STDHDRS)
var$O: var.c $(STDHDRS) expr.h

80
makefile.tc Normal file
View File

@@ -0,0 +1,80 @@
# Makefile for REMIND for Turbo C for MSDOS
# $Id: makefile.tc,v 1.1 1996-03-27 03:26:03 dfs Exp $
CC= tcc
VERSION= 03.00.13
HDRS= config.h err.h expr.h globals.h protos.h types.h version.h \
lang.h english.h german.h dutch.h finnish.h french.h norwgian.h \
danish.h polish.h
STDHDRS= config.h types.h protos.h globals.h err.h lang.h
LANGHDRS= english.h german.h dutch.h finnish.h french.h norwgian.h danish.h \
polish.h
SRCS= calendar.c dorem.c dosubst.c expr.c files.c funcs.c globals.c init.c \
moon.c main.c omit.c sort.c token.c trigger.c userfns.c utils.c var.c hbcal.c
OBJS=calendar.obj dorem.obj dosubst.obj expr.obj files.obj funcs.obj \
globals.obj init.obj main.obj omit.obj sort.obj token.obj trigger.obj \
utils.obj userfns.obj var.obj hbcal.obj
MANIFEST= readme.uni readme.dos copyrigh $(HDRS) $(SRCS) makefile rem rem.1 \
remind.1 remind-a.csh remind-a.sh test.rem test-rem test.cmp makefile.tc \
makefile.msc lnk.msc lnk.tc manifest.dos manifest.unx whatsnew.30 kall kall.1 \
tstlang.rem defs.rem readme.os2 makefile.os2 rem2ps.c rem2ps.h remind.def \
rem2ps.1 README.BCC lnk.bcc makefile.bcc os2func.c \
test-rem.bat test-rem.cmd test1.cmp test2.cmp
all: remind.exe rem2ps.exe
remind.exe: $(OBJS)
$(CC) @lnk.tc
rem2ps.exe: rem2ps.obj
$(CC) -erem2ps.exe rem2ps.obj
.c.obj:
$(CC) -w-pia -c -O -mm {$< }
rem2ps.obj: rem2ps.c rem2ps.h config.h lang.h
calendar.obj: calendar.c $(STDHDRS) expr.h
dorem.obj: dorem.c $(STDHDRS) expr.h
dosubst.obj: dosubst.c $(STDHDRS) $(LANGHDRS)
expr.obj: expr.c $(STDHDRS) expr.h
files.obj: files.c $(STDHDRS)
funcs.obj: funcs.c $(STDHDRS) expr.h version.h
globals.obj: globals.c config.h types.h globals.h err.h lang.h
init.obj: init.c $(STDHDRS) expr.h version.h
main.obj: main.c $(STDHDRS) expr.h
moon.obj: moon.c $(STDHDRS) expr.h
omit.obj: omit.c $(STDHDRS)
sort.obj: sort.c $(STDHDRS)
token.obj: token.c $(STDHDRS)
trigger.obj: trigger.c $(STDHDRS) expr.h
userfns.obj: userfns.c $(STDHDRS) expr.h
utils.obj: utils.c $(STDHDRS)
var.obj: var.c $(STDHDRS) expr.h
remind.zoo: $(MANIFEST)
zoo aI remind.zoo < manifest.dos

640
moon.c Normal file
View File

@@ -0,0 +1,640 @@
/***************************************************************/
/* */
/* MOON.C */
/* */
/* Calculations for figuring out moon phases. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: moon.c,v 1.1 1996-03-27 03:26:03 dfs Exp $";
/* All of these routines were adapted from the program "moontool"
by John Walker, February 1988. Here's the blurb from moontool:
... The information is generally accurate to within ten
minutes.
The algorithms used in this program to calculate the positions Sun and
Moon as seen from the Earth are given in the book "Practical Astronomy
With Your Calculator" by Peter Duffett-Smith, Second Edition,
Cambridge University Press, 1981. Ignore the word "Calculator" in the
title; this is an essential reference if you're interested in
developing software which calculates planetary positions, orbits,
eclipses, and the like. If you're interested in pursuing such
programming, you should also obtain:
"Astronomical Formulae for Calculators" by Jean Meeus, Third Edition,
Willmann-Bell, 1985. A must-have.
"Planetary Programs and Tables from -4000 to +2800" by Pierre
Bretagnon and Jean-Louis Simon, Willmann-Bell, 1986. If you want the
utmost (outside of JPL) accuracy for the planets, it's here.
"Celestial BASIC" by Eric Burgess, Revised Edition, Sybex, 1985. Very
cookbook oriented, and many of the algorithms are hard to dig out of
the turgid BASIC code, but you'll probably want it anyway.
Many of these references can be obtained from Willmann-Bell, P.O. Box
35025, Richmond, VA 23235, USA. Phone: (804) 320-7016. In addition
to their own publications, they stock most of the standard references
for mathematical and positional astronomy.
This program was written by:
John Walker
Autodesk, Inc.
2320 Marinship Way
Sausalito, CA 94965
(415) 332-2344 Ext. 829
Usenet: {sun!well}!acad!kelvin
This program is in the public domain: "Do what thou wilt shall be the
whole of the law". I'd appreciate receiving any bug fixes and/or
enhancements, which I'll incorporate in future versions of the
program. Please leave the original attribution information intact so
that credit and blame may be properly apportioned.
*/
#include "config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "types.h"
#include "protos.h"
#include "expr.h"
#include "globals.h"
#include "err.h"
/* Function prototypes */
PRIVATE long jdate ARGS((int y, int mon, int day));
PRIVATE double jtime ARGS((int y, int mon, int day, int hour, int min, int sec));
PRIVATE void jyear ARGS((double td, int *yy, int *mm, int *dd));
PRIVATE void jhms ARGS((double j, int *h, int *m, int *s));
PRIVATE double meanphase ARGS((double sdate, double phase, double *usek));
PRIVATE double truephase ARGS((double k, double phase));
PRIVATE double kepler ARGS((double m, double ecc));
PRIVATE double phase ARGS((double, double *, double *, double *, double *, double *, double *));
/* Astronomical constants */
#define epoch 2444238.5 /* 1980 January 0.0 */
/* Constants defining the Sun's apparent orbit */
#define elonge 278.833540 /* Ecliptic longitude of the Sun
at epoch 1980.0 */
#define elongp 282.596403 /* Ecliptic longitude of the Sun at
perigee */
#define eccent 0.016718 /* Eccentricity of Earth's orbit */
#define sunsmax 1.495985e8 /* Semi-major axis of Earth's orbit, km */
#define sunangsiz 0.533128 /* Sun's angular size, degrees, at
semi-major axis distance */
/* Elements of the Moon's orbit, epoch 1980.0 */
#define mmlong 64.975464 /* Moon's mean lonigitude at the epoch */
#define mmlongp 349.383063 /* Mean longitude of the perigee at the
epoch */
#define mlnode 151.950429 /* Mean longitude of the node at the
epoch */
#define minc 5.145396 /* Inclination of the Moon's orbit */
#define mecc 0.054900 /* Eccentricity of the Moon's orbit */
#define mangsiz 0.5181 /* Moon's angular size at distance a
from Earth */
#define msmax 384401.0 /* Semi-major axis of Moon's orbit in km */
#define mparallax 0.9507 /* Parallax at distance a from Earth */
#define synmonth 29.53058868 /* Synodic month (new Moon to new Moon) */
#define lunatbase 2423436.0 /* Base date for E. W. Brown's numbered
series of lunations (1923 January 16) */
/* Properties of the Earth */
#define earthrad 6378.16 /* Radius of Earth in kilometres */
#ifdef PI
#undef PI
#endif
#define PI 3.14159265358979323846
/* Handy mathematical functions */
#ifdef sgn
#undef sgn
#endif
#define sgn(x) (((x) < 0) ? -1 : ((x) > 0 ? 1 : 0)) /* Extract sign */
#ifdef abs
#undef abs
#endif
#define abs(x) ((x) < 0 ? (-(x)) : (x)) /* Absolute val */
#define fixangle(a) ((a) - 360.0 * (floor((a) / 360.0))) /* Fix angle */
#define torad(d) ((d) * (PI / 180.0)) /* Deg->Rad */
#define todeg(d) ((d) * (180.0 / PI)) /* Rad->Deg */
#define dsin(x) (sin(torad((x)))) /* Sin from deg */
#define dcos(x) (cos(torad((x)))) /* Cos from deg */
/***************************************************************/
/* */
/* jdate */
/* */
/* Convert a date and time to Julian day and fraction. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE long jdate(int y, int mon, int day)
#else
static long jdate(y, mon, day)
int y, mon, day;
#endif
{
long c, m;
m = mon+1;
if (m>2) {
m -= 3;
} else {
m += 9;
y--;
}
c = y/100L; /* Century */
y -= 100L * c;
return day + (c*146097L)/4 + (y*1461L)/4 + (m*153L+2)/5 + 1721119L;
}
/***************************************************************/
/* */
/* jtime */
/* */
/* Convert a GMT date and time to astronomical Julian time, */
/* i.e. Julian date plus day fraction, expressed as a double */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE double jtime(int y, int mon, int day, int hour, int min, int sec)
#else
static double jtime(y, mon, day, hour, min, sec)
int y, mon, day, hour, min, sec;
#endif
{
return (jdate(y, mon, day)-0.5) +
(sec + 60L * (long) min + 3600L * (long) hour) / 86400.0;
}
/***************************************************************/
/* */
/* jyear */
/* */
/* Convert a Julian date to year, month, day. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void jyear(double td, int *yy, int *mm, int *dd)
#else
static void jyear(td, yy, mm, dd)
double td;
int *yy, *mm, *dd;
#endif
{
double j, d, y, m;
td += 0.5; /* Astronomical to civil */
j = floor(td);
j = j - 1721119.0;
y = floor(((4 * j) - 1) / 146097.0);
j = (j * 4.0) - (1.0 + (146097.0 * y));
d = floor(j / 4.0);
j = floor(((4.0 * d) + 3.0) / 1461.0);
d = ((4.0 * d) + 3.0) - (1461.0 * j);
d = floor((d + 4.0) / 4.0);
m = floor(((5.0 * d) - 3) / 153.0);
d = (5.0 * d) - (3.0 + (153.0 * m));
d = floor((d + 5.0) / 5.0);
y = (100.0 * y) + j;
if (m < 10.0)
m = m + 2;
else {
m = m - 10;
y = y + 1;
}
*yy = y;
*mm = m;
*dd = d;
}
/***************************************************************/
/* */
/* jhms */
/* */
/* Convert a Julian time to hour, minutes and seconds. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void jhms(double j, int *h, int *m, int *s)
#else
static void jhms(j, h, m, s)
double j;
int *h, *m, *s;
#endif
{
long ij;
j += 0.5; /* Astronomical to civil */
ij = (j - floor(j)) * 86400.0;
*h = ij / 3600L;
*m = (ij / 60L) % 60L;
*s = ij % 60L;
}
/***************************************************************/
/* */
/* meanphase */
/* */
/* Calculates mean phase of the Moon for a */
/* given base date and desired phase: */
/* 0.0 New Moon */
/* 0.25 First quarter */
/* 0.5 Full moon */
/* 0.75 Last quarter */
/* Beware!!! This routine returns meaningless */
/* results for any other phase arguments. Don't */
/* attempt to generalise it without understanding */
/* that the motion of the moon is far more complicated */
/* than this calculation reveals. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE double meanphase(double sdate, double phase, double *usek)
#else
static double meanphase(sdate, phase, usek)
double sdate, phase;
double *usek;
#endif
{
double k, t, t2, t3, nt1;
/*** The following was the original code: It gave roundoff errors
causing moonphase info to fail for Dec 1994. ***/
/* jyear(sdate, &yy, &mm, &dd);
k = (yy + (mm/12.0) - 1900) * 12.368531; */
/*** The next line is the replacement ***/
k = (sdate - 2415020.0) / synmonth;
/* Time in Julian centuries from 1900 January 0.5 */
t = (sdate - 2415020.0) / 36525.0;
t2 = t * t; /* Square for frequent use */
t3 = t2 * t; /* Cube for frequent use */
*usek = k = floor(k) + phase;
nt1 = 2415020.75933 + synmonth * k
+ 0.0001178 * t2
- 0.000000155 * t3
+ 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
return nt1;
}
/***************************************************************/
/* */
/* truephase */
/* */
/* Given a K value used to determine the */
/* mean phase of the new moon, and a phase */
/* selector (0.0, 0.25, 0.5, 0.75), obtain */
/* the true, corrected phase time. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE double truephase(double k, double phase)
#else
static double truephase(k, phase)
double k, phase;
#endif
{
double t, t2, t3, pt, m, mprime, f;
int apcor = 0;
k += phase; /* Add phase to new moon time */
t = k / 1236.8531; /* Time in Julian centuries from
1900 January 0.5 */
t2 = t * t; /* Square for frequent use */
t3 = t2 * t; /* Cube for frequent use */
pt = 2415020.75933 /* Mean time of phase */
+ synmonth * k
+ 0.0001178 * t2
- 0.000000155 * t3
+ 0.00033 * dsin(166.56 + 132.87 * t - 0.009173 * t2);
m = 359.2242 /* Sun's mean anomaly */
+ 29.10535608 * k
- 0.0000333 * t2
- 0.00000347 * t3;
mprime = 306.0253 /* Moon's mean anomaly */
+ 385.81691806 * k
+ 0.0107306 * t2
+ 0.00001236 * t3;
f = 21.2964 /* Moon's argument of latitude */
+ 390.67050646 * k
- 0.0016528 * t2
- 0.00000239 * t3;
if ((phase < 0.01) || (abs(phase - 0.5) < 0.01)) {
/* Corrections for New and Full Moon */
pt += (0.1734 - 0.000393 * t) * dsin(m)
+ 0.0021 * dsin(2 * m)
- 0.4068 * dsin(mprime)
+ 0.0161 * dsin(2 * mprime)
- 0.0004 * dsin(3 * mprime)
+ 0.0104 * dsin(2 * f)
- 0.0051 * dsin(m + mprime)
- 0.0074 * dsin(m - mprime)
+ 0.0004 * dsin(2 * f + m)
- 0.0004 * dsin(2 * f - m)
- 0.0006 * dsin(2 * f + mprime)
+ 0.0010 * dsin(2 * f - mprime)
+ 0.0005 * dsin(m + 2 * mprime);
apcor = 1;
} else if ((abs(phase - 0.25) < 0.01 || (abs(phase - 0.75) < 0.01))) {
pt += (0.1721 - 0.0004 * t) * dsin(m)
+ 0.0021 * dsin(2 * m)
- 0.6280 * dsin(mprime)
+ 0.0089 * dsin(2 * mprime)
- 0.0004 * dsin(3 * mprime)
+ 0.0079 * dsin(2 * f)
- 0.0119 * dsin(m + mprime)
- 0.0047 * dsin(m - mprime)
+ 0.0003 * dsin(2 * f + m)
- 0.0004 * dsin(2 * f - m)
- 0.0006 * dsin(2 * f + mprime)
+ 0.0021 * dsin(2 * f - mprime)
+ 0.0003 * dsin(m + 2 * mprime)
+ 0.0004 * dsin(m - 2 * mprime)
- 0.0003 * dsin(2 * m + mprime);
if (phase < 0.5)
/* First quarter correction */
pt += 0.0028 - 0.0004 * dcos(m) + 0.0003 * dcos(mprime);
else
/* Last quarter correction */
pt += -0.0028 + 0.0004 * dcos(m) - 0.0003 * dcos(mprime);
apcor = 1;
}
if (!apcor) return 0.0;
return pt;
}
/***************************************************************/
/* */
/* kepler */
/* */
/* Solve the equation of Kepler. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE double kepler(double m, double ecc)
#else
static double kepler(m, ecc)
double m, ecc;
#endif
{
double e, delta;
#define EPSILON 1E-6
e = m = torad(m);
do {
delta = e - ecc * sin(e) - m;
e -= delta / (1 - ecc * cos(e));
} while (abs(delta) > EPSILON);
return e;
}
/***************************************************************/
/* */
/* PHASE -- Calculate phase of moon as a fraction: */
/* */
/* The argument is the time for which the phase is */
/* Requested, expressed as a Julian date and */
/* fraction. Returns the terminator phase angle as a */
/* percentage of a full circle (i.e., 0 to 1), and */
/* stores into pointer arguments the illuminated */
/* fraction of the Moon's disc, the Moon's age in */
/* days and fraction, the distance of the Moon from */
/* the centre of the Earth, and the angular diameter */
/* subtended by the Moon as seen by an observer at */
/* the centre of the Earth. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE double phase(double pdate,
double *pphase,
double *mage,
double *dist,
double *angdia,
double *sudist,
double *suangdia)
#else
static double phase(pdate, pphase, mage, dist, angdia, sudist, suangdia)
double pdate;
double *pphase; /* Illuminated fraction */
double *mage; /* Age of moon in days */
double *dist; /* Distance in kilometres */
double *angdia; /* Angular diameter in degrees */
double *sudist; /* Distance to Sun */
double *suangdia; /* Sun's angular diameter */
#endif
{
double Day, N, M, Ec, Lambdasun, ml, MM, MN, Ev, Ae, A3, MmP,
mEc, A4, lP, V, lPP, NP, y, x, Lambdamoon,
MoonAge, MoonPhase,
MoonDist, MoonDFrac, MoonAng,
F, SunDist, SunAng;
/* Calculation of the Sun's position */
Day = pdate - epoch; /* Date within epoch */
N = fixangle((360 / 365.2422) * Day); /* Mean anomaly of the Sun */
M = fixangle(N + elonge - elongp); /* Convert from perigee
co-ordinates to epoch 1980.0 */
Ec = kepler(M, eccent); /* Solve equation of Kepler */
Ec = sqrt((1 + eccent) / (1 - eccent)) * tan(Ec / 2);
Ec = 2 * todeg(atan(Ec)); /* 1 anomaly */
Lambdasun = fixangle(Ec + elongp); /* Sun's geocentric ecliptic
longitude */
/* Orbital distance factor */
F = ((1 + eccent * cos(torad(Ec))) / (1 - eccent * eccent));
SunDist = sunsmax / F; /* Distance to Sun in km */
SunAng = F * sunangsiz; /* Sun's angular size in degrees */
/* Calculation of the Moon's position */
/* Moon's mean longitude */
ml = fixangle(13.1763966 * Day + mmlong);
/* Moon's mean anomaly */
MM = fixangle(ml - 0.1114041 * Day - mmlongp);
/* Moon's ascending node mean longitude */
MN = fixangle(mlnode - 0.0529539 * Day);
/* Evection */
Ev = 1.2739 * sin(torad(2 * (ml - Lambdasun) - MM));
/* Annual equation */
Ae = 0.1858 * sin(torad(M));
/* Correction term */
A3 = 0.37 * sin(torad(M));
/* Corrected anomaly */
MmP = MM + Ev - Ae - A3;
/* Correction for the equation of the centre */
mEc = 6.2886 * sin(torad(MmP));
/* Another correction term */
A4 = 0.214 * sin(torad(2 * MmP));
/* Corrected longitude */
lP = ml + Ev + mEc - Ae + A4;
/* Variation */
V = 0.6583 * sin(torad(2 * (lP - Lambdasun)));
/* 1 longitude */
lPP = lP + V;
/* Corrected longitude of the node */
NP = MN - 0.16 * sin(torad(M));
/* Y inclination coordinate */
y = sin(torad(lPP - NP)) * cos(torad(minc));
/* X inclination coordinate */
x = cos(torad(lPP - NP));
/* Ecliptic longitude */
Lambdamoon = todeg(atan2(y, x));
Lambdamoon += NP;
/* Calculation of the phase of the Moon */
/* Age of the Moon in degrees */
MoonAge = lPP - Lambdasun;
/* Phase of the Moon */
MoonPhase = (1 - cos(torad(MoonAge))) / 2;
/* Calculate distance of moon from the centre of the Earth */
MoonDist = (msmax * (1 - mecc * mecc)) /
(1 + mecc * cos(torad(MmP + mEc)));
/* Calculate Moon's angular diameter */
MoonDFrac = MoonDist / msmax;
MoonAng = mangsiz / MoonDFrac;
if(pphase) *pphase = MoonPhase;
if(mage) *mage = synmonth * (fixangle(MoonAge) / 360.0);
if(dist) *dist = MoonDist;
if(angdia) *angdia = MoonAng;
if(sudist) *sudist = SunDist;
if(suangdia) *suangdia = SunAng;
return fixangle(MoonAge) / 360.0;
}
/***************************************************************/
/* */
/* MoonPhase */
/* */
/* Interface routine dealing in Remind representations. */
/* Given a local date and time, returns the moon phase at */
/* that date and time as a number from 0 to 360. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int MoonPhase(int date, int time)
#else
int MoonPhase(date, time)
int date, time;
#endif
{
int utcd, utct;
int y, m, d;
double jd, mp;
/* Convert from local to UTC */
LocalToUTC(date, time, &utcd, &utct);
/* Convert from Remind representation to year/mon/day */
FromJulian(utcd, &y, &m, &d);
/* Convert to a true Julian date -- sorry for the name clashes! */
jd = jtime(y, m, d, (utct / 60), (utct % 60), 0);
/* Calculate moon phase */
mp = 360.0 * phase(jd, NULL, NULL, NULL, NULL, NULL, NULL);
return (int) mp;
}
/***************************************************************/
/* */
/* HuntPhase */
/* */
/* Given a starting date and time and a target phase, find */
/* the first date on or after the starting date and time when */
/* the moon hits the specified phase. Phase must be from */
/* 0 to 3 for new, 1stq, full, 3rdq */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void HuntPhase(int startdate, int starttim, int phas, int *date, int *time)
#else
void HuntPhase(startdate, starttim, phas, date, time)
int startdate, starttim, phas, *date, *time;
#endif
{
int utcd, utct;
int y, m, d;
int h, min, s;
int d1, t1;
double k1, k2, jd, jdorig;
double nt1, nt2;
/* Convert from local to UTC */
LocalToUTC(startdate, starttim, &utcd, &utct);
/* Convert from Remind representation to year/mon/day */
FromJulian(utcd, &y, &m, &d);
/* Convert to a true Julian date -- sorry for the name clashes! */
jdorig = jtime(y, m, d, (utct / 60), (utct % 60), 0);
jd = jdorig - 45.0;
nt1 = meanphase(jd, 0.0, &k1);
while(1) {
jd += synmonth;
nt2 = meanphase(jd, 0.0, &k2);
if (nt1 <= jdorig && nt2 > jdorig) break;
nt1 = nt2;
k1 = k2;
}
jd = truephase(k1, phas/4.0);
if (jd < jdorig) jd = truephase(k2, phas/4.0);
/* Convert back to Remind format */
jyear(jd, &y, &m, &d);
jhms(jd, &h, &min, &s);
d1 = Julian(y, m, d);
t1 = h*60 + min;
UTCToLocal(d1, t1, date, time);
}

114
norwgian.h Normal file
View File

@@ -0,0 +1,114 @@
/***************************************************************/
/* */
/* NORWGIAN.H */
/* */
/* Support for the Norwegian language. */
/* */
/* This file is part of REMIND. */
/* This file is Copyright (C) 1993 by Trygve Randen. */
/* Remind is Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: norwgian.h,v 1.1 1996-03-27 03:26:03 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "Norwegian"
/* Day names */
#ifdef ISOLATIN1
# define L_SUNDAY "S\370ndag"
#else
# define L_SUNDAY "Soendag"
#endif
#define L_MONDAY "Mandag"
#define L_TUESDAY "Tirsdag"
#define L_WEDNESDAY "Onsdag"
#define L_THURSDAY "Torsdag"
#define L_FRIDAY "Fredag"
#ifdef ISOLATIN1
# define L_SATURDAY "L\370rdag"
#else
# define L_SATURDAY "Loerdag"
#endif
/* Day initials - first letter only */
#define L_DAYINIT "SMTOTFL"
/* Month names */
#define L_JAN "Januar"
#define L_FEB "Februar"
#define L_MAR "Mars"
#define L_APR "April"
#define L_MAY "Mai"
#define L_JUN "Juni"
#define L_JUL "Juli"
#define L_AUG "August"
#define L_SEP "September"
#define L_OCT "Oktober"
#define L_NOV "November"
#define L_DEC "Desember"
/* Today and tomorrow */
#define L_TODAY "i dag"
#define L_TOMORROW "i morgen"
/* The default banner */
#ifdef ISOLATIN1
# define L_BANNER "P\345minnelse for %w, %d. %m, %y%o:"
#else
# define L_BANNER "Paaminnelse for %w, %d. %m, %y%o:"
#endif
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "siden"
#ifdef ISOLATIN1
# define L_FROMNOW "fra n\345"
#else
# define L_FROMNOW "fra naa"
#endif
/* "in %d days' time" */
#define L_INXDAYS "om %d dager"
/* "on" as in "on date..." */
#define L_ON "den"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL "er"
/* Minutes, hours, at, etc */
#ifdef ISOLATIN1
# define L_NOW "n\345"
#else
# define L_NOW "naa"
#endif
#define L_AT "kl."
#define L_MINUTE "minutt"
#define L_HOUR "time"
#define L_IS "er"
#define L_WAS "var"
#define L_AND "og"
/* What to add to make "hour" plural */
#define L_HPLU "r"
/* What to add to make "minute" plural */
#define L_MPLU "er"
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#define L_ORDINAL_OVERRIDE plu = ".";
#define L_A_OVER sprintf(s, "%s %s, den %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
#define L_G_OVER sprintf(s, "%s %s, den %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER
#endif /* L_IN_DOSUBST */

363
omit.c Normal file
View File

@@ -0,0 +1,363 @@
/***************************************************************/
/* */
/* OMIT.C */
/* */
/* This file handles all global OMIT commands, and maintains */
/* the data structures for OMITted dates. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: omit.c,v 1.1 1996-03-27 03:26:04 dfs Exp $";
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "types.h"
#include "protos.h"
#include "globals.h"
#include "err.h"
PRIVATE int BexistsIntArray ARGS ((int array[], int num, int key));
PRIVATE void InsertIntoSortedArray ARGS ((int *array, int num, int key));
/* Arrays for the global omits */
static int FullOmitArray[MAX_FULL_OMITS];
static int PartialOmitArray[MAX_PARTIAL_OMITS];
/* How many of each omit types do we have? */
static int NumFullOmits, NumPartialOmits;
/* The structure for saving and restoring OMIT contexts */
typedef struct omitcontext {
struct omitcontext *next;
int numfull, numpart;
int *fullsave;
int *partsave;
} OmitContext;
/* The stack of saved omit contexts */
static OmitContext *SavedOmitContexts = NULL;
/***************************************************************/
/* */
/* ClearGlobalOmits */
/* */
/* Clear all the global OMIT context. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ClearGlobalOmits(void)
#else
int ClearGlobalOmits()
#endif
{
NumFullOmits = NumPartialOmits = 0;
return OK;
}
/***************************************************************/
/* */
/* DoClear */
/* */
/* The command-line function CLEAR-OMIT-CONTEXT */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoClear(ParsePtr p)
#else
int DoClear(p)
ParsePtr p;
#endif
{
ClearGlobalOmits();
return VerifyEoln(p);
}
/***************************************************************/
/* */
/* DestroyOmitContexts */
/* */
/* Free all the memory used by saved OMIT contexts. */
/* As a side effect, return the number of OMIT contexts */
/* destroyed. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DestroyOmitContexts(void)
#else
int DestroyOmitContexts()
#endif
{
OmitContext *c = SavedOmitContexts;
OmitContext *d;
int num = 0;
while (c) {
num++;
if (c->fullsave) free(c->fullsave);
if (c->partsave) free(c->partsave);
d = c->next;
free(c);
c = d;
}
SavedOmitContexts = NULL;
return num;
}
/***************************************************************/
/* */
/* PushOmitContext */
/* */
/* Push the OMIT context on to the stack. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PushOmitContext(ParsePtr p)
#else
int PushOmitContext(p)
ParsePtr p;
#endif
{
register int i;
OmitContext *context;
/* Create the saved context */
context = NEW(OmitContext);
if (!context) return E_NO_MEM;
context->numfull = NumFullOmits;
context->numpart = NumPartialOmits;
context->fullsave = (int *) malloc(NumFullOmits * sizeof(int));
if (NumFullOmits && !context->fullsave) {
free(context);
return E_NO_MEM;
}
context->partsave = (int *) malloc(NumPartialOmits * sizeof(int));
if (NumPartialOmits && !context->partsave) {
free(context->fullsave);
free(context);
return E_NO_MEM;
}
/* Copy the context over */
for (i=0; i<NumFullOmits; i++)
*(context->fullsave + i) = FullOmitArray[i];
for (i=0; i<NumPartialOmits; i++)
*(context->partsave + i) = PartialOmitArray[i];
/* Add the context to the stack */
context->next = SavedOmitContexts;
SavedOmitContexts = context;
return VerifyEoln(p);
}
/***************************************************************/
/* */
/* PopOmitContext */
/* */
/* Pop the OMIT context off of the stack. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PopOmitContext(ParsePtr p)
#else
int PopOmitContext(p)
ParsePtr p;
#endif
{
register int i;
OmitContext *c = SavedOmitContexts;
if (!c) return E_POP_NO_PUSH;
NumFullOmits = c->numfull;
NumPartialOmits = c->numpart;
/* Copy the context over */
for (i=0; i<NumFullOmits; i++)
FullOmitArray[i] = *(c->fullsave + i);
for (i=0; i<NumPartialOmits; i++)
PartialOmitArray[i] = *(c->partsave + i);
/* Remove the context from the stack */
SavedOmitContexts = c->next;
/* Free memory used by the saved context */
if (c->partsave) free(c->partsave);
if (c->fullsave) free(c->fullsave);
free(c);
return VerifyEoln(p);
}
/***************************************************************/
/* */
/* IsOmitted */
/* */
/* Return non-zero if date is OMITted, zero if it is not. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int IsOmitted(int jul, int localomit)
#else
int IsOmitted(jul, localomit)
int jul, localomit;
#endif
{
int y, m, d;
/* Is it omitted because of local omits? */
if (localomit & (1 << (jul % 7))) return 1;
/* Is it omitted because of fully-specified omits? */
if (BexistsIntArray(FullOmitArray, NumFullOmits, jul)) return 1;
/* Get the syndrome */
FromJulian(jul, &y, &m, &d);
if (BexistsIntArray(PartialOmitArray, NumPartialOmits, (m << 5) + d))
return 1;
/* Not omitted */
return 0;
}
/***************************************************************/
/* */
/* BexistsIntArray */
/* */
/* Perform a binary search on an integer array. Return 1 if */
/* element is found, 0 otherwise. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int BexistsIntArray(int array[], int num, int key)
#else
static int BexistsIntArray(array, num, key)
int array[], num, key;
#endif
{
int top=num-1, bot=0, mid;
while (top >= bot) {
mid = (top+bot)/2;
if (array[mid] == key) return 1;
else if (array[mid] > key) top = mid-1;
else bot=mid+1;
}
return 0;
}
/***************************************************************/
/* */
/* InsertIntoSortedArray */
/* */
/* Insert a key into a sorted array. We assume that there is */
/* room in the array for it. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void InsertIntoSortedArray(int *array, int num, int key)
#else
static void InsertIntoSortedArray(array, num, key)
int *array, num, key;
#endif
{
/* num is number of elements CURRENTLY in the array. */
int *cur = array+num;
while (cur > array && *(cur-1) > key) {
*cur = *(cur-1);
cur--;
}
*cur = key;
}
/***************************************************************/
/* */
/* DoOmit */
/* */
/* Do a global OMIT command. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoOmit(ParsePtr p)
#else
int DoOmit(p)
ParsePtr p;
#endif
{
int y = NO_YR, m = NO_MON, d = NO_DAY, r;
Token tok;
int parsing=1;
int syndrome;
/* Parse the OMIT. We need a month and day; year is optional. */
while(parsing) {
if ( (r=ParseToken(p, TokBuffer)) ) return r;
FindToken(TokBuffer, &tok);
switch (tok.type) {
case T_Year:
if (y != NO_YR) return E_YR_TWICE;
y = tok.val;
break;
case T_Month:
if (m != NO_MON) return E_MON_TWICE;
m = tok.val;
break;
case T_Day:
if (d != NO_DAY) return E_DAY_TWICE;
d = tok.val;
break;
case T_Delta:
break;
case T_Empty:
case T_Comment:
case T_RemType:
case T_Priority:
parsing = 0;
break;
default:
Eprint("%s: '%s' (OMIT)", ErrMsg[E_UNKNOWN_TOKEN], TokBuffer);
return E_UNKNOWN_TOKEN;
}
}
if (m == NO_MON || d == NO_DAY) return E_SPEC_MON_DAY;
if (y == NO_YR) {
if (NumPartialOmits == MAX_PARTIAL_OMITS) return E_2MANY_PART;
if (d > MonthDays[m]) return E_BAD_DATE;
syndrome = (m<<5) + d;
if (!BexistsIntArray(PartialOmitArray, NumPartialOmits, syndrome)) {
InsertIntoSortedArray(PartialOmitArray, NumPartialOmits, syndrome);
NumPartialOmits++;
}
} else {
if (NumFullOmits == MAX_FULL_OMITS) return E_2MANY_FULL;
if (d > DaysInMonth(m, y)) return E_BAD_DATE;
syndrome = Julian(y, m, d);
if (!BexistsIntArray(FullOmitArray, NumFullOmits, syndrome)) {
InsertIntoSortedArray(FullOmitArray, NumFullOmits, syndrome);
NumFullOmits++;
}
}
if (tok.type == T_RemType || tok.type == T_Priority) return E_PARSE_AS_REM;
return OK;
}

158
os2func.c Normal file
View File

@@ -0,0 +1,158 @@
/***************************************************************/
/* */
/* OS2FUNC.C */
/* */
/* Functions to support OS/2. */
/* */
/* This file is part of REMIND. */
/* */
/* This file is Copyright (C) 1993 by Russ Herman. */
/* REMIND is Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: os2func.c,v 1.1 1996-03-27 03:26:04 dfs Exp $";
#ifdef OS2_POPUP
#define INCL_VIO
#define INCL_KBD
#endif
#ifdef _MSC_VER
#define INCL_DOSPROCESS
#endif
#if defined(OS2_POPUP) || defined(_MSC_VER)
#include <os2.h>
#endif
#ifdef OS2_POPUP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef OS2DBG
#include <dos.h>
#include <stdlib.h>
#endif
#include "config.h"
#include "globals.h"
/* EMX defines PS_TYPE, so we undefine it here to avoid
a redefinition warning when we include "types.h" */
#ifdef PS_TYPE
#undef PS_TYPE
#endif
#include "types.h"
#include "protos.h"
#ifdef _MSC_VER
typedef USHORT APIRET;
#endif
static APIRET apiret = 0;
static KBDKEYINFO kbci;
static char *pszPressAny = "\r\nPress any key to continue";
static USHORT pflags = VP_WAIT; /* | VP_TRANSPARENT; */
static HKBD hkbd = 0;
static char VioSubstBuffer[SHELLSIZE + 1];
void StartPopUp()
{
if (OS2MODE)
if (!(DebugFlag & DB_ECHO_LINE))
VioPopUp(&pflags, 0);
}
void EndPopUp()
{
if (DebugFlag & DB_ECHO_LINE)
return;
if (OS2MODE) {
VioWrtTTY(pszPressAny, strlen(pszPressAny), 0);
KbdCharIn(&kbci, IO_WAIT, hkbd);
VioEndPopUp(0);
}
}
int PutsPopUp(char *s)
{
char c, *os = VioSubstBuffer;
if (DebugFlag & DB_ECHO_LINE)
printf("%s", s);
else {
do {
/* Convert \n to \r\n in auxiliary buffer for VIO */
if ((c= *s++) == '\n')
*os++ = '\r';
*os++ = c;
} while (c > 0);
VioWrtTTY(VioSubstBuffer, strlen(VioSubstBuffer), 0);
}
return(0);
}
int PutlPopUp(char *s)
{
StartPopUp();
PutsPopUp(s);
if (DebugFlag & DB_ECHO_LINE)
fputc('\n', stdout);
else
VioWrtTTY("\r\n", 2, 0);
EndPopUp();
return(0);
}
int PutcPopUp(int c)
{
char *s = " ";
if (DebugFlag & DB_ECHO_LINE)
fputc(c, stdout);
else {
switch (c) {
case '\n':
VioWrtTTY("\r\n", 2, 0);
break;
default:
s[0] = c;
VioWrtTTY(s, 1, 0);
break;
}
}
return(0);
}
#ifdef OS2DBG
#define DB_ECHO_LINE 16
int DebugFlag = 0;
void main(/* int argc, char **argv */)
{
int ret;
ret = os2fputs("Test VIO PopUp Writing");
if (ret)
fprintf(stderr, "Test VIO PopUP Writing returned %d %ld",
ret, apiret);
exit(ret);
}
#endif
#endif
#ifdef _MSC_VER
unsigned sleep(unsigned sec)
{
return DosSleep(sec * 1000L);
}
#endif
#ifndef __EMX__
int fork()
{
return(-1);
}
#endif

464
polish.h Normal file
View File

@@ -0,0 +1,464 @@
/***************************************************************/
/* */
/* POLISH.H */
/* */
/* Support for the Polish language. */
/* */
/* This file was submitted by Jerzy Sobczyk. I don't */
/* guarantee that there are no mistakes - I don't speak */
/* Polish. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: polish.h,v 1.1 1996-03-27 03:26:05 dfs Exp $ */
/* The very first define in a language support file must be L_LANGNAME: */
#define L_LANGNAME "Polish"
/* Day names */
#ifdef ISOLATIN1
# define L_SUNDAY "Niedziela"
# define L_MONDAY "Poniedzia\263ek"
# define L_TUESDAY "Wtorek"
# define L_WEDNESDAY "\246roda"
# define L_THURSDAY "Czwartek"
# define L_FRIDAY "Pi\261tek"
# define L_SATURDAY "Sobota"
#else
# define L_SUNDAY "Niedziela"
# define L_MONDAY "Poniedzialek"
# define L_TUESDAY "Wtorek"
# define L_WEDNESDAY "Sroda"
# define L_THURSDAY "Czwartek"
# define L_FRIDAY "Piatek"
# define L_SATURDAY "Sobota"
#endif
/* Day initials - first letter only */
#ifdef ISOLATIN1
#define L_DAYINIT "NPW\246CPS"
#else
#define L_DAYINIT "NPWSCPS"
#endif
/* Month names */
#ifdef ISOLATIN1
# define L_JAN "Stycze\361"
# define L_FEB "Luty"
# define L_MAR "Marzec"
# define L_APR "Kwiecie\361"
# define L_MAY "Maj"
# define L_JUN "Czerwiec"
# define L_JUL "Lipiec"
# define L_AUG "Sierpie\361"
# define L_SEP "Wrzesie\361"
# define L_OCT "Pa\274dziernik"
# define L_NOV "Listopad"
# define L_DEC "Grudzie\361"
#else
# define L_JAN "Styczen"
# define L_FEB "Luty"
# define L_MAR "Marzec"
# define L_APR "Kwiecien"
# define L_MAY "Maj"
# define L_JUN "Czerwiec"
# define L_JUL "Lipiec"
# define L_AUG "Sierpien"
# define L_SEP "Wrzesien"
# define L_OCT "Pazdziernik"
# define L_NOV "Listopad"
# define L_DEC "Grudzien"
#endif
/* Today and tomorrow */
#define L_TODAY "dzisiaj"
#define L_TOMORROW "jutro"
/* The default banner */
#define L_BANNER "Terminarz na %w, %d. %m %y%o:"
/* "am" and "pm" */
#define L_AM "am"
#define L_PM "pm"
/*** The following are only used in dosubst.c ***/
#ifdef L_IN_DOSUBST
/* Ago and from now */
#define L_AGO "temu"
#define L_FROMNOW "od teraz"
/* "in %d days' time" */
#define L_INXDAYS "za %d dni"
/* "on" as in "on date..." */
#define L_ON "-"
/* Pluralizing - this is a problem for many languages and may require
a more drastic fix */
#define L_PLURAL ""
/* Minutes, hours, at, etc */
#define L_NOW "teraz"
#define L_AT "o"
#define L_MINUTE "minut"
#define L_HOUR "godzin"
#ifdef ISOLATIN1
# define L_IS "b\352dzie"
# define L_WAS "by\263o"
#else
# define L_IS "bedzie"
# define L_WAS "bylo"
#endif
#define L_AND "i"
/* What to add to make "hour" or "minute" plural */
#ifdef ISOLATIN1
#define L_NPLU( N ) ((N == 1) ? "\352" : ((N==12) || (N==13) || (N==14)) ? "" : \
((N%10==2) || (N%10==3) || (N%10==4)) ? "y" : "" )
#else
#define L_NPLU( N ) ((N == 1) ? "e" : ((N==12) || (N==13) || (N==14)) ? "" : \
((N%10==2) || (N%10==3) || (N%10==4)) ? "y" : "" )
#endif
/* What to add to make "hour" plural */
#define L_HPLU L_NPLU( hdiff )
/* What to add to make "minute" plural */
#define L_MPLU L_NPLU( mdiff )
/* Define any overrides here, such as L_ORDINAL_OVERRIDE, L_A_OVER, etc.
See the file dosubst.c for more info. */
#ifdef ISOLATIN1
#define L_AMPM_OVERRIDE(ampm, hour) \
ampm = (hour<12) ? \
(hour<5) ? " w nocy" \
: (hour<10) ? " rano" \
: " przed po\263udniem" \
: (hour<18) ? " po po\263udniu" \
: (hour<22) ? " wieczorem" \
: " w nocy";
#else
#define L_AMPM_OVERRIDE(ampm, hour) \
ampm = (hour<12) ? \
(hour<5) ? " w nocy" \
: (hour<10) ? " rano" \
: " przed poludniem" \
: (hour<18) ? " po poludniu" \
: (hour<22) ? " wieczorem" \
: " w nocy";
#endif
#define L_ORDINAL_OVERRIDE plu = "";
#define L_A_OVER sprintf(s, "%s %s, %d. %s %d", L_ON, DayName[jul%7], d, MonthName[m], y);
#define L_G_OVER sprintf(s, "%s %s, %d. %s", L_ON, DayName[jul%7], d, MonthName[m]);
#define L_U_OVER L_A_OVER
#define L_V_OVER L_G_OVER
#endif /* L_IN_DOSUBST */
#define L_0_OVER sprintf(s, L_HPLU);
#define L_9_OVER sprintf(s, L_MPLU);
#define L_1_OVER \
if (tdiff == 0) \
sprintf(s, L_NOW); \
else if (tdiff > 0) \
{ \
if (hdiff == 0) \
sprintf(s, "za %d %s%s", mdiff, L_MINUTE, L_MPLU); \
else if (mdiff == 0) \
sprintf(s, "za %d %s%s", hdiff, L_HOUR, L_HPLU); \
else \
sprintf(s, "za %d %s%s %s %d %s%s", hdiff, L_HOUR, L_HPLU, \
L_AND, mdiff, L_MINUTE, L_MPLU); \
} \
else \
{ \
if (hdiff == 0) \
sprintf(s, "%d %s%s temu", mdiff, L_MINUTE, L_MPLU); \
else if (mdiff == 0) \
sprintf(s, "%d %s%s temu", hdiff, L_HOUR, L_HPLU); \
else \
sprintf(s, "%d %s%s %s %d %s%s temu", hdiff, L_HOUR, L_HPLU, \
L_AND, mdiff, L_MINUTE, L_MPLU); \
}
/* The next ones are used only when MK_GLOBALS is set */
#ifdef MK_GLOBALS
#define L_ERR_OVERRIDE 1
EXTERN char *ErrMsg[] =
{
#ifdef ISOLATIN1
"OK",
"Brakuj\261cy ']'",
"Brakuj\261cy nawias",
"Zbyt skomplikowane wyra\277enie - za du\277o operator\363w",
"Zbyt skomplikowane wyra\277enie - za du\277o argument\363w",
"Brakuj\261cy ')'",
"Nie zdefiniowana funkcja",
"Nielegalny znak",
"Spodziewany operator binarny",
"Brak pami\352ci",
"Niepoprawny numer",
"Pusty stos operator\363w - b\263\261d wewn\352trzny",
"Pusty stos zmiennych - b\263\261d wewn\352trzny",
"Niemo\277liwa konwersja",
"B\263\261d typu",
"Nadmiar daty",
"B\263\261d stosu - b\263\261d wewn\352trzny",
"Dzielenie przez zero",
"Niezdefiniowana zmienna",
"Niespodziewany koniec linii",
"Niespodziewany koniec pliku",
"B\263\261d wejscia/wyjscia",
"Za d\263uga linia",
"B\263\261d wewn\352trzny",
"Z\263a specyfikacja daty",
"Za ma\263o argument\363w",
"Za du\277o argument\363w",
"Nieprawid\263owy czas",
"Liczba za du\277a",
"Liczba za ma\263a",
"Nie mog\352 otworzy\346 pliku",
"Zbyt zagnie\277d\277one INCLUDE",
"B\263\261d sk\263adniowy",
"Nie mog\352 obliczy\346 przypomnienia",
"Zbyt zagnie\277d\277one IF",
"ELSE bez IF do pary",
"ENDIF bez IF do pary",
"Nie mog\352 omin\261\346 (OMIT) wszystkich dni",
"Niespodziewany wyraz w lini",
"POP-OMIT-CONTEXT bez PUSH-OMIT-CONTEXT",
"Komenda RUN zablokowana",
"B\263\261d dziedziny",
"Niepoprawny identyfikator",
"Wykryto rekursywne wywo\263anie funkcji",
"",
"Nie mog\352 zmieni\346 zmiennej systemowej",
"Funkcja biblioteki C nie mo\277e reprezentowac daty/czasu",
"Pr\363ba redefinicji funkcji wbudowanej",
"Nie wolno zagnie\277d\277a\346 definicji funkcji w wyra\277eniu",
"Aby u\277yc powt\363rzenia trzeba w pe\263ni wyspecyfikowa\346 dat\352",
"Rok podany dw\363krotnie",
"Miesi\261c podany dw\363krotnie",
"Dzie\361 podany dw\363krotnie",
"Nieznane s\263owo",
"W komendzie OMIT trzeba poda\346 miesi\261c i dzie\361",
"Za du\277o cz\352\266ciowych komend OMIT",
"Za du\277o pe\263nych komend OMIT",
"Ostrze\277enie: PUSH-OMIT-CONTEXT bez POP-OMIT-CONTEXT",
"B\263\261d odczytu pliku",
"Oczekiwany koniec linii",
"B\263\352dna data hebrajska",
"IIF wymaga nieparzystej liczby argument\363w",
"Ostrze\277enie: Brakujacy ENDIF",
"Oczekiwany przecinek",
"Dzie\361 tygodnia podany dw\363krotnie",
"Dozwolone tylko jedno z: BEFORE, AFTER i SKIP",
"Nie mo\277na zagnie\277d\277a\346 MSG, MSF, RUN, itp. w wyra\277eniu",
"Warto\266\346 powtorzenia podana dw\363krotnie",
"Warto\266\346 r\363\277nicy podana dw\363krotnie",
"Warto\266\346 cofni\352cia podana dw\363krotnie",
"S\263owo ONCE u\277yte dw\363krotnie.",
"Po AT oczekiwany jest czas",
"S\263owo UNTIL u\277yte dw\363krotnie",
"Niekompletna specyfikacja daty",
"S\263owo SCANFROM u\277yte dw\363krotnie",
"Zmienna",
"Warto\266\346",
"*NIE ZDEFINIOWANE*",
"Pocz\261tek UserFN",
"Koniec UserFN",
"Przemine\263o",
"Niepowodzenie w funkcji fork() - nie mog\352 kolejkowa\346 przypomnie\361",
"Nie ma dost\352pu do pliku",
"B\263\352dna data systemowa: Rok mniejszy ni\277 %d\n",
"Nieznana flaga odpluskwiania '%c'\n",
"Nieznana opcja '%c'\n",
"Nieznany u\277ytkownik '%s'\n",
"Nie mog\352 zmieni\346 gid na %d\n",
"Nie mog\352 zmieni\346 uid na %d\n",
"Brak pami\352ci na zmienne \266rodowiska\n",
"Brak znaku '='",
"Brak nazwy zmiennej",
"Brak wyra\277enia",
"Nie mog\352 zmieni\346 daty dost\352pu pliku %s\n",
"Remind: '-i' option: %s\n",
"Brak przypomnie\361.",
"%d Przypomnienia zakolejkowane na p\363\274niej.\n",
"Spodziewana liczba"
#else /* ISOLATIN1 */
"OK",
"Brakujacy ']'",
"Brakujacy nawias",
"Zbyt skomplikowane wyrazenie - za duzo operatorow",
"Zbyt skomplikowane wyrazenie - za duzo argumentow",
"Brakujacy ')'",
"Niezdefiniowana funkcja",
"Nielegalny znak",
"Spodziewany operator binarny",
"Brak pamieci",
"Niepoprawny numer",
"Pusty stos operatorow - blad wewnetrzny",
"Pusty stos zmiennych - blad wewnetrzny",
"Niemozliwa konwersja",
"Blad typu",
"Nadmiar daty",
"Blad stosu - blad wewnetrzny",
"Dzielenie przez zero",
"Niezdefiniowana zmienna",
"Niespodziewany koniec linii",
"Niespodziewany koniec pliku",
"Blad wejscia/wyjscia",
"Za dluga linia",
"Blad wewnetrzny",
"Zla specyfikacja daty",
"Za malo argumentow",
"Za duzo argumentow",
"Nieprawidlowy czas",
"Liczba za duza",
"Liczba za mala",
"Nie moge otworzyc pliku",
"INCLUDE zbyt zagniezdzone",
"Blad skladniowy",
"Nie moge obliczyc przypomnienia",
"Zbyt zagniezdzone IF",
"ELSE bez IF do pary",
"ENDIF bez IF do pary",
"Nie moge ominac (OMIT) wszystkich dni",
"Niespodziewany wyraz w lini",
"POP-OMIT-CONTEXT bez PUSH-OMIT-CONTEXT",
"Komenda RUN zablokowana",
"Blad dziedziny",
"Niepoprawny identyfikator",
"Wykryto rekursywne wywolanie funkcji",
"",
"Nie moga zmienic zmiennej systemowej",
"Funkcja biblioteki C nie moze reprezentowac daty/czasu",
"Proba redefinicji funkcji wbudowanej",
"Nie wolno zagniezdzac definicji funkcji w wyrazeniu",
"Aby uzyc powtorzenia trzeba w pelni wyspecyfikowac date",
"Rok podany dwokrotnie",
"Miesiac podany dwokrotnie",
"Dzien podany dwokrotnie",
"Nieznane slowo",
"W komendzie OMIT trzeba podac miesiac i dzien",
"Za duzo czesciowych komend OMIT",
"Za duzo pelnych komend OMIT",
"ostrzezenie: PUSH-OMIT-CONTEXT bez POP-OMIT-CONTEXT",
"Blad odczytu pliku",
"Oczekiwany koniec linii",
"Bledna data hebrajska",
"IIF wymaga nieparzystej liczby argumentow",
"Ostrzezenie: Brakujacy ENDIF",
"Oczekiwany przecinek",
"Dzien tygodnia podany dwokrotnie",
"Dozwolone tylko jedno z: BEFORE, AFTER i SKIP",
"Nie mozna zagniezdzac MSG, MSF, RUN, itp. w wyrazeniu",
"Wartosc powtorzenia podana dwokrotnie",
"Wartosc roznicy podana dwokrotnie",
"Wartosc cofniecia podana dwokrotnie",
"Slowo ONCE uzyte dwokrotnie.",
"Po AT oczekiwany jest czas",
"Slowo UNTIL uzyte dwokrotnie",
"Niekompletna specyfikacja daty",
"Slowo SCANFROM uzyte dwokrotnie",
"Zmienna",
"Wartosc",
"*UNDEFINED*",
"Poczatek UserFN",
"Koniec UserFN",
"Przeminelo",
"niepowodzenie w funkcji fork() - nie moge kolejkowac przypomnien",
"Nie ma dostepu do pliku",
"Bledna data systemowa: Rok mniejszy niz %d\n",
"Nieznana flaga odpluskwiania '%c'\n",
"Nieznana opcja '%c'\n",
"Nieznany uzytkownik '%s'\n",
"Nie moge zmienic gid na %d\n",
"Nie moge zmienic uid na %d\n",
"Brak pamieci na zmienne srodowiska\n",
"Brak znaku '='",
"Brak nazwy zmiennej",
"Brak wyrazenia",
"Nie moge zmienic daty dostepu pliku %s\n",
"Remind: '-i' option: %s\n",
"Brak przypomnien.",
"%d Przypomnienia zakolejkowane na pozniej.\n",
"Spodziewana liczba"
#endif /* ISOLATIN1 */
};
#endif /* MK_GLOBALS */
/* The following is only used in init.c */
#ifdef L_IN_INIT
#define L_USAGE_OVERRIDE 1
#ifdef HAVE_PROTOS
PUBLIC void Usage(void)
#else
void Usage()
#endif /* HAVE_PROTOS */
{
fprintf(ErrFp, "\nREMIND %s (%s version) Copyright 1992-1996 by David F. Skoll\n", VERSION, L_LANGNAME);
#ifdef BETA
fprintf(ErrFp, ">>>> BETA VERSION <<<<\n");
#endif
#ifdef ISOLATIN1
fprintf(ErrFp, "\nSpos\363b u\277ycia: remind [opcje] plik [data] [czas] [*powt\363rzenie]\n");
fprintf(ErrFp, "Opcje:\n");
fprintf(ErrFp, " -n Wypisz nast\352pne przypomnienia w prostym formacie\n");
fprintf(ErrFp, " -r Zablokuj dyrektywy RUN\n");
fprintf(ErrFp, " -c[n] Wypisz kalendarz na n (domy\266lnie 1) miesi\352cy\n");
fprintf(ErrFp, " -c+[n] Wypisz kalendarz na n (domy\266lnie 1) tygodni\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Ustaw szeroko\266\346, wype\263nienie i odst\352py w kalendarzu\n");
fprintf(ErrFp, " -s[+][n] Wypisz uproszczony kalendarz na n (1) miesi\352cy (tygodni)\n");
fprintf(ErrFp, " -p[n] To samo co -s, ale kompatybilne z rem2ps\n");
fprintf(ErrFp, " -v Obszerniejsze komentarze\n");
fprintf(ErrFp, " -o Ignoruj instrukcje ONCE\n");
fprintf(ErrFp, " -t Odpal wszystkie przysz\263e przypomnienia niezale\277nie od delty\n");
fprintf(ErrFp, " -h Praca bezszmerowa\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a Nie odpalaj przyponie\361 czasowych - kolejkuj je\n");
fprintf(ErrFp, " -q Nie kolejkuj przyponie\361 czasowych\n");
fprintf(ErrFp, " -f Nie przechod\274 do pracy w tle\n");
fprintf(ErrFp, " -z[n] Pracuj jako demon, budz\261c si\352 co n (5) minut\n");
#endif
fprintf(ErrFp, " -d... Odpluskwianie: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Komunikaty o b\263\352dach skieruj na stdout\n");
fprintf(ErrFp, " -b[n] Format czasu: 0=am/pm, 1=24godz., 2=\277aden\n");
fprintf(ErrFp, " -x[n] Limit powt\363rze\361 klauzuli SATISFY (domy\266lnie=150)\n");
fprintf(ErrFp, " -kcmd Wywo\263aj 'cmd' dla przypomnie\361 typu MSG\n");
fprintf(ErrFp, " -g[ddd] Sortuj przypomnienia wed\263ug daty, czasu i priorytetu\n");
fprintf(ErrFp, " -ivar=val Zainicjuj zmienn\261 var warto\266cia val i zachowaj ja\n");
fprintf(ErrFp, " -m Rozpocznij kalendarz od poniedzia\263ku zamiast od niedzieli\n");
#else /* ISOLATIN1 */
fprintf(ErrFp, "\nSposob uzycia: remind [opcje] plik [data] [czas] [*powtorzenie]\n");
fprintf(ErrFp, "Opcje:\n");
fprintf(ErrFp, " -n Wypisz nastepne przypomnienia w prostym formacie\n");
fprintf(ErrFp, " -r Zablokuj dyrektywy RUN\n");
fprintf(ErrFp, " -c[n] Wypisz kalendarz na n (domyslnie 1) miesiecy\n");
fprintf(ErrFp, " -c+[n] Wypisz kalendarz na n (domyslnie 1) tygodni\n");
fprintf(ErrFp, " -w[n[,p[,s]]] Ustaw szerokosc, wypelnienie i odstepy w kalendarzu\n");
fprintf(ErrFp, " -s[+][n] Wypisz uproszczony kalendarz na n (1) miesiecy (tygodni)\n");
fprintf(ErrFp, " -p[n] To samo co -s, ale kompatybilne z rem2ps\n");
fprintf(ErrFp, " -v Obszerniejsze komentarze\n");
fprintf(ErrFp, " -o Ignoruj instrukcje ONCE\n");
fprintf(ErrFp, " -t Odpal wszystkie przyszle przypomnienia niezaleznie od delty\n");
fprintf(ErrFp, " -h Praca bezszmerowa\n");
#ifdef HAVE_QUEUED
fprintf(ErrFp, " -a Nie odpalaj przyponien czasowych - kolejkuj je\n");
fprintf(ErrFp, " -q Nie kolejkuj przyponien czasowych\n");
fprintf(ErrFp, " -f Nie przechodz do pracy w tle\n");
fprintf(ErrFp, " -z[n] Pracuj jako demon, budzac sie co n (5) minut\n");
#endif
fprintf(ErrFp, " -d... Odpluskwianie: e=echo x=expr-eval t=trig v=dumpvars l=showline\n");
fprintf(ErrFp, " -e Komunikaty o bledach skieruj na stdout\n");
fprintf(ErrFp, " -b[n] Format czasu: 0=am/pm, 1=24godz., 2=zaden\n");
fprintf(ErrFp, " -x[n] Limit powtorzen klauzuli SATISFY (domyslnie=150)\n");
fprintf(ErrFp, " -kcmd Wywolaj 'cmd' dla przypomnien typu MSG\n");
fprintf(ErrFp, " -g[ddd] Sortuj przypomnienia wedlug daty, czasu i priorytetu\n");
fprintf(ErrFp, " -ivar=val Zainicjuj zmienna var wartoscia val i zachowaj ja\n");
fprintf(ErrFp, " -m Rozpocznij kalendarz od poniedzialku zamiast od niedzieli\n");
#endif /* ISOLATIN1 */
exit(1);
}
#endif /* L_IN_INIT */

171
protos.h Normal file
View File

@@ -0,0 +1,171 @@
/***************************************************************/
/* */
/* PROTOS.H */
/* */
/* Function Prototypes. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: protos.h,v 1.1 1996-03-27 03:26:05 dfs Exp $ */
#ifdef HAVE_PROTOS
#define ARGS(x) x
#else
#define ARGS(x) ()
#endif
/* Define a string assignment macro - be careful!!! */
#define STRSET(x, str) { if (x) free(x); (x) = StrDup(str); }
/* Define a general malloc routine for creating pointers to objects */
#define NEW(type) ((type *) malloc(sizeof(type)))
#ifdef NO_STRSTR
char *strstr ARGS ((char *s1, char *s2));
#endif
int CallUserFunc ARGS ((char *name, int nargs));
int DoFset ARGS ((ParsePtr p));
void ProduceCalendar ARGS ((void));
char *SimpleTime ARGS ((int tim, char *out));
int DoRem ARGS ((ParsePtr p));
int DoFlush ARGS ((ParsePtr p));
void DoExit ARGS ((ParsePtr p));
int ParseRem ARGS ((ParsePtr s, Trigger *trig, TimeTrig *tim));
#ifdef OS2_POPUP
int TriggerReminder ARGS ((ParsePtr p, Trigger *t, TimeTrig *tim, int jul,
int AsPopUp));
#else
int TriggerReminder ARGS ((ParsePtr p, Trigger *t, TimeTrig *tim, int jul));
#endif
int ShouldTriggerReminder ARGS ((Trigger *t, TimeTrig *tim, int jul));
int DoSubst ARGS ((ParsePtr p, char *out, Trigger *t, TimeTrig *tt, int jul, int mode));
int DoSubstFromString ARGS ((char *source, char *dest, int jul, int tim));
int EvalExpr ARGS ((char **e, Value *v));
int DoCoerce ARGS ((char type, Value *v));
void PrintValue ARGS ((Value *v, FILE *fp));
int CopyValue ARGS ((Value *dest, const Value *src));
int ReadLine ARGS ((void));
int OpenFile ARGS ((const char *fname));
int PopFile ARGS ((void));
int DoInclude ARGS ((ParsePtr p));
int IncludeFile ARGS ((const char *fname));
int GetAccessDate ARGS ((char *file));
int SetAccessDate ARGS ((char *fname, int jul));
int TopLevel ARGS ((void));
int CallFunc ARGS ((Operator *f, int nargs));
void InitRemind ARGS ((int argc, char *argv[]));
void Usage ARGS ((void));
int main ARGS ((int argc, char *argv[]));
int Julian ARGS ((int year, int month, int day));
void FromJulian ARGS ((int jul, int *y, int *m, int *d));
int ParseChar ARGS ((ParsePtr p, int *err, int peek));
int ParseToken ARGS ((ParsePtr p, char *out));
int ParseIdentifier ARGS ((ParsePtr p, char *out));
int EvaluateExpr ARGS ((ParsePtr p, Value *v));
int Evaluate ARGS ((char **s, Var *locals));
int FnPopValStack ARGS ((Value *val));
void Eprint ARGS ((const char *fmt, ...));
void OutputLine ARGS ((FILE *fp));
void CreateParser ARGS ((char *s, ParsePtr p));
void DestroyParser ARGS ((ParsePtr p));
void PushToken ARGS ((const char *tok));
long SystemTime ARGS ((int realtime));
int SystemDate ARGS ((int *y, int *m, int *d));
int DoIf ARGS ((ParsePtr p));
int DoElse ARGS ((ParsePtr p));
int DoEndif ARGS ((ParsePtr p));
int DoIfTrig ARGS ((ParsePtr p));
int ShouldIgnoreLine ARGS ((void));
int VerifyEoln ARGS ((ParsePtr p));
int DoDebug ARGS ((ParsePtr p));
int DoBanner ARGS ((ParsePtr p));
int DoRun ARGS ((ParsePtr p));
int DoErrMsg ARGS ((ParsePtr p));
int ClearGlobalOmits ARGS ((void));
int DoClear ARGS ((ParsePtr p));
int DestroyOmitContexts ARGS ((void));
int PushOmitContext ARGS ((ParsePtr p));
int PopOmitContext ARGS ((ParsePtr p));
int IsOmitted ARGS ((int jul, int localomit));
int DoOmit ARGS ((ParsePtr p));
int QueueReminder ARGS ((ParsePtr p, int typ, TimeTrig *tim, const char *sched));
void HandleQueuedReminders ARGS ((void));
char *FindInitialToken ARGS ((Token *tok, char *s));
void FindToken ARGS ((const char *s, Token *tok));
void FindNumericToken ARGS ((const char *s, Token *t));
int ComputeTrigger ARGS ((int today, Trigger *trig, int *err));
char *StrnCpy ARGS ((char *dest, const char *source, int n));
int StrMatch ARGS ((const char *s1, const char *s2, int n));
int StrinCmp ARGS ((const char *s1, const char *s2, int n));
char *StrDup ARGS ((const char *s));
int StrCmpi ARGS ((const char *s1, const char *s2));
Var *FindVar ARGS ((const char *str, int create));
int DeleteVar ARGS ((const char *str));
int SetVar ARGS ((const char *str, Value *val));
int GetVarValue ARGS ((const char *str, Value *val, Var *locals));
int DoSet ARGS ((Parser *p));
int DoUnset ARGS ((Parser *p));
int DoDump ARGS ((ParsePtr p));
void DumpVarTable ARGS ((void));
void DestroyVars ARGS ((int all));
int PreserveVar ARGS ((char *name));
int DoPreserve ARGS ((Parser *p));
int DoSatRemind ARGS ((Trigger *trig, TimeTrig *tim, ParsePtr p));
void DoMsgCommand ARGS ((char *cmd, char *msg));
int ParseNonSpaceChar ARGS ((ParsePtr p, int *err, int peek));
unsigned int HashVal ARGS ((const char *str));
int DateOK ARGS ((int y, int m, int d));
Operator *FindFunc ARGS ((char *name, Operator where[], int num));
int InsertIntoSortBuffer ARGS ((int jul, int tim, char *body, int typ, int prio));
void IssueSortedReminders ARGS ((void));
int UserFuncExists ARGS ((char *fn));
void JulToHeb ARGS((int jul, int *hy, int *hm, int *hd));
int HebNameToNum ARGS((const char *mname));
char *HebMonthName ARGS((int m, int y));
int RoshHashana ARGS((int i));
long DaysToHebYear ARGS((int y));
int DaysInHebYear ARGS((int y));
char *DaysInHebMonths ARGS((int ylen));
int HebToJul ARGS((int hy, int hm, int hd));
int GetValidHebDate ARGS((int yin, int min, int din, int adarbehave, int *mout, int *dout, int yahr));
int GetNextHebrewDate ARGS((int julstart, int hm, int hd, int yahr, int adarbehave, int *ans));
int ComputeJahr ARGS ((int y, int m, int d, int *ans));
int GetSysVar ARGS ((const char *name, Value *val));
int SetSysVar ARGS ((const char *name, Value *val));
void DumpSysVarByName ARGS ((const char *name));
int CalcMinsFromUTC ARGS ((int jul, int tim, int *mins, int *isdst));
#ifdef OS2_POPUP
void FillParagraph ARGS ((char *s, int AsPopUp));
#else
void FillParagraph ARGS ((char *s));
#endif
void LocalToUTC ARGS ((int locdate, int loctime, int *utcdate, int *utctime));
void UTCToLocal ARGS ((int utcdate, int utctime, int *locdate, int *loctime));
int MoonPhase ARGS ((int date, int time));
void HuntPhase ARGS ((int startdate, int starttim, int phas, int *date, int *time));
int CompareRems ARGS ((int dat1, int tim1, int prio1, int dat2, int tim2, int prio2, int bydate, int bytime, int byprio));
#ifdef __BORLANDC__
void __cdecl SigIntHandler ARGS ((int d));
#else
#ifdef SIGHANDLER_INT_ARG
void SigIntHandler ARGS ((int d));
#else
void SigIntHandler ARGS ((void));
#endif
#endif
void GotSigInt ARGS ((void));
#if defined(__OS2__)
int fork ARGS ((void));
#if defined(OS2_POPUP)
void StartPopUp ARGS ((void));
void EndPopUp ARGS ((void));
int PutcPopUp ARGS ((int c));
int PutlPopUp ARGS ((char *s));
int PutsPopUp ARGS ((char *s));
#endif
#endif

412
queue.c Normal file
View File

@@ -0,0 +1,412 @@
/***************************************************************/
/* */
/* QUEUE.C */
/* */
/* Queue up reminders for subsequent execution. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: queue.c,v 1.1 1996-03-27 03:26:05 dfs Exp $";
#include "config.h"
/* We only want object code generated if we have queued reminders */
#ifdef HAVE_QUEUED
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD
#include <unistd.h>
#endif
#if defined(__OS2__) || defined(__MSDOS__)
#include <io.h>
#if defined(__BORLANDC__)
#include <dos.h>
#endif
#include <process.h>
#endif
#include "globals.h"
#include "err.h"
#include "types.h"
#include "protos.h"
#include "expr.h"
/* List structure for holding queued reminders */
typedef struct queuedrem {
struct queuedrem *next;
int typ;
int RunDisabled;
int ntrig;
char *text;
char sched[VAR_NAME_LEN+1];
TimeTrig tt;
} QueuedRem;
/* Global variables */
static QueuedRem *QueueHead;
static time_t FileModTime;
static struct stat StatBuf;
PRIVATE void CheckInitialFile ARGS ((void));
PRIVATE int CalculateNextTime ARGS ((QueuedRem *q));
PRIVATE QueuedRem *FindNextReminder ARGS ((void));
PRIVATE int CalculateNextTimeUsingSched ARGS ((QueuedRem *q));
/***************************************************************/
/* */
/* QueueReminder */
/* */
/* Put the reminder on a queue for later, if queueing is */
/* enabled. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int QueueReminder(ParsePtr p, int typ, TimeTrig *tim, const char *sched)
#else
int QueueReminder(p, typ, tim, sched)
ParsePtr p;
int typ;
TimeTrig *tim;
char *sched;
#endif
{
QueuedRem *qelem;
if (DontQueue ||
tim->ttime == NO_TIME ||
typ == CAL_TYPE ||
tim->ttime < SystemTime(0) / 60 ||
((typ == RUN_TYPE) && RunDisabled)) return OK;
qelem = NEW(QueuedRem);
if (!qelem) {
return E_NO_MEM;
}
qelem->text = StrDup(p->pos); /* Guaranteed that parser is not nested. */
if (!qelem->text) {
free(qelem);
return E_NO_MEM;
}
qelem->typ = typ;
qelem->tt = *tim;
qelem->next = QueueHead;
qelem->RunDisabled = RunDisabled;
qelem->ntrig = 0;
strcpy(qelem->sched, sched);
QueueHead = qelem;
NumQueued++;
return OK;
}
/***************************************************************/
/* */
/* HandleQueuedReminders */
/* */
/* Handle the issuing of queued reminders in the background */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void HandleQueuedReminders(void)
#else
void HandleQueuedReminders()
#endif
{
QueuedRem *q = QueueHead;
long TimeToSleep;
unsigned SleepTime;
Parser p;
Trigger trig;
/* Suppress the BANNER from being issued */
NumTriggered = 1;
/* If we are not connected to a tty, then we must close the
* standard file descriptors. This is to prevent someone
* doing:
* remind file | <filter> | >log
* and have <filter> hung because the child (us) is still
* connected to it. This means the only commands that will be
* processed correctly are RUN commands, provided they mail
* the result back or use their own resource (as a window).
*/
if (!DontFork && (!isatty(1) || !isatty(2))) {
close(1);
close(2);
}
/* If we're a daemon, get the mod time of initial file */
if (Daemon) {
if (stat(InitialFile, &StatBuf)) {
fprintf(ErrFp, "Cannot stat %s - not running as daemon!\n",
InitialFile);
Daemon = 0;
} else FileModTime = StatBuf.st_mtime;
}
/* Initialize the queue - initialize all the entries time of issue */
while (q) {
q->tt.nexttime = (int) (SystemTime(0)/60 - 1);
q->tt.nexttime = CalculateNextTime(q);
q = q->next;
}
#ifdef __BORLANDC__
signal(SIGINT, SigIntHandler);
#else
if (!DontFork || Daemon) signal(SIGINT, SigIntHandler);
#endif
/* Sit in a loop, issuing reminders when necessary */
while(1) {
q = FindNextReminder();
/* If no more reminders to issue, we're done unless we're a daemon. */
if (!q && !Daemon) break;
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime(0);
while (TimeToSleep > 0L) {
SleepTime = (unsigned) ((TimeToSleep > 30000L) ? 30000 : TimeToSleep);
if (Daemon && SleepTime > 60*Daemon) SleepTime = 60*Daemon;
sleep(SleepTime);
if (Daemon && SleepTime) CheckInitialFile();
if (Daemon && !q)
TimeToSleep = (long) 60*Daemon;
else
TimeToSleep = (long) q->tt.nexttime * 60L - SystemTime(0);
}
/* Trigger the reminder */
CreateParser(q->text, &p);
trig.typ = q->typ;
RunDisabled = q->RunDisabled;
#ifdef OS2_POPUP
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday, 1);
#else
(void) TriggerReminder(&p, &trig, &q->tt, JulianToday);
#endif
fflush(stdout);
/* Calculate the next trigger time */
q->tt.nexttime = CalculateNextTime(q);
}
#ifdef __BORLANDC__
signal(SIGINT, SIG_DFL);
#endif
exit(0);
}
/***************************************************************/
/* */
/* CalculateNextTime */
/* */
/* Calculate the next time when a reminder should be issued. */
/* Return NO_TIME if reminder expired. */
/* Strategy is: If a sched() function is defined, call it. */
/* Otherwise, use AT time with delta and rep. If sched() */
/* fails, revert to AT with delta and rep. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int CalculateNextTime(QueuedRem *q)
#else
static int CalculateNextTime(q)
QueuedRem *q;
#endif
{
int tim = q->tt.ttime;
int rep = q->tt.rep;
int delta = q->tt.delta;
int curtime = q->tt.nexttime+1;
int r;
/* Increment number of times this one has been triggered */
q->ntrig++;
if (q->sched[0]) {
r = CalculateNextTimeUsingSched(q);
if (r != NO_TIME) return r;
}
if (delta == NO_DELTA)
if (tim < curtime) return NO_TIME; else return tim;
tim -= delta;
if (rep == NO_REP) rep = delta;
if (tim < curtime) tim += ((curtime - tim) / rep) * rep;
if (tim < curtime) tim += rep;
if (tim > q->tt.ttime) tim = q->tt.ttime;
if (tim < curtime) return NO_TIME; else return tim;
}
/***************************************************************/
/* */
/* FindNextReminder */
/* */
/* Find the next reminder to trigger */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE QueuedRem *FindNextReminder(void)
#else
static QueuedRem *FindNextReminder()
#endif
{
QueuedRem *q = QueueHead;
QueuedRem *ans = NULL;
while (q) {
if (q->tt.nexttime != NO_TIME) {
if (!ans) ans = q;
else if (q->tt.nexttime < ans->tt.nexttime) ans = q;
}
q = q->next;
}
return ans;
}
/***************************************************************/
/* */
/* GotSigInt */
/* */
/* Split out what's done on a SIGINT from the SIGINT Handler. */
/* This will be necessary for OS/2 multithreaded. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void GotSigInt(void)
#else
void GotSigInt()
#endif
{
QueuedRem *q = QueueHead;
printf("Contents of AT queue:%s", NL);
while (q) {
if (q->tt.nexttime != NO_TIME) {
printf("Trigger: %02d%c%02d Activate: %02d%c%02d Rep: %d Delta: %d Sched: %s",
q->tt.ttime / 60, TIMESEP, q->tt.ttime % 60,
q->tt.nexttime / 60, TIMESEP, q->tt.nexttime % 60,
q->tt.rep, q->tt.delta, q->sched);
if (*q->sched) printf("(%d)", q->ntrig+1);
printf("%s", NL);
printf("Text: %s %s%s%s", ((q->typ == MSG_TYPE) ? "MSG" :
((q->typ == MSF_TYPE) ? "MSF" :"RUN")),
q->text,
NL, NL);
}
q = q->next;
}
printf(NL);
}
/***************************************************************/
/* */
/* CheckInitialFile */
/* */
/* If the initial file has been modified, then restart the */
/* daemon. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void CheckInitialFile(void)
#else
static void CheckInitialFile()
#endif
{
/* If date has rolled around, or file has changed, spawn a new version. */
time_t tim = FileModTime;
int y, m, d;
if (stat(InitialFile, &StatBuf) == 0) tim = StatBuf.st_mtime;
if (tim != FileModTime ||
RealToday != SystemDate(&y, &m, &d))
execvp(ArgV[0], ArgV);
}
/***************************************************************/
/* */
/* CalculateNextTimeUsingSched */
/* */
/* Call the scheduling function. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int CalculateNextTimeUsingSched(QueuedRem *q)
#else
static int CalculateNextTimeUsingSched(q)
QueuedRem *q;
#endif
{
/* Use LineBuffer for temp. string storage. */
int r;
Value v;
char *s;
int LastTime = -1;
int ThisTime;
if (UserFuncExists(q->sched) != 1) {
q->sched[0] = 0;
return NO_TIME;
}
RunDisabled = q->RunDisabled; /* Don't want weird scheduling functions
to be a security hole! */
while(1) {
sprintf(LineBuffer, "%s(%d)", q->sched, q->ntrig);
s = LineBuffer;
r = EvalExpr(&s, &v);
if (r) {
q->sched[0] = 0;
return NO_TIME;
}
if (v.type == TIM_TYPE) {
ThisTime = v.v.val;
} else if (v.type == INT_TYPE) {
if (v.v.val > 0)
ThisTime = q->tt.nexttime + v.v.val;
else
ThisTime = q->tt.ttime + v.v.val;
} else {
DestroyValue(v);
q->sched[0] = 0;
return NO_TIME;
}
if (ThisTime < 0) ThisTime = 0; /* Can't be less than 00:00 */
if (ThisTime > 1439) ThisTime = 1439; /* or greater than 11:59 */
if (ThisTime > q->tt.nexttime) return ThisTime;
if (ThisTime <= LastTime) {
q->sched[0] = 0;
return NO_TIME;
}
LastTime = ThisTime;
q->ntrig++;
}
}
#endif /* HAVE_QUEUED from way at the top */

45
rem Normal file
View File

@@ -0,0 +1,45 @@
#!/bin/sh
#
# rem - by David Skoll - 26 February 1991
#
# $Id: rem,v 1.1 1996-03-27 03:26:06 dfs Exp $
#
# This script runs 'remind' with a default reminder file assumed. You
# can override the default by using "rem -F newfile ..." (But why would
# you use rem unless you wanted to accept the default??)
# ------ You may wish to change the defaults below this line ------
# The default reminder file
DEFAULT=$HOME/.reminders
# The executable file (you may wish to change this to /usr/local/bin/remind
# or whatever.
EXECUTABLE=remind
# No options yet
OPTIONS=""
# No parameters yet
PARAMETERS=""
# ------ You shouldn't change anything below this line -----
# Scan for options
while test "$1" != ""
do
case $1 in
-F) DEFAULT=$2
shift
shift ;;
-*) OPTIONS="$OPTIONS $1"
shift ;;
*) PARAMETERS=$*
break ;;
esac
done
$EXECUTABLE $OPTIONS $DEFAULT $PARAMETERS

34
rem.1 Normal file
View File

@@ -0,0 +1,34 @@
.TH REM 1 "26 February 1991"
.UC 4
.SH NAME
rem \- run 'remind' with a default reminder file
.SH SYNOPSIS
.B rem
[\-F \fIfilename\fR] [\fIremind_options\fR] [\fIremind_params\fR]
.SH DESCRIPTION
.B Rem
runs the \fBremind\fR program with a default reminder file of
"$HOME/.reminders". You can supply remind options on the command line,
as well as a date specification, just as with \fBremind\fR.
If you don't want to use the default filename, you can override it with
the "-F" option, followed by a space and a filename. (This, however,
defeats the purpose of \fBrem\fR)
.PP
For example, typing:
.PP
.nf
rem -c 1 jan 1992
.fi
.PP
has the same effect as typing:
.PP
.nf
remind -c $HOME/.reminders 1 jan 1992
.fi
.PP
.SH AUTHOR
David F. Skoll
.SH SEE ALSO
remind, kall

319
rem2ps.1 Normal file
View File

@@ -0,0 +1,319 @@
.TH REM2PS 1 "2 February 1994"
.UC4
.SH NAME
rem2ps \- draw a PostScript calendar from Remind output
.SH SYNOPSIS
.B rem2ps [\fIoptions\fR]
.SH DESCRIPTION
\fBRem2ps\fR reads the standard input, which should be the results of running
\fBRemind\fR with the \fB\-p\fR option. It emits PostScript code (which
draws a calendar) to the standard output.
.SH OPTIONS
.TP
.B \-v
Be more verbose. This causes \fBRem2ps\fR to print progress messages
to the standard error stream. Normally, it is silent.
.TP
.B \-n
Produce a calendar whose first column is Monday (rather than Sunday.)
.TP
.B \-p file
Include the contents of \fIfile\fR in the PostScript prologue. This
allows you to define procedures, variables etc. which can be used
by the \fBPS\fR and \fBPSFILE\fR reminders. You should not
include any document structuring comments in your prologue.
.TP
.B \-l
Produce the calendar in landscape mode rather than the default
portrait mode.
.TP
\fB\-c\fR[\fIn\fR]
If \fIn\fR is omitted, disables the small calendars for next and previous
months which are normally generated. If \fIn\fR is supplied, it can range
from 0 to 3, with the following meanings:
.RS
.TP
.B 0
Disable small calendars
.TP
.B 1
Place the small calendars at the bottom-right if there is room; otherwise,
place them at the top-left.
.TP
.B 2
Place the small calendars at the top-left if there is room; otherwise,
place them at the bottom-right.
.TP
.B 3
Place the previous month's small calendar at the top-left and the next
month's at the bottom-right if there is room; otherwise, follow \fIn\fR=1.
A moment's thought reveals that an option which splits the calendars if
there is room and otherwise follows \fIn\fR=2 yields the same results as
\fIn\fR=3.
.RE
.TP
.B \-i
Use ISO 8859-1 standard encoding for the PostScript fonts. If you do
not use this option, the default encoding is used.
.TP
.B \-e
Make the calendar fill the entire page. By default, the calendar is
slightly smaller than the page. This allows days with many reminders
to "expand" as needed. However, if you don't have days which expand,
you can use this option to make all of the boxes slightly bigger.
One caveat: If you do use the \fB\-e\fR option and one day has many
reminders, the calendar may expand off the page, losing some information.
Experiment!
.TP
.B \-m media
Set the page size. If you use the \-m option, you must specify the
media type, which can be one of the
following. (Sizes are approximate.)
.RS
.TP
Letter
8.5 x 11 in.
.TP
Legal
11 x 17 in.
.TP
Ledger
8.5 x 14 in.
.TP
Statement
5.5 x 8.5 in.
.TP
Executive
7.5 x 10 in.
.TP
A3
29.7 x 42 cm.
.TP
A4
21 x 29.7 cm.
.TP
A5
14.8 x 21 cm.
.TP
B4
25.7 x 36.4 cm.
.TP
B5
18.3 x 25.7 cm.
.TP
Folio
8.5 x 13 in.
.TP
Quarto
8.5 x 10.8 in.
.TP
10x14
10 x 14 in.
.PP
Type "rem2ps -m help" for a list of available media. Note that the media
type (and all \fBRem2ps\fR options) are case-sensitive. If you don't use
the \fB\-m\fR option, the media defaults to a compiled-in default - this
is usually Letter for North America and A4 for Europe. The "-m help"
option will display the compiled-in default.
.RE
.TP
\fB\-f\fR[\fBtshed\fR] \fIfont\fR
Set the font for the calendar title,
the small calendars, the day-of-week headings, the calendar
entries, and the day numbers, respectively. \fIFont\fR must be the
name of a valid PostScript font. The default fonts are equivalent to
specifying:
.RS
.PP
.nf
-ftshe Helvetica -fd Helvetica-BoldOblique
.fi
.PP
In other words, the heading, entry and small-calendar fonts are set
to Helvetica, and the font for the day numbers is set to
Helvetica-BoldOblique.
.RE
.TP
\fB\-s\fR[\fBthed\fR] \fIsize\fR
Set the size (in points) of the text for the the calendar title,
day-of-week headings, the calendar entries, and the day numbers,
respectively. \fISize\fR must be a decimal number. The default sizes
are equivalent to specifying:
.RS
.PP
.nf
-sthd 14 -se 8
.fi
.PP
In other words, the heading and day numbers are 14-point fonts, and the
calendar entries are printed in 8-point text.
.RE
.TP
\fB\-b\fR \fIsize\fR
Set the size of the blank white border in each calendar box to \fIsize\fR
points. The default border size is 6 points, or 1/12 in.
.TP
\fB\-t\fR \fIsize\fR
Set the thickness of the black calendar grid lines. The default is 1,
for a line thickness of one point (1/72 in.)
.TP
\fB\-o\fR[\fBlrtb\fR] \fIsize\fR
Set the left, right, top, and/or bottom margins to \fIsize\fR points.
For this option only, \fIsize\fR must be an integer. It represents the
margin size in units of 1/72 in. The default margin sizes are 36, for
half-inch margins. If you wish to punch holes in the calendar page to insert
it into a binder, you may wish to increase the left margin to one inch.
In that case, you should also decrease the heading font size to 12 points
for good output:
.PP
.nf
# This gives good results for putting into a binder
rem2ps -ol 72 -sh 12
.fi
.SH USAGE
To use \fBRem2ps\fR, you should pipe the output of \fBRemind\fR with the \fB\-p\fR
option to \fBRem2ps\fR, and then send the result to a printer. This is most easily
illustrated with examples:
.PP
.nf
remind -p12 /dev/null 1 jan 1994 | rem2ps | lpr -Plaser
.fi
.PP
That example creates a blank calendar for the entire year of 1994, and
sends it the the printer named "laser."
.PP
.nf
remind -p ~/.reminders | rem2ps -l -sd 18 > cal.ps
.fi
.PP
This reminder creates a calendar for the current month, filling in
entries from the reminder file "~/.reminders." The calendar is produced
in landscape mode, with a font size of 18 for the day numbers. The result
is put in the PostScript file "cal.ps."
.PP
.SH VARIABLES AVAILABLE TO USER-SUPPLIED POSTSCRIPT CODE
.PP
The following variables are available to \fBPS\fR and
\fBPSFILE\fR-type reminders. (This material is duplicated
in the \fBRemind\fR manual page.)
.TP
LineWidth
The width of the black grid lines making up the calendar.
.TP
Border
The border between the center of the grid lines and the space used to print
calendar entries. This border is normally blank space.
.TP
BoxWidth and BoxHeight
The width and height of the calendar box, from center-to-center of the
black gridlines.
.TP
InBoxHeight
The height from the center of the bottom black gridline to the top
of the regular calendar entry area. The space from here to the top
of the box is used only to draw the day number.
.TP
/DayFont, /TitleFont, /EntryFont, /SmallFont and /HeadFont
The fonts used to draw the day numbers, the month and year title,
the calendar entries, the small
calendars, and the day-of-week headings, respectively.
.TP
DaySize, TitleSize, EntrySize and HeadSize
The sizes of the above fonts. (The size of the small calendar font
is \fInot\fR defined here.) For example, if you wanted to print
the Hebrew date next to the regular day number in the calendar, use:
.PP
.nf
REM PS Border BoxHeight Border sub DaySize sub moveto \\
/DayFont findfont DaySize scalefont setfont \\
([hebday(today())] [hebmon(today())]) show
.fi
.PP
.RS
Note how /DayFont and DaySize are used.
.RE
.PP
Note that if you supply PostScript code, it is possible to produce invalid
PostScript files. Always test your PostScript thoroughly with a PostScript
viewer before sending it to the printer. You should not use any document
structuring comments in your PostScript code.
.PP
In addition, prior to drawing a calendar page, \fBRem2ps\fR emits
the following PostScript code:
.PP
.nf
save (mon) (yr) PreCal restore
.fi
.PP
where \fImon\fR and \fIyr\fR are the month and year of the calendar
page. The default \fBPreCal\fR procedure simply pops
the arguments and does nothing. However, you can define a \fBPreCal\fR
function in your prologue file to do whatever you want - it can draw a
background for the entire calendar, for instance.
.PP
In the context of the \fBPreCal\fR procedure, the following conditions
hold:
.TP
o
The PostScript origin is at the bottom left-hand corner of the page, and
PostScript units of 1/72" are in effect.
.TP
o
The variables MinX, MinY, MaxX and MaxY define the bounding box within
which the calendar will be drawn.
.TP
o
The font and font-size variables, as well as Border and LineWidth described
previously, are valid.
.PP
For an example, create a file called "myprolog" whose contents are:
.PP
.nf
/PreCal {
/yr exch def
/mon exch def
/xsiz1 MaxX MinX sub def
/ysiz1 MaxY MinY sub def
/xsiz xsiz1 MinX sub MinX sub def
/ysiz ysiz1 MinY sub MinY sub def
xsiz
ysiz
lt
{/len xsiz 1.41 mul def
MinX MinX add ysiz1 xsiz1 sub 2 div MinY add MinY add moveto}
{/len ysiz 1.41 mul def
xsiz1 ysiz1 sub 2 div MinX add MinX add MinY MinY add moveto}
ifelse
/Helvetica-Bold findfont 1 scalefont setfont
mon stringwidth pop
( ) stringwidth pop add
yr stringwidth pop add
len exch div /len exch def
/Helvetica-Bold findfont len scalefont setfont
0.95 setgray
45 rotate
mon show
( ) show
yr show
} bind def
.fi
.PP
Use that file with the \fBRem2ps\fR \fB\-p\fR option to create calendars
with the year and month in large grey letters in the background of the
calendar.
.PP
.SH AUTHOR
David F. Skoll
.SH BUGS
All \fBRem2ps\fR options are case-sensitive, unlike \fBRemind\fR.
Any time you supply
a font name or size, line thickness, or border width, it is treated as a
string and sent straight to the PostScript interpreter. Thus, if you
supply invalid fonts or sizes, \fBRem2ps\fR will not complain, but the
resulting PostScript output will probably not work.
.PP
You should ensure that the values you supply for margin widths are sensible.
If they are too big for the media size, \fBRem2ps\fR will not complain,
but again, the PostScript output will probably not work.
.SH SEE ALSO
\fBRemind\fR

957
rem2ps.c Normal file
View File

@@ -0,0 +1,957 @@
/***************************************************************/
/* */
/* REM2PS.C */
/* */
/* Print a PostScript calendar. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: rem2ps.c,v 1.1 1996-03-27 03:26:07 dfs Exp $";
#include "config.h"
#include "lang.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_UNISTD
#include <unistd.h>
#endif
#include "rem2ps.h"
#include "version.h"
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef __TURBOC__
#include <io.h>
#endif
#ifdef HAVE_PROTOS
#define ARGS(x) x
#else
#define ARGS(x) ()
#endif
#define NEW(type) ((type *) malloc(sizeof(type)))
typedef struct calentry {
struct calentry *next;
char *entry;
} CalEntry;
typedef struct {
char *name;
int xsize, ysize;
} PageType;
char Days[]=L_DAYINIT;
char *SmallCalLoc[] = {
"",
"bt",
"tb",
"sbt",
};
#define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0]))
char *SmallLocation;
int SmallCol1, SmallCol2;
PageType Pages[] =
{
{"Letter", 612, 792}, /* 8.5 x 11 in. */
{"Tabloid", 792, 1224}, /* 11 x 17 in. */
{"Ledger", 1224, 792}, /* 17 x 11 in. */
{"Legal", 612, 1008}, /* 8.5 x 14 in. */
{"Statement", 396, 612}, /* 5.5 x 8.5 in. */
{"Executive", 540, 720}, /* 7.5 x 10 in. */
{"A3", 842, 1190},
{"A4", 595, 842},
{"A5", 420, 595},
{"B4", 729, 1032},
{"B5", 519, 729},
{"Folio", 612, 936},
{"Quarto", 612, 780},
{"10x14", 720, 1008}
};
PageType DefaultPage[1] =
{
DEFAULT_PAGE
};
#define NUMPAGES (sizeof(Pages)/sizeof(Pages[0]))
CalEntry *CurEntries = NULL;
CalEntry *PsEntries[32];
PageType *CurPage;
char PortraitMode;
char NoSmallCal;
char UseISO;
char LineBuffer[LINELEN];
char *HeadFont="Helvetica";
char *TitleFont="Helvetica";
char *DayFont="Helvetica-BoldOblique";
char *EntryFont="Helvetica";
char *SmallFont="Helvetica";
char *LineWidth = "1";
char *HeadSize="14";
char *TitleSize="14";
char *DaySize="14";
char *EntrySize="8";
char *BorderSize = "6";
char *UserProlog = NULL;
int validfile = 0;
int CurDay;
int MaxDay;
int DayNum;
int WkDayNum;
int FirstWkDay;
int MondayFirst;
int LeftMarg, RightMarg, TopMarg, BotMarg;
int FillPage;
int Verbose = 0;
void Init ARGS ((int argc, char *argv[]));
void Usage ARGS ((char *s));
void DoPsCal ARGS ((void));
int DoQueuedPs ARGS ((void));
void DoSmallCal ARGS((char *m, int days, int first, int col, int which));
void WriteProlog ARGS ((void));
void WriteCalEntry ARGS ((void));
void WriteOneEntry ARGS ((char *s));
void GetSmallLocations ARGS ((void));
/***************************************************************/
/* */
/* MAIN PROGRAM */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int main(int argc, char *argv[])
#else
int main(argc, argv)
int argc;
char argv[];
#endif
{
/* If stdin is a tty - probably wrong. */
Init(argc, argv);
if (isatty(0)) {
Usage("Input should not come from a terminal");
}
/* Search for a valid input file */
while (!feof(stdin)) {
gets(LineBuffer);
if (!strcmp(LineBuffer, PSBEGIN)) {
if (!validfile) {
if (Verbose) {
fprintf(stderr, "Rem2PS: Version %s Copyright 1992-1996 by David F. Skoll\n\n", VERSION);
fprintf(stderr, "Generating PostScript calendar\n");
}
WriteProlog();
}
validfile++;
DoPsCal();
}
}
if (!validfile) {
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");
fprintf(stderr, " sure you fed me input produced by remind -p ...?\n");
exit(1);
}
printf("%%%%Trailer\n");
printf("%%%%Pages: %d\n", validfile);
if (Verbose) fprintf(stderr, "Rem2PS: Done\n");
return 0;
}
/***************************************************************/
/* */
/* DoPsCal - emit PostScript for the calendar. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void DoPsCal(void)
#else
void DoPsCal()
#endif
{
char month[40], year[40];
char prevm[40], nextm[40];
int days, wkday, prevdays, nextdays;
int sfirst;
int i;
int is_ps;
int firstcol;
CalEntry *c, *d;
/* Read the month and year name, followed by # days in month and 1st day of
month */
gets(LineBuffer);
sscanf(LineBuffer, "%s %s %d %d", month, year, &days, &wkday);
gets(LineBuffer);
sscanf(LineBuffer, "%s %d", prevm, &prevdays);
gets(LineBuffer);
sscanf(LineBuffer, "%s %d", nextm, &nextdays);
MaxDay = days;
FirstWkDay = wkday;
/* Print a message for the user */
if (Verbose) fprintf(stderr, " %s %s\n", month, year);
printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2],
year[2], year[3], validfile);
/* Emit PostScript to do the heading */
if (!PortraitMode) printf("XSIZE 0 translate 90 rotate\n");
printf("/SAVESTATE save def (%s) (%s) PreCal SAVESTATE restore\n", month, year);
printf("(%s %s) doheading\n", month, year);
/* Figure out the column of the first day in the calendar */
if (MondayFirst) {
firstcol = wkday-1;
if (firstcol < 0) firstcol = 6;
} else {
firstcol = wkday;
}
/* Calculate the minimum box size */
if (!FillPage) {
printf("/MinBoxSize ytop MinY sub 7 div def\n");
} else {
if ((days == 31 && firstcol >= 5) || (days == 30 && firstcol == 6))
printf("/MinBoxSize ytop MinY sub 6 div def\n");
else if (days == 28 && firstcol == 0 && NoSmallCal)
printf("/MinBoxSize ytop MinY sub 4 div def\n");
else
printf("/MinBoxSize ytop MinY sub 5 div def\n");
}
printf("/ysmalltop ytop def\n");
/* Do each entry */
CurEntries = NULL;
CurDay = 1;
WkDayNum = wkday;
while(1) {
if (feof(stdin)) {
fprintf(stderr, "Input from REMIND is corrupt!\n");
exit(1);
}
gets(LineBuffer);
if (!strcmp(LineBuffer, PSEND)) break;
/* Read the day number - a bit of a hack! */
DayNum = (LineBuffer[8] - '0') * 10 + LineBuffer[9] - '0';
if (DayNum != CurDay) {
for(; CurDay<DayNum; CurDay++) {
WriteCalEntry();
WkDayNum = (WkDayNum + 1) % 7;
}
}
/* Add the text */
c = NEW(CalEntry);
if (!c) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
is_ps = (*LineBuffer == 'F' || *LineBuffer == 'P');
c->next = NULL;
c->entry = malloc(strlen(LineBuffer+10) + 1 + is_ps);
if (!c->entry) {
fprintf(stderr, "malloc failed - aborting.\n");
exit(1);
}
strcpy(c->entry+is_ps, LineBuffer+10);
if (is_ps) {
/* Save the 'P' or 'F' flag */
*(c->entry) = *LineBuffer;
if (!PsEntries[DayNum]) PsEntries[DayNum] = c;
else {
d = PsEntries[DayNum];
while(d->next) d = d->next;
d->next = c;
}
} else {
/* Put on linked list */
if (!CurEntries) CurEntries = c;
else {
d = CurEntries;
while(d->next) d = d->next;
d->next = c;
}
}
}
for(; CurDay<=days; CurDay++) {
WriteCalEntry();
WkDayNum = (WkDayNum + 1) % 7;
}
/* If wkday < 2, set ysmall. If necessary (only for feb) increase cal size. */
printf("/ysmallbot ylast def\n");
/* Now draw the vertical lines */
GetSmallLocations();
for (i=0; i<=7; i++) {
printf("%d xincr mul MinX add ymin %d xincr mul MinX add topy L\n",
i, i);
}
/* print the small calendars */
if (!NoSmallCal) {
sfirst = wkday - (prevdays % 7);
if (sfirst < 0) sfirst += 7;
DoSmallCal(prevm, prevdays, sfirst, SmallCol1, 1);
sfirst = wkday + (days % 7);
if (sfirst >6) sfirst -= 7;
DoSmallCal(nextm, nextdays, sfirst, SmallCol2, 2);
}
/* Do it! */
printf("showpage\n");
}
/***************************************************************/
/* */
/* WriteProlog - write the PostScript prologue */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void WriteProlog(void)
#else
void WriteProlog()
#endif
{
int i;
int x = CurPage->xsize;
int y = CurPage->ysize;
char *isostuff;
FILE *fp;
int nread;
char buffer[LINELEN];
if (!PortraitMode) {
i = x; x = y; y = i;
}
if (UseISO)
isostuff = "reencodeISO";
else
isostuff = "copyFont";
/* Write the document structuring stuff */
printf("%%!PS-Adobe-\n");
printf("%%%%DocumentFonts: %s", HeadFont);
if (strcmp(TitleFont, HeadFont)) printf(" %s", TitleFont);
if (strcmp(TitleFont, DayFont) &&
strcmp(HeadFont, DayFont)) printf(" %s", DayFont);
if (strcmp(EntryFont, HeadFont) &&
strcmp(TitleFont, EntryFont) &&
strcmp(EntryFont, DayFont)) printf(" %s", EntryFont);
if (!NoSmallCal && strcmp(SmallFont, HeadFont) &&
strcmp(SmallFont, DayFont) &&
strcmp(TitleFont, SmallFont) &&
strcmp(SmallFont, EntryFont)) printf(" %s", SmallFont);
putchar('\n');
printf("%%%%Creator: Rem2PS\n");
printf("%%%%Pages: (atend)\n");
printf("%%%%Orientation: %s\n", PortraitMode ? "Portrait" : "Landscape");
printf("%%%%EndComments\n");
for (i=0; PSProlog1[i]; i++) puts(PSProlog1[i]);
if (!MondayFirst)
printf("[(%s) (%s) (%s) (%s) (%s) (%s) (%s)]\n",
L_SUNDAY, L_MONDAY, L_TUESDAY, L_WEDNESDAY,
L_THURSDAY, L_FRIDAY, L_SATURDAY);
else
printf("[(%s) (%s) (%s) (%s) (%s) (%s) (%s)]\n",
L_MONDAY, L_TUESDAY, L_WEDNESDAY,
L_THURSDAY, L_FRIDAY, L_SATURDAY, L_SUNDAY);
for (i=0; PSProlog2[i]; i++) puts(PSProlog2[i]);
printf("/HeadFont /%s %s\n", HeadFont, isostuff);
if (!NoSmallCal) printf("/SmallFont /%s %s\n", SmallFont, isostuff);
printf("/DayFont /%s %s\n", DayFont, isostuff);
printf("/EntryFont /%s %s\n", EntryFont, isostuff);
printf("/TitleFont /%s %s\n", TitleFont, isostuff);
printf("/HeadSize %s def\n", HeadSize);
printf("/DaySize %s def\n", DaySize);
printf("/EntrySize %s def\n", EntrySize);
printf("/TitleSize %s def\n", TitleSize);
printf("/XSIZE %d def\n", CurPage->xsize);
printf("/MinX %d def\n", LeftMarg);
printf("/MinY %d def\n", BotMarg);
printf("/MaxX %d def\n", x-RightMarg);
printf("/MaxY %d def\n", y-TopMarg);
printf("/Border %s def\n", BorderSize);
printf("/LineWidth %s def\n", LineWidth);
printf("%s setlinewidth\n", LineWidth);
/* Check if smallfont is fixed pitch */
if (!NoSmallCal) {
printf("/SmallFont findfont /FontInfo get /isFixedPitch get\n");
/* Define SmallString used to set smallfont size */
printf("{/SmallString (WW ) def}\n");
printf("{/SmallString (WW) def}\nifelse\n");
}
/* Do the user-supplied prolog file, if any */
if (UserProlog) {
fp = fopen(UserProlog, "r");
if (!fp) {
fprintf(stderr, "Could not open prologue file '%s'\n", UserProlog);
} else {
while(1) {
nread = fread(buffer, sizeof(char), LINELEN, fp);
if (!nread) break;
fwrite(buffer, sizeof(char), nread, stdout);
}
fclose(fp);
}
}
printf("%%%%EndProlog\n");
}
/***************************************************************/
/* */
/* WriteCalEntry - write all entries for one day */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void WriteCalEntry(void)
#else
void WriteCalEntry()
#endif
{
CalEntry *c = CurEntries;
CalEntry *d;
int begin, end, i, HadQPS;
/* Move to appropriate location */
printf("/CAL%d {\n", CurDay);
if (!MondayFirst)
printf("Border ytop %d xincr mul MinX add xincr\n", WkDayNum);
else
printf("Border ytop %d xincr mul MinX add xincr\n", (WkDayNum ? WkDayNum-1 : 6));
/* Set up the text array */
printf("[\n");
CurEntries = NULL;
while(c) {
WriteOneEntry(c->entry);
free(c->entry);
d = c->next;
free(c);
c = d;
}
printf("]\n");
/* Print the day number */
printf("(%d)\n", CurDay);
/* Do it! */
printf("DoCalBox\n");
/* Update ymin */
printf("/y exch def y ymin lt {/ymin y def} if\n");
printf("} def\n");
/* If WkDayNum is a Sunday or Monday, depending on MondayFirst,
move to next row. Also handle the queued PS and PSFILE reminders */
if ((!MondayFirst && WkDayNum == 6) ||
(MondayFirst && WkDayNum == 0) || CurDay == MaxDay) {
HadQPS = 0;
if (MondayFirst) begin = CurDay - (WkDayNum ? WkDayNum-1 : 6);
else begin = CurDay - WkDayNum;
if (begin < 1) begin = 1;
end = CurDay;
for (i=begin; i<=end; i++) {
if (PsEntries[i]) {
HadQPS = 1;
break;
}
}
/* Avoid problems with blotching if PS printer has roundoff errors */
if (HadQPS) printf("1 setgray\n");
for (i=begin; i<=end; i++) {
printf("CAL%d\n", i);
}
if (HadQPS) printf("0 setgray\n");
printf("/y ytop MinBoxSize sub def y ymin lt {/ymin y def} if\n");
/* Draw the line at the bottom of the row */
printf("MinX ymin MaxX ymin L\n");
/* Update ytop */
printf("/ylast ytop def\n");
printf("/ytop ymin def\n");
(void) DoQueuedPs();
/* Re-do the calendar stuff if there was any included PS code */
if (HadQPS) {
printf("/ytop ylast def\n");
for (i=begin; i<=end; i++) {
printf("CAL%d\n", i);
}
printf("/y ytop MinBoxSize sub def y ymin lt {/ymin y def} if\n");
printf("MinX ymin MaxX ymin L\n");
printf("/ylast ytop def\n");
printf("/ytop ymin def\n");
}
}
}
/***************************************************************/
/* */
/* WriteOneEntry - write an entry for one day */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void WriteOneEntry(char *s)
#else
void WriteOneEntry(s)
char *s;
#endif
{
int c;
printf(" [");
/* Chew up leading spaces */
while(isspace(*s)) s++;
putchar('(');
while(*s) {
c = *s++;
if (c == '\\' || c == '(' || c == ')') putchar('\\');
if (!isspace(c)) putchar(c);
else {
putchar(')');
while(isspace(*s)) s++;
if (!*s) {
printf("]\n");
return;
}
putchar('(');
}
}
printf(")]\n");
}
/***************************************************************/
/* */
/* Init - set up parameters */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void Init(int argc, char *argv[])
#else
void Init(argc, argv)
int argc;
char *argv[];
#endif
{
char *s, *t;
int i=1;
int j;
int offset;
PortraitMode = 1;
NoSmallCal = 0;
LeftMarg = 36;
RightMarg = 36;
TopMarg = 36;
BotMarg = 36;
UseISO = 0;
FillPage = 0;
MondayFirst = 0;
SmallLocation = "bt";
for(j=0; j<32; j++) PsEntries[i] = NULL;
CurPage = DefaultPage; /* Letter size by default */
while (i < argc) {
s = argv[i];
i++;
if (*s++ != '-') Usage("Options must begin with '-'");
switch(*s++) {
case 'n':
MondayFirst = 1;
break;
case 'p':
if (i == argc) Usage("Prologue filename must be supplied");
UserProlog = argv[i++];
break;
case 's':
if (i == argc) Usage("Size must be supplied");
t = argv[i++];
while(*s) {
switch(*s++) {
case 'h': HeadSize = t; break;
case 'e': EntrySize = t; break;
case 'd': DaySize = t; break;
case 't': TitleSize = t; break;
default: Usage("Size must specify h, t, e, or d");
}
}
break;
case 'f':
if (i == argc) Usage("Font must be supplied");
t = argv[i++];
while(*s) {
switch(*s++) {
case 'h': HeadFont = t; break;
case 'e': EntryFont = t; break;
case 'd': DayFont = t; break;
case 's': SmallFont = t; break;
case 't': TitleFont = t; break;
default: Usage("Font must specify s, h, t, e, or d");
}
}
break;
case 'v':
Verbose = 1;
break;
case 'm':
if (i == argc) Usage("Media must be supplied");
t = argv[i++];
CurPage = NULL;
for (j=0; j<NUMPAGES; j++)
if (!strcmp(t, Pages[j].name)) {
CurPage = &Pages[j];
break;
}
if (!CurPage) {
fprintf(stderr, "\nUnknown media specified.\n");
fprintf(stderr, "\nAvailable media types:\n");
for (j=0; j<NUMPAGES; j++)
fprintf(stderr, " %s\n", Pages[j].name);
fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
exit(1);
}
break;
case 'o':
if (i == argc) Usage("Offset must be supplied");
offset = atoi(argv[i++]);
if (offset < 36) offset = 36;
if (!*s) Usage("Offset must specify l, r, t or b");
while(*s) {
switch(*s++) {
case 'l': LeftMarg = offset; break;
case 'r': RightMarg = offset ; break;
case 't': TopMarg = offset; break;
case 'b': BotMarg = offset; break;
default: Usage("Offset must specify l, r, t or b");
}
}
break;
case 'b':
if (i == argc) Usage("Border must be supplied");
BorderSize = argv[i++];
break;
case 't':
if (i == argc) Usage("Line thickness must be supplied");
LineWidth = argv[i++];
break;
case 'l': PortraitMode = 0; break;
case 'i': UseISO = 1; break;
case 'c': j=(*s);
if (!j) {
SmallLocation = SmallCalLoc[0];
} else {
j -= '0';
if (j>=0 && j<NUMSMALL) {
SmallLocation = SmallCalLoc[j];
} else {
SmallLocation = SmallCalLoc[0];
}
}
break;
case 'e': FillPage = 1; break;
default: Usage("Unrecognized option");
}
}
}
/***************************************************************/
/* */
/* Usage - print usage information */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void Usage(char *s)
#else
void Usage(s)
char *s;
#endif
{
if (s) fprintf(stderr, "Rem2PS: %s\n\n", s);
fprintf(stderr, "Rem2PS: Produce a PostScript calendar from output of Remind.\n\n");
fprintf(stderr, "Usage: rem2ps [options]\n\n");
fprintf(stderr, "Options:\n\n");
fprintf(stderr, "-v Print progress messages to standard error\n");
fprintf(stderr, "-p file Include user-supplied PostScript code in prologue\n");
fprintf(stderr, "-l Do calendar in landscape mode\n");
fprintf(stderr, "-c[n] Control small calendars: 0=none; 1=bt; 2=tb; 3=sbt\n");
fprintf(stderr, " and next month\n");
fprintf(stderr, "-i Use ISO 8859-1 encoding in PostScript output\n");
fprintf(stderr, "-m media Set page size (eg, Letter, Legal, A4.) Case sensitive!\n");
fprintf(stderr, " (Default page size is %s)\n", DefaultPage[0].name);
fprintf(stderr, "-f[shted] font Set font for small cal, hdr, title, cal entries, day numbers\n");
fprintf(stderr, "-s[hted] size Set size for header, title, calendar entries and/or day numbers\n");
fprintf(stderr, "-b size Set border size for calendar entries\n");
fprintf(stderr, "-t size Set line thickness\n");
fprintf(stderr, "-e Make calendar fill entire page\n");
fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
fprintf(stderr, "-n Start calendar with Monday rather than Sunday\n");
exit(1);
}
/***************************************************************/
/* */
/* DoSmallCal - do the small calendar for previous or next */
/* month. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
void DoSmallCal(char *m, int days, int first, int col, int which)
#else
void DoSmallCal(m, days, first, col, which)
char *m;
int days, first, col;
#endif
{
/* Do the small calendar */
int i, j;
int row = 2;
if (MondayFirst) {
first--;
if (first < 0) first = 6;
}
/* Figure out the font size */
printf("/SmallFontSize MinBoxSize Border sub Border sub 8 div 2 sub def\n");
printf("/SmallFont findfont setfont\n");
printf("SmallString stringwidth pop /SmallWidth exch def\n");
printf("SmallWidth 7 mul xincr Border sub Border sub exch div /tmp exch def\n");
printf("tmp SmallFontSize lt {/SmallFontSize tmp def} if\n");
printf("/SmallFont findfont SmallFontSize scalefont setfont\n");
/* Recalculate SmallWidth */
printf("SmallString stringwidth pop /SmallWidth exch def\n");
/* Save graphics state */
printf("gsave\n");
/* Move origin to upper-left hand corner of appropriate box */
printf("%d xincr mul MinX add ysmall%d translate\n", col, which);
/* Print the month */
printf("SmallWidth 7 mul (%s) stringwidth pop sub 2 div Border add Border neg SmallFontSize sub moveto (%s) show\n", m, m);
/* Print the days of the week */
for (i=0; i<7; i++) {
if (MondayFirst) j=(i+1)%7;
else j=i;
printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize sub 2 sub moveto (%c) show\n", i, Days[j]);
}
/* Now do the days of the month */
for (i=1; i<=days; i++) {
printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize 2 add %d mul sub moveto (%d) show\n", first, row, i);
first++;
if (first == 7) { first = 0; row++; }
}
/* restore graphics state */
printf("grestore\n");
}
/***************************************************************/
/* */
/* DoQueuedPs - do the queued PS and PSFILE reminders. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoQueuedPs(void)
#else
int DoQueuedPs()
#endif
{
int i;
int HadPS = 0;
int wd;
int begin, end;
int nread;
CalEntry *e, *n;
FILE *fp;
int fnoff;
char buffer[LINELEN];
if (!MondayFirst) begin = CurDay - WkDayNum;
else begin = CurDay - (WkDayNum ? WkDayNum-1 : 6);
wd = 0;
while (begin < 1) begin++, wd++;
end = CurDay;
for (i=begin; i<=end; i++, wd++) {
e = PsEntries[i];
if (e) {
HadPS = 1;
printf("/SAVESTATE save def\n");
/* Translate coordinates to bottom of calendar box */
printf("%d xincr mul MinX add ytop translate\n", wd);
/* Set up convenient variables */
printf("/BoxWidth xincr def\n/BoxHeight ylast ytop sub def\n");
printf("/InBoxHeight BoxHeight border sub DaySize sub DaySize sub 2 add EntrySize add def \n");
}
while (e) {
/* Now do the user's PostScript code */
fnoff = 1;
while (isspace(*(e->entry+fnoff))) fnoff++;
if (*(e->entry) == 'P') {
printf("%s\n", e->entry+fnoff);
} else {
fp = fopen(e->entry+fnoff, "r");
if (!fp) {
fprintf(stderr, "Could not open PostScript file '%s'\n", e->entry+1);
} else {
while(1) {
nread = fread(buffer, sizeof(char), LINELEN, fp);
if (!nread) break;
fwrite(buffer, sizeof(char), nread, stdout);
}
fclose(fp);
}
}
/* Free the entry */
free(e->entry);
n = e->next;
free(e);
e = n;
}
if (PsEntries[i]) printf("\n SAVESTATE restore\n");
PsEntries[i] = NULL;
}
return HadPS;
}
/***************************************************************/
/* */
/* GetSmallLocations */
/* */
/* Set up the locations for the small calendars. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void GetSmallLocations(void)
#else
void GetSmallLocations()
#endif
{
char c;
char *s = SmallLocation;
int colfirst, collast;
/* Figure out the first and last columns */
colfirst = FirstWkDay;
collast = (FirstWkDay+MaxDay-1) % 7;
if (MondayFirst) {
colfirst = colfirst ? colfirst - 1 : 6;
collast = collast ? collast - 1 : 6;
}
NoSmallCal = 0;
while((c = *s++) != 0) {
switch(c) {
case 'b':
/* Adjust Feb. if we want it on the bottom */
if (MaxDay == 28 && colfirst == 0) {
printf("/ysmallbot ymin def /ymin ysmallbot MinBoxSize sub def\n");
printf("MinX ymin MaxX ymin L\n");
printf("/ysmall1 ysmallbot def /ysmall2 ysmallbot def\n");
SmallCol1 = 5;
SmallCol2 = 6;
return;
}
if (collast <= 4) {
printf("/ysmall1 ysmallbot def /ysmall2 ysmallbot def\n");
SmallCol1 = 5;
SmallCol2 = 6;
return;
}
break;
case 't':
if (colfirst >= 2) {
printf("/ysmall1 ysmalltop def /ysmall2 ysmalltop def\n");
SmallCol1 = 0;
SmallCol2 = 1;
return;
}
break;
case 's':
if (colfirst >= 1 && collast<=5) {
printf("/ysmall1 ysmalltop def /ysmall2 ysmallbot def\n");
SmallCol1 = 0;
SmallCol2 = 6;
return;
}
break;
}
}
NoSmallCal = 1;
return;
}

212
rem2ps.h Normal file
View File

@@ -0,0 +1,212 @@
/***************************************************************/
/* */
/* REM2PS.H */
/* */
/* Define the PostScript prologue */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: rem2ps.h,v 1.1 1996-03-27 03:26:08 dfs Exp $ */
char *PSProlog1[] =
{
"% This file was produced by Remind and Rem2PS, written by",
"% David F. Skoll.",
"/ISOLatin1Encoding where { pop save true }{ false } ifelse",
" /ISOLatin1Encoding [ StandardEncoding 0 45 getinterval aload pop /minus",
" StandardEncoding 46 98 getinterval aload pop /dotlessi /grave /acute",
" /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring",
" /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent",
" /sterling /currency /yen /brokenbar /section /dieresis /copyright",
" /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron",
" /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph",
" /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright",
" /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute",
" /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute",
" /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth",
" /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply",
" /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn",
" /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae",
" /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute",
" /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex",
" /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex",
" /udieresis /yacute /thorn /ydieresis ] def",
"{ restore } if",
"",
"/reencodeISO { %def",
" findfont dup length dict begin",
" { 1 index /FID ne { def }{ pop pop } ifelse } forall",
" /Encoding ISOLatin1Encoding def",
" currentdict end definefont pop",
"} bind def",
"/copyFont { %def",
" findfont dup length dict begin",
" { 1 index /FID ne { def } { pop pop } ifelse } forall",
" currentdict end definefont pop",
"} bind def",
"",
"% L - Draw a line",
"/L {",
" newpath moveto lineto stroke",
"} bind def",
"% string1 string2 strcat string",
"% Function: Concatenates two strings together.",
"/strcat {",
" 2 copy length exch length add",
" string dup",
" 4 2 roll",
" 2 index 0 3 index",
" putinterval",
" exch length exch putinterval",
"} bind def",
"% string doheading",
"/doheading",
"{",
" /monthyr exch def",
"",
" /TitleFont findfont",
" TitleSize scalefont setfont",
" monthyr stringwidth",
" /hgt exch def",
" 2 div MaxX MinX add 2 div exch sub /x exch def",
" MaxY Border sub TitleSize sub /y exch def",
" newpath x y moveto monthyr show",
" newpath x y moveto monthyr false charpath flattenpath pathbbox",
" pop pop Border sub /y exch def pop",
" MinX y MaxX y L",
" /topy y def",
" /HeadFont findfont HeadSize scalefont setfont",
"% Do the days of the week",
" MaxX MinX sub 7 div /xincr exch def",
" /x MinX def",
NULL
};
char *PSProlog2[] =
{
" {",
" HeadSize x y HeadSize 2 mul sub x xincr add y CenterText",
" x xincr add /x exch def",
" } forall",
" y HeadSize 2 mul sub /y exch def",
" MinX y MaxX y L",
" /ytop y def /ymin y def",
"}",
"def",
"/CenterText",
"{",
" /maxy exch def",
" /maxx exch def",
" /miny exch def",
" /minx exch def",
" /sz exch def",
" /str exch def",
" str stringwidth pop",
" 2 div maxx minx add 2 div exch sub",
" sz 2 div maxy miny add 2 div exch sub",
" moveto str show",
"} def",
"% Variables:",
"% curline - a string holding the current line",
"% y - current y pos",
"% yincr - increment to next line",
"% xleft - left margin",
"% width - max width.",
"% EnterOneWord - given a word, enter it into the box.",
"% string EnterOneWord",
"/EnterOneWord {",
" { EnterOneWordAux",
" {exit} if }",
" loop",
"} bind def",
"% EnterOneWordAux - if the word fits, enter it into box and return true.",
"% If it doesn't fit, put as much as will fit and return the string and false.",
"/EnterOneWordAux {",
" /word exch def",
" /tmpline curline word strcat def",
" tmpline stringwidth pop width gt",
" {MoveToNewLine}",
" {/curline tmpline ( ) strcat def /word () def}",
" ifelse",
" word () eq",
" {true}",
" {word false}",
" ifelse",
"} bind def",
"% MoveToNewLine - move to a new line, resetting word as appropriate",
"/MoveToNewLine {",
" curline () ne",
" {newpath xleft y moveto curline show /curline () def /y y yincr add def} ",
" {ChopWord}",
" ifelse",
"} bind def",
"% ChopWord - word won't fit. Chop it and find biggest piece that will fit",
"/ChopWord {",
" /curline () def",
" /len word length def",
" /Fcount len 1 sub def",
"",
" {",
" word 0 Fcount getinterval stringwidth pop width le",
" {exit} if",
" /Fcount Fcount 1 sub def",
" } loop",
"% Got the count. Display it and reset word",
" newpath xleft y moveto word 0 Fcount getinterval show",
" /y y yincr add def",
" /word word Fcount len Fcount sub getinterval def",
"} bind def",
"/FinishFormatting {",
" word () ne",
" {newpath xleft y moveto word show /word () def",
" /curline () def /y y yincr add def}",
" {curline () ne",
" {newpath xleft y moveto curline show /word () def",
" /curline () def /y y yincr add def} if}",
" ifelse",
"} bind def",
"% FillBoxWithText - fill a box with text",
"% text-array xleft width yincr y FillBoxWithText new-y",
"% Returns the new Y-coordinate.",
"/FillBoxWithText {",
" /y exch def",
" /yincr exch def",
" /width exch def",
" /xleft exch def",
" /curline () def",
" {EnterOneWord} forall",
" FinishFormatting",
" y",
"} bind def",
"% Variables for calendar boxes:",
"% ytop - current top position",
"% ymin - minimum y reached for current row",
"% border ytop xleft width textarray daynum DoCalBox ybot",
"% Do the entries for one calendar box. Returns lowest Y-coordinate reached",
"/DoCalBox {",
" /daynum exch def",
" /textarr exch def",
" /wid exch def",
" /xl exch def",
" /yt exch def",
" /border exch def",
"% Do the day number",
" /DayFont findfont DaySize scalefont setfont",
" xl wid add border sub daynum stringwidth pop sub",
" yt border sub DaySize sub moveto daynum show",
"% Do the text entries. Precharge the stack with current y pos.",
" /ycur yt border sub DaySize sub DaySize sub 2 add def",
" /EntryFont findfont EntrySize scalefont setfont",
" ycur",
" textarr",
" { exch 2 sub /ycur exch def xl border add wid border sub border sub EntrySize 2 add neg",
" ycur FillBoxWithText }",
" forall",
"} bind def",
"2 setlinecap",
"% Define a default PreCal procedure",
"/PreCal { pop pop } bind def",
NULL
};

46
remind-all.csh Normal file
View File

@@ -0,0 +1,46 @@
#!/bin/csh -f
# Shell script to mail all users reminders.
# $Id: remind-all.csh,v 1.1 1996-03-27 03:26:08 dfs Exp $
# Run it AFTER MIDNIGHT so that date is correct!
# On our system, we have the following in our crontab:
# 05 5 * * * /usr/share/lib/remind/remind-all > /dev/null 2>&1
# This script must be run by root. The -u option MUST be supplied
# to Remind, or a severe security hole will exist. Note that Remind
# must be compiled to support the -u option for this script to work.
# Also, the -r and -q options must be used.
# The following line gets a list of users for systems using SUN's
# NIS service:
set USERS = `ypcat passwd | awk -F: '{print $1}'`
# The following line gets a list of users by examining /etc/passwd:
# set USERS = `awk -F: '{print $1}' /etc/passwd`
# If neither of the above methods works, you must come up with some
# way of getting a list of users on the system
# Set the following variables as appropriate for your system
set REMIND = /usr/local/bin/remind
set MAIL = /usr/ucb/mail
set RM = "/usr/bin/rm -f"
set REMFILE = /tmp/RemFile.$$
# Scan each user's directory for a .reminders file
foreach i ($USERS)
if (-r ~$i/.reminders) then
# echo "$i has a .reminders file." DEBUGGING PURPOSES ONLY
$REMIND -u$i -h -r -q -iremind_all=1 ~$i/.reminders < /dev/null > $REMFILE
if (! -z $REMFILE) then
# echo "Sending mail to $i" DEBUGGING PURPOSES ONLY
$MAIL -s "Reminders" $i < $REMFILE
endif
$RM $REMFILE
endif
end

54
remind-all.sh Normal file
View File

@@ -0,0 +1,54 @@
#!/bin/sh
# Shell script to mail all users reminders.
# This file is part of REMIND
#
# $Id: remind-all.sh,v 1.1 1996-03-27 03:26:08 dfs Exp $
#
# REMIND is Copyright (C) 1992-1996 by David F. Skoll
# This file is Copyright (C) 1990 by Bill Aten
# Thanks to Bill Aten for this script.
# Run it AFTER MIDNIGHT so that date is correct!
# On our system, we have the following in our crontab:
# 02 00 * * * /usr/local/adm/remind-all >/dev/null 2>&1
# This script must be run by root. The -u option MUST be supplied
# to Remind, or a severe security hole will exist. Note that Remind
# must be compiled to support the -u option for this script to work.
# Also, the -r and -q options must be used.
# The following line gets a list of users for systems using SUN's
# NIS service:
# USERS=`ypcat passwd | awk -F: '{print $1}'`
# The following line gets a list of users by examining /etc/passwd:
USERS=`awk -F: '{print $1}' /etc/passwd`
# If neither of the above methods works, you must come up with some
# way of getting a list of users on the system
# Set the following variables as appropriate for your system
REMIND=/usr/local/bin/remind
MAIL=/usr/bin/mail
RM="/bin/rm -f"
REMFILE=/tmp/RemFile.$$
# Scan each user's directory for a .reminders file
for i in $USERS
do
HOME=`grep \^$i: /etc/passwd | awk -F: '{print $6}'`
if [ -r $HOME/.reminders ]; then
# echo "$i has a .reminders file." DEBUGGING PURPOSES ONLY
$REMIND -u$i -h -r -q -iremind_all=1 $HOME/.reminders < /dev/null > $REMFILE
if [ -s $REMFILE ]; then
# echo "Sending mail to $i" DEBUGGING PURPOSES ONLY
$MAIL -s "Reminders" $i < $REMFILE
fi
$RM $REMFILE
fi
done

3596
remind.1 Normal file

File diff suppressed because it is too large Load Diff

1
remind.def Normal file
View File

@@ -0,0 +1 @@
NAME WINDOWCOMPAT NEWFILES

262
sort.c Normal file
View File

@@ -0,0 +1,262 @@
/***************************************************************/
/* */
/* SORT.C */
/* */
/* Routines for sorting reminders by trigger date */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: sort.c,v 1.1 1996-03-27 03:26:10 dfs Exp $";
#include "config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <stdio.h>
#include <string.h>
#include "types.h"
#include "protos.h"
#include "expr.h"
#include "globals.h"
#include "err.h"
/* The structure of a sorted entry */
typedef struct sortrem {
struct sortrem *next;
char *text;
int trigdate;
int trigtime;
int typ;
int priority;
} Sortrem;
/* The sorted reminder queue */
static Sortrem *SortedQueue = (Sortrem *) NULL;
PRIVATE Sortrem *MakeSortRem ARGS ((int jul, int tim, char *body, int typ, int prio));
PRIVATE void IssueSortBanner ARGS ((int jul));
/***************************************************************/
/* */
/* MakeSortRem */
/* */
/* Create a new Sortrem entry - return NULL on failure. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE Sortrem *MakeSortRem(int jul, int tim, char *body, int typ, int prio)
#else
static Sortrem *MakeSortRem(jul, tim, body, typ, prio)
int jul, tim;
char *body;
int typ, prio;
#endif
{
Sortrem *new = NEW(Sortrem);
if (!new) return NULL;
new->text = StrDup(body);
if (!new->text) {
free(new);
return NULL;
}
new->trigdate = jul;
new->trigtime = tim;
new->typ = typ;
new->priority = prio;
new->next = NULL;
return new;
}
/***************************************************************/
/* */
/* InsertIntoSortBuffer */
/* */
/* Insert a reminder into the sort buffer */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int InsertIntoSortBuffer(int jul, int tim, char *body, int typ, int prio)
#else
int InsertIntoSortBuffer(jul, tim, body, typ, prio)
int jul;
int tim;
char *body;
int typ, prio;
#endif
{
Sortrem *new = MakeSortRem(jul, tim, body, typ, prio);
Sortrem *cur = SortedQueue, *prev = NULL;
int ShouldGoAfter;
if (!new) {
Eprint("%s", ErrMsg[E_NO_MEM]);
IssueSortedReminders();
SortByDate = 0;
SortByTime = 0;
SortByPrio = 0;
return E_NO_MEM;
}
/* Find the correct place in the sorted list */
if (!SortedQueue) {
SortedQueue = new;
return OK;
}
while (cur) {
ShouldGoAfter = CompareRems(new->trigdate, new->trigtime, new->priority,
cur->trigdate, cur->trigtime, cur->priority,
SortByDate, SortByTime, SortByPrio);
if (ShouldGoAfter <= 0) {
prev = cur;
cur = cur->next;
} else {
if (prev) {
prev->next = new;
new->next = cur;
} else {
SortedQueue = new;
new->next = cur;
}
return OK;
}
}
prev->next = new;
new->next = cur; /* For safety - actually redundant */
return OK;
}
/***************************************************************/
/* */
/* IssueSortedReminders */
/* */
/* Issue all of the sorted reminders and free memory. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void IssueSortedReminders(void)
#else
void IssueSortedReminders()
#endif
{
Sortrem *cur = SortedQueue;
Sortrem *next;
int olddate = NO_DATE;
while (cur) {
next = cur->next;
switch(cur->typ) {
case MSG_TYPE:
if (MsgCommand) {
DoMsgCommand(MsgCommand, cur->text);
} else {
if (cur->trigdate != olddate) {
IssueSortBanner(cur->trigdate);
olddate = cur->trigdate;
}
printf("%s", cur->text);
}
break;
case MSF_TYPE:
#ifdef OS2_POPUP
FillParagraph(cur->text, 0);
#else
FillParagraph(cur->text);
#endif
break;
case RUN_TYPE:
system(cur->text);
break;
}
free(cur->text);
free(cur);
cur = next;
}
SortedQueue = NULL;
}
/***************************************************************/
/* */
/* IssueSortBanner */
/* */
/* Issue a daily banner if the function sortbanner() is */
/* defined to take one argument. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void IssueSortBanner(int jul)
#else
static void IssueSortBanner(jul)
int jul;
#endif
{
char BanExpr[25];
int y, m, d;
Value v;
char *s = BanExpr;
if (UserFuncExists("sortbanner") != 1) return;
FromJulian(jul, &y, &m, &d);
sprintf(BanExpr, "sortbanner('%04d/%02d/%02d')", y, m+1, d);
y = EvalExpr(&s, &v);
if (y) return;
if (DoCoerce(STR_TYPE, &v)) return;
if (!DoSubstFromString(v.v.str, SubstBuffer, jul, NO_TIME))
if (*SubstBuffer) printf("%s\n", SubstBuffer);
DestroyValue(v);
}
/***************************************************************/
/* */
/* CompareRems */
/* */
/* Compare two reminders for sorting. Return 0 if they */
/* compare equal; 1 if rem2 should come after rem1, -1 if */
/* rem1 should come after rem2. bydate and bytime control */
/* sorting direction by date and time, resp. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int CompareRems(int dat1, int tim1, int prio1,
int dat2, int tim2, int prio2,
int bydate, int bytime, int byprio)
#else
int CompareRems(dat1, tim1, prio1, dat2, tim2, prio2, bydate, bytime, byprio)
int dat1, tim1, prio1, dat2, tim2, prio2, bydate, bytime, byprio;
#endif
{
int dafter, tafter, pafter;
dafter = (bydate != SORT_DESCEND) ? 1 : -1;
tafter = (bytime != SORT_DESCEND) ? 1 : -1;
pafter = (byprio != SORT_DESCEND) ? 1 : -1;
if (dat1 < dat2) return dafter;
if (dat1 > dat2) return -dafter;
if (tim1 == NO_TIME && tim2 != NO_TIME) return -1;
if (tim1 != NO_TIME && tim2 == NO_TIME) return 1;
if (tim1 < tim2) return tafter;
if (tim1 > tim2) return -tafter;
if (prio1 < prio2) return pafter;
if (prio1 > prio2) return -pafter;
return 0;
}

27
test-rem Normal file
View File

@@ -0,0 +1,27 @@
#!/bin/sh
# ---------------------------------------------------------------------------
# TEST-REM
#
# $Id: test-rem,v 1.1 1996-03-27 03:26:10 dfs Exp $
#
# This file runs an acceptance test for Remind. To use it, type:
# sh test-rem OR make test
# in the build directory.
#
# This file is part of REMIND.
# Copyright (C) 1992-1996 by David F. Skoll
# ---------------------------------------------------------------------------
TEST_GETENV="foo bar baz" ; export TEST_GETENV
./remind -e -dxte ./test.rem 16 feb 1991 > ./test.out
cmp -s ./test.out ./test.cmp
if [ "$?" = "0" ]; then
echo "Remind: Acceptance test PASSED"
exit 0
else
echo "Remind: Acceptance test FAILED"
echo ""
echo "Examine the file test.out to see where it differs from the"
echo "reference file test.cmp."
exit 1
fi

32
test-rem.bat Normal file
View File

@@ -0,0 +1,32 @@
@echo off
rem ---------------------------------------------------------------------------
rem TEST-REM
rem
rem $Id: test-rem.bat,v 1.1 1996-03-27 03:26:10 dfs Exp $
rem
rem This file runs an MSDOS acceptance test for Remind. To use it, type:
rem test-rem
rem in the build directory.
rem
rem This file is part of REMIND.
rem Copyright (C) 1992-1996 by David F. Skoll
rem ---------------------------------------------------------------------------
del test.out > nul
set TEST_GETENV=foo bar baz
if exist ..\msdos-ex\remind.exe goto bcc
remind -e -dxte ./test.rem 16 feb 1991 > test.out
goto cmp
:bcc
..\msdos-ex\remind -e -dxte .\test.rem 16 feb 1991 > test.out
:cmp
echo n | comp test.out test1.cmp
if errorlevel 1 goto oops
echo "Remind: Acceptance test PASSED"
goto quit
:oops
echo "Remind: Acceptance test FAILED"
echo ""
echo "Examine the file test.out to see where it differs from the"
echo "reference file test1.cmp."
:quit

34
test-rem.cmd Normal file
View File

@@ -0,0 +1,34 @@
@echo off
rem ---------------------------------------------------------------------------
rem TEST-REM
rem
rem $Id: test-rem.cmd,v 1.1 1996-03-27 03:26:11 dfs Exp $
rem
rem This file runs an OS/2 acceptance test for Remind. To use it, type:
rem test-rem
rem in the build directory.
rem
rem This file is part of REMIND.
rem Copyright (C) 1992-1996 by David F. Skoll
rem ---------------------------------------------------------------------------
del /f test.out > nul
setlocal
set TEST_GETENV=foo bar baz
if exist ..\os2-ex\remind.exe goto bcc
remind -e -dxte ./test.rem 16 feb 1991 > .\test.out
goto cmp
:bcc
..\os2-ex\remind -e -dxte .\test.rem 16 feb 1991 > .\test.out
:cmp
echo n | comp test.out test2.cmp
if errorlevel 1 goto oops
echo "Remind: Acceptance test PASSED"
goto quit
:oops
echo "Remind: Acceptance test FAILED"
echo ""
echo "Examine the file test.out to see where it differs from the"
echo "reference file test2.cmp."
:quit
endlocal

832
test.cmp Normal file
View File

@@ -0,0 +1,832 @@
# Test file for REMIND
#
# $Id: test.cmp,v 1.1 1996-03-27 03:26:11 dfs Exp $
#
# Use this file to test the date calculation routines
# of the REMIND program by typing:
#
# ./test-rem # From WITHIN Remind source directory!
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
./test.rem(8): Trig = Saturday, 16 February, 1991
Reminders for Saturday, 16th February, 1991:
today() => 1991/02/16
hebday(1991/02/16) => 2
today() => 1991/02/16
hebmon(1991/02/16) => "Adar"
today() => 1991/02/16
hebyear(1991/02/16) => 5751
Today is 2 Adar 5751
fset _h(x, y) trigger(hebdate(x,y))
[_h(1, "Tishrey")] MSG Rosh Hashana 1
Entering UserFN _h(1, "Tishrey")
x => 1
y => "Tishrey"
hebdate(1, "Tishrey") => 1991/09/09
trigger(1991/09/09) => "9 September 1991"
Leaving UserFN _h() => "9 September 1991"
./test.rem(11): Trig = Monday, 9 September, 1991
[_h(2, "Tishrey")] MSG Rosh Hashana 2
Entering UserFN _h(2, "Tishrey")
x => 2
y => "Tishrey"
hebdate(2, "Tishrey") => 1991/09/10
trigger(1991/09/10) => "10 September 1991"
Leaving UserFN _h() => "10 September 1991"
./test.rem(12): Trig = Tuesday, 10 September, 1991
[_h(3, "Tishrey")] MSG Tzom Gedalia
Entering UserFN _h(3, "Tishrey")
x => 3
y => "Tishrey"
hebdate(3, "Tishrey") => 1991/09/11
trigger(1991/09/11) => "11 September 1991"
Leaving UserFN _h() => "11 September 1991"
./test.rem(13): Trig = Wednesday, 11 September, 1991
[_h(10, "Tishrey")] MSG Yom Kippur
Entering UserFN _h(10, "Tishrey")
x => 10
y => "Tishrey"
hebdate(10, "Tishrey") => 1991/09/18
trigger(1991/09/18) => "18 September 1991"
Leaving UserFN _h() => "18 September 1991"
./test.rem(14): Trig = Wednesday, 18 September, 1991
[_h(15, "Tishrey")] MSG Sukkot 1
Entering UserFN _h(15, "Tishrey")
x => 15
y => "Tishrey"
hebdate(15, "Tishrey") => 1991/09/23
trigger(1991/09/23) => "23 September 1991"
Leaving UserFN _h() => "23 September 1991"
./test.rem(15): Trig = Monday, 23 September, 1991
[_h(25, "Kislev")] MSG Channuka
Entering UserFN _h(25, "Kislev")
x => 25
y => "Kislev"
hebdate(25, "Kislev") => 1991/12/02
trigger(1991/12/02) => "2 December 1991"
Leaving UserFN _h() => "2 December 1991"
./test.rem(16): Trig = Monday, 2 December, 1991
[_h(10, "Tevet")] MSG Asara B'Tevet
Entering UserFN _h(10, "Tevet")
x => 10
y => "Tevet"
hebdate(10, "Tevet") => 1991/12/17
trigger(1991/12/17) => "17 December 1991"
Leaving UserFN _h() => "17 December 1991"
./test.rem(17): Trig = Tuesday, 17 December, 1991
[_h(15, "Shvat")] MSG Tu B'Shvat
Entering UserFN _h(15, "Shvat")
x => 15
y => "Shvat"
hebdate(15, "Shvat") => 1992/01/20
trigger(1992/01/20) => "20 January 1992"
Leaving UserFN _h() => "20 January 1992"
./test.rem(18): Trig = Monday, 20 January, 1992
[_h(15, "Adar A")] MSG Purim Katan
Entering UserFN _h(15, "Adar A")
x => 15
y => "Adar A"
hebdate(15, "Adar A") => 1992/02/19
trigger(1992/02/19) => "19 February 1992"
Leaving UserFN _h() => "19 February 1992"
./test.rem(19): Trig = Wednesday, 19 February, 1992
[_h(14, "Adar")] MSG Purim
Entering UserFN _h(14, "Adar")
x => 14
y => "Adar"
hebdate(14, "Adar") => 1991/02/28
trigger(1991/02/28) => "28 February 1991"
Leaving UserFN _h() => "28 February 1991"
./test.rem(20): Trig = Thursday, 28 February, 1991
[_h(15, "Nisan")] MSG Pesach
Entering UserFN _h(15, "Nisan")
x => 15
y => "Nisan"
hebdate(15, "Nisan") => 1991/03/30
trigger(1991/03/30) => "30 March 1991"
Leaving UserFN _h() => "30 March 1991"
./test.rem(21): Trig = Saturday, 30 March, 1991
[_h(27, "Nisan")] MSG Yom HaShoah
Entering UserFN _h(27, "Nisan")
x => 27
y => "Nisan"
hebdate(27, "Nisan") => 1991/04/11
trigger(1991/04/11) => "11 April 1991"
Leaving UserFN _h() => "11 April 1991"
./test.rem(22): Trig = Thursday, 11 April, 1991
[_h(4, "Iyar")] MSG Yom HaZikaron
Entering UserFN _h(4, "Iyar")
x => 4
y => "Iyar"
hebdate(4, "Iyar") => 1991/04/18
trigger(1991/04/18) => "18 April 1991"
Leaving UserFN _h() => "18 April 1991"
./test.rem(23): Trig = Thursday, 18 April, 1991
[_h(5, "Iyar")] MSG Yom Ha'atzmaut
Entering UserFN _h(5, "Iyar")
x => 5
y => "Iyar"
hebdate(5, "Iyar") => 1991/04/19
trigger(1991/04/19) => "19 April 1991"
Leaving UserFN _h() => "19 April 1991"
./test.rem(24): Trig = Friday, 19 April, 1991
[_h(28, "Iyar")] MSG Yom Yerushalayim
Entering UserFN _h(28, "Iyar")
x => 28
y => "Iyar"
hebdate(28, "Iyar") => 1991/05/12
trigger(1991/05/12) => "12 May 1991"
Leaving UserFN _h() => "12 May 1991"
./test.rem(25): Trig = Sunday, 12 May, 1991
[_h(6, "Sivan")] MSG Shavuot
Entering UserFN _h(6, "Sivan")
x => 6
y => "Sivan"
hebdate(6, "Sivan") => 1991/05/19
trigger(1991/05/19) => "19 May 1991"
Leaving UserFN _h() => "19 May 1991"
./test.rem(26): Trig = Sunday, 19 May, 1991
[_h(9, "Av")] MSG Tish'a B'Av
Entering UserFN _h(9, "Av")
x => 9
y => "Av"
hebdate(9, "Av") => 1991/07/20
trigger(1991/07/20) => "20 July 1991"
Leaving UserFN _h() => "20 July 1991"
./test.rem(27): Trig = Saturday, 20 July, 1991
# Test some jahrzeit cases
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
[_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5759)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5759
hebdate(30, "Heshvan", 1991/02/16, 5759) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
./test.rem(31): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5760)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5760
hebdate(30, "Heshvan", 1991/02/16, 5760) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
./test.rem(32): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5761)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5761
hebdate(30, "Heshvan", 1991/02/16, 5761) => ./test.rem(33): 30 Heshvan 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5759)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5759
hebdate(30, "Kislev", 1991/02/16, 5759) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
./test.rem(35): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5760)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5760
hebdate(30, "Kislev", 1991/02/16, 5760) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
./test.rem(36): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5761)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5761
hebdate(30, "Kislev", 1991/02/16, 5761) => ./test.rem(37): 30 Kislev 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5755)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(30, "Adar A", 1991/02/16, 5755) => 1992/03/05
trigger(1992/03/05) => "5 March 1992"
Leaving UserFN _i() => "5 March 1992"
./test.rem(39): Trig = Thursday, 5 March, 1992
[_i(30, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5756)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(30, "Adar A", 1991/02/16, 5756) => ./test.rem(40): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(29, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5755)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(29, "Adar A", 1991/02/16, 5755) => 1991/03/15
trigger(1991/03/15) => "15 March 1991"
Leaving UserFN _i() => "15 March 1991"
./test.rem(41): Trig = Friday, 15 March, 1991
[_i(29, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5756)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(29, "Adar A", 1991/02/16, 5756) => ./test.rem(42): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
# Test each possible case of the basic reminders.
REM MSG Every Day
./test.rem(46): Trig = Saturday, 16 February, 1991
Every Day
REM 18 MSG Every 18th
./test.rem(48): Trig = Monday, 18 February, 1991
REM 15 MSG Every 15th
./test.rem(49): Trig = Friday, 15 March, 1991
REM Feb MSG February
./test.rem(51): Trig = Saturday, 16 February, 1991
February
REM Jan MSG January
./test.rem(52): Trig = Wednesday, 1 January, 1992
REM March MSG March
./test.rem(53): Trig = Friday, 1 March, 1991
REM 13 Jan MSG 13 Jan
./test.rem(55): Trig = Monday, 13 January, 1992
REM 15 Feb MSG 15 Feb
./test.rem(56): Trig = Saturday, 15 February, 1992
REM 28 Feb MSG 28 Feb
./test.rem(57): Trig = Thursday, 28 February, 1991
REM 29 Feb MSG 29 Feb
./test.rem(58): Trig = Saturday, 29 February, 1992
REM 5 Mar MSG 5 Mar
./test.rem(59): Trig = Tuesday, 5 March, 1991
REM 1990 MSG 1990
./test.rem(61): Expired
REM 1991 MSG 1991
./test.rem(62): Trig = Saturday, 16 February, 1991
1991
REM 1992 MSG 1991
./test.rem(63): Trig = Wednesday, 1 January, 1992
REM 1 1990 MSG 1 1990
./test.rem(65): Expired
REM 29 1991 MSG 29 1991
./test.rem(66): Trig = Friday, 29 March, 1991
REM 29 1992 MSG 29 1992
./test.rem(67): Trig = Wednesday, 29 January, 1992
REM 16 1991 MSG 16 1991
./test.rem(68): Trig = Saturday, 16 February, 1991
16 1991
REM Jan 1990 MSG Jan 1990
./test.rem(70): Expired
REM Feb 1991 MSG Feb 1991
./test.rem(71): Trig = Saturday, 16 February, 1991
Feb 1991
REM Dec 1991 MSG Dec 1991
./test.rem(72): Trig = Sunday, 1 December, 1991
REM May 1992 MSG May 1992
./test.rem(73): Trig = Friday, 1 May, 1992
REM 1 Jan 1991 MSG 1 Jan 1991
./test.rem(75): Expired
REM 16 Feb 1991 MSG 16 Feb 1991
./test.rem(76): Trig = Saturday, 16 February, 1991
16 Feb 1991
REM 29 Dec 1992 MSG 29 Dec 1992
./test.rem(77): Trig = Tuesday, 29 December, 1992
REM Sun MSG Sun
./test.rem(79): Trig = Sunday, 17 February, 1991
REM Fri Sat Tue MSG Fri Sat Tue
./test.rem(80): Trig = Saturday, 16 February, 1991
Fri Sat Tue
REM Sun 16 MSG Sun 16
./test.rem(82): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 MSG Mon Tue Wed Thu Fri 1
./test.rem(83): Trig = Friday, 1 March, 1991
REM Sun Feb MSG Sun Feb
./test.rem(85): Trig = Sunday, 17 February, 1991
REM Mon Tue March MSG Mon Tue March
./test.rem(86): Trig = Monday, 4 March, 1991
REM Sun 16 Feb MSG Sun 16 Feb
./test.rem(88): Trig = Sunday, 17 February, 1991
REM Mon Tue 10 March MSG Mon Tue 10 March
./test.rem(89): Trig = Monday, 11 March, 1991
REM Sat Sun 1991 MSG Sat Sun 1991
./test.rem(91): Trig = Saturday, 16 February, 1991
Sat Sun 1991
REM Mon Tue 1992 MSG Mon Tue 1992
./test.rem(92): Trig = Monday, 6 January, 1992
REM Sun 16 1991 MSG Sun 16 1991
./test.rem(94): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 1992 MSG Mon Tue Wed Thu Fri 1 1992
./test.rem(95): Trig = Wednesday, 1 January, 1992
REM Mon Feb 1991 MSG Mon Feb 1991
./test.rem(97): Trig = Monday, 18 February, 1991
REM Tue Jan 1992 MSG Tue Jan 1992
./test.rem(98): Trig = Tuesday, 7 January, 1992
REM Sun Mon 16 Feb 1991 MSG Sun Mon 16 Feb 1991
./test.rem(100): Trig = Sunday, 17 February, 1991
REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
./test.rem(101): Trig = Tuesday, 28 January, 1992
# Try some Backs
CLEAR-OMIT-CONTEXT
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
./test.rem(105): Trig = Thursday, 28 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
./test.rem(106): Trig = Thursday, 28 February, 1991
OMIT 28 Feb
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
./test.rem(109): Trig = Wednesday, 27 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun (28 Feb omitted)
./test.rem(110): Trig = Thursday, 28 February, 1991
CLEAR-OMIT-CONTEXT
# Try out UNTIL
REM Wed UNTIL 21 Feb 1991 MSG Wed UNTIL 21 Feb 1991
./test.rem(115): Trig = Wednesday, 20 February, 1991
# Try playing with the OMIT context
OMIT 28 Feb 1991
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
./test.rem(120): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
./test.rem(121): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
./test.rem(122): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
./test.rem(123): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
./test.rem(124): Trig = Friday, 1 March, 1991
PUSH-OMIT-CONTEXT
CLEAR-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1
./test.rem(128): Trig = Thursday, 28 February, 1991
REM 1 Mar --1 MSG 1 mar --1
./test.rem(129): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE
./test.rem(130): Trig = Thursday, 28 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP
./test.rem(131): Trig = Thursday, 28 February, 1991
REM 28 Feb AFTER MSG 28 Feb AFTER
./test.rem(132): Trig = Thursday, 28 February, 1991
POP-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
./test.rem(135): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
./test.rem(136): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
./test.rem(137): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
./test.rem(138): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
./test.rem(139): Trig = Friday, 1 March, 1991
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
./test.rem(142): Trig = Wednesday, 13 March, 1991
# Test BACK
CLEAR-OMIT-CONTEXT
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
./test.rem(146): Trig = Monday, 18 February, 1991
OMIT 17 Feb 1991
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 (17Feb91 omitted)
./test.rem(149): Trig = Monday, 18 February, 1991
18 Feb 1991 +1 (17Feb91 omitted)
REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
./test.rem(150): Trig = Monday, 18 February, 1991
CLEAR-OMIT-CONTEXT
# Test the scanfrom clause
REM Fri SATISFY 1
./test.rem(154): Trig = Friday, 22 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/22
trigger(1991/02/22) => "22 February 1991"
REM Fri after MSG 23 Feb 1991
./test.rem(156): Trig = Saturday, 23 February, 1991
CLEAR-OMIT-CONTEXT
REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
today() => 1991/02/16
1991/02/16 - 7 => 1991/02/09
trigger(1991/02/09) => "9 February 1991"
./test.rem(158): Trig = Friday, 15 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/15
trigger(1991/02/15) => "15 February 1991"
REM Fri after MSG 16 Feb 1991
./test.rem(160): Trig = Saturday, 16 February, 1991
16 Feb 1991
CLEAR-OMIT-CONTEXT
set a000 abs(1)
abs(1) => 1
set a001 abs(-1)
- 1 => -1
abs(-1) => 1
set a002 asc("foo")
asc("foo") => 102
set a003 baseyr()
baseyr() => 1990
set a004 char(66,55,66,77,66)
char(66, 55, 66, 77, 66) => "B7BMB"
set a005 choose(3, "foo", "bar", "baz", "blech")
choose(3, "foo", "bar", "baz", "blech") => "baz"
set a006 coerce("string", 1)
coerce("string", 1) => "1"
set a007 coerce("string", today())
today() => 1991/02/16
coerce("string", 1991/02/16) => "1991/02/16"
set a008 coerce("string", 11:44)
coerce("string", 11:44) => "11:44"
set a009 coerce("int", "badnews")
coerce("int", "badnews") => Can't coerce
./test.rem(171): Can't coerce
set a010 coerce("int", "12")
coerce("int", "12") => 12
set a011 coerce("int", 11:44)
coerce("int", 11:44) => 704
set a012 coerce("int", today())
today() => 1991/02/16
coerce("int", 1991/02/16) => 411
set a013 date(1992, 2, 2)
date(1992, 2, 2) => 1992/02/02
set a014 date(1993, 2, 29)
date(1993, 2, 29) => Bad date specification
./test.rem(176): Bad date specification
set a015 day(today())
today() => 1991/02/16
day(1991/02/16) => 16
set a016 daysinmon(2, 1991)
daysinmon(2, 1991) => 28
set a017 daysinmon(2, 1992)
daysinmon(2, 1992) => 29
set a018 defined("a017")
defined("a017") => 1
set a019 defined("a019")
defined("a019") => 0
set a020 filename()
filename() => "./test.rem"
set a021 getenv("TEST_GETENV")
getenv("TEST_GETENV") => "foo bar baz"
set a022 hour(11:22)
hour(11:22) => 11
set a023 iif(1, 1, 0)
iif(1, 1, 0) => 1
set a024 iif(0, 1, 0)
iif(0, 1, 0) => 0
set a025 index("barfoobar", "foo")
index("barfoobar", "foo") => 4
set a026 index("barfoobar", "bar", 2)
index("barfoobar", "bar", 2) => 7
set a027 isleap(today())
today() => 1991/02/16
isleap(1991/02/16) => 0
set a028 isleap(1992)
isleap(1992) => 1
omit [trigger(today())]
today() => 1991/02/16
trigger(1991/02/16) => "16 February 1991"
set a030 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 1
clear
set a029 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 0
set a031 lower("FOOBARBAZ")
lower("FOOBARBAZ") => "foobarbaz"
set a032 max(1, 2, 34, 1, 3)
max(1, 2, 34, 1, 3) => 34
set a033 max("foo", "bar", "baz")
max("foo", "bar", "baz") => "foo"
set a034 max(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
max(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/17
set a035 min(1, 2, 34, 1, 3)
min(1, 2, 34, 1, 3) => 1
set a036 min("foo", "bar", "baz")
min("foo", "bar", "baz") => "bar"
set a037 min(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
min(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/15
set a038 minute(11:33)
minute(11:33) => 33
set a039 mon(today())
today() => 1991/02/16
mon(1991/02/16) => "February"
set a040 monnum(today())
today() => 1991/02/16
monnum(1991/02/16) => 2
set a041 ord(3)
ord(3) => "3rd"
set a042 ord(4)
ord(4) => "4th"
set a043 ostype()
ostype() => "UNIX"
set a044 plural(2)
plural(2) => "s"
set a045 plural(2, "ies")
plural(2, "ies") => "iess"
set a046 plural(2, "y", "ies")
plural(2, "y", "ies") => "ies"
set a047 sgn(-2)
- 2 => -2
sgn(-2) => -1
set a048 shell("echo foo")
shell("echo foo") => "foo"
set a049 strlen("sadjflkhsldkfhsdlfjhk")
strlen("sadjflkhsldkfhsdlfjhk") => 21
set a050 substr(a049, 2)
a049 => 21
substr(21, 2) => Type mismatch
./test.rem(214): Type mismatch
set a051 substr(a050, 2, 6)
a050 => ./test.rem(215): Undefined variable: a050
set a052 time(1+2, 3+4)
1 + 2 => 3
3 + 4 => 7
time(3, 7) => 03:07
rem 10 jan 1992 AT 11:22 CAL
./test.rem(217): Trig = Friday, 10 January, 1992
set a053 trigdate()
trigdate() => 1992/01/10
set a054 trigtime()
trigtime() => 11:22
set a055 trigvalid()
trigvalid() => 1
set a056 upper("sdfjhsdf ksjdfh kjsdfh ksjdfh")
upper("sdfjhsdf ksjdfh kjsdfh ksjdfh") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "03.00.13"
set a059 wkday(today())
today() => 1991/02/16
wkday(1991/02/16) => "Saturday"
set a060 wkdaynum(today())
today() => 1991/02/16
wkdaynum(1991/02/16) => 6
set a061 year(today())
today() => 1991/02/16
year(1991/02/16) => 1991
set a062 1+2*(3+4-(5*7/2))
3 + 4 => 7
5 * 7 => 35
35 / 2 => 17
7 - 17 => -10
2 * -10 => -20
1 + -20 => -19
set a063 1>=2
1 >= 2 => 0
set a064 1<2 || 3 > 4
1 < 2 => 1
3 > 4 => 0
1 || 0 => 1
set a065 1 && 1
1 && 1 => 1
set a066 !a065
a065 => 1
! 1 => 0
set a067 typeof(2)
typeof(2) => "INT"
set a068 typeof("foo")
typeof("foo") => "STRING"
set a069 typeof(11:33)
typeof(11:33) => "TIME"
set a070 typeof(today())
today() => 1991/02/16
typeof(1991/02/16) => "DATE"
fset g(x,y) max(x,y)
fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
set a071 g(1, 2)
Entering UserFN g(1, 2)
x => 1
y => 2
max(1, 2) => 2
Leaving UserFN g() => 2
set a072 h(2, 3)
Entering UserFN h(2, 3)
x => 2
y => 3
2 + 3 => 5
x => 2
y => 3
2 * 3 => 6
Entering UserFN g(5, 6)
x => 5
y => 6
max(5, 6) => 6
Leaving UserFN g() => 6
x => 2
y => 3
2 - 3 => -1
x => 2
y => 3
2 / 3 => 0
Entering UserFN g(-1, 0)
x => -1
y => 0
max(-1, 0) => 0
Leaving UserFN g() => 0
min(6, 0) => 0
Leaving UserFN h() => 0
set a073 h("foo", 11:33)
Entering UserFN h("foo", 11:33)
x => "foo"
y => 11:33
"foo" + 11:33 => "foo11:33"
x => "foo"
y => 11:33
"foo" * 11:33 => Type mismatch
./test.rem(240): '*': Type mismatch
Leaving UserFN h() => Type mismatch
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
dosubst("%a %b %c %d %e %f %g %h", 1992/05/05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
msg [a074]%
./test.rem(242): Trig = Saturday, 16 February, 1991
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05/05/1992 on 05/05/1992 on Tuesday, 5 May on 05/05
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
dosubst("%i %j %k %l %m %n %o %p", 1992/05/05) => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
msg [a075]%
./test.rem(244): Trig = Saturday, 16 February, 1991
a075 => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
on 05/05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992/05/05 May 5 s
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
dosubst("%q %r %s %t %u %v %w %x", 1992/05/05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
msg [a076]%
./test.rem(246): Trig = Saturday, 16 February, 1991
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
set a077 dosubst("%y %z", '1992/5/5')
dosubst("%y %z", 1992/05/05) => "1992 92
"
msg [a077]%
./test.rem(248): Trig = Saturday, 16 February, 1991
a077 => "1992 92
"
1992 92
set a078 easterdate(today())
today() => 1991/02/16
easterdate(1991/02/16) => 1991/03/31
set a079 easterdate(1992)
easterdate(1992) => 1992/04/19
set a080 easterdate(1995)
easterdate(1995) => 1995/04/16
set a081 ""
dump
Variable Value
a017 29
a036 "bar"
a055 1
a074 "on Tuesday, 5 May, 1992 in 444 days' tim"...
a008 "11:44"
a027 0
a046 "ies"
a065 1
a018 1
a037 1991/02/15
a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a075 "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
a028 1
a047 -1
a066 0
a019 0
a038 33
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a076 "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
a029 0
a048 "foo"
a067 "INT"
a039 "February"
a058 "03.00.13"
a077 "1992 92
"
a049 21
a068 "STRING"
a059 "Saturday"
a078 1991/03/31
a069 "TIME"
a079 1992/04/19
a000 1
a010 12
a001 1
a020 "./test.rem"
a011 704
a030 1
a002 102
a021 "foo bar baz"
a040 2
a012 411
a031 "foobarbaz"
a003 1990
a022 11
a041 "3rd"
a060 6
a013 1992/02/02
a032 34
a070 "DATE"
a004 "B7BMB"
a023 1
a042 "4th"
a061 1991
a080 1995/04/16
a033 "foo"
a052 03:07
a071 2
a005 "baz"
a024 0
a043 "UNIX"
a062 -19
a081 ""
a015 16
a034 1991/02/17
a053 1992/01/10
a072 0
a006 "1"
a025 4
a044 "s"
a063 0
a016 28
a035 1
a054 11:22
a007 "1991/02/16"
a026 7
a045 "iess"
a064 1

255
test.rem Normal file
View File

@@ -0,0 +1,255 @@
# Test file for REMIND
#
# $Id: test.rem,v 1.1 1996-03-27 03:26:12 dfs Exp $
#
# Use this file to test the date calculation routines
# of the REMIND program by typing:
#
# ./test-rem # From WITHIN Remind source directory!
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
fset _h(x, y) trigger(hebdate(x,y))
[_h(1, "Tishrey")] MSG Rosh Hashana 1
[_h(2, "Tishrey")] MSG Rosh Hashana 2
[_h(3, "Tishrey")] MSG Tzom Gedalia
[_h(10, "Tishrey")] MSG Yom Kippur
[_h(15, "Tishrey")] MSG Sukkot 1
[_h(25, "Kislev")] MSG Channuka
[_h(10, "Tevet")] MSG Asara B'Tevet
[_h(15, "Shvat")] MSG Tu B'Shvat
[_h(15, "Adar A")] MSG Purim Katan
[_h(14, "Adar")] MSG Purim
[_h(15, "Nisan")] MSG Pesach
[_h(27, "Nisan")] MSG Yom HaShoah
[_h(4, "Iyar")] MSG Yom HaZikaron
[_h(5, "Iyar")] MSG Yom Ha'atzmaut
[_h(28, "Iyar")] MSG Yom Yerushalayim
[_h(6, "Sivan")] MSG Shavuot
[_h(9, "Av")] MSG Tish'a B'Av
# Test some jahrzeit cases
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
[_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
[_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
[_i(30, "Heshvan", today(), 5761)] MSG Illegal
[_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
[_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
[_i(30, "Kislev", today(), 5761)] MSG Illegal
[_i(30, "Adar A", today(), 5755)] MSG Leap
[_i(30, "Adar A", today(), 5756)] MSG Illegal
[_i(29, "Adar A", today(), 5755)] MSG Leap
[_i(29, "Adar A", today(), 5756)] MSG Illegal
# Test each possible case of the basic reminders.
REM MSG Every Day
REM 18 MSG Every 18th
REM 15 MSG Every 15th
REM Feb MSG February
REM Jan MSG January
REM March MSG March
REM 13 Jan MSG 13 Jan
REM 15 Feb MSG 15 Feb
REM 28 Feb MSG 28 Feb
REM 29 Feb MSG 29 Feb
REM 5 Mar MSG 5 Mar
REM 1990 MSG 1990
REM 1991 MSG 1991
REM 1992 MSG 1991
REM 1 1990 MSG 1 1990
REM 29 1991 MSG 29 1991
REM 29 1992 MSG 29 1992
REM 16 1991 MSG 16 1991
REM Jan 1990 MSG Jan 1990
REM Feb 1991 MSG Feb 1991
REM Dec 1991 MSG Dec 1991
REM May 1992 MSG May 1992
REM 1 Jan 1991 MSG 1 Jan 1991
REM 16 Feb 1991 MSG 16 Feb 1991
REM 29 Dec 1992 MSG 29 Dec 1992
REM Sun MSG Sun
REM Fri Sat Tue MSG Fri Sat Tue
REM Sun 16 MSG Sun 16
REM Mon Tue Wed Thu Fri 1 MSG Mon Tue Wed Thu Fri 1
REM Sun Feb MSG Sun Feb
REM Mon Tue March MSG Mon Tue March
REM Sun 16 Feb MSG Sun 16 Feb
REM Mon Tue 10 March MSG Mon Tue 10 March
REM Sat Sun 1991 MSG Sat Sun 1991
REM Mon Tue 1992 MSG Mon Tue 1992
REM Sun 16 1991 MSG Sun 16 1991
REM Mon Tue Wed Thu Fri 1 1992 MSG Mon Tue Wed Thu Fri 1 1992
REM Mon Feb 1991 MSG Mon Feb 1991
REM Tue Jan 1992 MSG Tue Jan 1992
REM Sun Mon 16 Feb 1991 MSG Sun Mon 16 Feb 1991
REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
# Try some Backs
CLEAR-OMIT-CONTEXT
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
OMIT 28 Feb
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun (28 Feb omitted)
CLEAR-OMIT-CONTEXT
# Try out UNTIL
REM Wed UNTIL 21 Feb 1991 MSG Wed UNTIL 21 Feb 1991
# Try playing with the OMIT context
OMIT 28 Feb 1991
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
PUSH-OMIT-CONTEXT
CLEAR-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1
REM 1 Mar --1 MSG 1 mar --1
REM 28 Feb BEFORE MSG 28 Feb BEFORE
REM 28 Feb SKIP MSG 28 Feb SKIP
REM 28 Feb AFTER MSG 28 Feb AFTER
POP-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
# Test BACK
CLEAR-OMIT-CONTEXT
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
OMIT 17 Feb 1991
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 (17Feb91 omitted)
REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
CLEAR-OMIT-CONTEXT
# Test the scanfrom clause
REM Fri SATISFY 1
OMIT [trigger(trigdate())]
REM Fri after MSG 23 Feb 1991
CLEAR-OMIT-CONTEXT
REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
OMIT [trigger(trigdate())]
REM Fri after MSG 16 Feb 1991
CLEAR-OMIT-CONTEXT
set a000 abs(1)
set a001 abs(-1)
set a002 asc("foo")
set a003 baseyr()
set a004 char(66,55,66,77,66)
set a005 choose(3, "foo", "bar", "baz", "blech")
set a006 coerce("string", 1)
set a007 coerce("string", today())
set a008 coerce("string", 11:44)
set a009 coerce("int", "badnews")
set a010 coerce("int", "12")
set a011 coerce("int", 11:44)
set a012 coerce("int", today())
set a013 date(1992, 2, 2)
set a014 date(1993, 2, 29)
set a015 day(today())
set a016 daysinmon(2, 1991)
set a017 daysinmon(2, 1992)
set a018 defined("a017")
set a019 defined("a019")
set a020 filename()
set a021 getenv("TEST_GETENV")
set a022 hour(11:22)
set a023 iif(1, 1, 0)
set a024 iif(0, 1, 0)
set a025 index("barfoobar", "foo")
set a026 index("barfoobar", "bar", 2)
set a027 isleap(today())
set a028 isleap(1992)
omit [trigger(today())]
set a030 isomitted(today())
clear
set a029 isomitted(today())
set a031 lower("FOOBARBAZ")
set a032 max(1, 2, 34, 1, 3)
set a033 max("foo", "bar", "baz")
set a034 max(today(), today()+1, today()-1)
set a035 min(1, 2, 34, 1, 3)
set a036 min("foo", "bar", "baz")
set a037 min(today(), today()+1, today()-1)
set a038 minute(11:33)
set a039 mon(today())
set a040 monnum(today())
set a041 ord(3)
set a042 ord(4)
set a043 ostype()
set a044 plural(2)
set a045 plural(2, "ies")
set a046 plural(2, "y", "ies")
set a047 sgn(-2)
set a048 shell("echo foo")
set a049 strlen("sadjflkhsldkfhsdlfjhk")
set a050 substr(a049, 2)
set a051 substr(a050, 2, 6)
set a052 time(1+2, 3+4)
rem 10 jan 1992 AT 11:22 CAL
set a053 trigdate()
set a054 trigtime()
set a055 trigvalid()
set a056 upper("sdfjhsdf ksjdfh kjsdfh ksjdfh")
set a057 value("a05"+"6")
set a058 version()
set a059 wkday(today())
set a060 wkdaynum(today())
set a061 year(today())
set a062 1+2*(3+4-(5*7/2))
set a063 1>=2
set a064 1<2 || 3 > 4
set a065 1 && 1
set a066 !a065
set a067 typeof(2)
set a068 typeof("foo")
set a069 typeof(11:33)
set a070 typeof(today())
fset g(x,y) max(x,y)
fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
set a071 g(1, 2)
set a072 h(2, 3)
set a073 h("foo", 11:33)
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
msg [a074]%
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
msg [a075]%
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
msg [a076]%
set a077 dosubst("%y %z", '1992/5/5')
msg [a077]%
set a078 easterdate(today())
set a079 easterdate(1992)
set a080 easterdate(1995)
set a081 ""
dump

832
test1.cmp Normal file
View File

@@ -0,0 +1,832 @@
# Test file for REMIND
#
# $Id: test1.cmp,v 1.1 1996-03-27 03:26:12 dfs Exp $
#
# Use this file to test the date calculation routines
# of the REMIND program by typing:
#
# ./test-rem # From WITHIN Remind source directory!
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
.\test.rem(8): Trig = Saturday, 16 February, 1991
Reminders for Saturday, 16th February, 1991:
today() => 1991/02/16
hebday(1991/02/16) => 2
today() => 1991/02/16
hebmon(1991/02/16) => "Adar"
today() => 1991/02/16
hebyear(1991/02/16) => 5751
Today is 2 Adar 5751
fset _h(x, y) trigger(hebdate(x,y))
[_h(1, "Tishrey")] MSG Rosh Hashana 1
Entering UserFN _h(1, "Tishrey")
x => 1
y => "Tishrey"
hebdate(1, "Tishrey") => 1991/09/09
trigger(1991/09/09) => "9 September 1991"
Leaving UserFN _h() => "9 September 1991"
.\test.rem(11): Trig = Monday, 9 September, 1991
[_h(2, "Tishrey")] MSG Rosh Hashana 2
Entering UserFN _h(2, "Tishrey")
x => 2
y => "Tishrey"
hebdate(2, "Tishrey") => 1991/09/10
trigger(1991/09/10) => "10 September 1991"
Leaving UserFN _h() => "10 September 1991"
.\test.rem(12): Trig = Tuesday, 10 September, 1991
[_h(3, "Tishrey")] MSG Tzom Gedalia
Entering UserFN _h(3, "Tishrey")
x => 3
y => "Tishrey"
hebdate(3, "Tishrey") => 1991/09/11
trigger(1991/09/11) => "11 September 1991"
Leaving UserFN _h() => "11 September 1991"
.\test.rem(13): Trig = Wednesday, 11 September, 1991
[_h(10, "Tishrey")] MSG Yom Kippur
Entering UserFN _h(10, "Tishrey")
x => 10
y => "Tishrey"
hebdate(10, "Tishrey") => 1991/09/18
trigger(1991/09/18) => "18 September 1991"
Leaving UserFN _h() => "18 September 1991"
.\test.rem(14): Trig = Wednesday, 18 September, 1991
[_h(15, "Tishrey")] MSG Sukkot 1
Entering UserFN _h(15, "Tishrey")
x => 15
y => "Tishrey"
hebdate(15, "Tishrey") => 1991/09/23
trigger(1991/09/23) => "23 September 1991"
Leaving UserFN _h() => "23 September 1991"
.\test.rem(15): Trig = Monday, 23 September, 1991
[_h(25, "Kislev")] MSG Channuka
Entering UserFN _h(25, "Kislev")
x => 25
y => "Kislev"
hebdate(25, "Kislev") => 1991/12/02
trigger(1991/12/02) => "2 December 1991"
Leaving UserFN _h() => "2 December 1991"
.\test.rem(16): Trig = Monday, 2 December, 1991
[_h(10, "Tevet")] MSG Asara B'Tevet
Entering UserFN _h(10, "Tevet")
x => 10
y => "Tevet"
hebdate(10, "Tevet") => 1991/12/17
trigger(1991/12/17) => "17 December 1991"
Leaving UserFN _h() => "17 December 1991"
.\test.rem(17): Trig = Tuesday, 17 December, 1991
[_h(15, "Shvat")] MSG Tu B'Shvat
Entering UserFN _h(15, "Shvat")
x => 15
y => "Shvat"
hebdate(15, "Shvat") => 1992/01/20
trigger(1992/01/20) => "20 January 1992"
Leaving UserFN _h() => "20 January 1992"
.\test.rem(18): Trig = Monday, 20 January, 1992
[_h(15, "Adar A")] MSG Purim Katan
Entering UserFN _h(15, "Adar A")
x => 15
y => "Adar A"
hebdate(15, "Adar A") => 1992/02/19
trigger(1992/02/19) => "19 February 1992"
Leaving UserFN _h() => "19 February 1992"
.\test.rem(19): Trig = Wednesday, 19 February, 1992
[_h(14, "Adar")] MSG Purim
Entering UserFN _h(14, "Adar")
x => 14
y => "Adar"
hebdate(14, "Adar") => 1991/02/28
trigger(1991/02/28) => "28 February 1991"
Leaving UserFN _h() => "28 February 1991"
.\test.rem(20): Trig = Thursday, 28 February, 1991
[_h(15, "Nisan")] MSG Pesach
Entering UserFN _h(15, "Nisan")
x => 15
y => "Nisan"
hebdate(15, "Nisan") => 1991/03/30
trigger(1991/03/30) => "30 March 1991"
Leaving UserFN _h() => "30 March 1991"
.\test.rem(21): Trig = Saturday, 30 March, 1991
[_h(27, "Nisan")] MSG Yom HaShoah
Entering UserFN _h(27, "Nisan")
x => 27
y => "Nisan"
hebdate(27, "Nisan") => 1991/04/11
trigger(1991/04/11) => "11 April 1991"
Leaving UserFN _h() => "11 April 1991"
.\test.rem(22): Trig = Thursday, 11 April, 1991
[_h(4, "Iyar")] MSG Yom HaZikaron
Entering UserFN _h(4, "Iyar")
x => 4
y => "Iyar"
hebdate(4, "Iyar") => 1991/04/18
trigger(1991/04/18) => "18 April 1991"
Leaving UserFN _h() => "18 April 1991"
.\test.rem(23): Trig = Thursday, 18 April, 1991
[_h(5, "Iyar")] MSG Yom Ha'atzmaut
Entering UserFN _h(5, "Iyar")
x => 5
y => "Iyar"
hebdate(5, "Iyar") => 1991/04/19
trigger(1991/04/19) => "19 April 1991"
Leaving UserFN _h() => "19 April 1991"
.\test.rem(24): Trig = Friday, 19 April, 1991
[_h(28, "Iyar")] MSG Yom Yerushalayim
Entering UserFN _h(28, "Iyar")
x => 28
y => "Iyar"
hebdate(28, "Iyar") => 1991/05/12
trigger(1991/05/12) => "12 May 1991"
Leaving UserFN _h() => "12 May 1991"
.\test.rem(25): Trig = Sunday, 12 May, 1991
[_h(6, "Sivan")] MSG Shavuot
Entering UserFN _h(6, "Sivan")
x => 6
y => "Sivan"
hebdate(6, "Sivan") => 1991/05/19
trigger(1991/05/19) => "19 May 1991"
Leaving UserFN _h() => "19 May 1991"
.\test.rem(26): Trig = Sunday, 19 May, 1991
[_h(9, "Av")] MSG Tish'a B'Av
Entering UserFN _h(9, "Av")
x => 9
y => "Av"
hebdate(9, "Av") => 1991/07/20
trigger(1991/07/20) => "20 July 1991"
Leaving UserFN _h() => "20 July 1991"
.\test.rem(27): Trig = Saturday, 20 July, 1991
# Test some jahrzeit cases
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
[_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5759)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5759
hebdate(30, "Heshvan", 1991/02/16, 5759) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
.\test.rem(31): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5760)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5760
hebdate(30, "Heshvan", 1991/02/16, 5760) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
.\test.rem(32): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5761)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5761
hebdate(30, "Heshvan", 1991/02/16, 5761) => .\test.rem(33): 30 Heshvan 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5759)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5759
hebdate(30, "Kislev", 1991/02/16, 5759) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
.\test.rem(35): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5760)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5760
hebdate(30, "Kislev", 1991/02/16, 5760) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
.\test.rem(36): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5761)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5761
hebdate(30, "Kislev", 1991/02/16, 5761) => .\test.rem(37): 30 Kislev 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5755)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(30, "Adar A", 1991/02/16, 5755) => 1992/03/05
trigger(1992/03/05) => "5 March 1992"
Leaving UserFN _i() => "5 March 1992"
.\test.rem(39): Trig = Thursday, 5 March, 1992
[_i(30, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5756)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(30, "Adar A", 1991/02/16, 5756) => .\test.rem(40): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(29, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5755)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(29, "Adar A", 1991/02/16, 5755) => 1991/03/15
trigger(1991/03/15) => "15 March 1991"
Leaving UserFN _i() => "15 March 1991"
.\test.rem(41): Trig = Friday, 15 March, 1991
[_i(29, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5756)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(29, "Adar A", 1991/02/16, 5756) => .\test.rem(42): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
# Test each possible case of the basic reminders.
REM MSG Every Day
.\test.rem(46): Trig = Saturday, 16 February, 1991
Every Day
REM 18 MSG Every 18th
.\test.rem(48): Trig = Monday, 18 February, 1991
REM 15 MSG Every 15th
.\test.rem(49): Trig = Friday, 15 March, 1991
REM Feb MSG February
.\test.rem(51): Trig = Saturday, 16 February, 1991
February
REM Jan MSG January
.\test.rem(52): Trig = Wednesday, 1 January, 1992
REM March MSG March
.\test.rem(53): Trig = Friday, 1 March, 1991
REM 13 Jan MSG 13 Jan
.\test.rem(55): Trig = Monday, 13 January, 1992
REM 15 Feb MSG 15 Feb
.\test.rem(56): Trig = Saturday, 15 February, 1992
REM 28 Feb MSG 28 Feb
.\test.rem(57): Trig = Thursday, 28 February, 1991
REM 29 Feb MSG 29 Feb
.\test.rem(58): Trig = Saturday, 29 February, 1992
REM 5 Mar MSG 5 Mar
.\test.rem(59): Trig = Tuesday, 5 March, 1991
REM 1990 MSG 1990
.\test.rem(61): Expired
REM 1991 MSG 1991
.\test.rem(62): Trig = Saturday, 16 February, 1991
1991
REM 1992 MSG 1991
.\test.rem(63): Trig = Wednesday, 1 January, 1992
REM 1 1990 MSG 1 1990
.\test.rem(65): Expired
REM 29 1991 MSG 29 1991
.\test.rem(66): Trig = Friday, 29 March, 1991
REM 29 1992 MSG 29 1992
.\test.rem(67): Trig = Wednesday, 29 January, 1992
REM 16 1991 MSG 16 1991
.\test.rem(68): Trig = Saturday, 16 February, 1991
16 1991
REM Jan 1990 MSG Jan 1990
.\test.rem(70): Expired
REM Feb 1991 MSG Feb 1991
.\test.rem(71): Trig = Saturday, 16 February, 1991
Feb 1991
REM Dec 1991 MSG Dec 1991
.\test.rem(72): Trig = Sunday, 1 December, 1991
REM May 1992 MSG May 1992
.\test.rem(73): Trig = Friday, 1 May, 1992
REM 1 Jan 1991 MSG 1 Jan 1991
.\test.rem(75): Expired
REM 16 Feb 1991 MSG 16 Feb 1991
.\test.rem(76): Trig = Saturday, 16 February, 1991
16 Feb 1991
REM 29 Dec 1992 MSG 29 Dec 1992
.\test.rem(77): Trig = Tuesday, 29 December, 1992
REM Sun MSG Sun
.\test.rem(79): Trig = Sunday, 17 February, 1991
REM Fri Sat Tue MSG Fri Sat Tue
.\test.rem(80): Trig = Saturday, 16 February, 1991
Fri Sat Tue
REM Sun 16 MSG Sun 16
.\test.rem(82): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 MSG Mon Tue Wed Thu Fri 1
.\test.rem(83): Trig = Friday, 1 March, 1991
REM Sun Feb MSG Sun Feb
.\test.rem(85): Trig = Sunday, 17 February, 1991
REM Mon Tue March MSG Mon Tue March
.\test.rem(86): Trig = Monday, 4 March, 1991
REM Sun 16 Feb MSG Sun 16 Feb
.\test.rem(88): Trig = Sunday, 17 February, 1991
REM Mon Tue 10 March MSG Mon Tue 10 March
.\test.rem(89): Trig = Monday, 11 March, 1991
REM Sat Sun 1991 MSG Sat Sun 1991
.\test.rem(91): Trig = Saturday, 16 February, 1991
Sat Sun 1991
REM Mon Tue 1992 MSG Mon Tue 1992
.\test.rem(92): Trig = Monday, 6 January, 1992
REM Sun 16 1991 MSG Sun 16 1991
.\test.rem(94): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 1992 MSG Mon Tue Wed Thu Fri 1 1992
.\test.rem(95): Trig = Wednesday, 1 January, 1992
REM Mon Feb 1991 MSG Mon Feb 1991
.\test.rem(97): Trig = Monday, 18 February, 1991
REM Tue Jan 1992 MSG Tue Jan 1992
.\test.rem(98): Trig = Tuesday, 7 January, 1992
REM Sun Mon 16 Feb 1991 MSG Sun Mon 16 Feb 1991
.\test.rem(100): Trig = Sunday, 17 February, 1991
REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
.\test.rem(101): Trig = Tuesday, 28 January, 1992
# Try some Backs
CLEAR-OMIT-CONTEXT
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
.\test.rem(105): Trig = Thursday, 28 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
.\test.rem(106): Trig = Thursday, 28 February, 1991
OMIT 28 Feb
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
.\test.rem(109): Trig = Wednesday, 27 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun (28 Feb omitted)
.\test.rem(110): Trig = Thursday, 28 February, 1991
CLEAR-OMIT-CONTEXT
# Try out UNTIL
REM Wed UNTIL 21 Feb 1991 MSG Wed UNTIL 21 Feb 1991
.\test.rem(115): Trig = Wednesday, 20 February, 1991
# Try playing with the OMIT context
OMIT 28 Feb 1991
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
.\test.rem(120): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
.\test.rem(121): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
.\test.rem(122): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
.\test.rem(123): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
.\test.rem(124): Trig = Friday, 1 March, 1991
PUSH-OMIT-CONTEXT
CLEAR-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1
.\test.rem(128): Trig = Thursday, 28 February, 1991
REM 1 Mar --1 MSG 1 mar --1
.\test.rem(129): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE
.\test.rem(130): Trig = Thursday, 28 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP
.\test.rem(131): Trig = Thursday, 28 February, 1991
REM 28 Feb AFTER MSG 28 Feb AFTER
.\test.rem(132): Trig = Thursday, 28 February, 1991
POP-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
.\test.rem(135): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
.\test.rem(136): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
.\test.rem(137): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
.\test.rem(138): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
.\test.rem(139): Trig = Friday, 1 March, 1991
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
.\test.rem(142): Trig = Wednesday, 13 March, 1991
# Test BACK
CLEAR-OMIT-CONTEXT
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
.\test.rem(146): Trig = Monday, 18 February, 1991
OMIT 17 Feb 1991
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 (17Feb91 omitted)
.\test.rem(149): Trig = Monday, 18 February, 1991
18 Feb 1991 +1 (17Feb91 omitted)
REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
.\test.rem(150): Trig = Monday, 18 February, 1991
CLEAR-OMIT-CONTEXT
# Test the scanfrom clause
REM Fri SATISFY 1
.\test.rem(154): Trig = Friday, 22 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/22
trigger(1991/02/22) => "22 February 1991"
REM Fri after MSG 23 Feb 1991
.\test.rem(156): Trig = Saturday, 23 February, 1991
CLEAR-OMIT-CONTEXT
REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
today() => 1991/02/16
1991/02/16 - 7 => 1991/02/09
trigger(1991/02/09) => "9 February 1991"
.\test.rem(158): Trig = Friday, 15 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/15
trigger(1991/02/15) => "15 February 1991"
REM Fri after MSG 16 Feb 1991
.\test.rem(160): Trig = Saturday, 16 February, 1991
16 Feb 1991
CLEAR-OMIT-CONTEXT
set a000 abs(1)
abs(1) => 1
set a001 abs(-1)
- 1 => -1
abs(-1) => 1
set a002 asc("foo")
asc("foo") => 102
set a003 baseyr()
baseyr() => 1990
set a004 char(66,55,66,77,66)
char(66, 55, 66, 77, 66) => "B7BMB"
set a005 choose(3, "foo", "bar", "baz", "blech")
choose(3, "foo", "bar", "baz", "blech") => "baz"
set a006 coerce("string", 1)
coerce("string", 1) => "1"
set a007 coerce("string", today())
today() => 1991/02/16
coerce("string", 1991/02/16) => "1991/02/16"
set a008 coerce("string", 11:44)
coerce("string", 11:44) => "11:44"
set a009 coerce("int", "badnews")
coerce("int", "badnews") => Can't coerce
.\test.rem(171): Can't coerce
set a010 coerce("int", "12")
coerce("int", "12") => 12
set a011 coerce("int", 11:44)
coerce("int", 11:44) => 704
set a012 coerce("int", today())
today() => 1991/02/16
coerce("int", 1991/02/16) => 411
set a013 date(1992, 2, 2)
date(1992, 2, 2) => 1992/02/02
set a014 date(1993, 2, 29)
date(1993, 2, 29) => Bad date specification
.\test.rem(176): Bad date specification
set a015 day(today())
today() => 1991/02/16
day(1991/02/16) => 16
set a016 daysinmon(2, 1991)
daysinmon(2, 1991) => 28
set a017 daysinmon(2, 1992)
daysinmon(2, 1992) => 29
set a018 defined("a017")
defined("a017") => 1
set a019 defined("a019")
defined("a019") => 0
set a020 filename()
filename() => ".\test.rem"
set a021 getenv("TEST_GETENV")
getenv("TEST_GETENV") => "foo bar baz"
set a022 hour(11:22)
hour(11:22) => 11
set a023 iif(1, 1, 0)
iif(1, 1, 0) => 1
set a024 iif(0, 1, 0)
iif(0, 1, 0) => 0
set a025 index("barfoobar", "foo")
index("barfoobar", "foo") => 4
set a026 index("barfoobar", "bar", 2)
index("barfoobar", "bar", 2) => 7
set a027 isleap(today())
today() => 1991/02/16
isleap(1991/02/16) => 0
set a028 isleap(1992)
isleap(1992) => 1
omit [trigger(today())]
today() => 1991/02/16
trigger(1991/02/16) => "16 February 1991"
set a030 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 1
clear
set a029 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 0
set a031 lower("FOOBARBAZ")
lower("FOOBARBAZ") => "foobarbaz"
set a032 max(1, 2, 34, 1, 3)
max(1, 2, 34, 1, 3) => 34
set a033 max("foo", "bar", "baz")
max("foo", "bar", "baz") => "foo"
set a034 max(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
max(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/17
set a035 min(1, 2, 34, 1, 3)
min(1, 2, 34, 1, 3) => 1
set a036 min("foo", "bar", "baz")
min("foo", "bar", "baz") => "bar"
set a037 min(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
min(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/15
set a038 minute(11:33)
minute(11:33) => 33
set a039 mon(today())
today() => 1991/02/16
mon(1991/02/16) => "February"
set a040 monnum(today())
today() => 1991/02/16
monnum(1991/02/16) => 2
set a041 ord(3)
ord(3) => "3rd"
set a042 ord(4)
ord(4) => "4th"
set a043 ostype()
ostype() => "MSDOS"
set a044 plural(2)
plural(2) => "s"
set a045 plural(2, "ies")
plural(2, "ies") => "iess"
set a046 plural(2, "y", "ies")
plural(2, "y", "ies") => "ies"
set a047 sgn(-2)
- 2 => -2
sgn(-2) => -1
set a048 shell("echo foo")
shell("echo foo") => "foo"
set a049 strlen("sadjflkhsldkfhsdlfjhk")
strlen("sadjflkhsldkfhsdlfjhk") => 21
set a050 substr(a049, 2)
a049 => 21
substr(21, 2) => Type mismatch
.\test.rem(214): Type mismatch
set a051 substr(a050, 2, 6)
a050 => .\test.rem(215): Undefined variable: a050
set a052 time(1+2, 3+4)
1 + 2 => 3
3 + 4 => 7
time(3, 7) => 03:07
rem 10 jan 1992 AT 11:22 CAL
.\test.rem(217): Trig = Friday, 10 January, 1992
set a053 trigdate()
trigdate() => 1992/01/10
set a054 trigtime()
trigtime() => 11:22
set a055 trigvalid()
trigvalid() => 1
set a056 upper("sdfjhsdf ksjdfh kjsdfh ksjdfh")
upper("sdfjhsdf ksjdfh kjsdfh ksjdfh") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "03.00.13"
set a059 wkday(today())
today() => 1991/02/16
wkday(1991/02/16) => "Saturday"
set a060 wkdaynum(today())
today() => 1991/02/16
wkdaynum(1991/02/16) => 6
set a061 year(today())
today() => 1991/02/16
year(1991/02/16) => 1991
set a062 1+2*(3+4-(5*7/2))
3 + 4 => 7
5 * 7 => 35
35 / 2 => 17
7 - 17 => -10
2 * -10 => -20
1 + -20 => -19
set a063 1>=2
1 >= 2 => 0
set a064 1<2 || 3 > 4
1 < 2 => 1
3 > 4 => 0
1 || 0 => 1
set a065 1 && 1
1 && 1 => 1
set a066 !a065
a065 => 1
! 1 => 0
set a067 typeof(2)
typeof(2) => "INT"
set a068 typeof("foo")
typeof("foo") => "STRING"
set a069 typeof(11:33)
typeof(11:33) => "TIME"
set a070 typeof(today())
today() => 1991/02/16
typeof(1991/02/16) => "DATE"
fset g(x,y) max(x,y)
fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
set a071 g(1, 2)
Entering UserFN g(1, 2)
x => 1
y => 2
max(1, 2) => 2
Leaving UserFN g() => 2
set a072 h(2, 3)
Entering UserFN h(2, 3)
x => 2
y => 3
2 + 3 => 5
x => 2
y => 3
2 * 3 => 6
Entering UserFN g(5, 6)
x => 5
y => 6
max(5, 6) => 6
Leaving UserFN g() => 6
x => 2
y => 3
2 - 3 => -1
x => 2
y => 3
2 / 3 => 0
Entering UserFN g(-1, 0)
x => -1
y => 0
max(-1, 0) => 0
Leaving UserFN g() => 0
min(6, 0) => 0
Leaving UserFN h() => 0
set a073 h("foo", 11:33)
Entering UserFN h("foo", 11:33)
x => "foo"
y => 11:33
"foo" + 11:33 => "foo11:33"
x => "foo"
y => 11:33
"foo" * 11:33 => Type mismatch
.\test.rem(240): '*': Type mismatch
Leaving UserFN h() => Type mismatch
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
dosubst("%a %b %c %d %e %f %g %h", 1992/05/05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
msg [a074]%
.\test.rem(242): Trig = Saturday, 16 February, 1991
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05/05/1992 on 05/05/1992 on Tuesday, 5 May on 05/05
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
dosubst("%i %j %k %l %m %n %o %p", 1992/05/05) => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
msg [a075]%
.\test.rem(244): Trig = Saturday, 16 February, 1991
a075 => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
on 05/05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992/05/05 May 5 s
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
dosubst("%q %r %s %t %u %v %w %x", 1992/05/05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
msg [a076]%
.\test.rem(246): Trig = Saturday, 16 February, 1991
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
set a077 dosubst("%y %z", '1992/5/5')
dosubst("%y %z", 1992/05/05) => "1992 92
"
msg [a077]%
.\test.rem(248): Trig = Saturday, 16 February, 1991
a077 => "1992 92
"
1992 92
set a078 easterdate(today())
today() => 1991/02/16
easterdate(1991/02/16) => 1991/03/31
set a079 easterdate(1992)
easterdate(1992) => 1992/04/19
set a080 easterdate(1995)
easterdate(1995) => 1995/04/16
set a081 ""
dump
Variable Value
a017 29
a036 "bar"
a055 1
a074 "on Tuesday, 5 May, 1992 in 444 days' tim"...
a008 "11:44"
a027 0
a046 "ies"
a065 1
a018 1
a037 1991/02/15
a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a075 "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
a028 1
a047 -1
a066 0
a019 0
a038 33
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a076 "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
a029 0
a048 "foo"
a067 "INT"
a039 "February"
a058 "03.00.13"
a077 "1992 92
"
a049 21
a068 "STRING"
a059 "Saturday"
a078 1991/03/31
a069 "TIME"
a079 1992/04/19
a000 1
a010 12
a001 1
a020 ".\test.rem"
a011 704
a030 1
a002 102
a021 "foo bar baz"
a040 2
a012 411
a031 "foobarbaz"
a003 1990
a022 11
a041 "3rd"
a060 6
a013 1992/02/02
a032 34
a070 "DATE"
a004 "B7BMB"
a023 1
a042 "4th"
a061 1991
a080 1995/04/16
a033 "foo"
a052 03:07
a071 2
a005 "baz"
a024 0
a043 "MSDOS"
a062 -19
a081 ""
a015 16
a034 1991/02/17
a053 1992/01/10
a072 0
a006 "1"
a025 4
a044 "s"
a063 0
a016 28
a035 1
a054 11:22
a007 "1991/02/16"
a026 7
a045 "iess"
a064 1

832
test2.cmp Normal file
View File

@@ -0,0 +1,832 @@
# Test file for REMIND
#
# $Id: test2.cmp,v 1.1 1996-03-27 03:26:13 dfs Exp $
#
# Use this file to test the date calculation routines
# of the REMIND program by typing:
#
# ./test-rem # From WITHIN Remind source directory!
REM MSG Today is [hebday(today())] [hebmon(today())] [hebyear(today())]
.\test.rem(8): Trig = Saturday, 16 February, 1991
Reminders for Saturday, 16th February, 1991:
today() => 1991/02/16
hebday(1991/02/16) => 2
today() => 1991/02/16
hebmon(1991/02/16) => "Adar"
today() => 1991/02/16
hebyear(1991/02/16) => 5751
Today is 2 Adar 5751
fset _h(x, y) trigger(hebdate(x,y))
[_h(1, "Tishrey")] MSG Rosh Hashana 1
Entering UserFN _h(1, "Tishrey")
x => 1
y => "Tishrey"
hebdate(1, "Tishrey") => 1991/09/09
trigger(1991/09/09) => "9 September 1991"
Leaving UserFN _h() => "9 September 1991"
.\test.rem(11): Trig = Monday, 9 September, 1991
[_h(2, "Tishrey")] MSG Rosh Hashana 2
Entering UserFN _h(2, "Tishrey")
x => 2
y => "Tishrey"
hebdate(2, "Tishrey") => 1991/09/10
trigger(1991/09/10) => "10 September 1991"
Leaving UserFN _h() => "10 September 1991"
.\test.rem(12): Trig = Tuesday, 10 September, 1991
[_h(3, "Tishrey")] MSG Tzom Gedalia
Entering UserFN _h(3, "Tishrey")
x => 3
y => "Tishrey"
hebdate(3, "Tishrey") => 1991/09/11
trigger(1991/09/11) => "11 September 1991"
Leaving UserFN _h() => "11 September 1991"
.\test.rem(13): Trig = Wednesday, 11 September, 1991
[_h(10, "Tishrey")] MSG Yom Kippur
Entering UserFN _h(10, "Tishrey")
x => 10
y => "Tishrey"
hebdate(10, "Tishrey") => 1991/09/18
trigger(1991/09/18) => "18 September 1991"
Leaving UserFN _h() => "18 September 1991"
.\test.rem(14): Trig = Wednesday, 18 September, 1991
[_h(15, "Tishrey")] MSG Sukkot 1
Entering UserFN _h(15, "Tishrey")
x => 15
y => "Tishrey"
hebdate(15, "Tishrey") => 1991/09/23
trigger(1991/09/23) => "23 September 1991"
Leaving UserFN _h() => "23 September 1991"
.\test.rem(15): Trig = Monday, 23 September, 1991
[_h(25, "Kislev")] MSG Channuka
Entering UserFN _h(25, "Kislev")
x => 25
y => "Kislev"
hebdate(25, "Kislev") => 1991/12/02
trigger(1991/12/02) => "2 December 1991"
Leaving UserFN _h() => "2 December 1991"
.\test.rem(16): Trig = Monday, 2 December, 1991
[_h(10, "Tevet")] MSG Asara B'Tevet
Entering UserFN _h(10, "Tevet")
x => 10
y => "Tevet"
hebdate(10, "Tevet") => 1991/12/17
trigger(1991/12/17) => "17 December 1991"
Leaving UserFN _h() => "17 December 1991"
.\test.rem(17): Trig = Tuesday, 17 December, 1991
[_h(15, "Shvat")] MSG Tu B'Shvat
Entering UserFN _h(15, "Shvat")
x => 15
y => "Shvat"
hebdate(15, "Shvat") => 1992/01/20
trigger(1992/01/20) => "20 January 1992"
Leaving UserFN _h() => "20 January 1992"
.\test.rem(18): Trig = Monday, 20 January, 1992
[_h(15, "Adar A")] MSG Purim Katan
Entering UserFN _h(15, "Adar A")
x => 15
y => "Adar A"
hebdate(15, "Adar A") => 1992/02/19
trigger(1992/02/19) => "19 February 1992"
Leaving UserFN _h() => "19 February 1992"
.\test.rem(19): Trig = Wednesday, 19 February, 1992
[_h(14, "Adar")] MSG Purim
Entering UserFN _h(14, "Adar")
x => 14
y => "Adar"
hebdate(14, "Adar") => 1991/02/28
trigger(1991/02/28) => "28 February 1991"
Leaving UserFN _h() => "28 February 1991"
.\test.rem(20): Trig = Thursday, 28 February, 1991
[_h(15, "Nisan")] MSG Pesach
Entering UserFN _h(15, "Nisan")
x => 15
y => "Nisan"
hebdate(15, "Nisan") => 1991/03/30
trigger(1991/03/30) => "30 March 1991"
Leaving UserFN _h() => "30 March 1991"
.\test.rem(21): Trig = Saturday, 30 March, 1991
[_h(27, "Nisan")] MSG Yom HaShoah
Entering UserFN _h(27, "Nisan")
x => 27
y => "Nisan"
hebdate(27, "Nisan") => 1991/04/11
trigger(1991/04/11) => "11 April 1991"
Leaving UserFN _h() => "11 April 1991"
.\test.rem(22): Trig = Thursday, 11 April, 1991
[_h(4, "Iyar")] MSG Yom HaZikaron
Entering UserFN _h(4, "Iyar")
x => 4
y => "Iyar"
hebdate(4, "Iyar") => 1991/04/18
trigger(1991/04/18) => "18 April 1991"
Leaving UserFN _h() => "18 April 1991"
.\test.rem(23): Trig = Thursday, 18 April, 1991
[_h(5, "Iyar")] MSG Yom Ha'atzmaut
Entering UserFN _h(5, "Iyar")
x => 5
y => "Iyar"
hebdate(5, "Iyar") => 1991/04/19
trigger(1991/04/19) => "19 April 1991"
Leaving UserFN _h() => "19 April 1991"
.\test.rem(24): Trig = Friday, 19 April, 1991
[_h(28, "Iyar")] MSG Yom Yerushalayim
Entering UserFN _h(28, "Iyar")
x => 28
y => "Iyar"
hebdate(28, "Iyar") => 1991/05/12
trigger(1991/05/12) => "12 May 1991"
Leaving UserFN _h() => "12 May 1991"
.\test.rem(25): Trig = Sunday, 12 May, 1991
[_h(6, "Sivan")] MSG Shavuot
Entering UserFN _h(6, "Sivan")
x => 6
y => "Sivan"
hebdate(6, "Sivan") => 1991/05/19
trigger(1991/05/19) => "19 May 1991"
Leaving UserFN _h() => "19 May 1991"
.\test.rem(26): Trig = Sunday, 19 May, 1991
[_h(9, "Av")] MSG Tish'a B'Av
Entering UserFN _h(9, "Av")
x => 9
y => "Av"
hebdate(9, "Av") => 1991/07/20
trigger(1991/07/20) => "20 July 1991"
Leaving UserFN _h() => "20 July 1991"
.\test.rem(27): Trig = Saturday, 20 July, 1991
# Test some jahrzeit cases
fset _i(x,y,z,a) trigger(hebdate(x,y,z,a))
[_i(30, "Heshvan", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5759)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5759
hebdate(30, "Heshvan", 1991/02/16, 5759) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
.\test.rem(31): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5760)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5760
hebdate(30, "Heshvan", 1991/02/16, 5760) => 1991/11/07
trigger(1991/11/07) => "7 November 1991"
Leaving UserFN _i() => "7 November 1991"
.\test.rem(32): Trig = Thursday, 7 November, 1991
[_i(30, "Heshvan", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Heshvan", 1991/02/16, 5761)
x => 30
y => "Heshvan"
z => 1991/02/16
a => 5761
hebdate(30, "Heshvan", 1991/02/16, 5761) => .\test.rem(33): 30 Heshvan 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Kislev", today(), 5759)] MSG Complete-Complete
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5759)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5759
hebdate(30, "Kislev", 1991/02/16, 5759) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
.\test.rem(35): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5760)] MSG Complete-Defective
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5760)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5760
hebdate(30, "Kislev", 1991/02/16, 5760) => 1991/12/07
trigger(1991/12/07) => "7 December 1991"
Leaving UserFN _i() => "7 December 1991"
.\test.rem(36): Trig = Saturday, 7 December, 1991
[_i(30, "Kislev", today(), 5761)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Kislev", 1991/02/16, 5761)
x => 30
y => "Kislev"
z => 1991/02/16
a => 5761
hebdate(30, "Kislev", 1991/02/16, 5761) => .\test.rem(37): 30 Kislev 5761: Invalid Hebrew date
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(30, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5755)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(30, "Adar A", 1991/02/16, 5755) => 1992/03/05
trigger(1992/03/05) => "5 March 1992"
Leaving UserFN _i() => "5 March 1992"
.\test.rem(39): Trig = Thursday, 5 March, 1992
[_i(30, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(30, "Adar A", 1991/02/16, 5756)
x => 30
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(30, "Adar A", 1991/02/16, 5756) => .\test.rem(40): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
[_i(29, "Adar A", today(), 5755)] MSG Leap
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5755)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5755
hebdate(29, "Adar A", 1991/02/16, 5755) => 1991/03/15
trigger(1991/03/15) => "15 March 1991"
Leaving UserFN _i() => "15 March 1991"
.\test.rem(41): Trig = Friday, 15 March, 1991
[_i(29, "Adar A", today(), 5756)] MSG Illegal
today() => 1991/02/16
Entering UserFN _i(29, "Adar A", 1991/02/16, 5756)
x => 29
y => "Adar A"
z => 1991/02/16
a => 5756
hebdate(29, "Adar A", 1991/02/16, 5756) => .\test.rem(42): No Adar A in 5756
Invalid Hebrew date
Leaving UserFN _i() => Invalid Hebrew date
# Test each possible case of the basic reminders.
REM MSG Every Day
.\test.rem(46): Trig = Saturday, 16 February, 1991
Every Day
REM 18 MSG Every 18th
.\test.rem(48): Trig = Monday, 18 February, 1991
REM 15 MSG Every 15th
.\test.rem(49): Trig = Friday, 15 March, 1991
REM Feb MSG February
.\test.rem(51): Trig = Saturday, 16 February, 1991
February
REM Jan MSG January
.\test.rem(52): Trig = Wednesday, 1 January, 1992
REM March MSG March
.\test.rem(53): Trig = Friday, 1 March, 1991
REM 13 Jan MSG 13 Jan
.\test.rem(55): Trig = Monday, 13 January, 1992
REM 15 Feb MSG 15 Feb
.\test.rem(56): Trig = Saturday, 15 February, 1992
REM 28 Feb MSG 28 Feb
.\test.rem(57): Trig = Thursday, 28 February, 1991
REM 29 Feb MSG 29 Feb
.\test.rem(58): Trig = Saturday, 29 February, 1992
REM 5 Mar MSG 5 Mar
.\test.rem(59): Trig = Tuesday, 5 March, 1991
REM 1990 MSG 1990
.\test.rem(61): Expired
REM 1991 MSG 1991
.\test.rem(62): Trig = Saturday, 16 February, 1991
1991
REM 1992 MSG 1991
.\test.rem(63): Trig = Wednesday, 1 January, 1992
REM 1 1990 MSG 1 1990
.\test.rem(65): Expired
REM 29 1991 MSG 29 1991
.\test.rem(66): Trig = Friday, 29 March, 1991
REM 29 1992 MSG 29 1992
.\test.rem(67): Trig = Wednesday, 29 January, 1992
REM 16 1991 MSG 16 1991
.\test.rem(68): Trig = Saturday, 16 February, 1991
16 1991
REM Jan 1990 MSG Jan 1990
.\test.rem(70): Expired
REM Feb 1991 MSG Feb 1991
.\test.rem(71): Trig = Saturday, 16 February, 1991
Feb 1991
REM Dec 1991 MSG Dec 1991
.\test.rem(72): Trig = Sunday, 1 December, 1991
REM May 1992 MSG May 1992
.\test.rem(73): Trig = Friday, 1 May, 1992
REM 1 Jan 1991 MSG 1 Jan 1991
.\test.rem(75): Expired
REM 16 Feb 1991 MSG 16 Feb 1991
.\test.rem(76): Trig = Saturday, 16 February, 1991
16 Feb 1991
REM 29 Dec 1992 MSG 29 Dec 1992
.\test.rem(77): Trig = Tuesday, 29 December, 1992
REM Sun MSG Sun
.\test.rem(79): Trig = Sunday, 17 February, 1991
REM Fri Sat Tue MSG Fri Sat Tue
.\test.rem(80): Trig = Saturday, 16 February, 1991
Fri Sat Tue
REM Sun 16 MSG Sun 16
.\test.rem(82): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 MSG Mon Tue Wed Thu Fri 1
.\test.rem(83): Trig = Friday, 1 March, 1991
REM Sun Feb MSG Sun Feb
.\test.rem(85): Trig = Sunday, 17 February, 1991
REM Mon Tue March MSG Mon Tue March
.\test.rem(86): Trig = Monday, 4 March, 1991
REM Sun 16 Feb MSG Sun 16 Feb
.\test.rem(88): Trig = Sunday, 17 February, 1991
REM Mon Tue 10 March MSG Mon Tue 10 March
.\test.rem(89): Trig = Monday, 11 March, 1991
REM Sat Sun 1991 MSG Sat Sun 1991
.\test.rem(91): Trig = Saturday, 16 February, 1991
Sat Sun 1991
REM Mon Tue 1992 MSG Mon Tue 1992
.\test.rem(92): Trig = Monday, 6 January, 1992
REM Sun 16 1991 MSG Sun 16 1991
.\test.rem(94): Trig = Sunday, 17 February, 1991
REM Mon Tue Wed Thu Fri 1 1992 MSG Mon Tue Wed Thu Fri 1 1992
.\test.rem(95): Trig = Wednesday, 1 January, 1992
REM Mon Feb 1991 MSG Mon Feb 1991
.\test.rem(97): Trig = Monday, 18 February, 1991
REM Tue Jan 1992 MSG Tue Jan 1992
.\test.rem(98): Trig = Tuesday, 7 January, 1992
REM Sun Mon 16 Feb 1991 MSG Sun Mon 16 Feb 1991
.\test.rem(100): Trig = Sunday, 17 February, 1991
REM Tue 28 Jan 1992 MSG Tue 28 Jan 1992
.\test.rem(101): Trig = Tuesday, 28 January, 1992
# Try some Backs
CLEAR-OMIT-CONTEXT
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun
.\test.rem(105): Trig = Thursday, 28 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun
.\test.rem(106): Trig = Thursday, 28 February, 1991
OMIT 28 Feb
REM 1 -1 OMIT sat sun MSG 1 -1 OMIT Sat Sun (28 Feb omitted)
.\test.rem(109): Trig = Wednesday, 27 February, 1991
REM 1 --1 OMIT sat sun MSG 1 --1 OMIT Sat Sun (28 Feb omitted)
.\test.rem(110): Trig = Thursday, 28 February, 1991
CLEAR-OMIT-CONTEXT
# Try out UNTIL
REM Wed UNTIL 21 Feb 1991 MSG Wed UNTIL 21 Feb 1991
.\test.rem(115): Trig = Wednesday, 20 February, 1991
# Try playing with the OMIT context
OMIT 28 Feb 1991
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
.\test.rem(120): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
.\test.rem(121): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
.\test.rem(122): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
.\test.rem(123): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
.\test.rem(124): Trig = Friday, 1 March, 1991
PUSH-OMIT-CONTEXT
CLEAR-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1
.\test.rem(128): Trig = Thursday, 28 February, 1991
REM 1 Mar --1 MSG 1 mar --1
.\test.rem(129): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE
.\test.rem(130): Trig = Thursday, 28 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP
.\test.rem(131): Trig = Thursday, 28 February, 1991
REM 28 Feb AFTER MSG 28 Feb AFTER
.\test.rem(132): Trig = Thursday, 28 February, 1991
POP-OMIT-CONTEXT
REM 1 Mar -1 MSG 1 mar -1 (28feb91 omitted)
.\test.rem(135): Trig = Wednesday, 27 February, 1991
REM 1 Mar --1 MSG 1 mar --1 (28Feb91 omitted)
.\test.rem(136): Trig = Thursday, 28 February, 1991
REM 28 Feb BEFORE MSG 28 Feb BEFORE (28Feb91 omitted)
.\test.rem(137): Trig = Wednesday, 27 February, 1991
REM 28 Feb SKIP MSG 28 Feb SKIP (28Feb91 omitted)
.\test.rem(138): Trig = Friday, 28 February, 1992
REM 28 Feb AFTER MSG 28 Feb AFTER (28Feb91 omitted)
.\test.rem(139): Trig = Friday, 1 March, 1991
REM 13 March 1991 *1 UNTIL 19 March 1991 MSG 13-19 Mar 91
.\test.rem(142): Trig = Wednesday, 13 March, 1991
# Test BACK
CLEAR-OMIT-CONTEXT
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1
.\test.rem(146): Trig = Monday, 18 February, 1991
OMIT 17 Feb 1991
REM 18 Feb 1991 +1 MSG 18 Feb 1991 +1 (17Feb91 omitted)
.\test.rem(149): Trig = Monday, 18 February, 1991
18 Feb 1991 +1 (17Feb91 omitted)
REM 18 Feb 1991 ++1 MSG 18 Feb 1991 ++1 (17Feb91 omitted)
.\test.rem(150): Trig = Monday, 18 February, 1991
CLEAR-OMIT-CONTEXT
# Test the scanfrom clause
REM Fri SATISFY 1
.\test.rem(154): Trig = Friday, 22 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/22
trigger(1991/02/22) => "22 February 1991"
REM Fri after MSG 23 Feb 1991
.\test.rem(156): Trig = Saturday, 23 February, 1991
CLEAR-OMIT-CONTEXT
REM Fri SCANFROM [trigger(today()-7)] SATISFY 1
today() => 1991/02/16
1991/02/16 - 7 => 1991/02/09
trigger(1991/02/09) => "9 February 1991"
.\test.rem(158): Trig = Friday, 15 February, 1991
OMIT [trigger(trigdate())]
trigdate() => 1991/02/15
trigger(1991/02/15) => "15 February 1991"
REM Fri after MSG 16 Feb 1991
.\test.rem(160): Trig = Saturday, 16 February, 1991
16 Feb 1991
CLEAR-OMIT-CONTEXT
set a000 abs(1)
abs(1) => 1
set a001 abs(-1)
- 1 => -1
abs(-1) => 1
set a002 asc("foo")
asc("foo") => 102
set a003 baseyr()
baseyr() => 1990
set a004 char(66,55,66,77,66)
char(66, 55, 66, 77, 66) => "B7BMB"
set a005 choose(3, "foo", "bar", "baz", "blech")
choose(3, "foo", "bar", "baz", "blech") => "baz"
set a006 coerce("string", 1)
coerce("string", 1) => "1"
set a007 coerce("string", today())
today() => 1991/02/16
coerce("string", 1991/02/16) => "1991/02/16"
set a008 coerce("string", 11:44)
coerce("string", 11:44) => "11:44"
set a009 coerce("int", "badnews")
coerce("int", "badnews") => Can't coerce
.\test.rem(171): Can't coerce
set a010 coerce("int", "12")
coerce("int", "12") => 12
set a011 coerce("int", 11:44)
coerce("int", 11:44) => 704
set a012 coerce("int", today())
today() => 1991/02/16
coerce("int", 1991/02/16) => 411
set a013 date(1992, 2, 2)
date(1992, 2, 2) => 1992/02/02
set a014 date(1993, 2, 29)
date(1993, 2, 29) => Bad date specification
.\test.rem(176): Bad date specification
set a015 day(today())
today() => 1991/02/16
day(1991/02/16) => 16
set a016 daysinmon(2, 1991)
daysinmon(2, 1991) => 28
set a017 daysinmon(2, 1992)
daysinmon(2, 1992) => 29
set a018 defined("a017")
defined("a017") => 1
set a019 defined("a019")
defined("a019") => 0
set a020 filename()
filename() => ".\test.rem"
set a021 getenv("TEST_GETENV")
getenv("TEST_GETENV") => "foo bar baz"
set a022 hour(11:22)
hour(11:22) => 11
set a023 iif(1, 1, 0)
iif(1, 1, 0) => 1
set a024 iif(0, 1, 0)
iif(0, 1, 0) => 0
set a025 index("barfoobar", "foo")
index("barfoobar", "foo") => 4
set a026 index("barfoobar", "bar", 2)
index("barfoobar", "bar", 2) => 7
set a027 isleap(today())
today() => 1991/02/16
isleap(1991/02/16) => 0
set a028 isleap(1992)
isleap(1992) => 1
omit [trigger(today())]
today() => 1991/02/16
trigger(1991/02/16) => "16 February 1991"
set a030 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 1
clear
set a029 isomitted(today())
today() => 1991/02/16
isomitted(1991/02/16) => 0
set a031 lower("FOOBARBAZ")
lower("FOOBARBAZ") => "foobarbaz"
set a032 max(1, 2, 34, 1, 3)
max(1, 2, 34, 1, 3) => 34
set a033 max("foo", "bar", "baz")
max("foo", "bar", "baz") => "foo"
set a034 max(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
max(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/17
set a035 min(1, 2, 34, 1, 3)
min(1, 2, 34, 1, 3) => 1
set a036 min("foo", "bar", "baz")
min("foo", "bar", "baz") => "bar"
set a037 min(today(), today()+1, today()-1)
today() => 1991/02/16
today() => 1991/02/16
1991/02/16 + 1 => 1991/02/17
today() => 1991/02/16
1991/02/16 - 1 => 1991/02/15
min(1991/02/16, 1991/02/17, 1991/02/15) => 1991/02/15
set a038 minute(11:33)
minute(11:33) => 33
set a039 mon(today())
today() => 1991/02/16
mon(1991/02/16) => "February"
set a040 monnum(today())
today() => 1991/02/16
monnum(1991/02/16) => 2
set a041 ord(3)
ord(3) => "3rd"
set a042 ord(4)
ord(4) => "4th"
set a043 ostype()
ostype() => "OS/2"
set a044 plural(2)
plural(2) => "s"
set a045 plural(2, "ies")
plural(2, "ies") => "iess"
set a046 plural(2, "y", "ies")
plural(2, "y", "ies") => "ies"
set a047 sgn(-2)
- 2 => -2
sgn(-2) => -1
set a048 shell("echo foo")
shell("echo foo") => "foo"
set a049 strlen("sadjflkhsldkfhsdlfjhk")
strlen("sadjflkhsldkfhsdlfjhk") => 21
set a050 substr(a049, 2)
a049 => 21
substr(21, 2) => Type mismatch
.\test.rem(214): Type mismatch
set a051 substr(a050, 2, 6)
a050 => .\test.rem(215): Undefined variable: a050
set a052 time(1+2, 3+4)
1 + 2 => 3
3 + 4 => 7
time(3, 7) => 03:07
rem 10 jan 1992 AT 11:22 CAL
.\test.rem(217): Trig = Friday, 10 January, 1992
set a053 trigdate()
trigdate() => 1992/01/10
set a054 trigtime()
trigtime() => 11:22
set a055 trigvalid()
trigvalid() => 1
set a056 upper("sdfjhsdf ksjdfh kjsdfh ksjdfh")
upper("sdfjhsdf ksjdfh kjsdfh ksjdfh") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a057 value("a05"+"6")
"a05" + "6" => "a056"
value("a056") => "SDFJHSDF KSJDFH KJSDFH KSJDFH"
set a058 version()
version() => "03.00.13"
set a059 wkday(today())
today() => 1991/02/16
wkday(1991/02/16) => "Saturday"
set a060 wkdaynum(today())
today() => 1991/02/16
wkdaynum(1991/02/16) => 6
set a061 year(today())
today() => 1991/02/16
year(1991/02/16) => 1991
set a062 1+2*(3+4-(5*7/2))
3 + 4 => 7
5 * 7 => 35
35 / 2 => 17
7 - 17 => -10
2 * -10 => -20
1 + -20 => -19
set a063 1>=2
1 >= 2 => 0
set a064 1<2 || 3 > 4
1 < 2 => 1
3 > 4 => 0
1 || 0 => 1
set a065 1 && 1
1 && 1 => 1
set a066 !a065
a065 => 1
! 1 => 0
set a067 typeof(2)
typeof(2) => "INT"
set a068 typeof("foo")
typeof("foo") => "STRING"
set a069 typeof(11:33)
typeof(11:33) => "TIME"
set a070 typeof(today())
today() => 1991/02/16
typeof(1991/02/16) => "DATE"
fset g(x,y) max(x,y)
fset h(x,y) min(g(x+y, x*y), g(x-y, x/y))
set a071 g(1, 2)
Entering UserFN g(1, 2)
x => 1
y => 2
max(1, 2) => 2
Leaving UserFN g() => 2
set a072 h(2, 3)
Entering UserFN h(2, 3)
x => 2
y => 3
2 + 3 => 5
x => 2
y => 3
2 * 3 => 6
Entering UserFN g(5, 6)
x => 5
y => 6
max(5, 6) => 6
Leaving UserFN g() => 6
x => 2
y => 3
2 - 3 => -1
x => 2
y => 3
2 / 3 => 0
Entering UserFN g(-1, 0)
x => -1
y => 0
max(-1, 0) => 0
Leaving UserFN g() => 0
min(6, 0) => 0
Leaving UserFN h() => 0
set a073 h("foo", 11:33)
Entering UserFN h("foo", 11:33)
x => "foo"
y => 11:33
"foo" + 11:33 => "foo11:33"
x => "foo"
y => 11:33
"foo" * 11:33 => Type mismatch
.\test.rem(240): '*': Type mismatch
Leaving UserFN h() => Type mismatch
set a074 dosubst("%a %b %c %d %e %f %g %h", '1992/5/5')
dosubst("%a %b %c %d %e %f %g %h", 1992/05/05) => "on Tuesday, 5 May, 1992 in 444 days' tim"...
msg [a074]%
.\test.rem(242): Trig = Saturday, 16 February, 1991
a074 => "on Tuesday, 5 May, 1992 in 444 days' tim"...
on Tuesday, 5 May, 1992 in 444 days' time on Tuesday 5 on 05/05/1992 on 05/05/1992 on Tuesday, 5 May on 05/05
set a075 dosubst("%i %j %k %l %m %n %o %p", '1992/5/5')
dosubst("%i %j %k %l %m %n %o %p", 1992/05/05) => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
msg [a075]%
.\test.rem(244): Trig = Saturday, 16 February, 1991
a075 => "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
on 05/05 on Tuesday, May 5th, 1992 on Tuesday, May 5th on 1992/05/05 May 5 s
set a076 dosubst("%q %r %s %t %u %v %w %x", '1992/5/5')
dosubst("%q %r %s %t %u %v %w %x", 1992/05/05) => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
msg [a076]%
.\test.rem(246): Trig = Saturday, 16 February, 1991
a076 => "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
s' 05 th 05 on Tuesday, 5th May, 1992 on Tuesday, 5th May Tuesday 444
set a077 dosubst("%y %z", '1992/5/5')
dosubst("%y %z", 1992/05/05) => "1992 92
"
msg [a077]%
.\test.rem(248): Trig = Saturday, 16 February, 1991
a077 => "1992 92
"
1992 92
set a078 easterdate(today())
today() => 1991/02/16
easterdate(1991/02/16) => 1991/03/31
set a079 easterdate(1992)
easterdate(1992) => 1992/04/19
set a080 easterdate(1995)
easterdate(1995) => 1995/04/16
set a081 ""
dump
Variable Value
a017 29
a036 "bar"
a055 1
a074 "on Tuesday, 5 May, 1992 in 444 days' tim"...
a008 "11:44"
a027 0
a046 "ies"
a065 1
a018 1
a037 1991/02/15
a056 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a075 "on 05/05 on Tuesday, May 5th, 1992 on Tu"...
a028 1
a047 -1
a066 0
a019 0
a038 33
a057 "SDFJHSDF KSJDFH KJSDFH KSJDFH"
a076 "s' 05 th 05 on Tuesday, 5th May, 1992 on"...
a029 0
a048 "foo"
a067 "INT"
a039 "February"
a058 "03.00.13"
a077 "1992 92
"
a049 21
a068 "STRING"
a059 "Saturday"
a078 1991/03/31
a069 "TIME"
a079 1992/04/19
a000 1
a010 12
a001 1
a020 ".\test.rem"
a011 704
a030 1
a002 102
a021 "foo bar baz"
a040 2
a012 411
a031 "foobarbaz"
a003 1990
a022 11
a041 "3rd"
a060 6
a013 1992/02/02
a032 34
a070 "DATE"
a004 "B7BMB"
a023 1
a042 "4th"
a061 1991
a080 1995/04/16
a033 "foo"
a052 03:07
a071 2
a005 "baz"
a024 0
a043 "OS/2"
a062 -19
a081 ""
a015 16
a034 1991/02/17
a053 1992/01/10
a072 0
a006 "1"
a025 4
a044 "s"
a063 0
a016 28
a035 1
a054 11:22
a007 "1991/02/16"
a026 7
a045 "iess"
a064 1

350
token.c Normal file
View File

@@ -0,0 +1,350 @@
/***************************************************************/
/* */
/* TOKEN.C */
/* */
/* Contains routines for parsing the reminder file and */
/* classifying the tokens parsed. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: token.c,v 1.1 1996-03-27 03:26:13 dfs Exp $";
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "types.h"
#include "globals.h"
#include "protos.h"
#include "err.h"
/* The macro PARSENUM parses a char pointer as an integer. It simply
executes 'return' if an initial non-numeric char is found. */
#define PARSENUM(var, string) \
if (!isdigit(*(string))) return; \
var = 0; \
while (isdigit(*(string))) { \
var *= 10; \
var += *(string) - '0'; \
string++; \
}
#define UPPER(c) (islower(c) ? toupper(c) : c)
/* The big array holding all recognized (literal) tokens in reminder file.
Keep this array sorted, or software will not work. */
Token TokArray[] = {
/* NAME MINLEN TYPE VALUE */
{ "after", 3, T_Skip, AFTER_SKIP },
{ "april", 3, T_Month, 3 },
{ "at", 2, T_At, 0 },
{ "august", 3, T_Month, 7 },
{ "banner", 3, T_Banner, 0 },
{ "before", 3, T_Skip, BEFORE_SKIP },
{ "cal", 3, T_RemType, CAL_TYPE },
{ "clear-omit-context", 5, T_Clr, 0 },
{ "debug", 5, T_Debug, 0 },
{ "december", 3, T_Month, 11 },
{ "dumpvars", 4, T_Dumpvars, 0 },
{ "else", 4, T_Else, 0 },
{ "endif", 5, T_EndIf, 0 },
{ "errmsg", 6, T_ErrMsg, 0 },
{ "exit", 4, T_Exit, 0 },
{ "february", 3, T_Month, 1 },
{ "flush", 5, T_Flush, 0 },
{ "friday", 3, T_WkDay, 4 },
{ "fset", 4, T_Fset, 0 },
{ "if", 2, T_If, 0 },
{ "iftrig", 6, T_IfTrig, 0 },
{ "include", 3, T_Include, 0 },
{ "january", 3, T_Month, 0 },
{ "july", 3, T_Month, 6 },
{ "june", 3, T_Month, 5 },
{ "march", 3, T_Month, 2 },
{ "may", 3, T_Month, 4 },
{ "monday", 3, T_WkDay, 0 },
{ "msf", 3, T_RemType, MSF_TYPE },
{ "msg", 3, T_RemType, MSG_TYPE },
{ "november", 3, T_Month, 10 },
{ "october", 3, T_Month, 9 },
{ "omit", 3, T_Omit, 0 },
{ "once", 3, T_Once, 0 },
{ "pop-omit-context", 3, T_Pop, 0 },
{ "preserve", 8, T_Preserve, 0 },
{ "priority", 8, T_Priority, 0 },
{ "ps", 2, T_RemType, PS_TYPE },
{ "psfile", 6, T_RemType, PSF_TYPE },
{ "push-omit-context", 4, T_Push, 0 },
{ "rem", 3, T_Rem, 0 },
{ "run", 3, T_RemType, RUN_TYPE },
{ "satisfy", 7, T_RemType, SAT_TYPE },
{ "saturday", 3, T_WkDay, 5 },
{ "scanfrom", 4, T_Scanfrom, 0 },
{ "sched", 5, T_Sched, 0 },
{ "september", 3, T_Month, 8 },
{ "set", 3, T_Set, 0 },
{ "skip", 3, T_Skip, SKIP_SKIP },
{ "sunday", 3, T_WkDay, 6 },
{ "thursday", 3, T_WkDay, 3 },
{ "tuesday", 3, T_WkDay, 1 },
{ "unset", 5, T_UnSet, 0 },
{ "until", 3, T_Until, 0 },
{ "wednesday", 3, T_WkDay, 2 }
};
/* If language != English, we must also search the following... */
#if LANG != ENGLISH
Token NonEnglishToks[] = {
/* NAME MINLEN TYPE VALUE */
{ L_MONDAY, 3, T_WkDay, 0 },
{ L_TUESDAY, 3, T_WkDay, 1 },
{ L_WEDNESDAY, 3, T_WkDay, 2 },
{ L_THURSDAY, 3, T_WkDay, 3 },
{ L_FRIDAY, 3, T_WkDay, 4 },
{ L_SATURDAY, 3, T_WkDay, 5 },
{ L_SUNDAY, 3, T_WkDay, 6 },
{ L_JAN, 3, T_Month, 0 },
{ L_FEB, 3, T_Month, 1 },
{ L_MAR, 3, T_Month, 2 },
{ L_APR, 3, T_Month, 3 },
{ L_MAY, 3, T_Month, 4 },
{ L_JUN, 3, T_Month, 5 },
{ L_JUL, 3, T_Month, 6 },
{ L_AUG, 3, T_Month, 7 },
{ L_SEP, 3, T_Month, 8 },
{ L_OCT, 3, T_Month, 9 },
{ L_NOV, 3, T_Month, 10 },
{ L_DEC, 3, T_Month, 11 }
};
#endif
PRIVATE int TokStrCmp ARGS((const Token *t, const char *s));
/***************************************************************/
/* */
/* FindInitialToken */
/* */
/* Find the initial token on the command line. If it's a */
/* left square bracket, return a T_Illegal type. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *FindInitialToken(Token *tok, char *s)
#else
char *FindInitialToken(tok, s)
Token *tok;
char *s;
#endif
{
char *t;
int len=0;
while (isspace(*s)) s++;
t = TokBuffer;
while (*s && !isspace(*s)) {
if (len < TOKSIZE) {
*t++ = *s++;
len++;
}else s++;
}
*t = 0;
FindToken(TokBuffer, tok);
return s;
}
/***************************************************************/
/* */
/* FindToken */
/* */
/* Given a string, which token is it? */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void FindToken(const char *s, Token *tok)
#else
void FindToken(s, tok)
char *s;
Token *tok;
#endif
{
register int top, bot, mid, r;
int l;
tok->type = T_Illegal;
if (! *s) {
tok->type = T_Empty;
return;
}
if (*s == '#' || *s == ';') {
tok->type = T_Comment;
return;
}
/* Quickly give up the search if first char not a letter */
if ( ! isalpha(*s)) {
FindNumericToken(s, tok);
return;
}
l = strlen(s);
bot = 0;
top = sizeof(TokArray) / sizeof(TokArray[0]) - 1;
while(top >= bot) {
mid = (top + bot) / 2;
r = TokStrCmp(&TokArray[mid], s);
if (!r) {
if (l >= TokArray[mid].MinLen) {
tok->type = TokArray[mid].type;
tok->val = TokArray[mid].val;
return;
} else {
while (mid && !TokStrCmp(&TokArray[mid-1],s)) mid--;
while (!TokStrCmp(&TokArray[mid], s) && l < TokArray[mid].MinLen)
mid++;
if (!TokStrCmp(&TokArray[mid], s)) {
tok->type = TokArray[mid].type;
tok->val = TokArray[mid].val;
return;
}
}
break;
}
if (r > 0) top = mid-1; else bot=mid+1;
}
/* If language is other than English, search the DayNames[] and MonthNames[]
array. */
#if LANG != ENGLISH
for (r=0; r<(sizeof(NonEnglishToks) / sizeof(Token)); r++) {
if (l >= NonEnglishToks[r].MinLen &&
!TokStrCmp(&NonEnglishToks[r], s)) {
tok->type = NonEnglishToks[r].type;
tok->val = NonEnglishToks[r].val;
return;
}
}
#endif
return;
}
/***************************************************************/
/* */
/* FindNumericToken */
/* */
/* Parse a numeric token: */
/* Year - number between 1990 and 2085, or 90-99. */
/* Day - number between 1 and 31 */
/* Delta - +[+]n */
/* Back - -[-]n */
/* Rep - *n */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void FindNumericToken(const char *s, Token *t)
#else
void FindNumericToken(s, t)
char *s;
Token *t;
#endif
{
int mult = 1, hour, min;
t->type = T_Illegal;
t->val = 0;
if (isdigit(*s)) {
PARSENUM(t->val, s);
/* If we hit a colon or a period, we've probably got a time hr:min */
if (*s == ':' || *s == '.' || *s == TIMESEP) {
s++;
hour = t->val;
PARSENUM(min, s);
if (*s || hour > 23 || min > 59) return; /* Illegal time */
t->val = hour*60 + min; /* Convert to minutes past midnight */
t->type = T_Time;
return;
}
/* If we hit a non-digit, error! */
if (*s) return;
/* Special hack - convert years between 90 and 99 to 1990 and 1999 */
if (t->val >= 90 && t->val <= 99) t->val += 1900;
/* Classify the number we've got */
if (t->val >= BASE && t->val <= BASE+YR_RANGE) t->type = T_Year;
else if (t->val >= 1 && t->val <= 31) t->type = T_Day;
else t->type = T_Number;
return;
} else if (*s == '*') {
s++;
PARSENUM(t->val, s);
if (*s) return; /* Illegal token if followed by non-numeric char */
t->type = T_Rep;
return;
} else if (*s == '+') {
s++;
if (*s == '+') { mult = -1; s++; }
PARSENUM(t->val, s);
if (*s) return; /* Illegal token if followed by non-numeric char */
t->type = T_Delta;
t->val *= mult;
return;
} else if (*s == '-') {
s++;
if (*s == '-') { mult = -1; s++; }
PARSENUM(t->val, s);
if (*s) return; /* Illegal token if followed by non-numeric char */
t->type = T_Back;
t->val *= mult;
return;
}
return; /* Unknown token type */
}
/***************************************************************/
/* */
/* TokStrCmp */
/* */
/* Compare a token to a string. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int TokStrCmp(const Token *t, const char *s)
#else
static int TokStrCmp(t, s)
Token *t;
char *s;
#endif
{
register int r;
char *tk = t->name;
while(*tk && *s) {
r = UPPER(*tk) - UPPER(*s);
tk++;
s++;
if (r) return r;
}
if (!*s) return 0;
return (*tk - *s);
}

469
trigger.c Normal file
View File

@@ -0,0 +1,469 @@
/***************************************************************/
/* */
/* TRIGGER.C */
/* */
/* Routines for figuring out the trigger date of a reminder */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: trigger.c,v 1.1 1996-03-27 03:26:14 dfs Exp $";
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "types.h"
#include "expr.h"
#include "protos.h"
#include "globals.h"
#include "err.h"
#define GOT_DAY 1
#define GOT_MON 2
#define GOT_YR 4
#define GOT_WD 8
static int JYear ARGS((int jul));
static int JMonth ARGS((int jul));
static int NextSimpleTrig ARGS((int startdate, Trigger *trig, int *err));
static int GetNextTriggerDate ARGS((Trigger *trig, int start, int *err, int *nextstart));
/***************************************************************/
/* */
/* NextSimpleTrig */
/* */
/* Compute the "simple" trigger date, taking into account */
/* ONLY the day of week, day, month and year components. */
/* Normally, returns -1 if the trigger has expired. As a */
/* special case, if D, M, Y [WD] are specified, returns the */
/* Julian date, regardless of whether it's expired. This is */
/* so that dates with a REP can be handled properly. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int NextSimpleTrig(int startdate, Trigger *trig, int *err)
#else
static int NextSimpleTrig(startdate, trig, err)
int startdate;
Trigger *trig;
int *err;
#endif
{
int typ = 0;
int d, m, y, j, d2, m2, y2;
*err = 0;
FromJulian(startdate, &y, &m, &d);
d2 = d;
m2 = m;
y2 = y;
if (trig->d != NO_DAY) typ |= GOT_DAY;
if (trig->m != NO_MON) typ |= GOT_MON;
if (trig->y != NO_YR) typ |= GOT_YR;
if (trig->wd != NO_WD) typ |= GOT_WD;
switch(typ) {
case 0:
case GOT_WD:
if (trig->wd != NO_WD)
while(! (trig->wd & (1 << (startdate%7)))) startdate++;
return startdate;
case GOT_DAY:
if (d > trig->d) {
m++;
if (m == 12) { m = 0; y++; }
}
while (trig->d > DaysInMonth(m, trig->y)) m++;
j = Julian(y, m, trig->d);
return j;
case GOT_MON:
if (m == trig->m) return startdate;
else if (m > trig->m) return Julian(y+1, trig->m, 1);
else return Julian(y, trig->m, 1);
case GOT_YR:
if (y == trig->y) return startdate;
else if (y < trig->y) return Julian(trig->y, 0, 1);
else return -1;
case GOT_DAY+GOT_MON:
if (m > trig->m || (m == trig->m && d > trig->d)) y++;
if (trig->d > MonthDays[trig->m]) {
*err = E_BAD_DATE;
return -1;
}
/* Take care of Feb. 29 */
while (trig->d > DaysInMonth(trig->m, y)) y++;
return Julian(y, trig->m, trig->d);
case GOT_DAY+GOT_YR:
if (y < trig->y) return Julian(trig->y, 0, trig->d);
else if (y > trig->y) return -1;
if (d > trig->d) {
m++;
if (m == 12) return -1;
}
while (trig->d > DaysInMonth(m, trig->y)) m++;
return Julian(trig->y, m, trig->d);
case GOT_MON+GOT_YR:
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
if (y < trig->y) return Julian(trig->y, trig->m, 1);
if (m == trig->m) return startdate;
return Julian(trig->y, trig->m, 1);
case GOT_DAY+GOT_MON+GOT_YR:
if (trig->d > DaysInMonth(trig->m, trig->y)) {
*err = E_BAD_DATE;
return -1;
}
return Julian(trig->y, trig->m, trig->d);
case GOT_YR+GOT_WD:
if (y > trig->y) return -1;
if (y < trig->y) j = Julian(trig->y, 0, 1);
else j = startdate;
while(! (trig->wd & (1 << (j%7)))) j++;
if (JYear(j) > trig->y) return -1;
return j;
case GOT_MON+GOT_WD:
if (m == trig->m) {
j = startdate;
while(! (trig->wd & (1 << (j%7)))) j++;
if (JMonth(j) == trig->m) return j;
}
if (m >= trig->m) j = Julian(y+1, trig->m, 1);
else j = Julian(y, trig->m, 1);
while(! (trig->wd & (1 << (j%7)))) j++;
return j; /* Guaranteed to be within the month */
case GOT_DAY+GOT_WD:
if (m !=0 || y > BASE) {
m2 = m-1;
if (m2 < 0) { y2 = y-1; m2 = 11; }
/* If there are fewer days in previous month, no match */
if (trig->d <= DaysInMonth(m2, y2)) {
j = Julian(y2, m2, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
}
}
/* Try this month */
if (trig->d <= DaysInMonth(m, y)) {
j = Julian(y, m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
}
/* Argh! Try next avail. month */
m2 = m+1;
if (m2 > 11) { m2 = 0; y++; }
while (trig->d > DaysInMonth(m2, y)) m2++;
j = Julian(y, m2, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
case GOT_WD+GOT_YR+GOT_DAY:
if (y > trig->y+1 || (y > trig->y && m>0)) return -1;
if (y > trig->y) {
j = Julian(trig->y, 11, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
} else if (y < trig->y) {
j = Julian(trig->y, 0, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
} else {
/* Try last month */
if (m > 0) {
m2 = m-1;
while (trig->d > DaysInMonth(m2, trig->y)) m2--;
j = Julian(trig->y, m2, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
}
}
/* Try this month */
if (trig->d <= DaysInMonth(m, trig->y)) {
j = Julian(trig->y, m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
}
/* Must be next month */
if (m == 11) return -1;
m++;
while (trig->d > DaysInMonth(m, trig->d)) m++;
j = Julian(trig->y, m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
case GOT_DAY+GOT_MON+GOT_WD:
/* Move up to the first valid year */
while (trig->d > DaysInMonth(trig->m, y)) y++;
/* Try this year */
j = Julian(y, trig->m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
if (j >= startdate) return j;
/* Must be next year */
y = y + 1;
while (trig->d > DaysInMonth(trig->m, y)) y++;
j = Julian(y, trig->m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
case GOT_WD+GOT_MON+GOT_YR:
if (y > trig->y || (y == trig->y && m > trig->m)) return -1;
if (trig->y > y || (trig->y == y && trig->m > m)) {
j = Julian(trig->y, trig->m, 1);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
} else {
j = startdate;
while(! (trig->wd & (1 << (j%7)))) j++;
FromJulian(j, &y2, &m2, &d2);
if (m2 == trig->m) return j; else return -1;
}
case GOT_WD+GOT_DAY+GOT_MON+GOT_YR:
j = Julian(trig->y, trig->m, trig->d);
while(! (trig->wd & (1 << (j%7)))) j++;
return j;
default:
Eprint("NextSimpleTrig %s %d", ErrMsg[E_SWERR], typ);
*err = E_SWERR;
return -1;
}
}
/***************************************************************/
/* */
/* JMonth - Given a Julian date, what's the month? */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int JMonth(int jul)
#else
static int JMonth(jul)
int jul;
#endif
{
int y, m, d;
FromJulian(jul, &y, &m, &d);
return m;
}
/***************************************************************/
/* */
/* JYear - Given a Julian date, what's the year? */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int JYear(int jul)
#else
static int JYear(jul)
int jul;
#endif
{
int y, m, d;
FromJulian(jul, &y, &m, &d);
return y;
}
/***************************************************************/
/* */
/* GetNextTriggerDate */
/* */
/* Given a trigger, compute the next trigger date. */
/* */
/* Returns the Julian date of next trigger, -1 if */
/* expired, -2 if can't compute trigger date. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int GetNextTriggerDate(Trigger *trig, int start, int *err, int *nextstart)
#else
static int GetNextTriggerDate(trig, start, err, nextstart)
Trigger *trig;
int start;
int *err;
int *nextstart;
#endif
{
int simple, mod;
/* First: Have we passed the UNTIL date? */
if (trig->until != NO_UNTIL &&
trig->until < start) return -1; /* expired */
/* Next: If it's an "AFTER"-type skip, back up
until we're at the start of a block of holidays */
if (trig->skip == AFTER_SKIP)
while (IsOmitted(start-1, trig->localomit)) start--;
/* Find the next simple trigger */
simple = NextSimpleTrig(start, trig, err);
/* Problems? */
if (*err || (simple == -1)) return -1;
/* Suggested starting point for next attempt */
*nextstart = simple+1;
/* If there's a BACK, back up... */
if (trig->back != NO_BACK) {
mod = trig->back;
if (mod < 0) simple += mod;
else
while(mod) {
simple--;
if (!IsOmitted(simple, trig->localomit)) mod--;
}
}
/* If there's a REP, calculate the next occurrence */
if (trig->rep != NO_REP) {
if (simple < start) {
mod = (start - simple) / trig->rep;
simple = simple + mod * trig->rep;
if (simple < start) simple += trig->rep;
}
}
/* If it's a "BEFORE"-type skip, back up */
if (trig->skip == BEFORE_SKIP)
while(IsOmitted(simple, trig->localomit)) simple--;
/* If it's an "AFTER"-type skip, jump ahead */
if (trig->skip == AFTER_SKIP)
while (IsOmitted(simple, trig->localomit)) simple++;
/* Return the date */
return simple;
}
/***************************************************************/
/* */
/* ComputeTrigger */
/* */
/* The main function. Compute the next trigger date given */
/* today's date. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int ComputeTrigger(int today, Trigger *trig, int *err)
#else
int ComputeTrigger(today, trig, err)
int today;
Trigger *trig;
int *err;
#endif
{
int nattempts = 0,
start = today,
nextstart,
y, m, d,
result;
LastTrigValid = 0;
/* Assume everything works */
*err = OK;
/* But check for obvious problems... */
if (trig->localomit == 1 + 2 + 4 + 8 + 16 + 32 + 64) {
*err = E_2MANY_LOCALOMIT;
return -1;
}
if (trig->rep != NO_REP &&
(trig->d == NO_DAY ||
trig->m == NO_MON ||
trig->y == NO_YR)) {
Eprint("%s", ErrMsg[E_REP_FULSPEC]);
*err = E_REP_FULSPEC;
return -1;
}
while (nattempts++ < TRIG_ATTEMPTS) {
result = GetNextTriggerDate(trig, start, err, &nextstart);
/* If there's an error, die immediately */
if (*err) return -1;
if (result == -1) {
if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%d): %s\n",
FileName, LineNo, ErrMsg[E_EXPIRED]);
}
return -1;
}
/* If result is >= today, great! */
if (result >= today &&
(trig->skip != SKIP_SKIP || !IsOmitted(result, trig->localomit))) {
LastTriggerDate = result; /* Save in global var */
LastTrigValid = 1;
if (DebugFlag & DB_PRTTRIG) {
FromJulian(result, &y, &m, &d);
fprintf(ErrFp, "%s(%d): Trig = %s, %d %s, %d\n",
FileName, LineNo,
DayName[result % 7],
d,
MonthName[m],
y);
}
return result;
}
/* If it's a simple trigger, no point in rescanning */
if (trig->back == NO_BACK &&
trig->skip == NO_SKIP &&
trig->rep == NO_REP) {
if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%d): %s\n",
FileName, LineNo, ErrMsg[E_EXPIRED]);
}
if (result != -1) {
LastTriggerDate = result;
LastTrigValid = 1;
}
return -1;
}
/* Keep scanning... unless there's no point in doing it.*/
if (nextstart <= start) {
if (result != -1) {
LastTriggerDate = result;
LastTrigValid = 1;
}
if (DebugFlag & DB_PRTTRIG) {
fprintf(ErrFp, "%s(%d): %s\n",
FileName, LineNo, ErrMsg[E_EXPIRED]);
}
return -1;
}
else start = nextstart;
}
/* We failed - too many attempts or trigger has expired*/
*err = E_CANT_TRIG;
return -1;
}

202
tstlang.rem Normal file
View File

@@ -0,0 +1,202 @@
#!remind -rq
# ---------------------------------------------------------------------------
#
# TSTLANG.REM
#
# $Id: tstlang.rem,v 1.1 1996-03-27 03:26:14 dfs Exp $
#
# Use this file to test new language headers you may want to create.
# Usage: remind -rq tstlang.rem
#
# Don't run it within about 2 hours of midnight (ie, between 10pm and 2am)
#
# Use the output to verify your translations.
#
# This file is part of REMIND.
# Copyright (C) 1992-1996 by David F. Skoll
#
# ---------------------------------------------------------------------------
if version()<"03.00.08"
errmsg %
errmsg This file only works with Remind version 03.00.08 and later - aborting
exit
endif
if !$RunOff || !$DontQueue || $DontTrigAts
errmsg %
errmsg Please run [filename()] with the -q and -r options, but%
errmsg not the -a option.
exit
endif
# Set up a few useful definitions
fset show(x) "%%" + x + " yields: " + char(34) + "%" + x + char(34) + "%"
set a trigger(today()+2) + " ++2"
set l language()
set tt now()+134
set tu now()-134
set d a + " at " + tt
set e a + " at " + tu
msg The above is the default banner for the [l] language.
msg The following are the two-day-in-advance substitutions:%
[a] msg [show("a")]
[a] msg [show("b")]
[a] msg [show("c")]
[a] msg [show("d")]
[a] msg [show("e")]
[a] msg [show("f")]
[a] msg [show("g")]
[a] msg [show("h")]
[a] msg [show("i")]
[a] msg [show("j")]
[a] msg [show("k")]
[a] msg [show("l")]
[a] msg [show("m")]
[a] msg [show("n")]
[a] msg [show("o")]
[a] msg [show("p")]
[a] msg [show("q")]
[a] msg [show("r")]
[a] msg [show("s")]
[a] msg [show("t")]
[a] msg [show("u")]
[a] msg [show("v")]
[a] msg [show("w")]
[a] msg [show("x")]
[a] msg [show("y")]
[a] msg [show("z")]
msg %_%_The following are the one-day-in-advance substitutions:%
set a trigger(today()+1) + " ++1"
set d a + " at " + tt
set e a + " at " + tu
[a] msg [show("a")]
[a] msg [show("b")]
[a] msg [show("c")]
[a] msg [show("d")]
[a] msg [show("e")]
[a] msg [show("f")]
[a] msg [show("g")]
[a] msg [show("h")]
[a] msg [show("i")]
[a] msg [show("j")]
[a] msg [show("k")]
[a] msg [show("l")]
[a] msg [show("m")]
[a] msg [show("n")]
[a] msg [show("o")]
[a] msg [show("p")]
[a] msg [show("q")]
[a] msg [show("r")]
[a] msg [show("s")]
[a] msg [show("t")]
[a] msg [show("u")]
[a] msg [show("v")]
[a] msg [show("w")]
[a] msg [show("x")]
[a] msg [show("y")]
[a] msg [show("z")]
msg %_%_The following are the current-day substitutions:%
set a trigger(today())
set d a + " at " + tt
set e a + " at " + tu
[a] msg [show("a")]
[a] msg [show("b")]
[a] msg [show("c")]
[a] msg [show("d")]
[a] msg [show("e")]
[a] msg [show("f")]
[a] msg [show("g")]
[a] msg [show("h")]
[a] msg [show("i")]
[a] msg [show("j")]
[a] msg [show("k")]
[a] msg [show("l")]
[a] msg [show("m")]
[a] msg [show("n")]
[a] msg [show("o")]
[a] msg [show("p")]
[a] msg [show("q")]
[a] msg [show("r")]
[a] msg [show("s")]
[a] msg [show("t")]
[a] msg [show("u")]
[a] msg [show("v")]
[a] msg [show("w")]
[a] msg [show("x")]
[a] msg [show("y")]
[a] msg [show("z")]
msg %_Time substititions for a time in the future:%
[d] msg [show("1")]
[d] msg [show("2")]
[d] msg [show("3")]
[d] msg [show("4")]
[d] msg [show("5")]
[d] msg [show("6")]
[d] msg [show("7")]
[d] msg [show("8")]
[d] msg [show("9")]
[d] msg [show("0")]
[d] msg [show("!")]
[d] msg [show("@")]
[d] msg [show("#")]
msg %_Time substititions for a time in the past:%
[e] msg [show("1")]
[e] msg [show("2")]
[e] msg [show("3")]
[e] msg [show("4")]
[e] msg [show("5")]
[e] msg [show("6")]
[e] msg [show("7")]
[e] msg [show("8")]
[e] msg [show("9")]
[e] msg [show("0")]
[e] msg [show("!")]
[e] msg [show("@")]
[e] msg [show("#")]
msg %_Time substititions for the current time:%
set e a + " at " + now()
[e] msg [show("1")]
[e] msg [show("2")]
[e] msg [show("3")]
[e] msg [show("4")]
[e] msg [show("5")]
[e] msg [show("6")]
[e] msg [show("7")]
[e] msg [show("8")]
[e] msg [show("9")]
[e] msg [show("0")]
[e] msg [show("!")]
[e] msg [show("@")]
[e] msg [show("#")]
msg %_The following are the days of the week:
fset showwd(x) "wkday("+x+") = " + wkday(x) + "%"
msg [showwd(0)]
msg [showwd(1)]
msg [showwd(2)]
msg [showwd(3)]
msg [showwd(4)]
msg [showwd(5)]
msg [showwd(6)]
msg %_The following are the months of the year:
fset showmon(x) "mon("+x+") = "+mon(x)+"%"
msg [showmon(1)]
msg [showmon(2)]
msg [showmon(3)]
msg [showmon(4)]
msg [showmon(5)]
msg [showmon(6)]
msg [showmon(7)]
msg [showmon(8)]
msg [showmon(9)]
msg [showmon(10)]
msg [showmon(11)]
msg [showmon(12)]

176
types.h Normal file
View File

@@ -0,0 +1,176 @@
/***************************************************************/
/* */
/* TYPES.H */
/* */
/* Type definitions all dumped here. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: types.h,v 1.1 1996-03-27 03:26:14 dfs Exp $ */
/* Values */
typedef struct {
char type;
union {
char *str;
int val;
} v;
} Value;
/* Define the type of operators */
typedef struct {
char *name;
char prec;
char type;
#ifdef HAVE_PROTOS
int (*func)(void);
#else
int (*func) ();
#endif
} Operator;
/* Define the structure of a variable */
typedef struct var {
struct var *next;
char name[VAR_NAME_LEN+1];
char preserve;
Value v;
} Var;
/* A trigger */
typedef struct {
int wd;
int d;
int m;
int y;
int back;
int delta;
int rep;
int localomit;
int skip;
int until;
int typ;
int once;
int scanfrom;
int priority;
char sched[VAR_NAME_LEN+1]; /* Scheduling function */
} Trigger;
/* A time trigger */
typedef struct {
int ttime;
int nexttime;
int delta;
int rep;
} TimeTrig;
/* The parse pointer */
typedef struct {
char isnested; /* Is it a nested expression? */
char allownested;
char *text; /* Start of text */
char *pos; /* Current position */
char *etext; /* Substituted text */
char *epos; /* Position in substituted text */
} Parser;
typedef Parser *ParsePtr; /* Pointer to parser structure */
/* Some useful manifest constants */
#define NO_BACK 0
#define NO_DELTA 0
#define NO_REP 0
#define NO_WD 0
#define NO_DAY -1
#define NO_MON -1
#define NO_YR -1
#define NO_UNTIL -1
#define NO_ONCE 0
#define ONCE_ONCE 1
#define NO_DATE -1
#define NO_SKIP 0
#define SKIP_SKIP 1
#define BEFORE_SKIP 2
#define AFTER_SKIP 3
#define NO_TIME 1500 /* >1440, ie > than the largest possible legal time */
#define NO_PRIORITY 5000 /* Default priority is midway between 0 and 9999 */
#define NO_TYPE 0
#define MSG_TYPE 1
#define RUN_TYPE 2
#define CAL_TYPE 3
#define SAT_TYPE 4
#define PS_TYPE 5
#define PSF_TYPE 6
#define MSF_TYPE 7
/* DEFINES for debugging flags */
#define DB_PRTLINE 1
#define DB_PRTEXPR 2
#define DB_PRTTRIG 4
#define DB_DUMP_VARS 8
#define DB_ECHO_LINE 16
/* Enumeration of the tokens */
enum TokTypes
{ T_Illegal,
/* Commands first */
T_Rem, T_Push, T_Pop, T_Preserve, T_Include, T_If, T_Else, T_EndIf,
T_IfTrig, T_ErrMsg,
T_Set, T_UnSet, T_Fset, T_Omit, T_Banner, T_Exit,
T_WkDay,
T_Month, T_Time,
T_Skip, T_At, T_RemType, T_Until, T_Year, T_Day, T_Rep, T_Delta, T_Back,
T_Once,
T_Empty,
T_Comment,
T_Number,
T_Clr,
T_Debug,
T_Dumpvars,
T_Scanfrom,
T_Flush,
T_Priority,
T_Sched
};
/* The structure of a token */
typedef struct {
char *name;
char MinLen;
enum TokTypes type;
int val;
} Token;
/* Flags for the state of the "if" stack */
#define IF_TRUE 0
#define IF_FALSE 1
#define BEFORE_ELSE 0
#define AFTER_ELSE 2
#define IF_MASK 3
#define IF_TRUE_MASK 1
#define IF_ELSE_MASK 2
/* Flags for the DoSubst function */
#define NORMAL_MODE 0
#define CAL_MODE 1
#define QUOTE_MARKER 1 /* Unlikely character to appear in reminder */
/* Flags for disabling run */
#define RUN_CMDLINE 1
#define RUN_SCRIPT 2
/* Flags for the SimpleCalendar format */
#define SC_AMPM 0 /* Time shown as 3:00am, etc. */
#define SC_MIL 1 /* 24-hour time format */
#define SC_NOTIME 2 /* Do not display time in SC format. */
/* Flags for sorting */
#define SORT_NONE 0
#define SORT_ASCEND 1
#define SORT_DESCEND 2

403
userfns.c Normal file
View File

@@ -0,0 +1,403 @@
/***************************************************************/
/* */
/* USERFNS.C */
/* */
/* This file contains the routines to support user-defined */
/* functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: userfns.c,v 1.1 1996-03-27 03:26:15 dfs Exp $";
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include "types.h"
#include "globals.h"
#include "protos.h"
#include "err.h"
#include "expr.h"
#define FUNC_HASH_SIZE 32 /* Size of User-defined function hash table */
/* Define the data structure used to hold a user-defined function */
typedef struct udf_struct {
struct udf_struct *next;
char name[VAR_NAME_LEN+1];
char *text;
Var *locals;
char IsCached;
char IsActive;
int nargs;
} UserFunc;
/* The hash table */
static UserFunc *FuncHash[FUNC_HASH_SIZE];
/* Access to built-in functions */
extern int NumFuncs;
extern Operator Func[];
/* We need access to the expression evaluation stack */
extern Value ValStack[];
extern int ValStackPtr;
PRIVATE void DestroyUserFunc ARGS ((UserFunc *f));
PRIVATE void FUnset ARGS ((char *name));
PRIVATE void FSet ARGS ((UserFunc *f));
PRIVATE int SetUpLocalVars ARGS ((UserFunc *f));
PRIVATE void DestroyLocalVals ARGS ((UserFunc *f));
/***************************************************************/
/* */
/* DoFset */
/* */
/* Define a user-defined function - the FSET command. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoFset(ParsePtr p)
#else
int DoFset(p)
ParsePtr p;
#endif
{
int r;
int c;
UserFunc *func;
Var *v;
/* Get the function name */
if ( (r=ParseIdentifier(p, TokBuffer)) ) return r;
if (*TokBuffer == '$') return E_BAD_ID;
/* Should be followed by '(' */
c = ParseNonSpaceChar(p, &r, 0);
if (r) return r;
if (c != '(') return E_PARSE_ERR;
func = NEW(UserFunc);
if (!func) return E_NO_MEM;
StrnCpy(func->name, TokBuffer, VAR_NAME_LEN);
if (!Hush) {
if (FindFunc(TokBuffer, Func, NumFuncs)) {
Eprint("%s: '%s'", ErrMsg[E_REDEF_FUNC],
TokBuffer);
}
}
func->locals = NULL;
func->text = NULL;
func->IsCached = 1;
func->IsActive = 0;
func->nargs = 0;
/* Get the local variables - we insert the local variables in REVERSE
order, but that's OK, because we pop them off the stack in reverse
order, too, so everything works out just fine. */
c=ParseNonSpaceChar(p, &r, 1);
if (r) return r;
if (c == ')') {
(void) ParseNonSpaceChar(p, &r, 0);
}
else {
while(1) {
if ( (r=ParseIdentifier(p, TokBuffer)) ) return r;
if (*TokBuffer == '$') return E_BAD_ID;
v = NEW(Var);
func->nargs++;
v->v.type = ERR_TYPE;
if (!v) {
DestroyUserFunc(func);
return E_NO_MEM;
}
StrnCpy(v->name, TokBuffer, VAR_NAME_LEN);
v->next = func->locals;
func->locals = v;
c = ParseNonSpaceChar(p, &r, 0);
if (c == ')') break;
else if (c != ',') {
DestroyUserFunc(func);
return E_PARSE_ERR;
}
}
}
/* Copy the text over */
if (p->isnested) {
Eprint("%s", ErrMsg[E_CANTNEST_FDEF]);
DestroyUserFunc(func);
return E_PARSE_ERR;
}
/* A bit of trickery here - if the definition is already cached,
no point in copying it. */
if (CurLine != LineBuffer) {
func->IsCached = 1;
func->text = p->pos;
} else {
func->IsCached = 0;
func->text = StrDup(p->pos);
if (!func->text) {
DestroyUserFunc(func);
return E_NO_MEM;
}
}
/* If an old definition of this function exists, destroy it */
FUnset(func->name);
/* Add the function definition */
FSet(func);
return OK;
}
/***************************************************************/
/* */
/* DestroyUserFunc */
/* */
/* Free up all the resources used by a user-defined function. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DestroyUserFunc(UserFunc *f)
#else
static void DestroyUserFunc(f)
UserFunc *f;
#endif
{
Var *v, *prev;
/* Free the local variables first */
v = f->locals;
while(v) {
DestroyValue(v->v);
prev = v;
v = v->next;
free(prev);
}
/* Free the function definition */
if (f->text && !f->IsCached) free(f->text);
/* Free the data structure itself */
free(f);
}
/***************************************************************/
/* */
/* FUnset */
/* */
/* Delete the function definition with the given name, if */
/* it exists. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void FUnset(char *name)
#else
static void FUnset(name)
char *name;
#endif
{
UserFunc *cur, *prev;
int h;
h = HashVal(name) % FUNC_HASH_SIZE;
cur = FuncHash[h];
prev = NULL;
while(cur) {
if (! StrinCmp(name, cur->name, VAR_NAME_LEN)) break;
prev = cur;
cur = cur->next;
}
if (!cur) return;
if (prev) prev->next = cur->next; else FuncHash[h] = cur->next;
DestroyUserFunc(cur);
}
/***************************************************************/
/* */
/* FSet */
/* */
/* Insert a user-defined function into the hash table. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void FSet(UserFunc *f)
#else
static void FSet(f)
UserFunc *f;
#endif
{
int h = HashVal(f->name) % FUNC_HASH_SIZE;
f->next = FuncHash[h];
FuncHash[h] = f;
}
/***************************************************************/
/* */
/* CallUserFunc */
/* */
/* Call a user-defined function. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int CallUserFunc(char *name, int nargs)
#else
int CallUserFunc(name, nargs)
char *name;
int nargs;
#endif
{
UserFunc *f;
int h = HashVal(name) % FUNC_HASH_SIZE;
int i;
char *s;
/* Search for the function */
f = FuncHash[h];
while (f && StrinCmp(name, f->name, VAR_NAME_LEN)) f = f->next;
if (!f) {
Eprint("%s: '%s'", ErrMsg[E_UNDEF_FUNC], name);
return E_UNDEF_FUNC;
}
/* Debugging stuff */
if (DebugFlag & DB_PRTEXPR) {
fprintf(ErrFp, "%s %s(", ErrMsg[E_ENTER_FUN], f->name);
for (i=0; i<nargs; i++) {
PrintValue(&ValStack[ValStackPtr - nargs + i], ErrFp);
if (i<nargs-1) fprintf(ErrFp, ", ");
}
fprintf(ErrFp, ")\n");
}
/* Detect illegal recursive call */
if (f->IsActive) {
if (DebugFlag &DB_PRTEXPR) {
fprintf(ErrFp, "%s %s() => ", ErrMsg[E_LEAVE_FUN], name);
fprintf(ErrFp, "%s\n", ErrMsg[E_RECURSIVE]);
}
return E_RECURSIVE;
}
/* Check number of args */
if (nargs != f->nargs) {
if (DebugFlag &DB_PRTEXPR) {
fprintf(ErrFp, "%s %s() => ", ErrMsg[E_LEAVE_FUN], name);
fprintf(ErrFp, "%s\n",
ErrMsg[(nargs < f->nargs) ? E_2FEW_ARGS : E_2MANY_ARGS]);
}
return (nargs < f->nargs) ? E_2FEW_ARGS : E_2MANY_ARGS;
}
/* Found the function - set up a local variable frame */
h = SetUpLocalVars(f);
if (h) {
if (DebugFlag &DB_PRTEXPR) {
fprintf(ErrFp, "%s %s() => ", ErrMsg[E_LEAVE_FUN], name);
fprintf(ErrFp, "%s\n", ErrMsg[h]);
}
return h;
}
/* Evaluate the expression */
f->IsActive = 1;
s = f->text;
/* Skip the opening bracket, if there's one */
while (isspace(*s)) s++;
if (*s == BEG_OF_EXPR) s++;
h = Evaluate(&s, f->locals);
f->IsActive = 0;
DestroyLocalVals(f);
if (DebugFlag &DB_PRTEXPR) {
fprintf(ErrFp, "%s %s() => ", ErrMsg[E_LEAVE_FUN], name);
if (h) fprintf(ErrFp, "%s\n", ErrMsg[h]);
else {
PrintValue(&ValStack[ValStackPtr-1], ErrFp);
fprintf(ErrFp, "\n");
}
}
return h;
}
/***************************************************************/
/* */
/* SetUpLocalVars */
/* */
/* Set up the local variables from the stack frame. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE int SetUpLocalVars(UserFunc *f)
#else
static int SetUpLocalVars(f)
UserFunc *f;
#endif
{
int i, r;
Var *var;
for (i=0, var=f->locals; var && i<f->nargs; var=var->next, i++) {
if ( (r=FnPopValStack(&(var->v))) ) {
DestroyLocalVals(f);
return r;
}
}
return OK;
}
/***************************************************************/
/* */
/* DestroyLocalVals */
/* */
/* Destroy the values of all local variables after evaluating */
/* the function. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DestroyLocalVals(UserFunc *f)
#else
static void DestroyLocalVals(f)
UserFunc *f;
#endif
{
Var *v = f->locals;
while(v) {
DestroyValue(v->v);
v = v->next;
}
}
/***************************************************************/
/* */
/* UserFuncExists */
/* */
/* Return the number of arguments accepted by the function if */
/* it is defined, or -1 if it is not defined. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int UserFuncExists(char *fn)
#else
int UserFuncExists(fn)
char *fn;
#endif
{
UserFunc *f;
int h = HashVal(fn) % FUNC_HASH_SIZE;
f = FuncHash[h];
while (f && StrinCmp(fn, f->name, VAR_NAME_LEN)) f = f->next;
if (!f) return -1;
else return f->nargs;
}

183
utils.c Normal file
View File

@@ -0,0 +1,183 @@
/***************************************************************/
/* */
/* UTILS.C */
/* */
/* Useful utility functions. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: utils.c,v 1.1 1996-03-27 03:26:15 dfs Exp $";
#include "config.h"
#include <string.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include "types.h"
#include "globals.h"
#include "protos.h"
#define UPPER(c) (islower(c) ? toupper(c) : c)
/***************************************************************/
/* */
/* StrnCpy */
/* */
/* Just like strncpy EXCEPT we ALWAYS copy the trailing 0. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *StrnCpy(char *dest, const char *source, int n)
#else
char *StrnCpy(dest, source, n)
char *dest, *source;
int n;
#endif
{
register char *odest = dest;
while (n-- && (*dest++ = *source++)) ;
if (*(dest-1)) *dest = 0;
return odest;
}
/***************************************************************/
/* */
/* StrMatch */
/* */
/* Checks that two strings match (case-insensitive) to at */
/* least the specified number of characters, or the length */
/* of the first string, whichever is greater. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int StrMatch(const char *s1, const char *s2, int n)
#else
int StrMatch(s1, s2, n)
char *s1, *s2;
int n;
#endif
{
int l;
if ((l = strlen(s1)) < n) return 0;
return !StrinCmp(s1, s2, l);
}
/***************************************************************/
/* */
/* StrinCmp - compare strings, case-insensitive */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int StrinCmp(const char *s1, const char *s2, int n)
#else
int StrinCmp(s1, s2, n)
char *s1, *s2;
int n;
#endif
{
register int r;
while (n && *s1 && *s2) {
n--;
r = UPPER(*s1) - UPPER(*s2);
if (r) return r;
s1++;
s2++;
}
if (n) return (UPPER(*s1) - UPPER(*s2)); else return 0;
}
/***************************************************************/
/* */
/* StrDup */
/* */
/* Like ANSI strdup */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC char *StrDup(const char *s)
#else
char *StrDup(s)
char *s;
#endif
{
char *ret = (char *) malloc(strlen(s)+1);
if (!ret) return (char *) NULL;
strcpy(ret, s);
return ret;
}
/***************************************************************/
/* */
/* StrCmpi */
/* */
/* Compare strings, case insensitive. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int StrCmpi(const char *s1, const char *s2)
#else
int StrCmpi(s1, s2)
char *s1, *s2;
#endif
{
int r;
while (*s1 && *s2) {
r = UPPER(*s1) - UPPER(*s2);
if (r) return r;
s1++;
s2++;
}
return UPPER(*s1) - UPPER(*s2);
}
#ifdef NO_STRSTR
#ifdef HAVE_PROTOS
PUBLIC char *strstr(char *s1, char *s2)
#else
char *strstr(s1, s2)
char *s1, *s2;
#endif
{
char *s = s1;
int len2 = strlen(s2);
int len1 = strlen(s1);
while (s-s1 <= len1-len2) {
if (!strncmp(s, s2, len2)) return s;
s++;
}
return NULL;
}
#endif
/***************************************************************/
/* */
/* DateOK */
/* */
/* Return 1 if the date is OK, 0 otherwise. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DateOK(int y, int m, int d)
#else
int DateOK(y, m, d)
int y, m, d;
#endif
{
if (d < 1 ||
m < 0 ||
y < BASE ||
m > 11 ||
y > BASE + YR_RANGE ||
d > DaysInMonth(m, y) ) return 0;
else return 1;
}

655
var.c Normal file
View File

@@ -0,0 +1,655 @@
/***************************************************************/
/* */
/* VAR.C */
/* */
/* This file contains routines, structures, etc for */
/* user- and system-defined variables. */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
static char const RCSID[] = "$Id: var.c,v 1.1 1996-03-27 03:26:16 dfs Exp $";
#include "config.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include <ctype.h>
#include "types.h"
#include "expr.h"
#include "globals.h"
#include "protos.h"
#include "err.h"
#define UPPER(c) (islower(c) ? toupper(c) : c)
/* The variable hash table */
#define VAR_HASH_SIZE 64
#define VARIABLE ErrMsg[E_VAR]
#define VALUE ErrMsg[E_VAL]
#define UNDEF ErrMsg[E_UNDEF]
static Var *VHashTbl[VAR_HASH_SIZE];
/***************************************************************/
/* */
/* HashVal */
/* Given a string, compute the hash value. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC unsigned int HashVal(const char *str)
#else
unsigned int HashVal(str)
char *str;
#endif
{
register unsigned int i=0;
register unsigned int j=1;
register unsigned int len=0;
while(*str && len < VAR_NAME_LEN) {
i += j * (unsigned int) UPPER(*str);
str++;
len++;
j = 3-j;
}
return i;
}
/***************************************************************/
/* */
/* FindVar */
/* Given a string, find the variable whose name is that */
/* string. If create is 1, create the variable. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC Var *FindVar(const char *str, int create)
#else
Var *FindVar(str, create)
char *str;
int create;
#endif
{
register int h;
register Var *v;
register Var *prev;
h = HashVal(str) % VAR_HASH_SIZE;
v = VHashTbl[h];
prev = NULL;
while(v) {
if (! StrinCmp(str, v->name, VAR_NAME_LEN)) return v;
prev = v;
v = v-> next;
}
if (!create) return v;
/* Create the variable */
v = NEW(Var);
if (!v) return v;
v->next = NULL;
v->v.type = INT_TYPE;
v->v.v.val = 0;
v->preserve = 0;
StrnCpy(v->name, str, VAR_NAME_LEN);
if (prev) prev->next = v; else VHashTbl[h] = v;
return v;
}
/***************************************************************/
/* */
/* DeleteVar */
/* Given a string, find the variable whose name is that */
/* string and delete it. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DeleteVar(const char *str)
#else
int DeleteVar(str)
char *str;
#endif
{
register int h;
register Var *v;
register Var *prev;
h = HashVal(str) % VAR_HASH_SIZE;
v = VHashTbl[h];
prev = NULL;
while(v) {
if (! StrinCmp(str, v->name, VAR_NAME_LEN)) break;
prev = v;
v = v-> next;
}
if (!v) return E_NOSUCH_VAR;
DestroyValue(v->v);
if (prev) prev->next = v->next; else VHashTbl[h] = v->next;
free(v);
return OK;
}
/***************************************************************/
/* */
/* SetVar */
/* */
/* Set the indicate variable to the specified value. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int SetVar(const char *str, Value *val)
#else
int SetVar(str, val)
char *str;
Value *val;
#endif
{
Var *v = FindVar(str, 1);
if (!v) return E_NO_MEM; /* Only way FindVar can fail */
DestroyValue(v->v);
v->v = *val;
return OK;
}
/***************************************************************/
/* */
/* GetVarValue */
/* */
/* Get a copy of the value of the variable. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetVarValue(const char *str, Value *val, Var *locals)
#else
int GetVarValue(str, val, locals)
char *str;
Value *val;
Var *locals;
#endif
{
Var *v;
/* Try searching local variables first */
v = locals;
while (v) {
if (! StrinCmp(str, v->name, VAR_NAME_LEN))
return CopyValue(val, &v->v);
v = v->next;
}
v=FindVar(str, 0);
if (!v) {
Eprint("%s: %s", ErrMsg[E_NOSUCH_VAR], str);
return E_NOSUCH_VAR;
}
return CopyValue(val, &v->v);
}
/***************************************************************/
/* */
/* DoSet - set a variable. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoSet (Parser *p)
#else
int DoSet (p)
Parser *p;
#endif
{
Value v;
int r;
r = ParseIdentifier(p, TokBuffer);
if (r) return r;
r = EvaluateExpr(p, &v);
if (r) return r;
if (*TokBuffer == '$') return SetSysVar(TokBuffer+1, &v);
else return SetVar(TokBuffer, &v);
}
/***************************************************************/
/* */
/* DoUnset - delete a bunch of variables. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoUnset (Parser *p)
#else
int DoUnset (p)
Parser *p;
#endif
{
int r;
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer) return E_EOLN;
(void) DeleteVar(TokBuffer); /* Ignore error - nosuchvar */
/* Keep going... */
while(1) {
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer) return OK;
(void) DeleteVar(TokBuffer);
}
}
/***************************************************************/
/* */
/* DoDump */
/* */
/* Command file command to dump variable table. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoDump(ParsePtr p)
#else
int DoDump(p)
ParsePtr p;
#endif
{
int r;
Var *v;
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') {
DumpVarTable();
return OK;
}
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
while(1) {
if (*TokBuffer == '$') {
DumpSysVarByName(TokBuffer+1);
} else {
v = FindVar(TokBuffer, 0);
TokBuffer[VAR_NAME_LEN] = 0;
if (!v) fprintf(ErrFp, "%*s %s\n", VAR_NAME_LEN, TokBuffer, UNDEF);
else {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n");
}
}
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer || *TokBuffer == '#' || *TokBuffer == ';') return OK;
}
}
/***************************************************************/
/* */
/* DumpVarTable */
/* */
/* Dump the variable table to stderr. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DumpVarTable(void)
#else
void DumpVarTable()
#endif
{
register Var *v;
register int i;
fprintf(ErrFp, "%*s %s\n\n", VAR_NAME_LEN, VARIABLE, VALUE);
for (i=0; i<VAR_HASH_SIZE; i++) {
v = VHashTbl[i];
while(v) {
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, v->name);
PrintValue(&(v->v), ErrFp);
fprintf(ErrFp, "\n");
v = v->next;
}
}
}
/***************************************************************/
/* */
/* DestroyVars */
/* */
/* Free all the memory used by variables, but don't delete */
/* preserved variables unless ALL is non-zero. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DestroyVars(int all)
#else
void DestroyVars(all)
int all;
#endif
{
int i;
Var *v, *next, *prev;
for (i=0; i<VAR_HASH_SIZE; i++) {
v = VHashTbl[i];
VHashTbl[i] = NULL;
prev = NULL;
while(v) {
if (all || !v->preserve) {
DestroyValue(v->v);
next = v->next;
free(v);
} else {
if (prev) prev->next = v;
else VHashTbl[i] = v;
prev = v;
next = v->next;
v->next = NULL;
}
v = next;
}
}
}
/***************************************************************/
/* */
/* PreserveVar */
/* */
/* Given the name of a variable, "preserve" it. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int PreserveVar(char *name)
#else
int PreserveVar(name)
char *name;
#endif
{
Var *v;
v = FindVar(name, 1);
if (!v) return E_NO_MEM;
v->preserve = 1;
return OK;
}
/***************************************************************/
/* */
/* DoPreserve - preserve a bunch of variables. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int DoPreserve (Parser *p)
#else
int DoPreserve (p)
Parser *p;
#endif
{
int r;
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer) return E_EOLN;
r = PreserveVar(TokBuffer);
if (r) return r;
/* Keep going... */
while(1) {
r = ParseToken(p, TokBuffer);
if (r) return r;
if (!*TokBuffer) return OK;
r = PreserveVar(TokBuffer);
if (r) return r;
}
}
/***************************************************************/
/* */
/* SYSTEM VARIABLES */
/* */
/* Interface for modifying and reading system variables. */
/* */
/***************************************************************/
/* The structure of a system variable */
typedef struct {
char *name;
char modifiable;
int type;
void *value;
int min;
int max;
} SysVar;
/* If the type of a sys variable is STR_TYPE, then min is redefined
to be a flag indicating whether or not the value has been malloc'd. */
#define been_malloced min
/* Flag for no min/max constraint */
#define ANY 4532
/* All of the system variables sorted alphabetically */
static SysVar SysVarArr[] = {
/* name mod type value min/mal max */
{ "CalcUTC", 1, INT_TYPE, &CalculateUTC, 0, 1 },
{ "CalMode", 0, INT_TYPE, &DoCalendar, 0, 0 },
{ "Daemon", 0, INT_TYPE, &Daemon, 0, 0 },
{ "DefaultPrio", 1, INT_TYPE, &DefaultPrio, 0, 9999 },
{ "DontFork", 0, INT_TYPE, &DontFork, 0, 0 },
{ "DontQueue", 0, INT_TYPE, &DontQueue, 0, 0 },
{ "DontTrigAts", 0, INT_TYPE, &DontIssueAts, 0, 0 },
{ "EndSent", 1, STR_TYPE, &EndSent, 0, 0 },
{ "EndSentIg", 1, STR_TYPE, &EndSentIg, 0, 0 },
{ "FirstIndent", 1, INT_TYPE, &FirstIndent, 0, 132 },
{ "FoldYear", 1, INT_TYPE, &FoldYear, 0, 1 },
{ "FormWidth", 1, INT_TYPE, &FormWidth, 20, 132 },
{ "HushMode", 0, INT_TYPE, &Hush, 0, 0 },
{ "IgnoreOnce", 0, INT_TYPE, &IgnoreOnce, 0, 0 },
{ "InfDelta", 0, INT_TYPE, &InfiniteDelta, 0, 0 },
{ "LatDeg", 1, INT_TYPE, &LatDeg, -90, 90 },
{ "LatMin", 1, INT_TYPE, &LatMin, -59, 59 },
{ "LatSec", 1, INT_TYPE, &LatSec, -59, 59 },
{ "Location", 1, STR_TYPE, &Location, 0, 0 },
{ "LongDeg", 1, INT_TYPE, &LongDeg, -180, 180 },
{ "LongMin", 1, INT_TYPE, &LongMin, -59, 59 },
{ "LongSec", 1, INT_TYPE, &LongSec, -59, 59 },
{ "MaxSatIter", 1, INT_TYPE, &MaxSatIter, 10, ANY },
{ "MinsFromUTC", 1, INT_TYPE, &MinsFromUTC, -13*60, 13*60 },
{ "NextMode", 0, INT_TYPE, &NextMode, 0, 0 },
{ "NumQueued", 0, INT_TYPE, &NumQueued, 0, 0 },
{ "NumTrig", 0, INT_TYPE, &NumTriggered, 0, 0 },
{ "PSCal", 0, INT_TYPE, &PsCal, 0, 0 },
{ "RunOff", 0, INT_TYPE, &RunDisabled, 0, 0 },
{ "SimpleCal", 0, INT_TYPE, &DoSimpleCalendar, 0, 0 },
{ "SortByDate", 0, INT_TYPE, &SortByDate, 0, 0},
{ "SortByPrio", 0, INT_TYPE, &SortByPrio, 0, 0},
{ "SortByTime", 0, INT_TYPE, &SortByTime, 0, 0},
{ "SubsIndent", 1, INT_TYPE, &SubsIndent, 0, 132}
};
#define NUMSYSVARS ( sizeof(SysVarArr) / sizeof(SysVar) )
PRIVATE SysVar *FindSysVar ARGS((const char *name));
PRIVATE void DumpSysVar ARGS((const char *name, const SysVar *v));
/***************************************************************/
/* */
/* SetSysVar */
/* */
/* Set a system variable to the indicated value. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int SetSysVar(const char *name, Value *value)
#else
int SetSysVar(name, value)
char *name;
Value *value;
#endif
{
SysVar *v = FindSysVar(name);
if (!v) return E_NOSUCH_VAR;
if (v->type != value->type) return E_BAD_TYPE;
if (!v->modifiable) {
Eprint("%s: '$%s'", ErrMsg[E_CANT_MODIFY], name);
return E_CANT_MODIFY;
}
/* If it's a string variable, special measures must be taken */
if (v->type == STR_TYPE) {
if (v->been_malloced) free(*((char **)(v->value)));
v->been_malloced = 1;
*((char **) v->value) = value->v.str;
value->type = ERR_TYPE; /* So that it's not accidentally freed */
} else {
if (v->max != ANY && value->v.val > v->max) return E_2HIGH;
if (v->min != ANY && value->v.val < v->min) return E_2LOW;
*((int *)v->value) = value->v.val;
}
return OK;
}
/***************************************************************/
/* */
/* GetSysVar */
/* */
/* Get the value of a system variable */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC int GetSysVar(const char *name, Value *val)
#else
int GetSysVar(name, val)
char *name;
Value *val;
#endif
{
SysVar *v = FindSysVar(name);
val->type = ERR_TYPE;
if (!v) return E_NOSUCH_VAR;
if (v->type == STR_TYPE) {
val->v.str = StrDup(*((char **) v->value));
if (!val->v.str) return E_NO_MEM;
} else {
val->v.val = *((int *) v->value);
}
val->type = v->type;
return OK;
}
/***************************************************************/
/* */
/* FindSysVar */
/* */
/* Find a system var with specified name. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE SysVar *FindSysVar(const char *name)
#else
static SysVar *FindSysVar(name)
char *name;
#endif
{
int top=NUMSYSVARS-1, bottom=0;
int mid=(top + bottom) / 2;
int r;
while (top >= bottom) {
r = StrCmpi(name, SysVarArr[mid].name);
if (!r) return &SysVarArr[mid];
else if (r>0) bottom = mid+1;
else top = mid-1;
mid = (top+bottom) / 2;
}
return NULL;
}
/***************************************************************/
/* */
/* DumpSysVarByName */
/* */
/* Given the name of a system variable, display it. */
/* If name is "", dump all system variables. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PUBLIC void DumpSysVarByName(const char *name)
#else
void DumpSysVarByName(name)
char *name;
#endif
{
int i;
SysVar *v;
if (!name || !*name) {
for (i=0; i<NUMSYSVARS; i++) DumpSysVar(name, SysVarArr + i);
return;
}
v = FindSysVar(name);
DumpSysVar(name, v);
return;
}
/***************************************************************/
/* */
/* DumpSysVar */
/* */
/* Dump the system variable. */
/* */
/***************************************************************/
#ifdef HAVE_PROTOS
PRIVATE void DumpSysVar(const char *name, const SysVar *v)
#else
static void DumpSysVar(name, v)
char *name;
SysVar *v;
#endif
{
char buffer[VAR_NAME_LEN+10];
if (name && !*name) name=NULL;
if (!v && !name) return; /* Shouldn't happen... */
buffer[0]='$'; buffer[1] = 0;
if (name) strcat(buffer, name); else strcat(buffer, v->name);
fprintf(ErrFp, "%*s ", VAR_NAME_LEN, buffer);
if (v) {
if (v->type == STR_TYPE) {
char *s = *((char **)v->value);
int y;
putc('"', ErrFp);
for (y=0; y<MAX_PRT_LEN && *s; y++) putc(*s++, ErrFp);
putc('"', ErrFp);
if (*s) fprintf(ErrFp, "...");
putc('\n', ErrFp);
} else {
if (!v->modifiable) fprintf(ErrFp, "%d\n", *((int *)v->value));
else {
fprintf(ErrFp, "%-10d ", *((int *)v->value));
if (v->min == ANY) fprintf(ErrFp, "(-Inf, ");
else fprintf(ErrFp, "[%d, ", v->min);
if (v->max == ANY) fprintf(ErrFp, "Inf)\n");
else fprintf(ErrFp, "%d]\n", v->max);
}
}
} else fprintf(ErrFp, "%s\n", UNDEF);
return;
}

13
version.h Normal file
View File

@@ -0,0 +1,13 @@
/***************************************************************/
/* */
/* VERSION.H */
/* */
/* What version of remind do we have? */
/* */
/* This file is part of REMIND. */
/* Copyright (C) 1992-1996 by David F. Skoll */
/* */
/***************************************************************/
/* $Id: version.h,v 1.1 1996-03-27 03:26:16 dfs Exp $ */
#define VERSION "03.00.13"