📄 partime.c
字号:
break; case TM_12: atmfield = &midnoon; } if (ptstash(atmfield, i)) return(0); /* ERR: val already set */ continue; } /* Token is number. Lots of hairy heuristics. */ if (!isdigit(*btoken.tcp)) { if (!goodzone(&btoken, 1, &m)) return 0; zone_offset = TZ_OFFSET + m; continue; } i = btoken.tval.tnum; /* Value now known to be valid; get it. */ if (btoken.tcnt == 3) /* 3 digits = HMM */ {hhmm4: if (ptstash(&atm->tm_min, i%100)) return(0); /* ERR: min conflict */ i /= 100;hh2: if (ptstash(&atm->tm_hour, i)) return(0); /* ERR: hour conflict */ continue; } if (4 < btoken.tcnt) goto year4; /* far in the future */ if(btoken.tcnt == 4) /* 4 digits = YEAR or HHMM */ { if (given(atm->tm_year)) goto hhmm4; /* Already got yr? */ if (given(atm->tm_hour)) goto year4; /* Already got hr? */ if(btoken.tbrk == ':') /* HHMM:SS ? */ if ( ptstash(&atm->tm_hour, i/100) || ptstash(&atm->tm_min, i%100)) return(0); /* ERR: hr/min clash */ else goto coltm2; /* Go handle SS */ if(btoken.tbrk != ',' && btoken.tbrk != '/' && (atoken=btoken, ptitoken(&atoken)) /* Peek */ && ( atoken.tflg ? !isdigit(*atoken.tcp) : atoken.tval.ttmw->wflgs & TWTIME)) /* HHMM-ZON */ goto hhmm4; goto year4; /* Give up, assume year. */ } /* From this point on, assume tcnt == 1 or 2 */ /* 2 digits = MM, DD, or HH (MM and SS caught at coltime) */ if(btoken.tbrk == ':') /* HH:MM[:SS] */ goto coltime; /* must be part of time. */ if (31 < i) return 0; /* Check for numerical-format date */ for (cp = "/-."; ch = *cp++;) { ord = (ch == '.' ? 0 : 1); /* n/m = D/M or M/D */ if(btoken.tbrk == ch) /* "NN-" */ { if(btoken.tbrkl != ch) { atoken = btoken; atoken.tcnt++; if (ptitoken(&atoken) && atoken.tflg == 0 && atoken.tval.ttmw->wtype == TM_MON) goto dd2; if(ord)goto mm2; else goto dd2; /* "NN-" */ } /* "-NN-" */ if (!given(atm->tm_mday) && given(atm->tm_year)) /* If "YYYY-NN-" */ goto mm2; /* then always MM */ if(ord)goto dd2; else goto mm2; } if(btoken.tbrkl == ch /* "-NN" */ && given(ord ? atm->tm_mon : atm->tm_mday)) if (!given(ord ? atm->tm_mday : atm->tm_mon)) /* MM/DD */ if(ord)goto dd2; else goto mm2; } /* Now reduced to choice between HH and DD */ if (given(atm->tm_hour)) goto dd2; /* Have hour? Assume day. */ if (given(atm->tm_mday)) goto hh2; /* Have day? Assume hour. */ if (given(atm->tm_mon)) goto dd2; /* Have month? Assume day. */ if(i > 24) goto dd2; /* Impossible HH means DD */ atoken = btoken; if (!ptitoken(&atoken)) /* Read ahead! */ if(atoken.tval.tnum) return(0); /* ERR: bad token */ else goto dd2; /* EOF, assume day. */ if ( atoken.tflg ? !isdigit(*atoken.tcp) : atoken.tval.ttmw->wflgs & TWTIME) /* If next token is a time spec, assume hour */ goto hh2; /* e.g. "3 PM", "11-EDT" */dd2: if (ptstash(&atm->tm_mday, i)) /* Store day (1 based) */ return(0); continue;mm2: if (ptstash(&atm->tm_mon, i-1)) /* Store month (make zero based) */ return(0); continue;year4: if ((i-=1900) < 0 || ptstash(&atm->tm_year, i)) /* Store year-1900 */ return(0); /* ERR: year conflict */ continue; /* Hack HH:MM[[:]SS] */coltime: if (ptstash(&atm->tm_hour, i)) return 0; if (!ptitoken(&btoken)) return(!btoken.tval.tnum); if(!btoken.tflg) return(0); /* ERR: HH:<alpha> */ if(btoken.tcnt == 4) /* MMSS */ if (ptstash(&atm->tm_min, btoken.tval.tnum/100) || ptstash(&atm->tm_sec, btoken.tval.tnum%100)) return(0); else continue; if(btoken.tcnt != 2 || ptstash(&atm->tm_min, btoken.tval.tnum)) return(0); /* ERR: MM bad */ if (btoken.tbrk != ':') continue; /* Seconds follow? */coltm2: if (!ptitoken(&btoken)) return(!btoken.tval.tnum); if(!btoken.tflg || btoken.tcnt != 2 /* Verify SS */ || ptstash(&atm->tm_sec, btoken.tval.tnum)) return(0); /* ERR: SS bad */ }}/* Store date/time value, return 0 if successful. * Fail if entry is already set. */ static intptstash(adr,val)int *adr;int val;{ register int *a; if (given(*(a=adr))) return 1; *a = val; return(0);}/* This subroutine is invoked for AM, PM, NOON and MIDNIGHT when wrapping up * just prior to returning from partime. */ static intpt12hack(tm, aval)register struct tm *tm;register int aval;{ register int h = tm->tm_hour; switch (aval) { case T12_AM: case T12_PM: if (h > 12) return 0; if (h == 12) tm->tm_hour = 0; if (aval == T12_PM) tm->tm_hour += 12; break; default: if (0 < tm->tm_min || 0 < tm->tm_sec) return 0; if (!given(h) || h==12) tm->tm_hour = aval; else if (aval==T12_MIDNIGHT && (h==0 || h==24)) return 0; } return 1;}/* Get a token and identify it to some degree. * Returns 0 on failure; token.tval will be 0 for normal EOF, otherwise * hit error of some sort */ static intptitoken(tkp)register struct token *tkp;{ register char const *cp; register int i, j, k; if (!pttoken(tkp))#ifdef DEBUG { VOID printf("EOF\n"); return(0); }#else return(0);#endif cp = tkp->tcp;#ifdef DEBUG VOID printf("Token: \"%.*s\" ", tkp->tcnt, cp);#endif if (tkp->tflg) { i = tkp->tcnt; if (*cp == '+' || *cp == '-') { cp++; i--; } while (0 <= --i) { j = tkp->tval.tnum*10; k = j + (*cp++ - '0'); if (j/10 != tkp->tval.tnum || k < j) { /* arithmetic overflow */ tkp->tval.tnum = 1; return 0; } tkp->tval.tnum = k; } } else if (!(tkp->tval.ttmw = ptmatchstr(cp, tkp->tcnt, tmwords))) {#ifdef DEBUG VOID printf("Not found!\n");#endif tkp->tval.tnum = 1; return 0; }#ifdef DEBUG if(tkp->tflg) VOID printf("Val: %d.\n",tkp->tval.tnum); else VOID printf("Found: \"%s\", val: %d, type %d\n", tkp->tval.ttmw->went,tkp->tval.ttmw->wval,tkp->tval.ttmw->wtype);#endif return(1);}/* Read token from input string into token structure */ static intpttoken(tkp)register struct token *tkp;{ register char const *cp; register int c; char const *astr; tkp->tcp = astr = cp = tkp->tcp + tkp->tcnt; tkp->tbrkl = tkp->tbrk; /* Set "last break" */ tkp->tcnt = tkp->tbrk = tkp->tflg = 0; tkp->tval.tnum = 0; while(c = *cp++) { switch(c) { case ' ': case '\t': /* Flush all whitespace */ case '\r': case '\n': case '\v': case '\f': if (!tkp->tcnt) { /* If no token yet */ tkp->tcp = cp; /* ignore the brk */ continue; /* and go on. */ } /* fall into */ case '(': case ')': /* Perhaps any non-alphanum */ case '-': case ',': /* shd qualify as break? */ case '+': case '/': case ':': case '.': /* Break chars */ if(tkp->tcnt == 0) /* If no token yet */ { tkp->tcp = cp; /* ignore the brk */ tkp->tbrkl = c; continue; /* and go on. */ } tkp->tbrk = c; return(tkp->tcnt); } if (!tkp->tcnt++) { /* If first char of token, */ if (isdigit(c)) { tkp->tflg = 1; if (astr<cp-2 && (cp[-2]=='-'||cp[-2]=='+')) { /* timezone is break+sign+digit */ tkp->tcp--; tkp->tcnt++; } } } else if ((isdigit(c)!=0) != tkp->tflg) { /* else check type */ tkp->tbrk = c; return --tkp->tcnt; /* Wrong type, back up */ } } return(tkp->tcnt); /* When hit EOF */} static struct tmwent const *ptmatchstr(astr,cnt,astruc) char const *astr; int cnt; struct tmwent const *astruc;{ register char const *cp, *mp; register int c; struct tmwent const *lastptr; int i; lastptr = 0; for(;mp = astruc->went; astruc += 1) { cp = astr; for(i = cnt; i > 0; i--) { switch (*cp++ - (c = *mp++)) { case 0: continue; /* Exact match */ case 'A'-'a': if (ctab[c] == Letter) continue; } break; } if(i==0) if (!*mp) return astruc; /* Exact match */ else if(lastptr) return(0); /* Ambiguous */ else lastptr = astruc; /* 1st ambig */ } return lastptr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -