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.