aboutsummaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libuuconf/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/libexec/uucp/libuuconf/time.c')
-rw-r--r--gnu/libexec/uucp/libuuconf/time.c406
1 files changed, 406 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libuuconf/time.c b/gnu/libexec/uucp/libuuconf/time.c
new file mode 100644
index 000000000000..33ce3f442c3c
--- /dev/null
+++ b/gnu/libexec/uucp/libuuconf/time.c
@@ -0,0 +1,406 @@
+/* time.c
+ Parse a time string into a uuconf_timespan structure.
+
+ Copyright (C) 1992 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP uuconf library.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License
+ as published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
+ */
+
+#include "uucnfi.h"
+
+#if USE_RCS_ID
+const char _uuconf_time_rcsid[] = "$Id: time.c,v 1.1 1993/08/05 18:26:07 conklin Exp $";
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+
+static int itadd_span P((struct sglobal *qglobal, int istart, int iend,
+ long ival, int cretry,
+ int (*picmp) P((long, long)),
+ struct uuconf_timespan **pqspan,
+ pointer pblock));
+static int itnew P((struct sglobal *qglobal, struct uuconf_timespan **pqset,
+ struct uuconf_timespan *qnext, int istart, int iend,
+ long ival, int cretry, pointer pblock));
+
+/* An array of weekday abbreviations. The code below assumes that
+ each one starts with a lower case letter. */
+
+static const struct
+{
+ const char *zname;
+ int imin;
+ int imax;
+} asTdays[] =
+{
+ { "any", 0, 6 },
+ { "wk", 1, 5 },
+ { "su", 0, 0 },
+ { "mo", 1, 1 },
+ { "tu", 2, 2 },
+ { "we", 3, 3 },
+ { "th", 4, 4 },
+ { "fr", 5, 5 },
+ { "sa", 6, 6 },
+ { "never", -1, -2 },
+ { NULL, 0, 0 }
+};
+
+/* Parse a time string and add it to a span list. This function is
+ given the value, the retry time, and the comparison function to
+ use. */
+
+int
+_uuconf_itime_parse (qglobal, ztime, ival, cretry, picmp, pqspan, pblock)
+ struct sglobal *qglobal;
+ char *ztime;
+ long ival;
+ int cretry;
+ int (*picmp) P((long, long));
+ struct uuconf_timespan **pqspan;
+ pointer pblock;
+{
+ struct uuconf_timespan *qlist;
+ char bfirst;
+ const char *z;
+
+ qlist = *pqspan;
+ if (qlist == (struct uuconf_timespan *) &_uuconf_unset)
+ qlist = NULL;
+
+ /* Expand the string using a timetable. Keep rechecking the string
+ until it does not match. */
+ while (TRUE)
+ {
+ char **pz;
+ char *zfound;
+
+ bfirst = *ztime;
+ if (isupper (BUCHAR (bfirst)))
+ bfirst = tolower (BUCHAR (bfirst));
+
+ zfound = NULL;
+ pz = qglobal->qprocess->pztimetables;
+
+ /* We want the last timetable to have been defined with this
+ name, so we always look through the entire table. */
+ while (*pz != NULL)
+ {
+ if ((bfirst == (*pz)[0]
+ || (isupper (BUCHAR ((*pz)[0]))
+ && bfirst == tolower (BUCHAR ((*pz)[0]))))
+ && strcasecmp (ztime, *pz) == 0)
+ zfound = pz[1];
+ pz += 2;
+ }
+ if (zfound == NULL)
+ break;
+ ztime = zfound;
+ }
+
+ /* Look through the time string. */
+ z = ztime;
+ while (*z != '\0')
+ {
+ int iday;
+ boolean afday[7];
+ int istart, iend;
+
+ if (*z == ',' || *z == '|')
+ ++z;
+ if (*z == '\0' || *z == ';')
+ break;
+
+ for (iday = 0; iday < 7; iday++)
+ afday[iday] = FALSE;
+
+ /* Get the days. */
+ do
+ {
+ bfirst = *z;
+ if (isupper (BUCHAR (bfirst)))
+ bfirst = tolower (BUCHAR (bfirst));
+ for (iday = 0; asTdays[iday].zname != NULL; iday++)
+ {
+ size_t clen;
+
+ if (bfirst != asTdays[iday].zname[0])
+ continue;
+
+ clen = strlen (asTdays[iday].zname);
+ if (strncasecmp (z, asTdays[iday].zname, clen) == 0)
+ {
+ int iset;
+
+ for (iset = asTdays[iday].imin;
+ iset <= asTdays[iday].imax;
+ iset++)
+ afday[iset] = TRUE;
+ z += clen;
+ break;
+ }
+ }
+ if (asTdays[iday].zname == NULL)
+ return UUCONF_SYNTAX_ERROR;
+ }
+ while (isalpha (BUCHAR (*z)));
+
+ /* Get the hours. */
+ if (! isdigit (BUCHAR (*z)))
+ {
+ istart = 0;
+ iend = 24 * 60;
+ }
+ else
+ {
+ char *zendnum;
+
+ istart = (int) strtol ((char *) z, &zendnum, 10);
+ if (*zendnum != '-' || ! isdigit (BUCHAR (zendnum[1])))
+ return UUCONF_SYNTAX_ERROR;
+ z = zendnum + 1;
+ iend = (int) strtol ((char *) z, &zendnum, 10);
+ z = zendnum;
+
+ istart = (istart / 100) * 60 + istart % 100;
+ iend = (iend / 100) * 60 + iend % 100;
+ }
+
+ /* Add the times we've found onto the list. */
+ for (iday = 0; iday < 7; iday++)
+ {
+ if (afday[iday])
+ {
+ int iminute, iret;
+
+ iminute = iday * 24 * 60;
+ if (istart < iend)
+ iret = itadd_span (qglobal, iminute + istart,
+ iminute + iend, ival, cretry, picmp,
+ &qlist, pblock);
+ else
+ {
+ /* Wrap around midnight. */
+ iret = itadd_span (qglobal, iminute, iminute + iend,
+ ival, cretry, picmp, &qlist, pblock);
+ if (iret == UUCONF_SUCCESS)
+ iret = itadd_span (qglobal, iminute + istart,
+ iminute + 24 * 60, ival, cretry,
+ picmp, &qlist, pblock);
+ }
+
+ if (iret != UUCONF_SUCCESS)
+ return iret;
+ }
+ }
+ }
+
+ *pqspan = qlist;
+
+ return UUCONF_SUCCESS;
+}
+
+/* Add a time span to an existing list of time spans. We keep the
+ list sorted by time to make this operation easier. This modifies
+ the existing list, and returns the modified version. It takes a
+ comparison function which should return < 0 if the first argument
+ should take precedence over the second argument and == 0 if they
+ are the same (for grades this is igradecmp; for sizes it is minus
+ (the binary operator)). */
+
+static int
+itadd_span (qglobal, istart, iend, ival, cretry, picmp, pqspan, pblock)
+ struct sglobal *qglobal;
+ int istart;
+ int iend;
+ long ival;
+ int cretry;
+ int (*picmp) P((long, long));
+ struct uuconf_timespan **pqspan;
+ pointer pblock;
+{
+ struct uuconf_timespan **pq;
+ int iret;
+
+ /* istart < iend */
+ for (pq = pqspan; *pq != NULL; pq = &(*pq)->uuconf_qnext)
+ {
+ int icmp;
+
+ /* Invariant: PREV (*pq) == NULL || PREV (*pq)->iend <= istart */
+ /* istart < iend && (*pq)->istart < (*pq)->iend */
+
+ if (iend <= (*pq)->uuconf_istart)
+ {
+ /* istart < iend <= (*pq)->istart < (*pq)->iend */
+ /* No overlap, and we're at the right spot. See if we can
+ combine these spans. */
+ if (iend == (*pq)->uuconf_istart
+ && cretry == (*pq)->uuconf_cretry
+ && (*picmp) (ival, (*pq)->uuconf_ival) == 0)
+ {
+ (*pq)->uuconf_istart = istart;
+ return UUCONF_SUCCESS;
+ }
+ /* We couldn't combine them. */
+ break;
+ }
+
+ if ((*pq)->uuconf_iend <= istart)
+ {
+ /* (*pq)->istart < (*pq)->iend <= istart < iend */
+ /* No overlap. Try attaching this span. */
+ if ((*pq)->uuconf_iend == istart
+ && (*pq)->uuconf_cretry == cretry
+ && ((*pq)->uuconf_qnext == NULL
+ || iend <= (*pq)->uuconf_qnext->uuconf_istart)
+ && (*picmp) (ival, (*pq)->uuconf_ival) == 0)
+ {
+ (*pq)->uuconf_iend = iend;
+ return UUCONF_SUCCESS;
+ }
+ /* Couldn't attach; keep looking for the right spot. We
+ might be able to combine part of the new span onto an
+ existing span, but it's probably not worth it. */
+ continue;
+ }
+
+ /* istart < iend
+ && (*pq)->istart < (*pq)->iend
+ && istart < (*pq)->iend
+ && (*pq)->istart < iend */
+ /* Overlap. */
+
+ icmp = (*picmp) (ival, (*pq)->uuconf_ival);
+
+ if (icmp == 0)
+ {
+ /* Just expand the old span to include the new span. */
+ if (istart < (*pq)->uuconf_istart)
+ (*pq)->uuconf_istart = istart;
+ if ((*pq)->uuconf_iend >= iend)
+ return UUCONF_SUCCESS;
+ if ((*pq)->uuconf_qnext == NULL
+ || iend <= (*pq)->uuconf_qnext->uuconf_istart)
+ {
+ (*pq)->uuconf_iend = iend;
+ return UUCONF_SUCCESS;
+ }
+ /* The span we are adding overlaps the next span as well.
+ Expand the old span up to the next old span, and keep
+ trying to add the new span. */
+ (*pq)->uuconf_iend = (*pq)->uuconf_qnext->uuconf_istart;
+ istart = (*pq)->uuconf_iend;
+ }
+ else if (icmp < 0)
+ {
+ /* Replace the old span with the new span. */
+ if ((*pq)->uuconf_istart < istart)
+ {
+ /* Save the initial portion of the old span. */
+ iret = itnew (qglobal, pq, *pq, (*pq)->uuconf_istart, istart,
+ (*pq)->uuconf_ival, (*pq)->uuconf_cretry,
+ pblock);
+ if (iret != UUCONF_SUCCESS)
+ return iret;
+ pq = &(*pq)->uuconf_qnext;
+ }
+ if (iend < (*pq)->uuconf_iend)
+ {
+ /* Save the final portion of the old span. */
+ iret = itnew (qglobal, &(*pq)->uuconf_qnext,
+ (*pq)->uuconf_qnext, iend, (*pq)->uuconf_iend,
+ (*pq)->uuconf_ival, (*pq)->uuconf_cretry,
+ pblock);
+ if (iret != UUCONF_SUCCESS)
+ return iret;
+ }
+ (*pq)->uuconf_ival = ival;
+ (*pq)->uuconf_istart = istart;
+ (*pq)->uuconf_cretry = cretry;
+ if ((*pq)->uuconf_qnext == NULL
+ || iend <= (*pq)->uuconf_qnext->uuconf_istart)
+ {
+ (*pq)->uuconf_iend = iend;
+ return UUCONF_SUCCESS;
+ }
+ /* Move this span up to the next one, and keep trying to add
+ the new span. */
+ (*pq)->uuconf_iend = (*pq)->uuconf_qnext->uuconf_istart;
+ istart = (*pq)->uuconf_iend;
+ }
+ else
+ {
+ /* Leave the old span untouched. */
+ if (istart < (*pq)->uuconf_istart)
+ {
+ /* Put in the initial portion of the new span. */
+ iret = itnew (qglobal, pq, *pq, istart, (*pq)->uuconf_istart,
+ ival, cretry, pblock);
+ if (iret != UUCONF_SUCCESS)
+ return iret;
+ pq = &(*pq)->uuconf_qnext;
+ }
+ if (iend <= (*pq)->uuconf_iend)
+ return UUCONF_SUCCESS;
+ /* Keep trying to add the new span. */
+ istart = (*pq)->uuconf_iend;
+ }
+ }
+
+ /* This is the spot for the new span, and there's no overlap. */
+
+ return itnew (qglobal, pq, *pq, istart, iend, ival, cretry, pblock);
+}
+
+/* A utility function to create a new uuconf_timespan structure. */
+
+static int
+itnew (qglobal, pqset, qnext, istart, iend, ival, cretry, pblock)
+ struct sglobal *qglobal;
+ struct uuconf_timespan **pqset;
+ struct uuconf_timespan *qnext;
+ int istart;
+ int iend;
+ long ival;
+ int cretry;
+ pointer pblock;
+{
+ register struct uuconf_timespan *qnew;
+
+ qnew = ((struct uuconf_timespan *)
+ uuconf_malloc (pblock, sizeof (struct uuconf_timespan)));
+ if (qnew == NULL)
+ {
+ qglobal->ierrno = errno;
+ return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
+ }
+
+ qnew->uuconf_qnext = qnext;
+ qnew->uuconf_istart = istart;
+ qnew->uuconf_iend = iend;
+ qnew->uuconf_ival = ival;
+ qnew->uuconf_cretry = cretry;
+
+ *pqset = qnew;
+
+ return UUCONF_SUCCESS;
+}