home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / strftm30 / part01 < prev    next >
Encoding:
Text File  |  1993-05-01  |  29.1 KB  |  1,183 lines

  1. Newsgroups: comp.sources.unix
  2. From: arnold@skeeve.atl.ga.us (Arnold Robbins)
  3. Subject: v26i208: strftime-3.0 - still more strftime(3) and date(1), Part01/01
  4. Sender: unix-sources-moderator@efficacy.home.vix.com
  5. Approved: WhoAmI@efficacy.home.vix.com
  6.  
  7. Submitted-By: arnold@skeeve.atl.ga.us (Arnold Robbins)
  8. Posting-Number: Volume 26, Issue 208
  9. Archive-Name: strftime-3.0/part01
  10.  
  11. Due to the impending release of 4.4 BSD, I had to do some work on gawk.  As
  12. part of that I updated my strftime+date package. Please post this ASAP,
  13. instead of 10 months from now... (:-)
  14.  
  15.     Thanks,
  16.  
  17.     arnold@skeeve.atl.ga.us (Arnold D. Robbins)
  18.  
  19. [ imagine the nerve of some people :-)... --vix ]
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 1 (of 1)."
  28. # Contents:  MANIFEST Makefile README date.1 date.c strftime.3
  29. #   strftime.c
  30. # Wrapped by vixie@efficacy.home.vix.com on Sun May  2 22:39:05 1993
  31. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  32. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  34. else
  35. echo shar: Extracting \"'MANIFEST'\" \(331 characters\)
  36. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  37. X   File Name        Archive #    Description
  38. X-----------------------------------------------------------
  39. X MANIFEST                   1    This shipping list
  40. X Makefile                   1    
  41. X README                     1    
  42. X date.1                     1    
  43. X date.c                     1    
  44. X strftime.3                 1    
  45. X strftime.c                 1    
  46. END_OF_FILE
  47. if test 331 -ne `wc -c <'MANIFEST'`; then
  48.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  49. fi
  50. # end of 'MANIFEST'
  51. fi
  52. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'Makefile'\"
  54. else
  55. echo shar: Extracting \"'Makefile'\" \(195 characters\)
  56. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  57. X# Makefile for PD date and strftime
  58. X
  59. XSRCS= date.c strftime.c
  60. XOBJS= date.o strftime.o
  61. XDOCS= date.1 strftime.3
  62. X
  63. Xdate: $(OBJS)
  64. X    $(CC) $(CFLAGS) $(OBJS) -o $@
  65. X
  66. Xdate.o: date.c
  67. X
  68. Xstrftime.o: strftime.c
  69. END_OF_FILE
  70. if test 195 -ne `wc -c <'Makefile'`; then
  71.     echo shar: \"'Makefile'\" unpacked with wrong size!
  72. fi
  73. # end of 'Makefile'
  74. fi
  75. if test -f 'README' -a "${1}" != "-c" ; then 
  76.   echo shar: Will not clobber existing file \"'README'\"
  77. else
  78. echo shar: Extracting \"'README'\" \(447 characters\)
  79. sed "s/^X//" >'README' <<'END_OF_FILE'
  80. XSun May  2 22:08:49 EDT 1993
  81. X
  82. XThis package implements the Posix 1003.2 date command, as a wrapper around
  83. Xan extended version of the ANSI strftime(3) library routine.
  84. XEverything in it is public domain.
  85. X
  86. XArnold Robbins -- The Basement Computer        | Laundry increases
  87. XInternet: arnold@skeeve.ATL.GA.US        | exponentially in the
  88. XUUCP:    { gatech, emory }!skeeve!arnold        | number of children.
  89. XBitnet:    Forget it. Get on a real network.    |    -- Miriam Robbins
  90. END_OF_FILE
  91. if test 447 -ne `wc -c <'README'`; then
  92.     echo shar: \"'README'\" unpacked with wrong size!
  93. fi
  94. # end of 'README'
  95. fi
  96. if test -f 'date.1' -a "${1}" != "-c" ; then 
  97.   echo shar: Will not clobber existing file \"'date.1'\"
  98. else
  99. echo shar: Extracting \"'date.1'\" \(1342 characters\)
  100. sed "s/^X//" >'date.1' <<'END_OF_FILE'
  101. X.TH DATE 1
  102. X.SH NAME
  103. Xdate \- write the date and time
  104. X.SH SYNOPSIS
  105. X.B date
  106. X[
  107. X.B \-u
  108. X] [
  109. X.RI + format
  110. X]
  111. X.SH DESCRIPTION
  112. X.I Date
  113. Xwrites the current date and time to the standard output.
  114. XIt is intended to be compliant with draft 11 of the Posix
  115. X1003.2 Command Language and Utilities standard.
  116. XTherefore, it is purposely
  117. X.I not
  118. Xusable by the super-user for setting the system time.
  119. X.LP
  120. X.I Date
  121. Xaccepts one option:
  122. X.TP
  123. X.B \-u
  124. XPerform operations as if the
  125. X.B TZ
  126. Xenvironment variable was set to
  127. X.BR GMT0 .
  128. X.LP
  129. XIf an argument to 
  130. X.I date
  131. Xis given that begins with a ``+'',
  132. Xthen the output is controlled by the contents of the rest of
  133. Xthe string.  Normal text is output unmodified, while field descriptors
  134. Xin the format string are substituted for.
  135. X.LP
  136. XThe
  137. X.I date
  138. Xprogram is essentially a wrapper around
  139. X.IR strftime (3);
  140. Xsee there for a description of the available formatting options.
  141. X.LP
  142. XIf no format string is given, or if it does not begin with a ``+'',
  143. Xthen the default format of \fB"%a %b %e %H:%M:%S %Z %Y"\fR will
  144. Xbe used.  This produces the traditional style of output, such as
  145. X``Sun Mar 17 10:32:47 EST 1991''.
  146. X.SH SEE ALSO
  147. Xtime(2), strftime(3), localtime(3)
  148. X.SH BUGS
  149. XThis version only works for the POSIX locale.
  150. X.SH AUTHOR
  151. X.nf
  152. XArnold Robbins
  153. X.sp
  154. XINTERNET: arnold@skeeve.atl.ga.us
  155. XUUCP:     emory!skeeve!arnold
  156. XPhone:    +1 404 248 9324
  157. X.fi
  158. END_OF_FILE
  159. if test 1342 -ne `wc -c <'date.1'`; then
  160.     echo shar: \"'date.1'\" unpacked with wrong size!
  161. fi
  162. # end of 'date.1'
  163. fi
  164. if test -f 'date.c' -a "${1}" != "-c" ; then 
  165.   echo shar: Will not clobber existing file \"'date.c'\"
  166. else
  167. echo shar: Extracting \"'date.c'\" \(1044 characters\)
  168. sed "s/^X//" >'date.c' <<'END_OF_FILE'
  169. X/*
  170. X * date.c
  171. X *
  172. X * Public domain implementation of Posix 1003.2 Draft 11
  173. X * date command.  Lets strftime() do the dirty work.
  174. X */
  175. X
  176. X#include <stdio.h>
  177. X#include <sys/types.h>
  178. X#include <time.h>
  179. X
  180. Xextern char *malloc();
  181. Xextern size_t strftime();
  182. Xextern int getopt();
  183. Xextern int optind;
  184. X
  185. Xint
  186. Xmain(argc, argv)
  187. Xint argc;
  188. Xchar **argv;
  189. X{
  190. X    time_t clock;
  191. X    struct tm *now;
  192. X    int c, size, ret;
  193. X    char *defhow = "%a %b %e %H:%M:%S %Z %Y";
  194. X    char *howto = defhow;
  195. X    char *buf;
  196. X
  197. X    while ((c = getopt(argc, argv, "u")) != -1)
  198. X        switch (c) {
  199. X        case 'u':
  200. X            putenv("TZ=GMT0");
  201. X            break;
  202. X        default:
  203. X            fprintf(stderr, "usage: %s [-u] [+format_str]\n",
  204. X                argv[0]);
  205. X            exit(1);
  206. X        }
  207. X
  208. X    time(& clock);
  209. X    now = localtime(& clock);
  210. X
  211. X    if (optind < argc && argv[optind][0] == '+')
  212. X        howto = & argv[optind][1];
  213. X
  214. X    size = strlen(howto) * 10;
  215. X    if ((buf = malloc(size)) == NULL) {
  216. X        perror("not enough memory");
  217. X        exit(1);
  218. X    }
  219. X
  220. X    ret = strftime(buf, size, howto, now);
  221. X    if (ret != 0)
  222. X        printf("%s\n", buf);
  223. X    else {
  224. X        fprintf(stderr, "conversion failed\n");
  225. X        exit(1);
  226. X    }
  227. X    
  228. X    exit(0);
  229. X}
  230. END_OF_FILE
  231. if test 1044 -ne `wc -c <'date.c'`; then
  232.     echo shar: \"'date.c'\" unpacked with wrong size!
  233. fi
  234. # end of 'date.c'
  235. fi
  236. if test -f 'strftime.3' -a "${1}" != "-c" ; then 
  237.   echo shar: Will not clobber existing file \"'strftime.3'\"
  238. else
  239. echo shar: Extracting \"'strftime.3'\" \(7705 characters\)
  240. sed "s/^X//" >'strftime.3' <<'END_OF_FILE'
  241. X.TH STRFTIME 3
  242. X.SH NAME
  243. Xstrftime \- generate formatted time information
  244. X.SH SYNOPSIS
  245. X.ft B
  246. X.nf
  247. X#include <sys/types.h>
  248. X#include <time.h>
  249. X.sp
  250. Xsize_t strftime(char *s, size_t maxsize, const char *format,
  251. X    const struct tm *timeptr);
  252. X.SH DESCRIPTION
  253. XThe following description is transcribed verbatim from the December 7, 1988
  254. Xdraft standard for ANSI C.
  255. XThis draft is essentially identical in technical content
  256. Xto the final version of the standard.
  257. X.LP
  258. XThe
  259. X.B strftime
  260. Xfunction places characters into the array pointed to by
  261. X.B s
  262. Xas controlled by the string pointed to by
  263. X.BR format .
  264. XThe format shall be a multibyte character sequence, beginning and ending in
  265. Xits initial shift state.
  266. XThe
  267. X.B format
  268. Xstring consists of zero or more conversion specifiers and ordinary
  269. Xmultibyte characters.  A conversion specifier consists of a
  270. X.B %
  271. Xcharacter followed by a character that determines the behavior of the
  272. Xconversion specifier.
  273. XAll ordinary multibyte characters (including the terminating null
  274. Xcharacter) are copied unchanged into the array.
  275. XIf copying takes place between objects that overlap the behavior is undefined.
  276. XNo more than
  277. X.B maxsize
  278. Xcharacters are placed into the array.
  279. XEach conversion specifier is replaced by appropriate characters as described
  280. Xin the following list.
  281. XThe appropriate characters are determined by the
  282. X.B LC_TIME
  283. Xcategory of the current locale and by the values contained in the
  284. Xstructure pointed to by
  285. X.BR timeptr .
  286. X.TP
  287. X.B %a
  288. Xis replaced by the locale's abbreviated weekday name.
  289. X.TP
  290. X.B %A
  291. Xis replaced by the locale's full weekday name.
  292. X.TP
  293. X.B %b
  294. Xis replaced by the locale's abbreviated month name.
  295. X.TP
  296. X.B %B
  297. Xis replaced by the locale's full month name.
  298. X.TP
  299. X.B %c
  300. Xis replaced by the locale's appropriate date and time representation.
  301. X.TP
  302. X.B %d
  303. Xis replaced by the day of the month as a decimal number
  304. X.RB ( 01 - 31 ).
  305. X.TP
  306. X.B %H
  307. Xis replaced by the hour (24-hour clock) as a decimal number
  308. X.RB ( 00 - 23 ).
  309. X.TP
  310. X.B %I
  311. Xis replaced by the hour (12-hour clock) as a decimal number
  312. X.RB ( 01 - 12 ).
  313. X.TP
  314. X.B %j
  315. Xis replaced by the day of the year as a decimal number
  316. X.RB ( 001 - 366 ).
  317. X.TP
  318. X.B %m
  319. Xis replaced by the month as a decimal number
  320. X.RB ( 01 - 12 ).
  321. X.TP
  322. X.B %M
  323. Xis replaced by the minute as a decimal number
  324. X.RB ( 00 - 59 ).
  325. X.TP
  326. X.B %p
  327. Xis replaced by the locale's equivalent of the AM/PM designations associated
  328. Xwith a 12-hour clock.
  329. X.TP
  330. X.B %S
  331. Xis replaced by the second as a decimal number
  332. X.RB ( 00 - 61 ).
  333. X.TP
  334. X.B %U
  335. Xis replaced by the week number of the year (the first Sunday as the first
  336. Xday of week 1) as a decimal number
  337. X.RB ( 00 - 53 ).
  338. X.TP
  339. X.B %w
  340. Xis replaced by the weekday as a decimal number
  341. X.RB [ "0 " (Sunday)- 6 ].
  342. X.TP
  343. X.B %W
  344. Xis replaced by the week number of the year (the first Monday as the first
  345. Xday of week 1) as a decimal number
  346. X.RB ( 00 - 53 ).
  347. X.TP
  348. X.B %x
  349. Xis replaced by the locale's appropriate date representation.
  350. X.TP
  351. X.B %X
  352. Xis replaced by the locale's appropriate time representation.
  353. X.TP
  354. X.B %y
  355. Xis replaced by the year without century as a decimal number
  356. X.RB ( 00 - 99 ).
  357. X.TP
  358. X.B %Y
  359. Xis replaced by the year with century as a decimal number.
  360. X.TP
  361. X.B %Z
  362. Xis replaced by the time zone name or abbreviation, or by no characters if
  363. Xno time zone is determinable.
  364. X.TP
  365. X.B %%
  366. Xis replaced by
  367. X.BR % .
  368. X.LP
  369. XIf a conversion specifier is not one of the above, the behavior is
  370. Xundefined.
  371. X.SH RETURNS
  372. XIf the total number of resulting characters including the terminating null
  373. Xcharacter is not more than
  374. X.BR maxsize ,
  375. Xthe
  376. X.B strftime
  377. Xfunction returns the number of characters placed into the array pointed to
  378. Xby
  379. X.B s
  380. Xnot including the terminating null character.
  381. XOtherwise, zero is returned and the contents of the array are indeterminate.
  382. X.SH NON-ANSI EXTENSIONS
  383. XIf
  384. X.B SYSV_EXT
  385. Xis defined when the routine is compiled, then the following additional
  386. Xconversions will be available.
  387. XThese are borrowed from the System V
  388. X.IR cftime (3)
  389. Xand
  390. X.IR ascftime (3)
  391. Xroutines.
  392. X.TP
  393. X.B %D
  394. Xis equivalent to specifying
  395. X.BR %m/%d/%y .
  396. X.TP
  397. X.B %e
  398. Xis replaced by the day of the month,
  399. Xpadded with a blank if it is only one digit.
  400. X.TP
  401. X.B %h
  402. Xis equivalent to
  403. X.BR %b ,
  404. Xabove.
  405. X.TP
  406. X.B %n
  407. Xis replaced with a newline character (\s-1ASCII LF\s+1).
  408. X.TP
  409. X.B %r
  410. Xis equivalent to specifying
  411. X.BR "%I:%M:%S %p" .
  412. X.TP
  413. X.B %R
  414. Xis equivalent to specifying
  415. X.BR %H:%M .
  416. X.TP
  417. X.B %T
  418. Xis equivalent to specifying
  419. X.BR %H:%M:%S .
  420. X.TP
  421. X.B %t
  422. Xis replaced with a \s-1TAB\s+1 character.
  423. X.PP
  424. XIf
  425. X.B SUNOS_EXT
  426. Xis defined when the routine is compiled, then the following additional
  427. Xconversions will be available.
  428. XThese are borrowed from the SunOS version of
  429. X.IR strftime .
  430. X.TP
  431. X.B %k
  432. Xis replaced by the hour (24-hour clock) as a decimal number
  433. X.RB ( 0 - 23 ).
  434. XSingle digit numbers are padded with a blank.
  435. X.TP
  436. X.B %l
  437. Xis replaced by the hour (12-hour clock) as a decimal number
  438. X.RB ( 1 - 12 ).
  439. XSingle digit numbers are padded with a blank.
  440. X.SH POSIX 1003.2 EXTENSIONS
  441. XIf
  442. X.B POSIX2_DATE
  443. Xis defined, then all of the conversions available with
  444. X.B SYSV_EXT
  445. Xand
  446. X.B SUNOS_EXT
  447. Xare available, as well as the
  448. Xfollowing additional conversions:
  449. X.TP
  450. X.B %C
  451. XThe century, as a number between 00 and 99.
  452. X.TP
  453. X.B %u
  454. Xis replaced by the weekday as a decimal number
  455. X.RB [ "1 " (Monday)- 7 ].
  456. X.TP
  457. X.B %V
  458. Xis replaced by the week number of the year (the first Monday as the first
  459. Xday of week 1) as a decimal number
  460. X.RB ( 01 - 53 ).
  461. XThe method for determining the week number is as specified by ISO 8601
  462. X(to wit: if the week containing January 1 has four or more days in the
  463. Xnew year, then it is week 1, otherwise it is week 53 of the previous year
  464. Xand the next week is week 1).
  465. X.LP
  466. XThe text of the POSIX standard for the
  467. X.I date
  468. Xutility describes
  469. X.B %U
  470. Xand
  471. X.B %W
  472. Xthis way:
  473. X.TP
  474. X.B %U
  475. Xis replaced by the week number of the year (the first Sunday as the first
  476. Xday of week 1) as a decimal number
  477. X.RB ( 00 - 53 ).
  478. XAll days in a new year preceding the first Sunday are considered to be
  479. Xin week 0.
  480. X.TP
  481. X.B %W
  482. Xis replaced by the week number of the year (the first Monday as the first
  483. Xday of week 1) as a decimal number
  484. X.RB ( 00 - 53 ).
  485. XAll days in a new year preceding the first Sunday are considered to be
  486. Xin week 0.
  487. X(Note: this last statement is quoted verbatim from the POSIX standard.
  488. XIt probably means to say ``all days in a new year preceding the first
  489. X.I Monday
  490. Xare considered to be in week 0.'')
  491. X.LP
  492. XIn addition, the alternate representations
  493. X.BR %Ec ,
  494. X.BR %EC ,
  495. X.BR %Ex ,
  496. X.BR %Ey ,
  497. X.BR %EY ,
  498. X.BR %Od ,
  499. X.BR %Oe ,
  500. X.BR %OH ,
  501. X.BR %OI ,
  502. X.BR %Om ,
  503. X.BR %OM ,
  504. X.BR %OS ,
  505. X.BR %Ou ,
  506. X.BR %OU ,
  507. X.BR %OV ,
  508. X.BR %Ow ,
  509. X.BR %OW ,
  510. Xand
  511. X.B %Oy
  512. Xare recognized, but their normal representations are used.
  513. X.SH VMS EXTENSIONS
  514. XIf
  515. X.B VMS_EXT
  516. Xis defined, then the following additional conversion is available:
  517. X.TP
  518. X.B %v
  519. XThe date in VMS format (e.g. 20-JUN-1991).
  520. X.SH SEE ALSO
  521. X.IR time (2),
  522. X.IR ctime (3),
  523. X.IR localtime (3),
  524. X.IR tzset (3)
  525. X.SH BUGS
  526. XThis version does not handle multibyte characters or pay attention to the
  527. Xsetting of the
  528. X.B LC_TIME
  529. Xenvironment variable.
  530. X.LP
  531. XIt is not clear what is ``appropriate'' for the C locale; the values
  532. Xreturned are a best guess on the author's part.
  533. X.SH CAVEATS
  534. XThe pre-processor symbol
  535. X.B POSIX_SEMANTICS
  536. Xis automatically defined, which forces the code to call
  537. X.IR tzset (3)
  538. Xwhenever the
  539. X.B TZ
  540. Xenvironment variable has changed.
  541. XIf this routine will be used in an application that will not be changing
  542. X.BR TZ ,
  543. Xthen there may be some performance improvements by not defining
  544. X.BR POSIX_SEMANTICS .
  545. X.SH AUTHOR
  546. X.nf
  547. XArnold Robbins
  548. X.sp
  549. XINTERNET: arnold@skeeve.atl.ga.us
  550. XUUCP:     emory!skeeve!arnold
  551. XPhone:    +1 404 248 9324
  552. X.fi
  553. X.SH ACKNOWLEDGEMENTS
  554. XThanks to Geoff Clare <gwc@root.co.uk> for helping debug earlier
  555. Xversions of this routine, and for advice about POSIX semantics.
  556. XAdditional thanks to Arthur David Olsen <ado@elsie.nci.nih.gov>
  557. Xfor some code improvements.
  558. END_OF_FILE
  559. if test 7705 -ne `wc -c <'strftime.3'`; then
  560.     echo shar: \"'strftime.3'\" unpacked with wrong size!
  561. fi
  562. # end of 'strftime.3'
  563. fi
  564. if test -f 'strftime.c' -a "${1}" != "-c" ; then 
  565.   echo shar: Will not clobber existing file \"'strftime.c'\"
  566. else
  567. echo shar: Extracting \"'strftime.c'\" \(13629 characters\)
  568. sed "s/^X//" >'strftime.c' <<'END_OF_FILE'
  569. X/*
  570. X * strftime.c
  571. X *
  572. X * Public-domain relatively quick-and-dirty implementation of
  573. X * ANSI library routine for System V Unix systems.
  574. X *
  575. X * It's written in old-style C for maximal portability.
  576. X * However, since I'm used to prototypes, I've included them too.
  577. X *
  578. X * If you want stuff in the System V ascftime routine, add the SYSV_EXT define.
  579. X * For extensions from SunOS, add SUNOS_EXT.
  580. X * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
  581. X * For complete POSIX semantics, add POSIX_SEMANTICS.
  582. X *
  583. X * The code for %c, %x, and %X is my best guess as to what's "appropriate".
  584. X * This version ignores LOCALE information.
  585. X * It also doesn't worry about multi-byte characters.
  586. X * So there.
  587. X *
  588. X * This file is also shipped with GAWK (GNU Awk), gawk specific bits of
  589. X * code are included if GAWK is defined.
  590. X *
  591. X * Arnold Robbins
  592. X * January, February, March, 1991
  593. X * Updated March, April 1992
  594. X * Updated May, 1993
  595. X *
  596. X * Fixes from ado@elsie.nci.nih.gov
  597. X * February 1991, May 1992
  598. X */
  599. X
  600. X#ifndef GAWK
  601. X#include <stdio.h>
  602. X#include <ctype.h>
  603. X#include <string.h>
  604. X#include <time.h>
  605. X#include <sys/types.h>
  606. X#endif
  607. X
  608. X/* defaults: season to taste */
  609. X#define SYSV_EXT    1    /* stuff in System V ascftime routine */
  610. X#define SUNOS_EXT    1    /* stuff in SunOS strftime routine */
  611. X#define POSIX2_DATE    1    /* stuff in Posix 1003.2 date command */
  612. X#define VMS_EXT        1    /* include %v for VMS date format */
  613. X#ifndef GAWK
  614. X#define POSIX_SEMANTICS    1    /* call tzset() if TZ changes */
  615. X#endif
  616. X
  617. X#if defined(POSIX2_DATE)
  618. X#if ! defined(SYSV_EXT)
  619. X#define SYSV_EXT    1
  620. X#endif
  621. X#if ! defined(SUNOS_EXT)
  622. X#define SUNOS_EXT    1
  623. X#endif
  624. X#endif
  625. X
  626. X#if defined(POSIX2_DATE)
  627. X#define adddecl(stuff)    stuff
  628. X#else
  629. X#define adddecl(stuff)
  630. X#endif
  631. X
  632. X#undef strchr    /* avoid AIX weirdness */
  633. X
  634. X#ifndef __STDC__
  635. X#define const    /**/
  636. Xextern void *malloc();
  637. Xextern void *realloc();
  638. Xextern void tzset();
  639. Xextern char *strchr();
  640. Xextern char *getenv();
  641. Xstatic int weeknumber();
  642. Xadddecl(static int iso8601wknum();)
  643. X#else
  644. Xextern void *malloc(unsigned count);
  645. Xextern void *realloc(void *ptr, unsigned count);
  646. Xextern void tzset(void);
  647. Xextern char *strchr(const char *str, int ch);
  648. Xextern char *getenv(const char *v);
  649. Xstatic int weeknumber(const struct tm *timeptr, int firstweekday);
  650. Xadddecl(static int iso8601wknum(const struct tm *timeptr);)
  651. X#endif
  652. X
  653. X#ifdef __GNUC__
  654. X#define inline    __inline__
  655. X#else
  656. X#define inline    /**/
  657. X#endif
  658. X
  659. X#define range(low, item, hi)    max(low, min(item, hi))
  660. X
  661. X#if !defined(MSDOS) && !defined(TZNAME_MISSING)
  662. Xextern char *tzname[2];
  663. Xextern int daylight;
  664. X#endif
  665. X
  666. X/* min --- return minimum of two numbers */
  667. X
  668. X#ifndef __STDC__
  669. Xstatic inline int
  670. Xmin(a, b)
  671. Xint a, b;
  672. X#else
  673. Xstatic inline int
  674. Xmin(int a, int b)
  675. X#endif
  676. X{
  677. X    return (a < b ? a : b);
  678. X}
  679. X
  680. X/* max --- return maximum of two numbers */
  681. X
  682. X#ifndef __STDC__
  683. Xstatic inline int
  684. Xmax(a, b)
  685. Xint a, b;
  686. X#else
  687. Xstatic inline int
  688. Xmax(int a, int b)
  689. X#endif
  690. X{
  691. X    return (a > b ? a : b);
  692. X}
  693. X
  694. X/* strftime --- produce formatted time */
  695. X
  696. X#ifndef __STDC__
  697. Xsize_t
  698. Xstrftime(s, maxsize, format, timeptr)
  699. Xchar *s;
  700. Xsize_t maxsize;
  701. Xconst char *format;
  702. Xconst struct tm *timeptr;
  703. X#else
  704. Xsize_t
  705. Xstrftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
  706. X#endif
  707. X{
  708. X    char *endp = s + maxsize;
  709. X    char *start = s;
  710. X    char tbuf[100];
  711. X    int i;
  712. X    static short first = 1;
  713. X#ifdef POSIX_SEMANTICS
  714. X    static char *savetz = NULL;
  715. X    static int savetzlen = 0;
  716. X    char *tz;
  717. X#endif /* POSIX_SEMANTICS */
  718. X
  719. X    /* various tables, useful in North America */
  720. X    static char *days_a[] = {
  721. X        "Sun", "Mon", "Tue", "Wed",
  722. X        "Thu", "Fri", "Sat",
  723. X    };
  724. X    static char *days_l[] = {
  725. X        "Sunday", "Monday", "Tuesday", "Wednesday",
  726. X        "Thursday", "Friday", "Saturday",
  727. X    };
  728. X    static char *months_a[] = {
  729. X        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  730. X        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
  731. X    };
  732. X    static char *months_l[] = {
  733. X        "January", "February", "March", "April",
  734. X        "May", "June", "July", "August", "September",
  735. X        "October", "November", "December",
  736. X    };
  737. X    static char *ampm[] = { "AM", "PM", };
  738. X
  739. X    if (s == NULL || format == NULL || timeptr == NULL || maxsize == 0)
  740. X        return 0;
  741. X
  742. X    if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize)
  743. X        return 0;
  744. X
  745. X#ifndef POSIX_SEMANTICS
  746. X    if (first) {
  747. X        tzset();
  748. X        first = 0;
  749. X    }
  750. X#else    /* POSIX_SEMANTICS */
  751. X    tz = getenv("TZ");
  752. X    if (first) {
  753. X        if (tz != NULL) {
  754. X            int tzlen = strlen(tz);
  755. X
  756. X            savetz = (char *) malloc(tzlen + 1);
  757. X            if (savetz != NULL) {
  758. X                savetzlen = tzlen + 1;
  759. X                strcpy(savetz, tz);
  760. X            }
  761. X        }
  762. X        tzset();
  763. X        first = 0;
  764. X    }
  765. X    /* if we have a saved TZ, and it is different, recapture and reset */
  766. X    if (tz && savetz && (tz[0] != savetz[0] || strcmp(tz, savetz) != 0)) {
  767. X        i = strlen(tz) + 1;
  768. X        if (i > savetzlen) {
  769. X            savetz = (char *) realloc(savetz, i);
  770. X            if (savetz) {
  771. X                savetzlen = i;
  772. X                strcpy(savetz, tz);
  773. X            }
  774. X        } else
  775. X            strcpy(savetz, tz);
  776. X        tzset();
  777. X    }
  778. X#endif    /* POSIX_SEMANTICS */
  779. X
  780. X    for (; *format && s < endp - 1; format++) {
  781. X        tbuf[0] = '\0';
  782. X        if (*format != '%') {
  783. X            *s++ = *format;
  784. X            continue;
  785. X        }
  786. X    again:
  787. X        switch (*++format) {
  788. X        case '\0':
  789. X            *s++ = '%';
  790. X            goto out;
  791. X
  792. X        case '%':
  793. X            *s++ = '%';
  794. X            continue;
  795. X
  796. X        case 'a':    /* abbreviated weekday name */
  797. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  798. X                strcpy(tbuf, "?");
  799. X            else
  800. X                strcpy(tbuf, days_a[timeptr->tm_wday]);
  801. X            break;
  802. X
  803. X        case 'A':    /* full weekday name */
  804. X            if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
  805. X                strcpy(tbuf, "?");
  806. X            else
  807. X                strcpy(tbuf, days_l[timeptr->tm_wday]);
  808. X            break;
  809. X
  810. X#ifdef SYSV_EXT
  811. X        case 'h':    /* abbreviated month name */
  812. X#endif
  813. X        case 'b':    /* abbreviated month name */
  814. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  815. X                strcpy(tbuf, "?");
  816. X            else
  817. X                strcpy(tbuf, months_a[timeptr->tm_mon]);
  818. X            break;
  819. X
  820. X        case 'B':    /* full month name */
  821. X            if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
  822. X                strcpy(tbuf, "?");
  823. X            else
  824. X                strcpy(tbuf, months_l[timeptr->tm_mon]);
  825. X            break;
  826. X
  827. X        case 'c':    /* appropriate date and time representation */
  828. X            sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
  829. X                days_a[range(0, timeptr->tm_wday, 6)],
  830. X                months_a[range(0, timeptr->tm_mon, 11)],
  831. X                range(1, timeptr->tm_mday, 31),
  832. X                range(0, timeptr->tm_hour, 23),
  833. X                range(0, timeptr->tm_min, 59),
  834. X                range(0, timeptr->tm_sec, 61),
  835. X                timeptr->tm_year + 1900);
  836. X            break;
  837. X
  838. X        case 'd':    /* day of the month, 01 - 31 */
  839. X            i = range(1, timeptr->tm_mday, 31);
  840. X            sprintf(tbuf, "%02d", i);
  841. X            break;
  842. X
  843. X        case 'H':    /* hour, 24-hour clock, 00 - 23 */
  844. X            i = range(0, timeptr->tm_hour, 23);
  845. X            sprintf(tbuf, "%02d", i);
  846. X            break;
  847. X
  848. X        case 'I':    /* hour, 12-hour clock, 01 - 12 */
  849. X            i = range(0, timeptr->tm_hour, 23);
  850. X            if (i == 0)
  851. X                i = 12;
  852. X            else if (i > 12)
  853. X                i -= 12;
  854. X            sprintf(tbuf, "%02d", i);
  855. X            break;
  856. X
  857. X        case 'j':    /* day of the year, 001 - 366 */
  858. X            sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
  859. X            break;
  860. X
  861. X        case 'm':    /* month, 01 - 12 */
  862. X            i = range(0, timeptr->tm_mon, 11);
  863. X            sprintf(tbuf, "%02d", i + 1);
  864. X            break;
  865. X
  866. X        case 'M':    /* minute, 00 - 59 */
  867. X            i = range(0, timeptr->tm_min, 59);
  868. X            sprintf(tbuf, "%02d", i);
  869. X            break;
  870. X
  871. X        case 'p':    /* am or pm based on 12-hour clock */
  872. X            i = range(0, timeptr->tm_hour, 23);
  873. X            if (i < 12)
  874. X                strcpy(tbuf, ampm[0]);
  875. X            else
  876. X                strcpy(tbuf, ampm[1]);
  877. X            break;
  878. X
  879. X        case 'S':    /* second, 00 - 61 */
  880. X            i = range(0, timeptr->tm_sec, 61);
  881. X            sprintf(tbuf, "%02d", i);
  882. X            break;
  883. X
  884. X        case 'U':    /* week of year, Sunday is first day of week */
  885. X            sprintf(tbuf, "%d", weeknumber(timeptr, 0));
  886. X            break;
  887. X
  888. X        case 'w':    /* weekday, Sunday == 0, 0 - 6 */
  889. X            i = range(0, timeptr->tm_wday, 6);
  890. X            sprintf(tbuf, "%d", i);
  891. X            break;
  892. X
  893. X        case 'W':    /* week of year, Monday is first day of week */
  894. X            sprintf(tbuf, "%d", weeknumber(timeptr, 1));
  895. X            break;
  896. X
  897. X        case 'x':    /* appropriate date representation */
  898. X            sprintf(tbuf, "%s %s %2d %d",
  899. X                days_a[range(0, timeptr->tm_wday, 6)],
  900. X                months_a[range(0, timeptr->tm_mon, 11)],
  901. X                range(1, timeptr->tm_mday, 31),
  902. X                timeptr->tm_year + 1900);
  903. X            break;
  904. X
  905. X        case 'X':    /* appropriate time representation */
  906. X            sprintf(tbuf, "%02d:%02d:%02d",
  907. X                range(0, timeptr->tm_hour, 23),
  908. X                range(0, timeptr->tm_min, 59),
  909. X                range(0, timeptr->tm_sec, 61));
  910. X            break;
  911. X
  912. X        case 'y':    /* year without a century, 00 - 99 */
  913. X            i = timeptr->tm_year % 100;
  914. X            sprintf(tbuf, "%d", i);
  915. X            break;
  916. X
  917. X        case 'Y':    /* year with century */
  918. X            sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
  919. X            break;
  920. X
  921. X        case 'Z':    /* time zone name or abbrevation */
  922. X            i = 0;
  923. X            if (
  924. X#ifndef TZNAME_MISSING
  925. X                daylight &&
  926. X#endif
  927. X                timeptr->tm_isdst)
  928. X                i = 1;
  929. X#ifdef TZNAME_MISSING
  930. X            strcpy(tbuf, timeptr->tm_zone);
  931. X#else
  932. X            strcpy(tbuf, tzname[i]);
  933. X#endif
  934. X            break;
  935. X
  936. X#ifdef SYSV_EXT
  937. X        case 'n':    /* same as \n */
  938. X            tbuf[0] = '\n';
  939. X            tbuf[1] = '\0';
  940. X            break;
  941. X
  942. X        case 't':    /* same as \t */
  943. X            tbuf[0] = '\t';
  944. X            tbuf[1] = '\0';
  945. X            break;
  946. X
  947. X        case 'D':    /* date as %m/%d/%y */
  948. X            strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);
  949. X            break;
  950. X
  951. X        case 'e':    /* day of month, blank padded */
  952. X            sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
  953. X            break;
  954. X
  955. X        case 'r':    /* time as %I:%M:%S %p */
  956. X            strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);
  957. X            break;
  958. X
  959. X        case 'R':    /* time as %H:%M */
  960. X            strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);
  961. X            break;
  962. X
  963. X        case 'T':    /* time as %H:%M:%S */
  964. X            strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);
  965. X            break;
  966. X#endif
  967. X
  968. X#ifdef SUNOS_EXT
  969. X        case 'k':    /* hour, 24-hour clock, blank pad */
  970. X            sprintf(tbuf, "%2d", range(0, timeptr->tm_hour, 23));
  971. X            break;
  972. X
  973. X        case 'l':    /* hour, 12-hour clock, 1 - 12, blank pad */
  974. X            i = range(0, timeptr->tm_hour, 23);
  975. X            if (i == 0)
  976. X                i = 12;
  977. X            else if (i > 12)
  978. X                i -= 12;
  979. X            sprintf(tbuf, "%2d", i);
  980. X            break;
  981. X#endif
  982. X
  983. X
  984. X#ifdef VMS_EXT
  985. X        case 'v':    /* date as dd-bbb-YYYY */
  986. X            sprintf(tbuf, "%2d-%3.3s-%4d",
  987. X                range(1, timeptr->tm_mday, 31),
  988. X                months_a[range(0, timeptr->tm_mon, 11)],
  989. X                timeptr->tm_year + 1900);
  990. X            for (i = 3; i < 6; i++)
  991. X                if (islower(tbuf[i]))
  992. X                    tbuf[i] = toupper(tbuf[i]);
  993. X            break;
  994. X#endif
  995. X
  996. X
  997. X#ifdef POSIX2_DATE
  998. X        case 'C':
  999. X            sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
  1000. X            break;
  1001. X
  1002. X
  1003. X        case 'E':
  1004. X        case 'O':
  1005. X            /* POSIX locale extensions, ignored for now */
  1006. X            goto again;
  1007. X
  1008. X        case 'V':    /* week of year according ISO 8601 */
  1009. X#if defined(GAWK) && defined(VMS_EXT)
  1010. X        {
  1011. X            extern int do_lint;
  1012. X            extern void warning();
  1013. X            static int warned = 0;
  1014. X
  1015. X            if (! warned && do_lint) {
  1016. X                warned = 1;
  1017. X                warning(
  1018. X    "conversion %%V added in P1003.2/11.3; for VMS style date, use %%v");
  1019. X            }
  1020. X        }
  1021. X#endif
  1022. X            sprintf(tbuf, "%d", iso8601wknum(timeptr));
  1023. X            break;
  1024. X
  1025. X        case 'u':
  1026. X        /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
  1027. X            sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
  1028. X                    timeptr->tm_wday);
  1029. X            break;
  1030. X#endif    /* POSIX2_DATE */
  1031. X        default:
  1032. X            tbuf[0] = '%';
  1033. X            tbuf[1] = *format;
  1034. X            tbuf[2] = '\0';
  1035. X            break;
  1036. X        }
  1037. X        i = strlen(tbuf);
  1038. X        if (i)
  1039. X            if (s + i < endp - 1) {
  1040. X                strcpy(s, tbuf);
  1041. X                s += i;
  1042. X            } else
  1043. X                return 0;
  1044. X    }
  1045. Xout:
  1046. X    if (s < endp && *format == '\0') {
  1047. X        *s = '\0';
  1048. X        return (s - start);
  1049. X    } else
  1050. X        return 0;
  1051. X}
  1052. X
  1053. X#ifdef POSIX2_DATE
  1054. X/* iso8601wknum --- compute week number according to ISO 8601 */
  1055. X
  1056. X#ifndef __STDC__
  1057. Xstatic int
  1058. Xiso8601wknum(timeptr)
  1059. Xconst struct tm *timeptr;
  1060. X#else
  1061. Xstatic int
  1062. Xiso8601wknum(const struct tm *timeptr)
  1063. X#endif
  1064. X{
  1065. X    /*
  1066. X     * From 1003.2 D11.3:
  1067. X     *    If the week (Monday to Sunday) containing January 1
  1068. X     *    has four or more days in the new year, then it is week 1;
  1069. X     *    otherwise it is week 53 of the previous year, and the
  1070. X     *    next week is week 1.
  1071. X     *
  1072. X     * ADR: This means if Jan 1 was Monday through Thursday,
  1073. X     *    it was week 1, otherwise week 53.
  1074. X     */
  1075. X
  1076. X    int simple_wknum, jan1day, diff, ret;
  1077. X
  1078. X    /* get week number, Monday as first day of the week */
  1079. X    simple_wknum = weeknumber(timeptr, 1) + 1;
  1080. X
  1081. X    /*
  1082. X     * With thanks and tip of the hatlo to ado@elsie.nci.nih.gov
  1083. X     *
  1084. X     * What day of the week does January 1 fall on?
  1085. X     * We know that
  1086. X     *    (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
  1087. X     *        (timeptr->tm_wday - jan1.tm_wday) MOD 7
  1088. X     * and that
  1089. X     *     jan1.tm_yday == 1
  1090. X     * and that
  1091. X     *     timeptr->tm_wday MOD 7 == timeptr->tm_wday
  1092. X     * from which it follows that. . .
  1093. X      */
  1094. X    jan1day = (timeptr->tm_yday - 1) % 7 - timeptr->tm_wday;
  1095. X    if (jan1day < 0)
  1096. X        jan1day += 7;
  1097. X
  1098. X    /*
  1099. X     * If Jan 1 was a Monday through Thursday, it was in
  1100. X     * week 1.  Otherwise it was last year's week 53, which is
  1101. X     * this year's week 0.
  1102. X     */
  1103. X    if (jan1day >= 1 && jan1day <= 4)
  1104. X        diff = 0;
  1105. X    else
  1106. X        diff = 1;
  1107. X    ret = simple_wknum - diff;
  1108. X    if (ret == 0)    /* we're in the first week of the year */
  1109. X        ret = 53;
  1110. X    return ret;
  1111. X}
  1112. X#endif
  1113. X
  1114. X/* weeknumber --- figure how many weeks into the year */
  1115. X
  1116. X/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
  1117. X
  1118. X#ifndef __STDC__
  1119. Xstatic int
  1120. Xweeknumber(timeptr, firstweekday)
  1121. Xconst struct tm *timeptr;
  1122. Xint firstweekday;
  1123. X#else
  1124. Xstatic int
  1125. Xweeknumber(const struct tm *timeptr, int firstweekday)
  1126. X#endif
  1127. X{
  1128. X    if (firstweekday == 0)
  1129. X        return (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7;
  1130. X    else
  1131. X        return (timeptr->tm_yday + 7 -
  1132. X            (timeptr->tm_wday ? (timeptr->tm_wday - 1) : 6)) / 7;
  1133. X}
  1134. X
  1135. X#if 0
  1136. X/* ADR --- I'm loathe to mess with ado's code ... */
  1137. X
  1138. XDate:         Wed, 24 Apr 91 20:54:08 MDT
  1139. XFrom: Michal Jaegermann <audfax!emory!vm.ucs.UAlberta.CA!NTOMCZAK>
  1140. XTo: arnold@audiofax.com
  1141. X
  1142. XHi Arnold,
  1143. Xin a process of fixing of strftime() in libraries on Atari ST I grabbed
  1144. Xsome pieces of code from your own strftime.  When doing that it came
  1145. Xto mind that your weeknumber() function compiles a little bit nicer
  1146. Xin the following form:
  1147. X/*
  1148. X * firstweekday is 0 if starting in Sunday, non-zero if in Monday
  1149. X */
  1150. X{
  1151. X    return (timeptr->tm_yday - timeptr->tm_wday +
  1152. X        (firstweekday ? (timeptr->tm_wday ? 8 : 1) : 7)) / 7;
  1153. X}
  1154. XHow nicer it depends on a compiler, of course, but always a tiny bit.
  1155. X
  1156. X   Cheers,
  1157. X   Michal
  1158. X   ntomczak@vm.ucs.ualberta.ca
  1159. X#endif
  1160. END_OF_FILE
  1161. if test 13629 -ne `wc -c <'strftime.c'`; then
  1162.     echo shar: \"'strftime.c'\" unpacked with wrong size!
  1163. fi
  1164. # end of 'strftime.c'
  1165. fi
  1166. echo shar: End of archive 1 \(of 1\).
  1167. cp /dev/null ark1isdone
  1168. MISSING=""
  1169. for I in 1 ; do
  1170.     if test ! -f ark${I}isdone ; then
  1171.     MISSING="${MISSING} ${I}"
  1172.     fi
  1173. done
  1174. if test "${MISSING}" = "" ; then
  1175.     echo You have the archive.
  1176.     rm -f ark[1-9]isdone
  1177. else
  1178.     echo You still need to unpack the following archives:
  1179.     echo "        " ${MISSING}
  1180. fi
  1181. ##  End of shell archive.
  1182. exit 0
  1183.