This is fdate.c in view mode; [Download] [Up]
/* * Copyright (c) 1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS" AND CARNEGIE MELLON UNIVERSITY * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT * SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Users of this software agree to return to Carnegie Mellon any * improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * Export of this software is permitted only after complying with the * regulations of the U.S. Deptartment of Commerce relating to the * Export of Technical Data. */ # include <sys/types.h> # include <sys/time.h> /* * HISTORY * $Log: fdate.c,v $ * Revision 1.2 90/12/11 17:52:25 mja * Add copyright/disclaimer for distribution. * * 30-Apr-85 Steven Shafer (sas) at Carnegie-Mellon University * Adapted for 4.2 BSD UNIX: macro file name changed. * * * March 1984 - Leonard Hamey (lgh) at Carnegie-Mellon University * Created. */ # define TEXT 1 # define FAIL 2 # define OPTIONAL 3 # define SUCCEED 4 # define YES 1 # define NO 0 # define MAYBE 2 # define SMONTHS 0 # define SWDAYS 12 # define SNOON 19 # define SMIDNIGHT 20 # define SAM 21 # define SPM 22 # define STH 23 # define SST 24 # define SND 25 # define SRD 26 # define NOON 0 # define HOUR 1 # define AM 2 # define MIN 3 # define SEC 4 # define WDAY 5 # define DAY 6 # define TH 7 # define NMONTH 8 # define MONTH 9 # define YEAR 10 # define YDAY 11 # define MIDNIGHT 12 # define TIME 13 static char *strings[] = { "jan*uary", "feb*ruary", "mar*ch", "apr*il", "may", "jun*e", "jul*y", "aug*ust", "sep*tember", "oct*ober", "nov*ember", "dec*ember", "sun*day", "mon*day", "tue*s*day", "wed*nesday", "thu*r*s*day", "fri*day", "sat*urday", "noon", "00:00", "am", "pm", "th", "st", "nd", "rd" }; static char *keys[] = { "noon", "hour", "am", "min", "sec", "wday", "day", "th", "nmonth", "month", "year", "yday", "midnight", "time", 0 }; /* The following is a macro definition of %time. */ static char *mactime = "[%midnight|%noon|%0hour:%min:%?sec|{%hour{:%?min}%am}]"; static char *p; static int resp; static char *result; char *fdate (resb, patt, tm) char *resb, *patt; struct tm *tm; { result = resb; resp = 0; p = patt; dofield (' ', tm); result[resp] = '\0'; return (result); } static dofield (doing, tm) char doing; struct tm *tm; { int ndep, s, sresp, sresp2; int fail; char ch; fail = MAYBE; sresp = resp; while (*p) { if (*p == '{' || *p == '[') { ch = *p++; s = dofield (ch, tm); if (s == FAIL && doing == '[') fail = YES; else if (s == SUCCEED && doing == '{') fail = NO; } else if (*p == '}' || *p == ']' || *p == '|') { if (doing == '{' && fail == MAYBE) fail = YES; if (fail == YES) { resp = sresp; if (*p == '|') { p++; fail = MAYBE; /* try next */ continue; } p++; } else if (*p == '|') { /* Scan to matching bracket/brace */ ndep = 1; while (ndep > 0) { if (*p == '{' || *p == '[') ndep++; else if (*p == '}' || *p == ']') ndep--; p++; } } else p++; return (fail == YES ? FAIL : SUCCEED); } else if (*p == '%') { sresp2 = resp; s = percent (tm); if (doing == '{') { if (s == FAIL) /* Discard failure results */ resp = sresp2; else if (s == SUCCEED) fail = NO; } else if (doing == '[') { if (s == FAIL) fail = YES; } } else { result[resp++] = *p; p++; } if (fail == YES) { /* Failure: scan for barline or closing bracket/brace; leave ptr there */ resp = sresp; ndep = 1; while (ndep > 0) { if (*p == '|' && ndep == 1) break; if (*p == '[' | *p == '{') ndep++; else if (*p == ']' || *p == '}') { ndep--; if (ndep == 0) return (FAIL); } p++; } } } return (SUCCEED); } static percent (tm) struct tm *tm; { register char *pp; char *spp; int query, lead0, prec, upcase, sresp, s; char *savep; register int ks; register char *k; char foldc (); int formfld (); char *fldp; pp = p + 1; if (*pp == '%' || *pp == '{' || *pp == '}' || *pp == '|' || *pp == '[' || *pp == ']') { p += 2; result[resp++] = *pp; return (TEXT); /* Was just text */ } query = *pp == '?'; /* Query? */ if (query) pp++; lead0 = *pp == '0'; /* Leading zero? */ if (lead0) pp++; if (*pp >= '1' && *pp <= '9') /* Precision? */ { prec = *pp - '0'; pp++; } else prec = 0; upcase = 0; /* Case? */ if (*pp >= 'A' && *pp <= 'Z') upcase = 1; if (pp[1] >= 'A' && pp[1] <= 'Z') upcase = 2; spp = pp; for (ks = 0; keys[ks]; ks++) /* Check for keyword */ { for (k = keys[ks], pp = spp; *k; k++, pp++) if (foldc (*k) != foldc (*pp)) break; if (! *k) /* Match found */ break; } if (! keys[ks]) /* No match */ { result[resp++] = '%'; /* Treat as text */ p++; return (TEXT); } p = pp; if (ks == TIME) /* Macro */ { savep = p; sresp = resp; p = mactime + 1; /* Skip leading bracket */ s = dofield (mactime[0], tm); p = savep; return (s); } /* Match found */ s = formfld (tm, ks, lead0, prec, &fldp); sresp = resp; if (s == OPTIONAL) { if (query) s = FAIL; else s = SUCCEED; } if (s == SUCCEED) { for (; *fldp; fldp++) result[resp++] = *fldp; casefix (&result[sresp], upcase); } return (s); } static char foldc (c) char c; { return (c < 'a' || c > 'z' ? c : c - 'a' + 'A'); } static char nstr[30]; static char sfield[30]; static int thmem; static formfld (tm, field, lead0, prec, result) struct tm *tm; int field, lead0, prec; char **result; { int fld, ddiff, s; struct tm ctm, *localtime (); long ctime, time (); sfield[0] = '\0'; *result = sfield; if (field != TH) thmem = -1; switch (field) { case NOON: if (tm->tm_hour == 12 && tm->tm_min == 0 && tm->tm_sec == 0) { *result = strings[SNOON]; return (SUCCEED); } return (FAIL); case HOUR: for (; prec > 2; prec--) strcat (sfield, " "); if (lead0) sprintf (nstr, "%02d", tm->tm_hour); else if (prec < 2) sprintf (nstr, "%d", (tm->tm_hour + 11) % 12 + 1); else sprintf (nstr, "%2d", (tm->tm_hour + 11) % 12 + 1); strcat (sfield, nstr); thmem = tm->tm_hour; return (tm->tm_hour >= 0 ? SUCCEED : FAIL); case MIN: fld = tm->tm_min; case SEC: if (field == SEC) fld = tm->tm_sec; if (prec == 0) prec = 2; for (; prec > 2; prec--) strcat (sfield, " "); if (prec < 2) sprintf (nstr, "%d", fld); else sprintf (nstr, "%02d", fld); strcat (sfield, nstr); thmem = fld; return (fld > 0 ? SUCCEED : (fld == 0 ? OPTIONAL : FAIL)); case AM: if (tm->tm_hour >= 12) *result = strings[SPM]; else if (tm->tm_hour >= 0) *result = strings[SAM]; return (tm->tm_hour >= 0 ? SUCCEED : FAIL); case WDAY: if (tm->tm_wday >= 0 && tm->tm_wday < 7) { copyword (sfield, strings[SWDAYS + tm->tm_wday], prec); return (SUCCEED); } return (FAIL); case MONTH: if (tm->tm_mon >= 0 && tm->tm_mon < 12) { copyword (sfield, strings[SMONTHS + tm->tm_mon], prec); return (SUCCEED); } return (FAIL); case DAY: fld = tm->tm_mday; case NMONTH: case YDAY: if (field == NMONTH) fld = tm->tm_mon + 1; else if (field == YDAY) fld = tm->tm_yday; if (prec == 0) prec = 1; if (lead0) { strcpy (nstr, "%09d"); nstr[2] = prec + '0'; } else { strcpy (nstr, "%9d"); nstr[1] = prec + '0'; } sprintf (sfield, nstr, fld); thmem = fld; return (fld >= 0 ? SUCCEED : FAIL); case TH: if (thmem >= 0) { if ((thmem / 10) % 10 == 1) *result = strings[STH]; else if (thmem % 10 == 1) *result = strings[SST]; else if (thmem % 10 == 2) *result = strings[SND]; else if (thmem % 10 == 3) *result = strings[SRD]; else *result = strings[STH]; return (SUCCEED); } return (FAIL); case YEAR: ctime = time (0); ctm = *localtime (&ctime); ddiff = (tm->tm_year - ctm.tm_year) * 366 + tm->tm_yday - ctm.tm_yday; if (tm->tm_year >= -1900) { if (prec == 0 || prec > 3) sprintf (nstr, "%04d", tm->tm_year + 1900); else sprintf (nstr, "%02d", (tm->tm_year + 1900) % 100); *result = nstr; return (ddiff < 0 || ddiff > 300 ? SUCCEED : OPTIONAL); } return (FAIL); case MIDNIGHT: if (tm->tm_hour == 0 && tm->tm_min == 0 && tm->tm_sec == 0) { *result = strings[SMIDNIGHT]; return (SUCCEED); } return (FAIL); } } /* copyword: Copy <from> to <to> subject to precision <prec>. Asterisks in * <from> mark valid truncation points. The longest string no longer than * <prec> and broken at a valid truncation point is returned in <to>. Note * that the result may exceed <prec> in length only if there are no valid * truncation points short enough. The shortest is then taken. * * e.g. Tue*s*day. Precision 1-3 -> Tue, Precision 4-6 -> Tues, * Precision 0 and 7... -> Tuesday. */ static copyword (to, from, prec) char *to, *from; int prec; { int ast = 0, top = 0; if (prec == 0) prec = 999; for (; *from; from++) { if (*from == '*') ast = top; else { to[top] = *from; top++; } if (top > prec && ast > 0) { /* Required precision exceeded and asterisk found */ to[ast] = '\0'; /* Truncate at asterisk */ return; } } to[top] = '\0'; return; } /* casefix: select case of word. 1: first letter raised. 2: all raised. */ static casefix (text, upcase) char *text; int upcase; { if (upcase == 1) *text = foldc (*text); else if (upcase > 0) foldup (text, text); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.