|
|
1.1 ! root 1: /* time.c ! 2: Parse a time string into a uuconf_timespan structure. ! 3: ! 4: Copyright (C) 1992 Ian Lance Taylor ! 5: ! 6: This file is part of the Taylor UUCP uuconf library. ! 7: ! 8: This library is free software; you can redistribute it and/or ! 9: modify it under the terms of the GNU Library General Public License ! 10: as published by the Free Software Foundation; either version 2 of ! 11: the License, or (at your option) any later version. ! 12: ! 13: This library is distributed in the hope that it will be useful, but ! 14: WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 16: Library General Public License for more details. ! 17: ! 18: You should have received a copy of the GNU Library General Public ! 19: License along with this library; if not, write to the Free Software ! 20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 21: ! 22: The author of the program may be contacted at [email protected] or ! 23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. ! 24: */ ! 25: ! 26: #include "uucnfi.h" ! 27: ! 28: #if USE_RCS_ID ! 29: const char _uuconf_time_rcsid[] = "$Id: time.c,v 1.1 93/07/30 08:07:59 bin Exp Locker: bin $"; ! 30: #endif ! 31: ! 32: #include <ctype.h> ! 33: #include <errno.h> ! 34: ! 35: static int itadd_span P((struct sglobal *qglobal, int istart, int iend, ! 36: long ival, int cretry, ! 37: int (*picmp) P((long, long)), ! 38: struct uuconf_timespan **pqspan, ! 39: pointer pblock)); ! 40: static int itnew P((struct sglobal *qglobal, struct uuconf_timespan **pqset, ! 41: struct uuconf_timespan *qnext, int istart, int iend, ! 42: long ival, int cretry, pointer pblock)); ! 43: ! 44: /* An array of weekday abbreviations. The code below assumes that ! 45: each one starts with a lower case letter. */ ! 46: ! 47: static const struct ! 48: { ! 49: const char *zname; ! 50: int imin; ! 51: int imax; ! 52: } asTdays[] = ! 53: { ! 54: { "any", 0, 6 }, ! 55: { "wk", 1, 5 }, ! 56: { "su", 0, 0 }, ! 57: { "mo", 1, 1 }, ! 58: { "tu", 2, 2 }, ! 59: { "we", 3, 3 }, ! 60: { "th", 4, 4 }, ! 61: { "fr", 5, 5 }, ! 62: { "sa", 6, 6 }, ! 63: { "never", -1, -2 }, ! 64: { NULL, 0, 0 } ! 65: }; ! 66: ! 67: /* Parse a time string and add it to a span list. This function is ! 68: given the value, the retry time, and the comparison function to ! 69: use. */ ! 70: ! 71: int ! 72: _uuconf_itime_parse (qglobal, ztime, ival, cretry, picmp, pqspan, pblock) ! 73: struct sglobal *qglobal; ! 74: char *ztime; ! 75: long ival; ! 76: int cretry; ! 77: int (*picmp) P((long, long)); ! 78: struct uuconf_timespan **pqspan; ! 79: pointer pblock; ! 80: { ! 81: struct uuconf_timespan *qlist; ! 82: char bfirst; ! 83: const char *z; ! 84: ! 85: qlist = *pqspan; ! 86: if (qlist == (struct uuconf_timespan *) &_uuconf_unset) ! 87: qlist = NULL; ! 88: ! 89: /* Expand the string using a timetable. Keep rechecking the string ! 90: until it does not match. */ ! 91: while (TRUE) ! 92: { ! 93: char **pz; ! 94: char *zfound; ! 95: ! 96: bfirst = *ztime; ! 97: if (isupper (BUCHAR (bfirst))) ! 98: bfirst = tolower (BUCHAR (bfirst)); ! 99: ! 100: zfound = NULL; ! 101: pz = qglobal->qprocess->pztimetables; ! 102: ! 103: /* We want the last timetable to have been defined with this ! 104: name, so we always look through the entire table. */ ! 105: while (*pz != NULL) ! 106: { ! 107: if ((bfirst == (*pz)[0] ! 108: || (isupper (BUCHAR ((*pz)[0])) ! 109: && bfirst == tolower (BUCHAR ((*pz)[0])))) ! 110: && strcasecmp (ztime, *pz) == 0) ! 111: zfound = pz[1]; ! 112: pz += 2; ! 113: } ! 114: if (zfound == NULL) ! 115: break; ! 116: ztime = zfound; ! 117: } ! 118: ! 119: /* Look through the time string. */ ! 120: z = ztime; ! 121: while (*z != '\0') ! 122: { ! 123: int iday; ! 124: boolean afday[7]; ! 125: int istart, iend; ! 126: ! 127: if (*z == ',' || *z == '|') ! 128: ++z; ! 129: if (*z == '\0' || *z == ';') ! 130: break; ! 131: ! 132: for (iday = 0; iday < 7; iday++) ! 133: afday[iday] = FALSE; ! 134: ! 135: /* Get the days. */ ! 136: do ! 137: { ! 138: bfirst = *z; ! 139: if (isupper (BUCHAR (bfirst))) ! 140: bfirst = tolower (BUCHAR (bfirst)); ! 141: for (iday = 0; asTdays[iday].zname != NULL; iday++) ! 142: { ! 143: size_t clen; ! 144: ! 145: if (bfirst != asTdays[iday].zname[0]) ! 146: continue; ! 147: ! 148: clen = strlen (asTdays[iday].zname); ! 149: if (strncasecmp (z, asTdays[iday].zname, clen) == 0) ! 150: { ! 151: int iset; ! 152: ! 153: for (iset = asTdays[iday].imin; ! 154: iset <= asTdays[iday].imax; ! 155: iset++) ! 156: afday[iset] = TRUE; ! 157: z += clen; ! 158: break; ! 159: } ! 160: } ! 161: if (asTdays[iday].zname == NULL) ! 162: return UUCONF_SYNTAX_ERROR; ! 163: } ! 164: while (isalpha (BUCHAR (*z))); ! 165: ! 166: /* Get the hours. */ ! 167: if (! isdigit (BUCHAR (*z))) ! 168: { ! 169: istart = 0; ! 170: iend = 24 * 60; ! 171: } ! 172: else ! 173: { ! 174: char *zendnum; ! 175: ! 176: istart = (int) strtol ((char *) z, &zendnum, 10); ! 177: if (*zendnum != '-' || ! isdigit (BUCHAR (zendnum[1]))) ! 178: return UUCONF_SYNTAX_ERROR; ! 179: z = zendnum + 1; ! 180: iend = (int) strtol ((char *) z, &zendnum, 10); ! 181: z = zendnum; ! 182: ! 183: istart = (istart / 100) * 60 + istart % 100; ! 184: iend = (iend / 100) * 60 + iend % 100; ! 185: } ! 186: ! 187: /* Add the times we've found onto the list. */ ! 188: for (iday = 0; iday < 7; iday++) ! 189: { ! 190: if (afday[iday]) ! 191: { ! 192: int iminute, iret; ! 193: ! 194: iminute = iday * 24 * 60; ! 195: if (istart < iend) ! 196: iret = itadd_span (qglobal, iminute + istart, ! 197: iminute + iend, ival, cretry, picmp, ! 198: &qlist, pblock); ! 199: else ! 200: { ! 201: /* Wrap around midnight. */ ! 202: iret = itadd_span (qglobal, iminute, iminute + iend, ! 203: ival, cretry, picmp, &qlist, pblock); ! 204: if (iret == UUCONF_SUCCESS) ! 205: iret = itadd_span (qglobal, iminute + istart, ! 206: iminute + 24 * 60, ival, cretry, ! 207: picmp, &qlist, pblock); ! 208: } ! 209: ! 210: if (iret != UUCONF_SUCCESS) ! 211: return iret; ! 212: } ! 213: } ! 214: } ! 215: ! 216: *pqspan = qlist; ! 217: ! 218: return UUCONF_SUCCESS; ! 219: } ! 220: ! 221: /* Add a time span to an existing list of time spans. We keep the ! 222: list sorted by time to make this operation easier. This modifies ! 223: the existing list, and returns the modified version. It takes a ! 224: comparison function which should return < 0 if the first argument ! 225: should take precedence over the second argument and == 0 if they ! 226: are the same (for grades this is igradecmp; for sizes it is minus ! 227: (the binary operator)). */ ! 228: ! 229: static int ! 230: itadd_span (qglobal, istart, iend, ival, cretry, picmp, pqspan, pblock) ! 231: struct sglobal *qglobal; ! 232: int istart; ! 233: int iend; ! 234: long ival; ! 235: int cretry; ! 236: int (*picmp) P((long, long)); ! 237: struct uuconf_timespan **pqspan; ! 238: pointer pblock; ! 239: { ! 240: struct uuconf_timespan **pq; ! 241: int iret; ! 242: ! 243: /* istart < iend */ ! 244: for (pq = pqspan; *pq != NULL; pq = &(*pq)->uuconf_qnext) ! 245: { ! 246: int icmp; ! 247: ! 248: /* Invariant: PREV (*pq) == NULL || PREV (*pq)->iend <= istart */ ! 249: /* istart < iend && (*pq)->istart < (*pq)->iend */ ! 250: ! 251: if (iend <= (*pq)->uuconf_istart) ! 252: { ! 253: /* istart < iend <= (*pq)->istart < (*pq)->iend */ ! 254: /* No overlap, and we're at the right spot. See if we can ! 255: combine these spans. */ ! 256: if (iend == (*pq)->uuconf_istart ! 257: && cretry == (*pq)->uuconf_cretry ! 258: && (*picmp) (ival, (*pq)->uuconf_ival) == 0) ! 259: { ! 260: (*pq)->uuconf_istart = istart; ! 261: return UUCONF_SUCCESS; ! 262: } ! 263: /* We couldn't combine them. */ ! 264: break; ! 265: } ! 266: ! 267: if ((*pq)->uuconf_iend <= istart) ! 268: { ! 269: /* (*pq)->istart < (*pq)->iend <= istart < iend */ ! 270: /* No overlap. Try attaching this span. */ ! 271: if ((*pq)->uuconf_iend == istart ! 272: && (*pq)->uuconf_cretry == cretry ! 273: && ((*pq)->uuconf_qnext == NULL ! 274: || iend <= (*pq)->uuconf_qnext->uuconf_istart) ! 275: && (*picmp) (ival, (*pq)->uuconf_ival) == 0) ! 276: { ! 277: (*pq)->uuconf_iend = iend; ! 278: return UUCONF_SUCCESS; ! 279: } ! 280: /* Couldn't attach; keep looking for the right spot. We ! 281: might be able to combine part of the new span onto an ! 282: existing span, but it's probably not worth it. */ ! 283: continue; ! 284: } ! 285: ! 286: /* istart < iend ! 287: && (*pq)->istart < (*pq)->iend ! 288: && istart < (*pq)->iend ! 289: && (*pq)->istart < iend */ ! 290: /* Overlap. */ ! 291: ! 292: icmp = (*picmp) (ival, (*pq)->uuconf_ival); ! 293: ! 294: if (icmp == 0) ! 295: { ! 296: /* Just expand the old span to include the new span. */ ! 297: if (istart < (*pq)->uuconf_istart) ! 298: (*pq)->uuconf_istart = istart; ! 299: if ((*pq)->uuconf_iend >= iend) ! 300: return UUCONF_SUCCESS; ! 301: if ((*pq)->uuconf_qnext == NULL ! 302: || iend <= (*pq)->uuconf_qnext->uuconf_istart) ! 303: { ! 304: (*pq)->uuconf_iend = iend; ! 305: return UUCONF_SUCCESS; ! 306: } ! 307: /* The span we are adding overlaps the next span as well. ! 308: Expand the old span up to the next old span, and keep ! 309: trying to add the new span. */ ! 310: (*pq)->uuconf_iend = (*pq)->uuconf_qnext->uuconf_istart; ! 311: istart = (*pq)->uuconf_iend; ! 312: } ! 313: else if (icmp < 0) ! 314: { ! 315: /* Replace the old span with the new span. */ ! 316: if ((*pq)->uuconf_istart < istart) ! 317: { ! 318: /* Save the initial portion of the old span. */ ! 319: iret = itnew (qglobal, pq, *pq, (*pq)->uuconf_istart, istart, ! 320: (*pq)->uuconf_ival, (*pq)->uuconf_cretry, ! 321: pblock); ! 322: if (iret != UUCONF_SUCCESS) ! 323: return iret; ! 324: pq = &(*pq)->uuconf_qnext; ! 325: } ! 326: if (iend < (*pq)->uuconf_iend) ! 327: { ! 328: /* Save the final portion of the old span. */ ! 329: iret = itnew (qglobal, &(*pq)->uuconf_qnext, ! 330: (*pq)->uuconf_qnext, iend, (*pq)->uuconf_iend, ! 331: (*pq)->uuconf_ival, (*pq)->uuconf_cretry, ! 332: pblock); ! 333: if (iret != UUCONF_SUCCESS) ! 334: return iret; ! 335: } ! 336: (*pq)->uuconf_ival = ival; ! 337: (*pq)->uuconf_istart = istart; ! 338: (*pq)->uuconf_cretry = cretry; ! 339: if ((*pq)->uuconf_qnext == NULL ! 340: || iend <= (*pq)->uuconf_qnext->uuconf_istart) ! 341: { ! 342: (*pq)->uuconf_iend = iend; ! 343: return UUCONF_SUCCESS; ! 344: } ! 345: /* Move this span up to the next one, and keep trying to add ! 346: the new span. */ ! 347: (*pq)->uuconf_iend = (*pq)->uuconf_qnext->uuconf_istart; ! 348: istart = (*pq)->uuconf_iend; ! 349: } ! 350: else ! 351: { ! 352: /* Leave the old span untouched. */ ! 353: if (istart < (*pq)->uuconf_istart) ! 354: { ! 355: /* Put in the initial portion of the new span. */ ! 356: iret = itnew (qglobal, pq, *pq, istart, (*pq)->uuconf_istart, ! 357: ival, cretry, pblock); ! 358: if (iret != UUCONF_SUCCESS) ! 359: return iret; ! 360: pq = &(*pq)->uuconf_qnext; ! 361: } ! 362: if (iend <= (*pq)->uuconf_iend) ! 363: return UUCONF_SUCCESS; ! 364: /* Keep trying to add the new span. */ ! 365: istart = (*pq)->uuconf_iend; ! 366: } ! 367: } ! 368: ! 369: /* This is the spot for the new span, and there's no overlap. */ ! 370: ! 371: return itnew (qglobal, pq, *pq, istart, iend, ival, cretry, pblock); ! 372: } ! 373: ! 374: /* A utility function to create a new uuconf_timespan structure. */ ! 375: ! 376: static int ! 377: itnew (qglobal, pqset, qnext, istart, iend, ival, cretry, pblock) ! 378: struct sglobal *qglobal; ! 379: struct uuconf_timespan **pqset; ! 380: struct uuconf_timespan *qnext; ! 381: int istart; ! 382: int iend; ! 383: long ival; ! 384: int cretry; ! 385: pointer pblock; ! 386: { ! 387: register struct uuconf_timespan *qnew; ! 388: ! 389: qnew = ((struct uuconf_timespan *) ! 390: uuconf_malloc (pblock, sizeof (struct uuconf_timespan))); ! 391: if (qnew == NULL) ! 392: { ! 393: qglobal->ierrno = errno; ! 394: return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO; ! 395: } ! 396: ! 397: qnew->uuconf_qnext = qnext; ! 398: qnew->uuconf_istart = istart; ! 399: qnew->uuconf_iend = iend; ! 400: qnew->uuconf_ival = ival; ! 401: qnew->uuconf_cretry = cretry; ! 402: ! 403: *pqset = qnew; ! 404: ! 405: return UUCONF_SUCCESS; ! 406: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.