Repost CMD003 part 6
Mark Mallett
mem at sii.UUCP
Sun Jun 23 06:46:03 AEST 1985
<->
CMD003 TOPS20 style parsing Part 6 of 6
This is the 6th of 6 pieces of COMND, a TOPS-20 style parsing
library for CP/M (and other) systems, edit level 003. Its contents are
suitable for unpacking by the standard "sh" shell. Remove this header,
and any trailer added by the news/mail system, and run the rest through
the shell like this:
sh part6
and you will get the following files:
cmdpfd.c Date/Time function parsing.
cmdpsd.c Date/Time function stub.
cmdoss.cpm O/S specific routines for CP/M.
date.cpm Date/Time O/S specific routines for CP/M 3.0 (CPM+).
If you are unwilling to unpack it on a unix system, it should be fairly
simple to write a program to unpack it somewhere else.
**** End of Header, remove to here+1 ****
echo "unpacking file cmdpfd.c"
cat <<'EEOOFF' >cmdpfd.c
/* cmdpfd.c COMND module; Date/time function parse.
Copyright (C) 1985 Mark E. Mallett
Permission is hereby granted to distribute this file indiscriminately.
This file contains the code for the date/time parsing function.
Edit history
When Who What
------ --- --------------------------------
84xxxx MEM Create file.
Routines included:
CFPdat Parse date and/or time
*/
#include "stdio.h" /* Standard system defs */
#include "comnd.h" /* COMND interface definitions */
#include "comndi.h" /* COMND internal definitions */
typedef /* Structure for "special" dates */
struct {
int _mo; /* Month (1 - 12) */
int _da; /* Day of month (1 - 31) */
} SMD;
/* External routines */
/* External data */
extern int CMDbel; /* Beep request flag */
/* Internal (public) routines */
/* Internal (public) data */
/* Local (static) data */
/* Tables for date and time parsing. */
static char *Mnmtbl[] = { /* Month names */
"January", "February", "March",
"April", "May", "June",
"July", "August", "September",
"October", "November", "December",
NULL};
static char *Snmtbl[] = { /* Table of special names */
"April-Fools-Day",
"Christmas",
"Erics-Birthday",
"Fourth-of-July",
"Halloween",
"New-Years-Day",
"Valentines-day",
NULL
};
static SMD Sndtbl[] = { /* month/day for special names */
4, 1, /* April fools */
12, 25, /* Christmas */
8, 19, /* Eric's birthday */
7, 4, /* Fourth of July */
10, 31, /* Halloween */
1, 1, /* New Year's Day */
2, 14, /* Valentine's day */
0, 0}; /* end */
static char *Dowtbl[] = { /* Day-of-week table */
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", NULL
};
static char *Todtbl[] = { /* Time-of-day table */
"noon",
NULL
};
static CFB Timcfb = {_CMNUM, _CFHPP|_CFSDH, 0, 10,
"Time in the form hh:mm:ss", 0};
static CFB Todcfb = {_CMKEY, _CFHPP, &Timcfb, &Todtbl,
"Time of day, ", 0};
static CFB Plscfb = {_CMTOK, _CFHPP|_CFSDH, 0, "+",
"+ for future offset from now", 0};
static CFB Mincfb = {_CMTOK, _CFHPP|_CFSDH, &Plscfb, "-",
"- for past offset from now", 0};
static CFB Adncfb = {_CMNUM, _CFHPP|_CFSDH, &Mincfb, 10,
"Decimal month number", 0};
static CFB Dowcfb = {_CMKEY, _CFHPP, &Adncfb, &Dowtbl,
"Day of week, ", 0};
static CFB Snmcfb = {_CMKEY, _CFHPP, &Dowcfb, &Snmtbl,
"Special date, ", 0};
static CFB Mnmcfb = {_CMKEY, _CFHPP, &Snmcfb, &Mnmtbl,
"Month name, ", 0};
static CFB Clncfb = {_CMTOK, 0, 0, ":", 0, 0};
static CFB Cmycfb = {_CMTOK, _CFHPP|_CFSDH, 0, ",",
"Comma and year", 0};
static CFB Domcfb = {_CMNUM, _CFHPP|_CFSDH, 0, 10, "Day of month", 0};
static CFB Yrcfb = {_CMNUM, _CFHPP|_CFSDH, 0, 10, "Year", 0};
/*
*//* CFPdat (CSBptr, CFBptr, ccptr)
Function parse for type=_CMDAT, date and/or time
This function parses a date and/or time. It does this by calling
COMND recursively, with special date/time parsing function blocks.
Accepts :
CSBptr Address of command state block
CFBptr Address of command function block
ccptr Address of CC table (N/A here)
Returns :
<value> Parse status, _CPxxx as defined in comndi.h.
*/
CFPdat (CSBptr, CFBptr, ccptr)
CSB *CSBptr; /* Addr of command state block */
CFB *CFBptr; /* Addr of command function block */
WORD *ccptr; /* Addr of CC table */
{
IND int i,j,t; /* Scratch */
IND int id,it; /* Internal date and time */
IND int *rslptr; /* Result pointer */
rslptr = CSBptr -> CSB_ABF; /* Get pointer to result buffer */
curdtm (&id, &it); /* Get today's date/time */
if (CFBptr -> CFB_FLG & _CFDTD) /* If date wanted */
{
i = CFPdtd (CSBptr, CFBptr); /* Try for date */
if (!CFBptr -> CFB_FLG & _CFDTT) /* If time not wanted */
return (i); /* Just return the result */
switch (i) /* Go by parse result of date */
{
case _CPABT: /* If abort... */
return (_CPABT); /* return abort code */
case _CPSUCC: /* Success(!) */
id = rslptr[0]; /* Remember date */
j = COMND (CSBptr, &Clncfb); /* Try for colon for time */
if (j == _CRNOP) /* If not parsed */
{
rslptr[0] = id; /* Put date back */
rslptr[1] = it; /* Use current time */
return (_CPSUCC); /* Return ok */
}
else if (j != _CROK) /* If not OK */
return (_CPABT); /* stop now */
break; /* Continue with getting time! */
case _CPAGN: /* Try again later.. */
case _CPGVH: /* Gave help */
case _CPNOP: /* Could not parse.. */
rslptr[0] = id; /* Store current date */
break; /* Quit and continue */
}
}
/* Try for time, if wanted */
if (!(CFBptr -> CFB_FLG & _CFDTT)) /* If time not wanted */
return (i); /* return result of date parse */
id = rslptr[0]; /* Remember date */
t = CFPdtt(CSBptr, CFBptr); /* Try to parse time */
rslptr[0] = id; /* Pass back date, if any */
if (!(CFBptr -> CFB_FLG & _CFDTD)) /* If we did not parse a date */
return (t); /* return result of time attempt. */
if (i == _CPGVH) /* If date gave help */
return (_CPGVH); /* then we HAVE to return that code */
return (t); /* Otherwise return what time said. */
}
/*
*//* CFBdtd (CSBptr, CFBptr)
Parse date portion of date/time
This function parses a date. It does this by calling COMND
recursively.
Accepts :
CSBptr Address of command state block
CFBptr Address of command function block
Returns :
<value> Parse status, _CPxxx as defined in comndi.h.
*/
CFPdtd (CSBptr, CFBptr)
CSB *CSBptr; /* Addr of command state block */
CFB *CFBptr; /* Addr of command function block */
{
IND CFB *CFBmat; /* Matching CFB address */
IND int m,d,y,id,it; /* Date values */
IND int *rslptr; /* Result pointer */
IND char **kptr; /* Keyword ptr ptr */
IND int i; /* Scratch */
IND int prem; /* Remembers parse point */
prem = CSBptr -> CSB_PRS; /* Remember the current parse point */
rslptr = CSBptr -> CSB_ABF; /* Point to result area */
i = COMNDr (CSBptr, &Mnmcfb, 1); /* Try parsing the date. */
if ((i != _CPSUCC) && (i != _CPCPE)) /* If not successful parse */
return (i); /* then return whatever it was */
CFBmat = CSBptr -> CSB_CFB; /* Get addr of matching CFB */
if (CFBmat == &Plscfb) /* Plus date/time */
{
fprintf (stderr, "Relative date/time not supported\n");
return (_CPABT);
}
else if (CFBmat == &Mincfb) /* Minus date/time */
{
fprintf (stderr, "Relative date/time not supported\n");
return (_CPABT);
}
else if ((CFBmat == &Mnmcfb) || (CFBmat == &Snmcfb))
/* Month or special date in year */
{
kptr = (char **) (CSBptr -> CSB_RVL._ADR);
/* Get the table entry address */
if (CFBmat == &Mnmcfb)
{
m = (kptr - &Mnmtbl[0]) +1; /* Get month number */
/* Get day of month */
i = COMNDr (CSBptr, &Domcfb, 2); /* Try for day of month */
if ((i != _CPSUCC) && (i != _CPCPE)) /* Check not success */
{
CSBptr -> CSB_PRS = prem; /* Reset parse pointer */
return (i); /* return */
}
d = CSBptr -> CSB_RVL._INT; /* Get day of month */
}
else /* Special... */
{
i = (kptr - &Snmtbl[0]); /* Get index */
m = Sndtbl[i]._mo; /* Get month */
d = Sndtbl[i]._da; /* and day */
}
i = COMNDr (CSBptr, &Cmycfb, 2); /* Try for comma and year */
if ((i != _CPSUCC) && (i != _CPCPE)) /* Check not success */
{
CSBptr -> CSB_PRS = prem; /* Reset parse pointer */
return (i);
}
i = COMNDr (CSBptr, &Yrcfb, 2); /* Now try for year */
if ((i != _CPSUCC) && (i != _CPCPE)) /* Check not success */
{
CSBptr -> CSB_PRS = prem; /* Reset parse pointer */
return (i);
}
y = CSBptr -> CSB_RVL._INT; /* Get year */
i = cvedid (rslptr, &it, m, d, y, 0, 0);
if (i != 0)
{
fprintf (stderr, "Bad component in date: %d\n", i);
fprintf (stderr, "Inputs were %d/%d/%d\n", m, d, y);
return (_CPNOP); /* Bad parse */
}
return (_CPSUCC); /* Got it. */
}
else
return (_CPNOP); /* Nope. */
}
/*
*//* CFBdtt (CSBptr, CFBptr)
Parse time portion of date/time
This function parses a time. It does this by calling COMND
recursively.
Accepts :
CSBptr Address of command state block
CFBptr Address of command function block
Returns :
<value> Parse status, _CPxxx as defined in comndi.h.
*/
CFPdtt (CSBptr, CFBptr)
CSB *CSBptr; /* Addr of command state block */
CFB *CFBptr; /* Addr of command function block */
{
IND int i; /* Scratch */
i = COMNDr (CSBptr, &Todcfb, 2); /* Try parsing the time */
return (i); /* Return now. */
}
EEOOFF
echo "unpacking file cmdpsd.c"
cat <<'EEOOFF' >cmdpsd.c
/* cmdpsd.c COMND module; Stub for date/time function parse.
Copyright (C) 1985 Mark E. Mallett
Permission is hereby granted to distribute this file indiscriminately.
This file is a stub for the date/time parsing function, and
is to be included in the link when date/time functions are not used
(in order to save memory on small machines like mine).
Edit history
When Who What
------ --- --------------------------------
850527 MEM Create file.
Routines included:
CFPdat Parse date and/or time
CMDpsd fake routine to drag in this module.
*/
#include "stdio.h" /* Standard system defs */
#include "comnd.h" /* COMND interface definitions */
#include "comndi.h" /* COMND internal definitions */
/* External routines */
/* External data */
/* Internal (public) routines */
/* Internal (public) data */
/* Local (static) data */
/*
*//* CMDpsd()
Parse stub for date/time
If the COMND files are stored in an object library (for the linker), you
can put this module first and call this routine directly in order to
drag in this module and satisfy the references with the stub(s) in this
routine. Or you can keep this module separate and link it in before
referencing the library.
*/
CMDpsd()
{}
/*
*//* CFPdat (CSBptr, CFBptr, ccptr)
Function parse for type=_CMDAT, date and/or time
This is a stub for the _CMDAT function processor. It will indicate
an invalid function call.
Accepts :
CSBptr Address of command state block
CFBptr Address of command function block
ccptr Address of CC table (N/A here)
Returns :
<value> Parse status of _CPABT.
*/
CFPdat (CSBptr, CFBptr, ccptr)
CSB *CSBptr; /* Addr of command state block */
CFB *CFBptr; /* Addr of command function block */
WORD *ccptr; /* Addr of CC table */
{
CSBptr -> CSB_RCD = _CRIFC; /* Set invalid function code */
return (_CPABT); /* Abort, right now */
}
EEOOFF
echo "unpacking file cmdoss.cpm"
cat <<'EEOOFF' >cmdoss.cpm
/* cmdoss.cpm COMND module; OS-specific routines for CP/M-80
Copyright (C) 1985 Mark E. Mallett
Permission is hereby granted to distribute this file indiscriminately.
Edit history
When Who What
------ --- --------------------------------
84xxxx MEM Create file.
Routines included are:
CMDfob Flush terminal output buffer.
CMDgtc Get character from terminal without echo
CMDptc Output character to terminal (buffered)
CMDpzs Put NUL-terminated string to terminal
*/
#include "stdio.h" /* Standard system defs */
#include "mem.h" /* Include my standard names */
/* External routines */
/* External data */
/* Internal (public) routines */
/* Internal (public) data */
/* Local (static) data */
BYTE Coline[201] = {0}; /* Output line */
int Colpos = {0}; /* Position in output line */
/*
*//* CMDgtc()
Get terminal input character, no echo.
*/
CMDgtc()
{
IND int c;
while ((c = CPM(6,0xffff)&0xff) == 0)
;
return (c&0x7f);
}
/*
*//* CMDpzs (sptr)
Output a zero-terminated string to the console.
Inputs
sptr Address of the zero-terminated string
Outputs
The string (buffered) out to the terminal.
Notes
CMDfob() can be called to flush the output.
*/
CMDpzs (sptr)
BYTE *sptr; /* Address of string to output */
{
while (*sptr != NUL) /* Until end.. */
CMDpoc (*sptr++); /* Output. */
}
/*
*//* CMDptc(c)
Output c to the terminal, buffered.
*/
CMDptc(c)
{
Coline[Colpos++] = c; /* Store char */
if ((c == '\n') || (Colpos == 200)) /* If read to break */
CMDfob(); /* break */
}
/*
*//* CMDfob()
Break console output.
*/
CMDfob()
{
if (Colpos)
{
write (fileno(stdout),Coline,Colpos); /* Write the line */
Colpos = 0; /* Reset pointer */
}
}
EEOOFF
echo "unpacking file date.cpm"
cat <<'EEOOFF' >date.cpm
/* date.cpm Date/Time support for CP/M-80 v 3.0
Copyright (C) 1985 Mark E. Mallett
Permission is hereby granted to distribute this file indiscriminately.
Edit history
When Who What
------ --- --------------------------------
84xxxx MEM Create file.
Included are
curdtm Get current date/time
cvedid Convert external to internal date
cvided Convert internal to external date
*/
#include "stdio.h"
#include "mem.h" /* Get my standard defs */
#include "cpm.h" /* Get CP/M call definitions */
/* Local definitions */
typedef /* date/time structure */
struct
{
int DAT_DAT; /* Days since Jan 1 1978 */
BYTE DAT_HRS; /* BCD hours */
BYTE DAT_MIN; /* BCD minutes */
}
DAT; /* Date */
/* External variables */
/* External routines */
/* Locals */
static int mdtbl[] = {31,28,31,30,31,30,31,31,30,31,30,31};
/* Days in each month */
/*
*//* curdtm (id, it)
Get date/time from operating system
Accepts :
id Address of where to store the date in internal form
it Address of where to store the time in internal form
Returns :
*id Date as an int.
*it Time as an int.
*/
curdtm (id, it)
int *id; /* Address of date variable */
int *it; /* Address of time variable */
{
IND DAT date; /* Date value */
IND int i; /* Scratch */
CPM (_MRGDT, &date); /* Call system to get date */
*id = date.DAT_DAT; /* Get days since Jan 1 1978 */
i = (date.DAT_HRS>>4)&0x0F;
i = i*10 + (date.DAT_HRS&0x0F);
i = i*6 + ((date.DAT_MIN>>4)&0x0F);
i = i*10 + (date.DAT_MIN&0x0F);
*it = i; /* Return the time. */
}
/*
*//* cvedid (id, it, m, d, y, hh, mm)
Convert external date/time to internal date/time
Accepts :
id Address of internal date variable (int)
it Address of internal time variable (int)
m Month number (1-12)
d Day number (1-31)
y Year number (1978-??)
hh Hour (0 - 23)
mm Minutes (0 - 59)
Returns :
<value> 0 if ok inputs
-1 = bad year
-2 = bad month
-3 = bad day of month
*id Internal date value
*it Internal time value
*/
cvedid (id, it, m, d, y, hh, mm)
int *id, *it; /* Addr of date and time variables */
int m, d, y, hh, mm; /* Date and time component values */
{
IND int i,j; /* Scratch */
*it = hh*60+mm; /* Takes care of time */
if ((y < 1978) || (y > 2070))
return (-1);
mdtbl[1] = 28; /* Setup February */
if (y%4 == 0) /* if leap year */
mdtbl[1] = 29;
m--; /* Make month and day zero-based */
d--;
if ((m < 0) || (m > 11)) /* Check out month */
return (-2);
if ((d < 0) || (d >= mdtbl[m])) /* Check out day of month */
return (-3);
i = 0; /* Calculate days */
for (j=0; j < m; j++)
i += mdtbl[j];
i += d;
i += (y-1978)*365;
i += (y-1976)/4;
*id = i+1; /* Return day */
return (0); /* Give good status */
}
/*
*//* cvided (id, it, m, d, y, hh, mm)
Convert internal date/time values to external values
Accepts :
id Date in internal form
it Time in internal form
*m Where to put month number
*d Where to put day number
*y Where to put year number
*hh Where to put hours
*mm Where to put minutes
Returns :
*m Month number (1-12)
*d Day number (1-31)
*y Year number (1978-??)
*hh Hour (0-23)
*mm Minutes (0-59)
*/
cvided (id, it, m, d, y, hh, mm)
int id, it; /* Internal date/time */
int *m, *d, *y, *hh, *mm; /* Where to put components */
{
IND int i,j; /* Scratch */
IND int yr,ly,mo,day; /* Various values */
i = id-1; /* day 1 = Jan 1 1978 */
ly = (i+672)/1461; /* Number of leap days passed. */
yr = (i-ly)/365; /* Number of full years passed */
i = i-(yr*365)-((yr+1)/4); /* Number of day in this year */
yr = yr+1978; /* What year it is */
mdtbl[1] = 28; /* Presume not leap year */
if (yr%4 == 0) /* If is */
mdtbl[1] = 29; /* then set feb days */
for (j=0,mo=0; j <= i; mo++) /* Find month */
j = j+mdtbl[mo]; /* Add days */
j = j-mdtbl[--mo]; /* Subtract off last month */
day = (i-j)+1; /* Get real day. */
*y = yr; /* Return component values */
*m = mo+1;
*d = day;
*hh = it/60;
*mm = it%60;
}
EEOOFF
More information about the Comp.sources.unix
mailing list