home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / arc5.21 / part05 < prev    next >
Text File  |  1988-06-30  |  65KB  |  2,514 lines

  1. Subject:  v15i081:  ARC (PC compression program), v5.21, Part05/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: hyc@math.lsa.umich.edu
  7. Posting-number: Volume 15, Issue 81
  8. Archive-name: arc5.21/part05
  9.  
  10. #--------------------------------CUT HERE-------------------------------------
  11. #! /bin/sh
  12. #
  13. # This is a shell archive.  Save this into a file, edit it
  14. # and delete all lines above this comment.  Then give this
  15. # file to sh by executing the command "sh file".  The files
  16. # will be extracted into the current directory owned by
  17. # you with default permissions.
  18. #
  19. # The files contained herein are:
  20. #
  21. # -rw-r--r--  1 hyc         11514 Jun 13 13:54 arcsqs.c
  22. # -rw-r--r--  1 hyc          4680 Jun 13 00:43 arcsvc.c
  23. # -rw-r--r--  1 hyc          1284 Apr 19 01:40 arctst.c
  24. # -rw-r--r--  1 hyc          5347 Jun 18 03:13 arcunp.c
  25. # -rw-r--r--  1 hyc          2484 Jun  2 16:28 arcusq.c
  26. # -rw-r--r--  1 hyc          9032 Jun 13 13:56 dtime.c
  27. # -rw-r--r--  1 hyc          7327 Apr 11 19:11 dtimep.lex
  28. # -rw-r--r--  1 hyc           356 Apr 11 19:12 lexedit.sed
  29. # -rw-r--r--  1 hyc          3713 Jun 13 13:59 lexstring.c
  30. # -rw-r--r--  1 hyc          2241 Apr 11 19:13 libtws.3
  31. # -rw-r--r--  1 hyc          9053 Jun  6 01:04 marc.c
  32. #
  33. echo 'x - arcsqs.c'
  34. if test -f arcsqs.c; then echo 'shar: not overwriting arcsqs.c'; else
  35. sed 's/^X//' << '________This_Is_The_END________' > arcsqs.c
  36. X/*
  37. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  38. X */
  39. X
  40. X/*  ARC - Archive utility - SQUASH
  41. X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  42. X This is a quick hack to ARCLZW to make it handle squashed archives.
  43. X Dan Lanciani (ddl@harvard.*) July 87
  44. X*/
  45. X
  46. X/*
  47. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  48. X */
  49. X
  50. X#include <stdio.h>
  51. X#include "arc.h"
  52. X
  53. X#if    MSDOS
  54. Xchar    *setmem();
  55. X#else
  56. Xchar    *memset();
  57. X#endif
  58. Xint    getc_unp();
  59. Xvoid    putc_pak(), putc_unp();
  60. Xstatic void    putcode();
  61. X
  62. X/* definitions for the new dynamic Lempel-Zev crunching */
  63. X
  64. X#define BITS   13        /* maximum bits per code */
  65. X#define HSIZE  10007        /* 80% occupancy */
  66. X#define INIT_BITS 9        /* initial number of bits/code */
  67. Xstatic int      n_bits;        /* number of bits/code */
  68. Xstatic int      maxcode;    /* maximum code, given n_bits */
  69. X#define MAXCODE(n)      ((1<<(n)) - 1)    /* maximum code calculation */
  70. Xstatic int      maxcodemax = 1 << BITS;    /* largest possible code (+1) */
  71. X
  72. Xstatic unsigned char buf[BITS];    /* input/output buffer */
  73. X
  74. Xstatic unsigned char lmask[9] =    /* left side masks */
  75. X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  76. Xstatic unsigned char rmask[9] =    /* right side masks */
  77. X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  78. X
  79. Xstatic int      offset;        /* byte offset for code output */
  80. Xstatic long     in_count;    /* length of input */
  81. Xstatic long     bytes_out;    /* length of compressed output */
  82. Xstatic unsigned short ent;
  83. X
  84. Xlong     htab[HSIZE];    /* hash code table   (crunch) */
  85. Xunsigned short codetab[HSIZE];    /* string code table (crunch) */
  86. X
  87. Xstatic unsigned short *prefix = codetab;  /* prefix code table (uncrunch) */
  88. Xstatic unsigned char *suffix=(unsigned char *)htab;  /* suffix table (uncrunch) */
  89. Xstatic int      free_ent;    /* first unused entry */
  90. Xstatic int      firstcmp;    /* true at start of compression */
  91. Xunsigned char stack[HSIZE];    /* local push/pop stack */
  92. X
  93. X/*
  94. X * block compression parameters -- after all codes are used up,
  95. X * and compression rate changes, start over.
  96. X */
  97. X
  98. Xstatic int      clear_flg;
  99. Xstatic long     ratio;
  100. X#define CHECK_GAP 10000        /* ratio check interval */
  101. Xstatic long     checkpoint;
  102. X
  103. X/*
  104. X * the next two codes should not be changed lightly, as they must not
  105. X * lie within the contiguous general code space.
  106. X */
  107. X#define FIRST   257        /* first free entry */
  108. X#define CLEAR   256        /* table clear output code */
  109. X
  110. Xstatic void
  111. Xcl_block(t)            /* table clear for block compress */
  112. X    FILE           *t;    /* our output file */
  113. X{
  114. X    long            rat;
  115. X
  116. X    checkpoint = in_count + CHECK_GAP;
  117. X
  118. X    if (in_count > 0x007fffffL) {    /* shift will overflow */
  119. X        rat = bytes_out >> 8;
  120. X        if (rat == 0)    /* Don't divide by zero */
  121. X            rat = 0x7fffffffL;
  122. X        else
  123. X            rat = in_count / rat;
  124. X    } else
  125. X        rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  126. X
  127. X    if (rat > ratio)
  128. X        ratio = rat;
  129. X    else {
  130. X        ratio = 0;
  131. X        setmem(htab, HSIZE * sizeof(long), 0xff);
  132. X        free_ent = FIRST;
  133. X        clear_flg = 1;
  134. X        putcode(CLEAR, t);
  135. X    }
  136. X}
  137. X
  138. X/*****************************************************************
  139. X *
  140. X * Output a given code.
  141. X * Inputs:
  142. X *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  143. X *              that n_bits =< (long)wordsize - 1.
  144. X * Outputs:
  145. X *      Outputs code to the file.
  146. X * Assumptions:
  147. X *      Chars are 8 bits long.
  148. X * Algorithm:
  149. X *      Maintain a BITS character long buffer (so that 8 codes will
  150. X * fit in it exactly).  When the buffer fills up empty it and start over.
  151. X */
  152. X
  153. Xstatic void
  154. Xputcode(code, t)        /* output a code */
  155. X    int             code;    /* code to output */
  156. X    FILE           *t;    /* where to put it */
  157. X{
  158. X    int             r_off = offset;    /* right offset */
  159. X    int             bits = n_bits;    /* bits to go */
  160. X    unsigned char  *bp = buf;    /* buffer pointer */
  161. X    int             n;    /* index */
  162. X    register int    ztmp;
  163. X
  164. X    if (code >= 0) {    /* if a real code *//* Get to the first byte. */
  165. X        bp += (r_off >> 3);
  166. X        r_off &= 7;
  167. X
  168. X        /*
  169. X         * Since code is always >= 8 bits, only need to mask the
  170. X         * first hunk on the left. 
  171. X         */
  172. X        ztmp = (code << r_off) & lmask[r_off];
  173. X        *bp = (*bp & rmask[r_off]) | ztmp;
  174. X        bp++;
  175. X        bits -= (8 - r_off);
  176. X        code >>= (8 - r_off);
  177. X
  178. X        /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  179. X        if (bits >= 8) {
  180. X            *bp++ = code;
  181. X            code >>= 8;
  182. X            bits -= 8;
  183. X        }
  184. X        /* Last bits. */
  185. X        if (bits)
  186. X            *bp = code;
  187. X
  188. X        offset += n_bits;
  189. X
  190. X        if (offset == (n_bits << 3)) {
  191. X            bp = buf;
  192. X            bits = n_bits;
  193. X            bytes_out += bits;
  194. X            do
  195. X                putc_pak(*bp++, t);
  196. X            while (--bits);
  197. X            offset = 0;
  198. X        }
  199. X        /*
  200. X         * If the next entry is going to be too big for the code
  201. X         * size, then increase it, if possible. 
  202. X         */
  203. X        if (free_ent > maxcode || clear_flg > 0) {    /* Write the whole
  204. X                                 * buffer, because the
  205. X                                 * input side won't
  206. X                                 * discover the size
  207. X                                 * increase until after
  208. X                                 * it has read it. */
  209. X            if (offset > 0) {
  210. X                bp = buf;    /* reset pointer for writing */
  211. X                bytes_out += n = n_bits;
  212. X                while (n--)
  213. X                    putc_pak(*bp++, t);
  214. X            }
  215. X            offset = 0;
  216. X
  217. X            if (clear_flg) {    /* reset if clearing */
  218. X                maxcode = MAXCODE(n_bits = INIT_BITS);
  219. X                clear_flg = 0;
  220. X            } else {/* else use more bits */
  221. X                n_bits++;
  222. X                if (n_bits == BITS)
  223. X                    maxcode = maxcodemax;
  224. X                else
  225. X                    maxcode = MAXCODE(n_bits);
  226. X            }
  227. X        }
  228. X    } else {        /* dump the buffer on EOF */
  229. X        bytes_out += n = (offset + 7) / 8;
  230. X
  231. X        if (offset > 0)
  232. X            while (n--)
  233. X                putc_pak(*bp++, t);
  234. X        offset = 0;
  235. X    }
  236. X}
  237. X
  238. X/*****************************************************************
  239. X *
  240. X * Read one code from the standard input.  If EOF, return -1.
  241. X * Inputs:
  242. X *      cmpin
  243. X * Outputs:
  244. X *      code or -1 is returned.
  245. X */
  246. X
  247. Xstatic int
  248. Xgetcode(f)            /* get a code */
  249. X    FILE           *f;    /* file to get from */
  250. X{
  251. X    int             code;
  252. X    static int      offset = 0, size = 0;
  253. X    int             r_off, bits;
  254. X    unsigned char  *bp = buf;
  255. X
  256. X    if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
  257. X        /* If the next entry will be too big for the current code
  258. X         * size, then we must increase the size. This implies reading
  259. X         * a new buffer full, too. */
  260. X        if (free_ent > maxcode) {
  261. X            n_bits++;
  262. X            if (n_bits == BITS)
  263. X                maxcode = maxcodemax;    /* won't get any bigger
  264. X                             * now */
  265. X            else
  266. X                maxcode = MAXCODE(n_bits);
  267. X        }
  268. X        if (clear_flg > 0) {
  269. X            maxcode = MAXCODE(n_bits = INIT_BITS);
  270. X            clear_flg = 0;
  271. X        }
  272. X        for (size = 0; size < n_bits; size++) {
  273. X            if ((code = getc_unp(f)) == EOF)
  274. X                break;
  275. X            else
  276. X                buf[size] = code;
  277. X        }
  278. X        if (size <= 0)
  279. X            return -1;    /* end of file */
  280. X
  281. X        offset = 0;
  282. X        /* Round size down to integral number of codes */
  283. X        size = (size << 3) - (n_bits - 1);
  284. X    }
  285. X    r_off = offset;
  286. X    bits = n_bits;
  287. X
  288. X    /*
  289. X     * Get to the first byte. 
  290. X     */
  291. X    bp += (r_off >> 3);
  292. X    r_off &= 7;
  293. X
  294. X    /* Get first part (low order bits) */
  295. X    code = (*bp++ >> r_off);
  296. X    bits -= 8 - r_off;
  297. X    r_off = 8 - r_off;    /* now, offset into code word */
  298. X
  299. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  300. X    if (bits >= 8) {
  301. X        code |= *bp++ << r_off;
  302. X        r_off += 8;
  303. X        bits -= 8;
  304. X    }
  305. X    /* high order bits. */
  306. X    code |= (*bp & rmask[bits]) << r_off;
  307. X    offset += n_bits;
  308. X
  309. X    return code;
  310. X}
  311. X
  312. X/*
  313. X * compress a file
  314. X *
  315. X * Algorithm:  use open addressing double hashing (no chaining) on the
  316. X * prefix code / next character combination.  We do a variant of Knuth's
  317. X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  318. X * secondary probe.  Here, the modular division first probe is gives way
  319. X * to a faster exclusive-or manipulation.  Also do block compression with
  320. X * an adaptive reset, where the code table is cleared when the compression
  321. X * ratio decreases, but after the table fills.  The variable-length output
  322. X * codes are re-sized at this point, and a special CLEAR code is generated
  323. X * for the decompressor.
  324. X */
  325. X
  326. Xvoid
  327. Xsqinit_cm()            /* initialize for compression */
  328. X{
  329. X    offset = 0;
  330. X    bytes_out = 0;
  331. X    clear_flg = 0;
  332. X    ratio = 0;
  333. X    in_count = 1;
  334. X    checkpoint = CHECK_GAP;
  335. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  336. X    free_ent = FIRST;
  337. X    setmem(htab, HSIZE * sizeof(long), 0xff);
  338. X    n_bits = INIT_BITS;    /* set starting code size */
  339. X
  340. X    firstcmp = 1;        /* next byte will be first */
  341. X}
  342. X
  343. Xvoid
  344. Xsqputc_cm(c, t)            /* compress a character */
  345. X    unsigned char   c;    /* character to compress */
  346. X    FILE           *t;    /* where to put it */
  347. X{
  348. X    static long     fcode;
  349. X    static int      hshift;
  350. X    int             i;
  351. X    int             disp;
  352. X
  353. X    if (firstcmp) {        /* special case for first byte */
  354. X        ent = c;    /* remember first byte */
  355. X
  356. X        hshift = 0;
  357. X        for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
  358. X            hshift++;
  359. X        hshift = 8 - hshift;    /* set hash code range bund */
  360. X
  361. X        firstcmp = 0;    /* no longer first */
  362. X        return;
  363. X    }
  364. X    in_count++;
  365. X    fcode = (long) (((long) c << BITS) + ent);
  366. X    i = (c << hshift) ^ ent;/* xor hashing */
  367. X
  368. X    if (htab[i] == fcode) {
  369. X        ent = codetab[i];
  370. X        return;
  371. X    } else if (htab[i] < 0)    /* empty slot */
  372. X        goto nomatch;
  373. X    disp = HSIZE - i;    /* secondary hash (after G.Knott) */
  374. X    if (i == 0)
  375. X        disp = 1;
  376. X
  377. Xprobe:
  378. X    if ((i -= disp) < 0)
  379. X        i += HSIZE;
  380. X
  381. X    if (htab[i] == fcode) {
  382. X        ent = codetab[i];
  383. X        return;
  384. X    }
  385. X    if (htab[i] > 0)
  386. X        goto probe;
  387. X
  388. Xnomatch:
  389. X    putcode(ent, t);
  390. X    ent = c;
  391. X    if (free_ent < maxcodemax) {
  392. X        codetab[i] = free_ent++;    /* code -> hashtable */
  393. X        htab[i] = fcode;
  394. X    } else if ((long) in_count >= checkpoint)
  395. X        cl_block(t);
  396. X}
  397. X
  398. Xlong 
  399. Xsqpred_cm(t)            /* finish compressing a file */
  400. X    FILE           *t;    /* where to put it */
  401. X{
  402. X    putcode(ent, t);    /* put out the final code */
  403. X    putcode(-1, t);        /* tell output we are done */
  404. X
  405. X    return bytes_out;    /* say how big it got */
  406. X}
  407. X
  408. X/*
  409. X * Decompress a file.  This routine adapts to the codes in the file
  410. X * building the string table on-the-fly; requiring no table to be stored
  411. X * in the compressed file.  The tables used herein are shared with those of
  412. X * the compress() routine.  See the definitions above.
  413. X */
  414. X
  415. Xvoid
  416. Xsqdecomp(f, t)            /* decompress a file */
  417. X    FILE           *f;    /* file to read codes from */
  418. X    FILE           *t;    /* file to write text to */
  419. X{
  420. X    unsigned char  *stackp;
  421. X    int             finchar;
  422. X    int             code, oldcode, incode;
  423. X
  424. X    n_bits = INIT_BITS;    /* set starting code size */
  425. X    clear_flg = 0;
  426. X
  427. X    /*
  428. X     * As above, initialize the first 256 entries in the table. 
  429. X     */
  430. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  431. X    for (code = 255; code >= 0; code--) {
  432. X        prefix[code] = 0;
  433. X        suffix[code] = (unsigned char) code;
  434. X    }
  435. X    free_ent = FIRST;
  436. X
  437. X    finchar = oldcode = getcode(f);
  438. X    if (oldcode == -1)    /* EOF already? */
  439. X        return;        /* Get out of here */
  440. X    putc_unp((char) finchar, t);    /* first code must be 8 bits=char */
  441. X    stackp = stack;
  442. X
  443. X    while ((code = getcode(f)) > -1) {
  444. X        if (code == CLEAR) {
  445. X            for (code = 255; code >= 0; code--)
  446. X                prefix[code] = 0;
  447. X            clear_flg = 1;
  448. X            free_ent = FIRST - 1;
  449. X            if ((code = getcode(f)) == -1)    /* O, untimely death! */
  450. X                break;
  451. X        }
  452. X        incode = code;
  453. X        /*
  454. X         * Special case for KwKwK string. 
  455. X         */
  456. X        if (code >= free_ent) {
  457. X            if (code > free_ent) {
  458. X                if (warn) {
  459. X                    printf("Corrupted compressed file.\n");
  460. X                    printf("Invalid code %d when max is %d.\n",
  461. X                        code, free_ent);
  462. X                }
  463. X                nerrs++;
  464. X                return;
  465. X            }
  466. X            *stackp++ = finchar;
  467. X            code = oldcode;
  468. X        }
  469. X        /*
  470. X         * Generate output characters in reverse order 
  471. X         */
  472. X        while (code >= 256) {
  473. X            *stackp++ = suffix[code];
  474. X            code = prefix[code];
  475. X        }
  476. X        *stackp++ = finchar = suffix[code];
  477. X
  478. X        /*
  479. X         * And put them out in forward order 
  480. X         */
  481. X        do
  482. X            putc_unp(*--stackp, t);
  483. X        while (stackp > stack);
  484. X
  485. X        /*
  486. X         * Generate the new entry. 
  487. X         */
  488. X        if ((code = free_ent) < maxcodemax) {
  489. X            prefix[code] = (unsigned short) oldcode;
  490. X            suffix[code] = finchar;
  491. X            free_ent = code + 1;
  492. X        }
  493. X        /*
  494. X         * Remember previous code. 
  495. X         */
  496. X        oldcode = incode;
  497. X    }
  498. X}
  499. ________This_Is_The_END________
  500. if test `wc -c < arcsqs.c` -ne    11514; then
  501.     echo 'shar: arcsqs.c was damaged during transit (should have been    11514 bytes)'
  502. fi
  503. fi        ; : end of overwriting check
  504. echo 'x - arcsvc.c'
  505. if test -f arcsvc.c; then echo 'shar: not overwriting arcsvc.c'; else
  506. sed 's/^X//' << '________This_Is_The_END________' > arcsvc.c
  507. X/*
  508. X * $Header: arcsvc.c,v 1.8 88/06/13 00:42:59 hyc Locked $
  509. X */
  510. X
  511. X/*  ARC - Archive utility - ARCSVC
  512. X
  513. X    Version 2.23, created on 04/22/87 at 13:10:10
  514. X
  515. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  516. X
  517. X    By:     Thom Henderson
  518. X
  519. X    Description:
  520. X     This file contains service routines needed to maintain an archive.
  521. X
  522. X    Language:
  523. X     Computer Innovations Optimizing C86
  524. X*/
  525. X#include <stdio.h>
  526. X#include "arc.h"
  527. X#if    MTS
  528. X#include <mts.h>
  529. X#endif
  530. X
  531. Xvoid    abort(), setstamp();
  532. Xint    unlink();
  533. X
  534. Xvoid
  535. Xopenarc(chg)            /* open archive */
  536. X    int             chg;    /* true to open for changes */
  537. X{
  538. X    FILE           *fopen();/* file opener */
  539. X
  540. X    if (!(arc = fopen(arcname, "rb"))) {
  541. X        if (chg) {
  542. X            if (note)
  543. X                printf("Creating new archive: %s\n", arcname);
  544. X        }
  545. X        else
  546. X            abort("Archive not found: %s", arcname);
  547. X    }
  548. X#if    MTS    /* allow reading archives of max MTS record length */
  549. X    else {
  550. X        char *buffer, *malloc();
  551. X        int inlen;
  552. X        struct GDDSECT *region;
  553. X
  554. X        region=gdinfo(arc->_fd);
  555. X        inlen=region->GDINLEN;
  556. X        buffer=malloc(inlen);
  557. X        setbuf(arc, buffer);
  558. X        arc->_bufsiz=inlen;
  559. X    }
  560. X#endif
  561. X    if (chg) {        /* if opening for changes */
  562. X        if (!(new = fopen(newname, "wb")))
  563. X            abort("Cannot create archive copy: %s", newname);
  564. X
  565. X    changing = chg;        /* note if open for changes */
  566. X    }
  567. X}
  568. X
  569. Xvoid
  570. Xclosearc(chg)            /* close an archive */
  571. X    int             chg;    /* true if archive was changed */
  572. X{
  573. X    if (arc) {        /* if we had an initial archive */
  574. X        fclose(arc);
  575. X        if (kludge)    /* kludge to update timestamp */
  576. X#if    !MTS
  577. X            setstamp(arcname, olddate, oldtime);
  578. X#endif
  579. X    }
  580. X    if (chg) {        /* if things have changed */
  581. X        fclose(new);    /* close the new copy */
  582. X        if (arc) {    /* if we had an original archive */
  583. X            if (keepbak) {    /* if a backup is wanted */
  584. X                unlink(bakname);    /* erase any old copies */
  585. X                if (move(arcname, bakname))
  586. X                    abort("Cannot rename %s to %s", arcname, bakname);
  587. X                printf("Keeping backup archive: %s\n", bakname);
  588. X            } else if (unlink(arcname))
  589. X                abort("Cannot delete old archive: %s", arcname);
  590. X        }
  591. X        if (move(newname, arcname))
  592. X            abort("Cannot move %s to %s", newname, arcname);
  593. X#if    !MTS
  594. X        setstamp(arcname, arcdate, arctime);
  595. X#endif
  596. X    }
  597. X}
  598. X
  599. X/*
  600. X * CRC computation logic
  601. X * 
  602. X * The logic for this method of calculating the CRC 16 bit polynomial is taken
  603. X * from an article by David Schwaderer in the April 1985 issue of PC Tech
  604. X * Journal.
  605. X */
  606. X
  607. Xstatic short      crctab[] =    /* CRC lookup table */
  608. X{
  609. X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  610. X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  611. X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  612. X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  613. X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  614. X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  615. X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  616. X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  617. X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  618. X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  619. X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  620. X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  621. X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  622. X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  623. X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  624. X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  625. X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  626. X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  627. X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  628. X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  629. X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  630. X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  631. X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  632. X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  633. X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  634. X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  635. X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  636. X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  637. X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  638. X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  639. X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  640. X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  641. X};
  642. X
  643. Xint
  644. Xaddcrc(crc, c)            /* update a CRC check */
  645. X    int             crc;    /* running CRC value */
  646. X    unsigned char   c;    /* character to add */
  647. X{
  648. X    return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff];
  649. X}
  650. ________This_Is_The_END________
  651. if test `wc -c < arcsvc.c` -ne     4680; then
  652.     echo 'shar: arcsvc.c was damaged during transit (should have been     4680 bytes)'
  653. fi
  654. fi        ; : end of overwriting check
  655. echo 'x - arctst.c'
  656. if test -f arctst.c; then echo 'shar: not overwriting arctst.c'; else
  657. sed 's/^X//' << '________This_Is_The_END________' > arctst.c
  658. X/*
  659. X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $
  660. X */
  661. X
  662. X/*
  663. X * ARC - Archive utility - ARCTST
  664. X * 
  665. X * Version 2.12, created on 02/03/86 at 23:00:40
  666. X * 
  667. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  668. X * 
  669. X * By:  Thom Henderson
  670. X * 
  671. X * Description: This file contains the routines used to test archive integrity.
  672. X * 
  673. X * Language: Computer Innovations Optimizing C86
  674. X */
  675. X#include <stdio.h>
  676. X#include "arc.h"
  677. X
  678. Xvoid    openarc();
  679. Xint    readhdr(), unpack();
  680. X
  681. Xvoid
  682. Xtstarc()
  683. X{                /* test integrity of an archive */
  684. X    struct heads    hdr;    /* file header */
  685. X    long            arcsize, ftell();    /* archive size */
  686. X
  687. X    openarc(0);        /* open archive for reading */
  688. X    fseek(arc, 0L, 2);    /* move to end of archive */
  689. X    arcsize = ftell(arc);    /* see how big it is */
  690. X    fseek(arc, 0L, 0);    /* return to top of archive */
  691. X
  692. X    while (readhdr(&hdr, arc)) {
  693. X        if (ftell(arc) + hdr.size > arcsize) {
  694. X            printf("Archive truncated in file %s\n", hdr.name);
  695. X            nerrs++;
  696. X            break;
  697. X        } else {
  698. X            printf("Testing file: %-12s  ", hdr.name);
  699. X            fflush(stdout);
  700. X            if (unpack(arc, NULL, &hdr))
  701. X                nerrs++;
  702. X            else
  703. X                printf("okay\n");
  704. X        }
  705. X    }
  706. X
  707. X    if (nerrs < 1)
  708. X        printf("No errors detected\n");
  709. X    else if (nerrs == 1)
  710. X        printf("One error detected\n");
  711. X    else
  712. X        printf("%d errors detected\n", nerrs);
  713. X}
  714. ________This_Is_The_END________
  715. if test `wc -c < arctst.c` -ne     1284; then
  716.     echo 'shar: arctst.c was damaged during transit (should have been     1284 bytes)'
  717. fi
  718. fi        ; : end of overwriting check
  719. echo 'x - arcunp.c'
  720. if test -f arcunp.c; then echo 'shar: not overwriting arcunp.c'; else
  721. sed 's/^X//' << '________This_Is_The_END________' > arcunp.c
  722. X/*
  723. X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
  724. X */
  725. X
  726. X/*
  727. X * ARC - Archive utility - ARCUNP
  728. X * 
  729. X * Version 3.17, created on 02/13/86 at 10:20:08
  730. X * 
  731. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  732. X * 
  733. X * By:  Thom Henderson
  734. X * 
  735. X * Description: This file contains the routines used to expand a file when
  736. X * taking it out of an archive.
  737. X * 
  738. X * Language: Computer Innovations Optimizing C86
  739. X */
  740. X#include <stdio.h>
  741. X#include "arc.h"
  742. X#if    MTS
  743. X#include <ctype.h>
  744. X#endif
  745. X
  746. Xvoid    setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
  747. Xvoid    abort(), putc_tst();
  748. Xint    getc_usq(), getc_ucr(), addcrc();
  749. X
  750. X/* stuff for repeat unpacking */
  751. X
  752. X#define DLE 0x90        /* repeat byte flag */
  753. X
  754. Xstatic int      state;        /* repeat unpacking state */
  755. X
  756. X/* repeat unpacking states */
  757. X
  758. X#define NOHIST 0        /* no relevant history */
  759. X#define INREP 1            /* sending a repeated value */
  760. X
  761. Xstatic short    crcval;        /* CRC check value */
  762. Xstatic long     size;        /* bytes to read */
  763. X#if    !DOS
  764. Xstatic int    gotcr;        /* got a carriage return? */
  765. X#endif
  766. X
  767. Xint
  768. Xunpack(f, t, hdr)        /* unpack an archive entry */
  769. X    FILE           *f, *t;    /* source, destination */
  770. X    struct heads   *hdr;    /* pointer to file header data */
  771. X{
  772. X    int             c;    /* one char of stream */
  773. X    void            putc_unp();
  774. X    void            putc_ncr();
  775. X    int             getc_unp();
  776. X
  777. X    /* setups common to all methods */
  778. X#if    !DOS
  779. X    gotcr = 0;
  780. X#endif
  781. X    crcval = 0;        /* reset CRC check value */
  782. X    size = hdr->size;    /* set input byte counter */
  783. X    state = NOHIST;        /* initial repeat unpacking state */
  784. X    setcode();        /* set up for decoding */
  785. X
  786. X    /* use whatever method is appropriate */
  787. X
  788. X    switch (hdrver) {    /* choose proper unpack method */
  789. X    case 1:        /* standard packing */
  790. X    case 2:
  791. X        while ((c = getc_unp(f)) != EOF)
  792. X            putc_unp((char) c, t);
  793. X        break;
  794. X
  795. X    case 3:        /* non-repeat packing */
  796. X        while ((c = getc_unp(f)) != EOF)
  797. X            putc_ncr((unsigned char) c, t);
  798. X        break;
  799. X
  800. X    case 4:        /* Huffman squeezing */
  801. X        init_usq(f);
  802. X        while ((c = getc_usq(f)) != EOF)
  803. X            putc_ncr((unsigned char) c, t);
  804. X        break;
  805. X
  806. X    case 5:        /* Lempel-Zev compression */
  807. X        init_ucr(0);
  808. X        while ((c = getc_ucr(f)) != EOF)
  809. X            putc_unp((char) c, t);
  810. X        break;
  811. X
  812. X    case 6:        /* Lempel-Zev plus non-repeat */
  813. X        init_ucr(0);
  814. X        while ((c = getc_ucr(f)) != EOF)
  815. X            putc_ncr((unsigned char) c, t);
  816. X        break;
  817. X
  818. X    case 7:        /* L-Z plus ncr with new hash */
  819. X        init_ucr(1);
  820. X        while ((c = getc_ucr(f)) != EOF)
  821. X            putc_ncr((unsigned char) c, t);
  822. X        break;
  823. X
  824. X    case 8:        /* dynamic Lempel-Zev */
  825. X        decomp(f, t);
  826. X        break;
  827. X
  828. X    case 9:        /* Squashing */
  829. X        sqdecomp(f, t);
  830. X        break;
  831. X
  832. X    default:        /* unknown method */
  833. X        if (warn) {
  834. X            printf("I don't know how to unpack file %s\n", hdr->name);
  835. X            printf("I think you need a newer version of ARC\n");
  836. X            nerrs++;
  837. X        }
  838. X        fseek(f, hdr->size, 1);    /* skip over bad file */
  839. X        return 1;    /* note defective file */
  840. X    }
  841. X
  842. X    /* cleanups common to all methods */
  843. X
  844. X    if (crcval != hdr->crc) {
  845. X        if (warn || kludge) {
  846. X            printf("WARNING: File %s fails CRC check\n", hdr->name);
  847. X            nerrs++;
  848. X        }
  849. X        return 1;    /* note defective file */
  850. X    }
  851. X    return 0;        /* file is okay */
  852. X}
  853. X
  854. X/*
  855. X * This routine is used to put bytes in the output file.  It also performs
  856. X * various housekeeping functions, such as maintaining the CRC check value.
  857. X */
  858. X
  859. Xvoid
  860. Xputc_unp(c, t)            /* output an unpacked byte */
  861. X    char            c;    /* byte to output */
  862. X    FILE           *t;    /* file to output to */
  863. X{
  864. X    crcval = addcrc(crcval, c);    /* update the CRC check value */
  865. X#if    MTS
  866. X    if (!image)
  867. X        atoe(&c, 1);
  868. X#endif
  869. X#if    DOS
  870. X    putc_tst(c, t);
  871. X#else
  872. X    if (image)
  873. X        putc_tst(c, t);
  874. X    else {
  875. X        if (gotcr) {
  876. X            gotcr = 0;
  877. X            if (c != '\n')
  878. X                putc_tst('\r', t);
  879. X        }
  880. X        if (c == '\r')
  881. X            gotcr = 1;
  882. X        else
  883. X            putc_tst(c, t);
  884. X    }
  885. X#endif
  886. X}
  887. X
  888. X/*
  889. X * This routine is used to decode non-repeat compression.  Bytes are passed
  890. X * one at a time in coded format, and are written out uncoded. The data is
  891. X * stored normally, except that runs of more than two characters are
  892. X * represented as:
  893. X * 
  894. X * <char> <DLE> <count>
  895. X * 
  896. X * With a special case that a count of zero indicates a DLE as data, not as a
  897. X * repeat marker.
  898. X */
  899. X
  900. Xvoid
  901. Xputc_ncr(c, t)            /* put NCR coded bytes */
  902. X    unsigned char   c;    /* next byte of stream */
  903. X    FILE           *t;    /* file to receive data */
  904. X{
  905. X    static int      lastc;    /* last character seen */
  906. X
  907. X    switch (state) {    /* action depends on our state */
  908. X    case NOHIST:        /* no previous history */
  909. X        if (c == DLE)    /* if starting a series */
  910. X            state = INREP;    /* then remember it next time */
  911. X        else
  912. X            putc_unp(lastc = c, t);    /* else nothing unusual */
  913. X        return;
  914. X
  915. X    case INREP:        /* in a repeat */
  916. X        if (c)        /* if count is nonzero */
  917. X            while (--c)    /* then repeatedly ... */
  918. X                putc_unp(lastc, t);    /* ... output the byte */
  919. X        else
  920. X            putc_unp(DLE, t);    /* else output DLE as data */
  921. X        state = NOHIST;    /* back to no history */
  922. X        return;
  923. X
  924. X    default:
  925. X        abort("Bad NCR unpacking state (%d)", state);
  926. X    }
  927. X}
  928. X
  929. X/*
  930. X * This routine provides low-level byte input from an archive.  This routine
  931. X * MUST be used, as end-of-file is simulated at the end of the archive entry.
  932. X */
  933. X
  934. Xint
  935. Xgetc_unp(f)            /* get a byte from an archive */
  936. X    FILE           *f;    /* archive file to read */
  937. X{
  938. X    register int    xx;
  939. X    unsigned char        code();
  940. X
  941. X    if (!size)        /* if no data left */
  942. X        return EOF;    /* then pretend end of file */
  943. X
  944. X    size--;            /* deduct from input counter */
  945. X    xx = getc(f);
  946. X    return code(xx);    /* and return next decoded byte */
  947. X}
  948. ________This_Is_The_END________
  949. if test `wc -c < arcunp.c` -ne     5347; then
  950.     echo 'shar: arcunp.c was damaged during transit (should have been     5347 bytes)'
  951. fi
  952. fi        ; : end of overwriting check
  953. echo 'x - arcusq.c'
  954. if test -f arcusq.c; then echo 'shar: not overwriting arcusq.c'; else
  955. sed 's/^X//' << '________This_Is_The_END________' > arcusq.c
  956. X/*
  957. X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $
  958. X */
  959. X
  960. X/*
  961. X * ARC - Archive utility - ARCUSQ
  962. X * 
  963. X * Version 3.14, created on 07/25/86 at 13:04:19
  964. X * 
  965. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  966. X * 
  967. X * By:  Thom Henderson
  968. X * 
  969. X * Description: This file contains the routines used to expand a file which was
  970. X * packed using Huffman squeezing.
  971. X * 
  972. X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
  973. X * adapted to CI-C86 by Robert J. Beilstein.
  974. X * 
  975. X * Language: Computer Innovations Optimizing C86
  976. X */
  977. X#include <stdio.h>
  978. X#include "arc.h"
  979. X
  980. Xvoid    abort();
  981. Xint    getc_unp();
  982. X
  983. X/* stuff for Huffman unsqueezing */
  984. X
  985. X#define ERROR (-1)
  986. X
  987. X#define SPEOF 256        /* special endfile token */
  988. X#define NUMVALS 257        /* 256 data values plus SPEOF */
  989. X
  990. Xextern    struct nd {        /* decoding tree */
  991. X    int    child[2];    /* left, right */
  992. X}               node[NUMVALS];    /* use large buffer */
  993. X
  994. Xstatic int      bpos;        /* last bit position read */
  995. Xstatic int      curin;        /* last byte value read */
  996. Xstatic int      numnodes;    /* number of nodes in decode tree */
  997. X
  998. Xstatic          short
  999. Xget_int(f)            /* get a 16bit integer */
  1000. X    FILE           *f;    /* file to get it from */
  1001. X{
  1002. X    int    i,j;
  1003. X    i = getc_unp(f);
  1004. X    j = getc_unp(f) << 8;
  1005. X    return (i | j) & 0xFFFF;
  1006. X}
  1007. X
  1008. Xvoid
  1009. Xinit_usq(f)            /* initialize Huffman unsqueezing */
  1010. X    FILE           *f;    /* file containing squeezed data */
  1011. X{
  1012. X    int             i;    /* node index */
  1013. X
  1014. X    bpos = 99;        /* force initial read */
  1015. X
  1016. X    numnodes = get_int(f);
  1017. X
  1018. X    if (numnodes < 0 || numnodes >= NUMVALS)
  1019. X        abort("File has an invalid decode tree");
  1020. X
  1021. X    /* initialize for possible empty tree (SPEOF only) */
  1022. X
  1023. X    node[0].child[0] = -(SPEOF + 1);
  1024. X    node[0].child[1] = -(SPEOF + 1);
  1025. X
  1026. X    for (i = 0; i < numnodes; ++i) {    /* get decoding tree from
  1027. X                         * file */
  1028. X        node[i].child[0] = get_int(f);
  1029. X        node[i].child[1] = get_int(f);
  1030. X    }
  1031. X}
  1032. X
  1033. Xint
  1034. Xgetc_usq(f)            /* get byte from squeezed file */
  1035. X    FILE           *f;    /* file containing squeezed data */
  1036. X{
  1037. X    int             i;    /* tree index */
  1038. X
  1039. X    /* follow bit stream in tree to a leaf */
  1040. X
  1041. X    for (i = 0; i >= 0;) {    /* work down(up?) from root */
  1042. X        if (++bpos > 7) {
  1043. X            if ((curin = getc_unp(f)) == ERROR)
  1044. X                return (ERROR);
  1045. X            bpos = 0;
  1046. X
  1047. X            /* move a level deeper in tree */
  1048. X            i = node[i].child[1 & curin];
  1049. X        } else
  1050. X            i = node[i].child[1 & (curin >>= 1)];
  1051. X    }
  1052. X
  1053. X    /* decode fake node index to original data value */
  1054. X
  1055. X    i = -(i + 1);
  1056. X
  1057. X    /* decode special endfile token to normal EOF */
  1058. X
  1059. X    i = (i == SPEOF) ? EOF : i;
  1060. X    return i;
  1061. X}
  1062. ________This_Is_The_END________
  1063. if test `wc -c < arcusq.c` -ne     2484; then
  1064.     echo 'shar: arcusq.c was damaged during transit (should have been     2484 bytes)'
  1065. fi
  1066. fi        ; : end of overwriting check
  1067. echo 'x - dtime.c'
  1068. if test -f dtime.c; then echo 'shar: not overwriting dtime.c'; else
  1069. sed 's/^X//' << '________This_Is_The_END________' > dtime.c
  1070. X/* dtime.c - routines to do ``ARPA-style'' time structures
  1071. X
  1072. Xver  date   who remarks
  1073. X--- ------- --- -------------------------------------------------------------
  1074. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1075. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1076. X              of Marshall Rose.
  1077. X
  1078. X*/
  1079. X
  1080. X
  1081. X#include "tws.h"
  1082. X#include <stdio.h>
  1083. X#include <sys/types.h>
  1084. X#include <time.h>
  1085. X#ifdef  SYS5
  1086. X#include <string.h>
  1087. X#else SYS5
  1088. X#include <strings.h>
  1089. X#include <sys/timeb.h>
  1090. X#endif SYS5
  1091. X
  1092. X#ifdef    SYS5
  1093. Xextern int  daylight;
  1094. Xextern long timezone;
  1095. Xextern char *tzname[];
  1096. X#endif    SYS5
  1097. X
  1098. X/*   */
  1099. X
  1100. X#define    abs(a) ( a >= 0 ? a : -a )
  1101. X
  1102. Xchar *tw_moty[] = {
  1103. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1104. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
  1105. X
  1106. Xchar *tw_dotw[] = {
  1107. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
  1108. X
  1109. Xchar *tw_ldotw[] = {
  1110. X    "Sunday", "Monday", "Tuesday", "Wednesday",
  1111. X    "Thursday", "Friday", "Saturday", NULL };
  1112. X
  1113. X/*   */
  1114. X
  1115. Xstatic struct zone
  1116. X    {
  1117. X    char *std;
  1118. X    char *dst;
  1119. X    int shift;
  1120. X    }
  1121. X    zones[] = {
  1122. X    "GMT", "BST", 0,
  1123. X    "EST", "EDT", -5,
  1124. X    "CST", "CDT", -6,
  1125. X    "MST", NULL, -7,
  1126. X    "PST", "PDT", -8,
  1127. X    "A", NULL, -1,
  1128. X    "B", NULL, -2,
  1129. X    "C", NULL, -3,
  1130. X    "D", NULL, -4,
  1131. X    "E", NULL, -5,
  1132. X    "F", NULL, -6,
  1133. X    "G", NULL, -7,
  1134. X    "H", NULL, -8,
  1135. X    "I", NULL, -9,
  1136. X    "K", NULL, -10,
  1137. X    "L", NULL, -11,
  1138. X    "M", NULL, -12,
  1139. X    "N", NULL, 1,
  1140. X#ifndef    HUJI
  1141. X    "O", NULL, 2,
  1142. X#else    HUJI
  1143. X    "JST", "JDT", 2,
  1144. X#endif    HUJI
  1145. X    "P", NULL, 3,
  1146. X    "Q", NULL, 4,
  1147. X    "R", NULL, 5,
  1148. X    "S", NULL, 6,
  1149. X    "T", NULL, 7,
  1150. X    "U", NULL, 8,
  1151. X    "V", NULL, 9,
  1152. X    "W", NULL, 10,
  1153. X    "X", NULL, 11,
  1154. X    "Y", NULL, 12,
  1155. X    NULL };
  1156. X
  1157. X#define CENTURY 19
  1158. X
  1159. Xlong time( );
  1160. Xstruct tm *localtime( );
  1161. X
  1162. X/*   */
  1163. X
  1164. Xchar *dtimenow( )
  1165. X    {
  1166. X    long clock;
  1167. X
  1168. X    (void) time( &clock );
  1169. X    return ( dtime( &clock ) );
  1170. X    }
  1171. X
  1172. X
  1173. Xchar *
  1174. Xdctime( tw )
  1175. Xstruct tws *tw;
  1176. X    {
  1177. X    static char buffer[25];
  1178. X
  1179. X    if ( tw == NULL )
  1180. X    return ( NULL );
  1181. X
  1182. X    (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
  1183. X        tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
  1184. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1185. X        tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year );
  1186. X
  1187. X    return ( buffer );
  1188. X    }
  1189. X
  1190. X/*   */
  1191. X
  1192. Xstruct tws *
  1193. Xdtwstime( )
  1194. X    {
  1195. X    long clock;
  1196. X
  1197. X    (void) time( &clock );
  1198. X    return ( dlocaltime( &clock ) );
  1199. X    }
  1200. X
  1201. X
  1202. Xstruct tws *
  1203. Xdlocaltime( clock )
  1204. Xlong *clock;
  1205. X    {
  1206. X    register struct tm *tm;
  1207. X#ifndef SYS5
  1208. X    struct timeb tb;
  1209. X#endif not SYS5
  1210. X    static struct tws tw;
  1211. X
  1212. X    if ( clock == NULL )
  1213. X    return ( NULL );
  1214. X    tw.tw_flags = TW_NULL;
  1215. X
  1216. X    tm = localtime( clock );
  1217. X    tw.tw_sec = tm -> tm_sec;
  1218. X    tw.tw_min = tm -> tm_min;
  1219. X    tw.tw_hour = tm -> tm_hour;
  1220. X    tw.tw_mday = tm -> tm_mday;
  1221. X    tw.tw_mon = tm -> tm_mon;
  1222. X    tw.tw_year = tm -> tm_year;
  1223. X    tw.tw_wday = tm -> tm_wday;
  1224. X    tw.tw_yday = tm -> tm_yday;
  1225. X    if ( tm -> tm_isdst )
  1226. X    tw.tw_flags |= TW_DST;
  1227. X#ifndef  SYS5
  1228. X    ftime( &tb );
  1229. X    tw.tw_zone = -tb.timezone;
  1230. X#else   SYS5
  1231. X    tzset( );
  1232. X    tw.tw_zone = -(timezone / 60);
  1233. X#endif  SYS5
  1234. X    tw.tw_flags &= ~TW_SDAY;
  1235. X    tw.tw_flags |= TW_SEXP;
  1236. X    tw.tw_clock = *clock;
  1237. X
  1238. X    return ( &tw );
  1239. X    }
  1240. X
  1241. X
  1242. Xstruct tws *
  1243. Xdgmtime( clock )
  1244. Xlong *clock;
  1245. X    {
  1246. X    register struct tm *tm;
  1247. X    static struct tws tw;
  1248. X
  1249. X    if ( clock == NULL )
  1250. X    return ( NULL );
  1251. X    tw.tw_flags = TW_NULL;
  1252. X
  1253. X    tm = gmtime( clock );
  1254. X    tw.tw_sec = tm -> tm_sec;
  1255. X    tw.tw_min = tm -> tm_min;
  1256. X    tw.tw_hour = tm -> tm_hour;
  1257. X    tw.tw_mday = tm -> tm_mday;
  1258. X    tw.tw_mon = tm -> tm_mon;
  1259. X    tw.tw_year = tm -> tm_year;
  1260. X    tw.tw_wday = tm -> tm_wday;
  1261. X    tw.tw_yday = tm -> tm_yday;
  1262. X    if ( tm -> tm_isdst )
  1263. X    tw.tw_flags |= TW_DST;
  1264. X    tw.tw_zone = 0;
  1265. X    tw.tw_flags &= ~TW_SDAY;
  1266. X    tw.tw_flags |= TW_SEXP;
  1267. X    tw.tw_clock = *clock;
  1268. X
  1269. X    return( &tw );
  1270. X    }
  1271. X
  1272. X/*   */
  1273. X
  1274. Xchar *
  1275. Xdasctime( tw, flags )
  1276. Xstruct tws *tw;
  1277. Xint flags;
  1278. X    {
  1279. X    static char buffer[80], result[80];
  1280. X
  1281. X    if ( tw == NULL )
  1282. X    return ( NULL );
  1283. X
  1284. X    (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s",
  1285. X        tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year,
  1286. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1287. X        dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) );
  1288. X
  1289. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP )
  1290. X    (void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer );
  1291. X    else
  1292. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL )
  1293. X        (void) strcpy( result, buffer );
  1294. X    else
  1295. X        (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] );
  1296. X
  1297. X    return ( result );
  1298. X    }
  1299. X
  1300. X/*   */
  1301. X
  1302. Xchar *
  1303. Xdtimezone( offset, flags )
  1304. Xint offset, flags;
  1305. X    {
  1306. X    register int hours, mins;
  1307. X    register struct zone *z;
  1308. X    static char buffer[10];
  1309. X
  1310. X    if ( offset < 0 )
  1311. X    {
  1312. X    mins = -((-offset) % 60);
  1313. X    hours = -((-offset) / 60);
  1314. X    }
  1315. X    else
  1316. X    {
  1317. X    mins = offset % 60;
  1318. X    hours = offset / 60;
  1319. X    }
  1320. X
  1321. X    if ( !(flags & TW_ZONE) && mins == 0 )
  1322. X    for ( z = zones; z -> std; z++ )
  1323. X        if ( z -> shift == hours )
  1324. X        return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std );
  1325. X
  1326. X#ifdef    DSTXXX
  1327. X    if ( flags & TW_DST )
  1328. X    hours += 1;
  1329. X#endif    DSTXXX
  1330. X    (void) sprintf( buffer, "%s%02d%02d",
  1331. X        offset < 0 ? "-" : "+", abs( hours ), abs( mins ) );
  1332. X    return ( buffer );
  1333. X    }
  1334. X
  1335. X/*   */
  1336. X
  1337. Xvoid
  1338. Xtwscopy( tb, tw )
  1339. Xstruct tws *tb, *tw;
  1340. X    {
  1341. X#ifdef    notdef
  1342. X    tb -> tw_sec = tw -> tw_sec;
  1343. X    tb -> tw_min = tw -> tw_min;
  1344. X    tb -> tw_hour = tw -> tw_hour;
  1345. X    tb -> tw_mday = tw -> tw_mday;
  1346. X    tb -> tw_mon = tw -> tw_mon;
  1347. X    tb -> tw_year = tw -> tw_year;
  1348. X    tb -> tw_wday = tw -> tw_wday;
  1349. X    tb -> tw_yday = tw -> tw_yday;
  1350. X    tb -> tw_zone = tw -> tw_zone;
  1351. X    tb -> tw_clock = tw -> tw_clock;
  1352. X    tb -> tw_flags = tw -> tw_flags;
  1353. X#else    not notdef
  1354. X    *tb = *tw;
  1355. X#endif    not notdef
  1356. X    }
  1357. X
  1358. X
  1359. Xint
  1360. Xtwsort( tw1, tw2 )
  1361. Xstruct tws *tw1, *tw2;
  1362. X    {
  1363. X    register long c1, c2;
  1364. X
  1365. X    (void) twclock( tw1 );
  1366. X    (void) twclock( tw2 );
  1367. X
  1368. X    return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
  1369. X        : c1 == c2 ? 0 : -1 );
  1370. X    }
  1371. X
  1372. X/*   */
  1373. X
  1374. X
  1375. X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */
  1376. X#define JD1970 2440587L
  1377. X
  1378. X
  1379. Xlong
  1380. Xtwjuliandate( tw )
  1381. Xstruct tws *tw;
  1382. X    {
  1383. X    register int mday, mon, year;
  1384. X    register long a, b;
  1385. X    double jd;
  1386. X
  1387. X    if ( (mday = tw -> tw_mday) < 1 || mday > 31 ||
  1388. X        (mon = tw -> tw_mon + 1) < 1 || mon > 12 ||
  1389. X        (year = tw -> tw_year) < 1 || year > 10000 )
  1390. X    return ( -1L );
  1391. X    if ( year < 100 )
  1392. X    year += CENTURY * 100;
  1393. X
  1394. X    if ( mon == 1 || mon == 2 )
  1395. X    {
  1396. X    --year;
  1397. X    mon += 12;
  1398. X    }
  1399. X    if ( year < 1583 )
  1400. X    return ( -1L );
  1401. X    a = year / 100;
  1402. X    b = 2 - a + a / 4;
  1403. X    b += (long) ( (double) year * 365.25 );
  1404. X    b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
  1405. X    jd = mday + b + 1720994.5;
  1406. X    return ( (long) jd );
  1407. X    }
  1408. X
  1409. X
  1410. Xlong
  1411. Xtwsubdayclock( tw )
  1412. Xstruct tws *tw;
  1413. X    {
  1414. X    register int sec, min, hour;
  1415. X    register long result;
  1416. X
  1417. X    if ( (sec = tw -> tw_sec) < 0 || sec > 59 ||
  1418. X        (min = tw -> tw_min) < 0 || min > 59 ||
  1419. X        (hour = tw -> tw_hour) < 0 || hour > 23 )
  1420. X    return ( -1L );
  1421. X
  1422. X    result = ( hour * 60 + min ) * 60 + sec;
  1423. X    result -= 60 * tw -> tw_zone;
  1424. X    if ( tw -> tw_flags & TW_DST )
  1425. X    result -= 60 * 60;
  1426. X
  1427. X    return ( result );
  1428. X    }
  1429. X
  1430. X
  1431. Xlong
  1432. Xtwclock( tw )
  1433. Xstruct tws *tw;
  1434. X    {
  1435. X    register long jd, sdc, result;
  1436. X
  1437. X    if ( tw -> tw_clock != 0L )
  1438. X    return ( tw -> tw_clock );
  1439. X
  1440. X    if ( ( jd = twjuliandate( tw ) ) == -1L )
  1441. X    return ( tw -> tw_clock = -1L );
  1442. X    if ( ( sdc = twsubdayclock( tw ) ) == -1L )
  1443. X    return ( tw -> tw_clock = -1L );
  1444. X
  1445. X    result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
  1446. X
  1447. X    return ( tw -> tw_clock = result );
  1448. X    }
  1449. X
  1450. X/*   */
  1451. X
  1452. X/*** twsubtract - subtract tw2 from tw1, returning result in seconds
  1453. X
  1454. XThe point of this routine is that using twclock( tw1 ) - twclock( tw2 )
  1455. Xwould limit you to dates after the Unix* Epoch ( 01 January 1970 ).  This
  1456. Xroutine avoids that limit.  However, because the result is represented
  1457. Xby 32 bits, it is still limited to a span of two billion seconds, which is
  1458. Xabout 66 years.
  1459. X
  1460. X*/
  1461. X
  1462. Xlong
  1463. Xtwsubtract( tw1, tw2 )
  1464. Xstruct tws *tw1, *tw2;
  1465. X    {
  1466. X    register long jd1, jd2, sdc1, sdc2, result;
  1467. X
  1468. X    if ( ( jd1 = twjuliandate( tw1 ) ) == -1L )
  1469. X    return ( 0L );
  1470. X    if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L )
  1471. X    return ( 0L );
  1472. X
  1473. X    if ( ( jd2 = twjuliandate( tw2 ) ) == -1L )
  1474. X    return ( 0L );
  1475. X    if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L )
  1476. X    return ( 0L );
  1477. X    
  1478. X    result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 );
  1479. X
  1480. X    return ( result );
  1481. X    }
  1482. X
  1483. X/*   */
  1484. X
  1485. X/*
  1486. X *    Simple calculation of day of the week.  Algorithm used is Zeller's
  1487. X *    congruence.  Currently, we assume if tw -> tw_year < 100
  1488. X *    then the century is CENTURY.
  1489. X */
  1490. X
  1491. Xset_dotw( tw )
  1492. Xstruct tws *tw;
  1493. X    {
  1494. X    register int month, day, year, century;
  1495. X
  1496. X    month = tw -> tw_mon - 1;
  1497. X    day = tw -> tw_mday;
  1498. X    year = tw -> tw_year % 100;
  1499. X    century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY;
  1500. X
  1501. X    if ( month <= 0 )
  1502. X    {
  1503. X    month += 12;
  1504. X    if ( --year < 0 )
  1505. X        {
  1506. X        year += 100;
  1507. X        century--;
  1508. X        }
  1509. X    }
  1510. X
  1511. X    tw -> tw_wday =
  1512. X    ((26 * month - 2) / 10 + day + year + year / 4
  1513. X        - 3 * century / 4 + 1) % 7;
  1514. X
  1515. X    tw -> tw_flags &= ~TW_SDAY;
  1516. X    tw -> tw_flags |= TW_SIMP;
  1517. X    }
  1518. X
  1519. X
  1520. X/* * Unix is a virus from outer space. */
  1521. ________This_Is_The_END________
  1522. if test `wc -c < dtime.c` -ne     9032; then
  1523.     echo 'shar: dtime.c was damaged during transit (should have been     9032 bytes)'
  1524. fi
  1525. fi        ; : end of overwriting check
  1526. echo 'x - dtimep.lex'
  1527. if test -f dtimep.lex; then echo 'shar: not overwriting dtimep.lex'; else
  1528. sed 's/^X//' << '________This_Is_The_END________' > dtimep.lex
  1529. X%e 2000
  1530. X%p 5000
  1531. X%n 1000
  1532. X%a 4000
  1533. X%START    Z
  1534. Xsun    (sun(day)?)
  1535. Xmon    (mon(day)?)
  1536. Xtue    (tue(sday)?)
  1537. Xwed    (wed(nesday)?)
  1538. Xthu    (thu(rsday)?)
  1539. Xfri    (fri(day)?)
  1540. Xsat    (sat(urday)?)
  1541. X
  1542. XDAY    ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
  1543. X
  1544. Xjan    (jan(uary)?)
  1545. Xfeb    (feb(ruary)?)
  1546. Xmar    (mar(ch)?)
  1547. Xapr    (apr(il)?)
  1548. Xmay    (may)
  1549. Xjun    (jun(e)?)
  1550. Xjul    (jul(y)?)
  1551. Xaug    (aug(ust)?)
  1552. Xsep    (sep(tember)?)
  1553. Xoct    (oct(ober)?)
  1554. Xnov    (nov(ember)?)
  1555. Xdec    (dec(ember)?)
  1556. X
  1557. XMONTH    ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
  1558. X
  1559. Xw    ([ \t]*)
  1560. XW    ([ \t]+)
  1561. XD    ([0-9]?[0-9])
  1562. Xd    [0-9]
  1563. X%{
  1564. X/* dtimep.lex - routines to do ``ARPA-style'' time parsing
  1565. X
  1566. Xver  date   who remarks
  1567. X--- ------- --- -------------------------------------------------------------
  1568. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1569. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1570. X              of Marshall Rose.
  1571. X
  1572. X*/
  1573. X
  1574. X#include "tws.h"
  1575. X#include <ctype.h>
  1576. X#include <sys/types.h>
  1577. X#include <time.h>
  1578. X#ifdef SYS5
  1579. X#include <string.h>
  1580. X#else SYS5
  1581. X#include <strings.h>
  1582. X#include <sys/timeb.h>
  1583. X#endif SYS5
  1584. X
  1585. X#ifdef SYS5
  1586. Xextern int  daylight;
  1587. Xextern long timezone;
  1588. Xextern char *tzname[];
  1589. X#endif SYS5
  1590. X
  1591. X/*
  1592. X * Table to convert month names to numeric month.  We use the
  1593. X * fact that the low order 5 bits of the sum of the 2nd & 3rd
  1594. X * characters of the name is a hash with no collisions for the 12
  1595. X * valid month names.  (The mask to 5 bits maps any combination of
  1596. X * upper and lower case into the same hash value).
  1597. X */
  1598. Xstatic int month_map[] = {
  1599. X    0,
  1600. X    6,    /* 1 - Jul */
  1601. X    3,    /* 2 - Apr */
  1602. X    5,    /* 3 - Jun */
  1603. X    0,
  1604. X    10,    /* 5 - Nov */
  1605. X    0,
  1606. X    1,    /* 7 - Feb */
  1607. X    11,    /* 8 - Dec */
  1608. X    0,
  1609. X    0,
  1610. X    0,
  1611. X    0,
  1612. X    0,
  1613. X    0,
  1614. X    0,    /*15 - Jan */
  1615. X    0,
  1616. X    0,
  1617. X    0,
  1618. X    2,    /*19 - Mar */
  1619. X    0,
  1620. X    8,    /*21 - Sep */
  1621. X    0,
  1622. X    9,    /*23 - Oct */
  1623. X    0,
  1624. X    0,
  1625. X    4,    /*26 - May */
  1626. X    0,
  1627. X    7 };    /*28 - Aug */
  1628. X/*
  1629. X * Same trick for day-of-week using the hash function
  1630. X *  (c1 & 7) + (c2 & 4)
  1631. X */
  1632. Xstatic int day_map[] = {
  1633. X    0,
  1634. X    0,
  1635. X    0,
  1636. X    6,    /* 3 - Sat */
  1637. X    4,    /* 4 - Thu */
  1638. X    0,
  1639. X    5,    /* 6 - Fri */
  1640. X    0,    /* 7 - Sun */
  1641. X    2,    /* 8 - Tue */
  1642. X    1    /* 9 - Mon */,
  1643. X    0,
  1644. X    3 };    /*11 - Wed */
  1645. X#define SETDAY tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
  1646. X        tw.tw_flags |= TW_SEXP;\
  1647. X        cp += 2;
  1648. X#define SETMONTH tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
  1649. X         cp += 2;\
  1650. X         SKIPD;
  1651. X#define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
  1652. X#define CVT2 ( (*cp++ - '0')*10 + (*cp++ - '0') )
  1653. X#define CVT3 ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1654. X#define CVT4 ( ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1655. X#define SKIPD while ( ! isdigit( *cp++ ) ) ; --cp;
  1656. X#define ZONE(x) tw.tw_zone=(x);
  1657. X#define ZONED(x) tw.tw_zone=(x); tw.tw_flags |= TW_DST;
  1658. X#define LC(c) (isupper( c ) ? tolower( c ) : ( c ))
  1659. X%}
  1660. X%%
  1661. X%{
  1662. Xstruct tws *
  1663. Xdparsetime( str )
  1664. Xchar *str;
  1665. X    {
  1666. X    register int i;
  1667. X    static struct tws tw;
  1668. X    register char *cp;
  1669. X    register int gotdate = 0;
  1670. X#ifndef SYS5
  1671. X    struct timeb    tb;
  1672. X#endif not SYS5
  1673. X    long clock;
  1674. X
  1675. X    start_cond = 0;
  1676. X
  1677. X    /* Zero out the struct. */
  1678. X    bzero( (char *) &tw, sizeof tw );
  1679. X
  1680. X    /* Set default time zone. */
  1681. X#ifndef SYS5
  1682. X    ftime( &tb );
  1683. X    tw.tw_zone = -tb.timezone;
  1684. X#else SYS5
  1685. X    tzset( );
  1686. X    tw.tw_zone = -(timezone / 60);
  1687. X#endif SYS5
  1688. X
  1689. X    for ( ; ; )
  1690. X    switch ( cp = str, lex_string( &str, start_cond ) )
  1691. X        {
  1692. X        case -1:
  1693. X        if ( ! gotdate )
  1694. X            return ( NULL );
  1695. X        tw.tw_flags |= TW_JUNK;
  1696. X        /* fall through */
  1697. X        case 0:
  1698. X        if ( tw.tw_year == 0 )
  1699. X            {
  1700. X            /* Set default year. */
  1701. X            time( &clock );
  1702. X            tw.tw_year = localtime( &clock ) -> tm_year;
  1703. X            }
  1704. X        return ( &tw );
  1705. X
  1706. X%}
  1707. X{DAY}","?{w}                SETDAY;
  1708. X"("{DAY}")"(","?)            cp++, SETDAY;
  1709. X
  1710. X{D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w}    {
  1711. X#ifdef EUROPE
  1712. X                    tw.tw_mday = CVT1OR2; cp++;
  1713. X                    tw.tw_mon  = CVT1OR2 - 1; cp++;
  1714. X#else EUROPE
  1715. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1716. X                    tw.tw_mday  = CVT1OR2; cp++;
  1717. X#endif EUROPE
  1718. X                    for ( i = 0; isdigit( *cp ); )
  1719. X                        i = i * 10 + (*cp++ - '0');
  1720. X                    tw.tw_year = i;
  1721. X                    gotdate++;
  1722. X                    }
  1723. X{D}("/"|"-"){D}{w}            {
  1724. X#ifdef EUROPE
  1725. X                    tw.tw_mday = CVT1OR2; cp++;
  1726. X                    tw.tw_mon  = CVT1OR2 - 1;
  1727. X#else EUROPE
  1728. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1729. X                    tw.tw_mday  = CVT1OR2;
  1730. X#endif EUROPE
  1731. X                    gotdate++;
  1732. X                    }
  1733. X{D}(("-"{MONTH}"-")|(" "{MONTH}" ")|({MONTH})){D}?{d}{d}({W}at)?{w}    {
  1734. X                    tw.tw_mday = CVT1OR2;
  1735. X                    while ( ! isalpha( *cp++ ) )
  1736. X                        ;
  1737. X                    SETMONTH;
  1738. X                    for ( i = 0; isdigit( *cp ); )
  1739. X                        i = i * 10 + (*cp++ - '0');
  1740. X                    tw.tw_year = i;
  1741. X                    gotdate++;
  1742. X                    }
  1743. X{D}"-"?{MONTH}({W}at)?{w}        {
  1744. X                    tw.tw_mday = CVT1OR2;
  1745. X                    while ( ! isalpha( *cp++ ) )
  1746. X                        ;
  1747. X                    SETMONTH;
  1748. X                    gotdate++;
  1749. X                    }
  1750. X{MONTH}{W}{D}","{W}{D}?{d}{d}{w}    {
  1751. X                    cp++;
  1752. X                    SETMONTH;
  1753. X                    tw.tw_mday = CVT1OR2;
  1754. X                    SKIPD;
  1755. X                    for ( i = 0; isdigit( *cp ); )
  1756. X                        i = i * 10 + (*cp++ - '0');
  1757. X                    tw.tw_year = i;
  1758. X                    gotdate++;
  1759. X                    }
  1760. X{MONTH}{W}{D}{w}            {
  1761. X                    cp++;
  1762. X                    SETMONTH;
  1763. X                    tw.tw_mday = CVT1OR2;
  1764. X                    gotdate++;
  1765. X                    }
  1766. X
  1767. X{D}:{D}:{D}({w}am)?{w}            {
  1768. X                    tw.tw_hour = CVT1OR2; cp++;
  1769. X                    tw.tw_min  = CVT1OR2; cp++;
  1770. X                    tw.tw_sec  = CVT1OR2;
  1771. X                    BEGIN Z;
  1772. X                    }
  1773. X{D}:{D}:{D}{w}pm{w}            {
  1774. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1775. X                    tw.tw_min  = CVT1OR2; cp++;
  1776. X                    tw.tw_sec  = CVT1OR2;
  1777. X                    BEGIN Z;
  1778. X                    }
  1779. X{D}:{D}({w}am)?{w}            {
  1780. X                    tw.tw_hour = CVT1OR2; cp++;
  1781. X                    tw.tw_min  = CVT1OR2;
  1782. X                    BEGIN Z;
  1783. X                    }
  1784. X{D}:{D}{w}pm{w}                {
  1785. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1786. X                    tw.tw_min  = CVT1OR2;
  1787. X                    BEGIN Z;
  1788. X                    }
  1789. X[0-2]{d}{d}{d}{d}{d}{w}            {
  1790. X                    tw.tw_hour = CVT1OR2;
  1791. X                    tw.tw_min  = CVT1OR2;
  1792. X                    tw.tw_sec  = CVT1OR2;
  1793. X                    BEGIN Z;
  1794. X                    }
  1795. X[0-2]{d}{d}{d}{w}            {
  1796. X                    tw.tw_hour = CVT1OR2;
  1797. X                    tw.tw_min  = CVT1OR2;
  1798. X                    BEGIN Z;
  1799. X                    }
  1800. X<Z>"-"?ut                ZONE(0 * 60);
  1801. X<Z>"-"?gmt                ZONE(0 * 60);
  1802. X<Z>"-"?jst                ZONE(2 * 60);
  1803. X<Z>"-"?jdt                ZONED(2 * 60);
  1804. X<Z>"-"?est                ZONE(-5 * 60);
  1805. X<Z>"-"?edt                ZONED(-5 * 60);
  1806. X<Z>"-"?cst                ZONE(-6 * 60);
  1807. X<Z>"-"?cdt                ZONED(-6 * 60);
  1808. X<Z>"-"?mst                ZONE(-7 * 60);
  1809. X<Z>"-"?mdt                ZONED(-7 * 60);
  1810. X<Z>"-"?pst                ZONE(-8 * 60);
  1811. X<Z>"-"?pdt                ZONED(-8 * 60);
  1812. X<Z>"-"?nst                ZONE(-(3 * 60 + 30));
  1813. X<Z>"-"?ast                ZONE(-4 * 60);
  1814. X<Z>"-"?adt                ZONED(-4 * 60);
  1815. X<Z>"-"?yst                ZONE(-9 * 60);
  1816. X<Z>"-"?ydt                ZONED(-9 * 60);
  1817. X<Z>"-"?hst                ZONE(-10 * 60);
  1818. X<Z>"-"?hdt                ZONED(-10 * 60);
  1819. X<Z>"-"?bst                ZONED(-1 * 60);
  1820. X<Z>[a-i]                tw.tw_zone = 60 * (('a'-1) - LC (*cp));
  1821. X<Z>[k-m]                tw.tw_zone = 60 * ('a' - LC (*cp));
  1822. X<Z>[n-y]                tw.tw_zone = 60 * (LC (*cp) - 'm');
  1823. X<Z>"+"[0-1]{d}{d}{d}            {
  1824. X                    cp++;
  1825. X                    tw.tw_zone = ((cp[0] * 10 + cp[1])
  1826. X                             -('0' * 10   + '0'))*60
  1827. X                            +((cp[2] * 10 + cp[3])
  1828. X                             -('0' * 10   + '0'));
  1829. X#ifdef DSTXXX
  1830. X                    zonehack (&tw);
  1831. X#endif DSTXXX
  1832. X                    cp += 4;
  1833. X                    }
  1834. X<Z>"-"[0-1]{d}{d}{d}            {
  1835. X                    cp++;
  1836. X                    tw.tw_zone = (('0' * 10   + '0')
  1837. X                             -(cp[0] * 10 + cp[1]))*60
  1838. X                            +(('0' * 10   + '0')
  1839. X                             -(cp[2] * 10 + cp[3]));
  1840. X#ifdef DSTXXX
  1841. X                    zonehack (&tw);
  1842. X#endif DSTXXX
  1843. X                    cp += 4;
  1844. X                    }
  1845. X
  1846. X<Z>{W}{d}{d}{d}{d}            {
  1847. X                    SKIPD;
  1848. X                    tw.tw_year = CVT4;
  1849. X                    }
  1850. X\n    |
  1851. X{W}    ;
  1852. X%%
  1853. X
  1854. X#ifdef DSTXXX
  1855. Xstatic
  1856. Xzonehack( tw )
  1857. Xregister struct tws *tw;
  1858. X    {
  1859. X    register struct tm *tm;
  1860. X
  1861. X    if ( twclock( tw ) == -1L )
  1862. X    return;
  1863. X
  1864. X    tm = localtime( &tw -> tw_clock );
  1865. X    if ( tm -> tm_isdst )
  1866. X    {
  1867. X    tw -> tw_flags |= TW_DST;
  1868. X    tw -> tw_zone -= 60;
  1869. X    }
  1870. X    }
  1871. X#endif DSTXXX
  1872. X
  1873. X
  1874. X#ifdef SYS5
  1875. X/* Not all SYS5's have bzero( ). */
  1876. X
  1877. Xbzero( b, length )
  1878. Xchar *b;
  1879. Xint length;
  1880. X    {
  1881. X    while ( length-- > 0 )
  1882. X    *b++ = 0;
  1883. X    }
  1884. X#endif
  1885. ________This_Is_The_END________
  1886. if test `wc -c < dtimep.lex` -ne     7327; then
  1887.     echo 'shar: dtimep.lex was damaged during transit (should have been     7327 bytes)'
  1888. fi
  1889. fi        ; : end of overwriting check
  1890. echo 'x - lexedit.sed'
  1891. if test -f lexedit.sed; then echo 'shar: not overwriting lexedit.sed'; else
  1892. sed 's/^X//' << '________This_Is_The_END________' > lexedit.sed
  1893. X2,/^extern int yylineno;$/c\
  1894. Xstatic int start_cond = 0;\
  1895. X#define BEGIN start_cond =
  1896. X/^struct yysvf \*yyestate;$/,/^extern struct yysvf yysvec/d
  1897. X/^# define YYNEWLINE /,/^int nstr;/d
  1898. X/^while((nstr = yylook()/,/^if(yywrap()) /d
  1899. X/^case -1:$/,/^fprintf(yyout,"bad switch yylook /c\
  1900. X    default: return(0);
  1901. X/^struct yysvf *yybgin = yysvec+1;$/d
  1902. X/^int yylineno /,$d
  1903. ________This_Is_The_END________
  1904. if test `wc -c < lexedit.sed` -ne      356; then
  1905.     echo 'shar: lexedit.sed was damaged during transit (should have been      356 bytes)'
  1906. fi
  1907. fi        ; : end of overwriting check
  1908. echo 'x - lexstring.c'
  1909. if test -f lexstring.c; then echo 'shar: not overwriting lexstring.c'; else
  1910. sed 's/^X//' << '________This_Is_The_END________' > lexstring.c
  1911. X#include <stdio.h>
  1912. X#include <ctype.h>
  1913. X
  1914. X#define YYLERR yysvec
  1915. X#define YYTYPE int
  1916. X#define YYLMAX 256
  1917. X
  1918. Xstruct yysvf { 
  1919. X    struct yywork *yystoff;
  1920. X    struct yysvf *yyother;
  1921. X    int *yystops;
  1922. X};
  1923. X
  1924. Xstruct yywork { 
  1925. X    YYTYPE    verify;
  1926. X    YYTYPE    advance; 
  1927. X}; 
  1928. X
  1929. Xextern int yyvstop[];
  1930. Xextern struct yywork yycrank[];
  1931. Xextern struct yysvf yysvec[];
  1932. Xextern struct yywork *yytop;
  1933. Xextern char yymatch[];
  1934. Xextern char yyextra[];
  1935. X
  1936. X#ifdef LEXDEBUG
  1937. Xstatic int debug = 0;
  1938. X#endif
  1939. X
  1940. Xlex_string( strptr, start_cond)
  1941. X    char    **strptr;
  1942. X    int    start_cond;
  1943. X{
  1944. X    register struct yysvf *state, **lsp;
  1945. X    register struct yywork *tran;
  1946. X    register int ch;
  1947. X    register char    *cp = *strptr;
  1948. X    register int    *found;
  1949. X    struct    yysvf *yylstate[YYLMAX];
  1950. X
  1951. X    /* start off machines */
  1952. X    lsp = yylstate;
  1953. X    state = yysvec+1+start_cond;
  1954. X    for (;;){
  1955. X#ifdef LEXDEBUG
  1956. X        if(debug)
  1957. X            fprintf(stderr,"state %d\n",state-yysvec-1);
  1958. X#endif
  1959. X        tran = state->yystoff;
  1960. X        if(tran == yycrank)
  1961. X            /* may not be any transitions */
  1962. X            if (state->yyother == 0 ||
  1963. X                state->yyother->yystoff == yycrank)
  1964. X                break;
  1965. X
  1966. X        ch = *cp++;
  1967. X#ifdef ONECASE
  1968. X        if (isupper(ch) )
  1969. X            ch = tolower(ch);
  1970. X#endif
  1971. Xtryagain:
  1972. X#ifdef LEXDEBUG
  1973. X        if(debug){
  1974. X            fprintf(stderr,"char ");
  1975. X            allprint(ch);
  1976. X            putchar('\n');
  1977. X        }
  1978. X#endif
  1979. X        if ( tran > yycrank){
  1980. X            tran += ch;
  1981. X            if (tran <= yytop && tran->verify+yysvec == state){
  1982. X                if ((state = tran->advance+yysvec) == YYLERR){
  1983. X                    /* error transitions */
  1984. X                    --cp;
  1985. X                    break;
  1986. X                }
  1987. X                *lsp++ = state;
  1988. X                goto contin;
  1989. X            }
  1990. X
  1991. X        } else if(tran < yycrank) {
  1992. X            /* r < yycrank */
  1993. X            tran = yycrank+(yycrank-tran) + ch;
  1994. X#ifdef LEXDEBUG
  1995. X            if (debug)
  1996. X                fprintf(stderr,"compressed state\n");
  1997. X#endif
  1998. X            if(tran <= yytop && tran->verify+yysvec == state){
  1999. X                if ((state = tran->advance+yysvec) == YYLERR)
  2000. X                    /* error transitions */
  2001. X                    break;
  2002. X
  2003. X                *lsp++ = state;
  2004. X                goto contin;
  2005. X            }
  2006. X            tran += (yymatch[ch] - ch);
  2007. X#ifdef LEXDEBUG
  2008. X            if(debug){
  2009. X                fprintf(stderr,"try fall back character ");
  2010. X                allprint(yymatch[ch]);
  2011. X                putchar('\n');
  2012. X            }
  2013. X#endif
  2014. X            if(tran <= yytop && tran->verify+yysvec == state){
  2015. X                if(tran->advance+yysvec == YYLERR)
  2016. X                    /* error transition */
  2017. X                    break;
  2018. X
  2019. X                *lsp++ = state = tran->advance+yysvec;
  2020. X                goto contin;
  2021. X            }
  2022. X        }
  2023. X        if ((state = state->yyother) &&
  2024. X            (tran = state->yystoff) != yycrank){
  2025. X#ifdef LEXDEBUG
  2026. X            if(debug)
  2027. X                fprintf(stderr,"fall back to state %d\n",
  2028. X                    state-yysvec-1);
  2029. X#endif
  2030. X            goto tryagain;
  2031. X        } else
  2032. X            break;
  2033. X
  2034. Xcontin:
  2035. X#ifdef LEXDEBUG
  2036. X        if(debug){
  2037. X            fprintf(stderr,"state %d char ",state-yysvec-1);
  2038. X            allprint(ch);
  2039. X            putchar('\n');
  2040. X        }
  2041. X#endif
  2042. X        ;
  2043. X    }
  2044. X#ifdef LEXDEBUG
  2045. X    if(debug){
  2046. X        fprintf(stderr,"stopped at %d with ",*(lsp-1)-yysvec-1);
  2047. X        allprint(ch);
  2048. X        putchar('\n');
  2049. X    }
  2050. X#endif
  2051. X    while (lsp-- > yylstate){
  2052. X        if (*lsp != 0 && (found= (*lsp)->yystops) && *found > 0){
  2053. X            if(yyextra[*found]){
  2054. X                /* must backup */
  2055. X                ch = -*found;
  2056. X                do {
  2057. X                    while (*found && *found++ != ch)
  2058. X                        ;
  2059. X                 } while (lsp > yylstate &&
  2060. X                      (found = (*--lsp)->yystops));
  2061. X            }
  2062. X#ifdef LEXDEBUG
  2063. X            if(debug){
  2064. X                fprintf(stderr,"\nmatch ");
  2065. X                for ( cp = *strptr;
  2066. X                      cp <= ((*strptr)+(lsp-yylstate));
  2067. X                      cp++)
  2068. X                    allprint( *cp );
  2069. X                fprintf(stderr," action %d\n",*found);
  2070. X            }
  2071. X#endif
  2072. X            *strptr += (lsp - yylstate + 1);
  2073. X            return(*found);
  2074. X        }
  2075. X    }
  2076. X    /* the string didn't match anything - if we're looking at
  2077. X     * eos, just return 0.  Otherwise, bump the string pointer
  2078. X     * and return -1.
  2079. X     */
  2080. X#ifdef LEXDEBUG
  2081. X    if(debug)
  2082. X        fprintf(stderr,"\nno match\n");
  2083. X#endif
  2084. X    if ( **strptr ) {
  2085. X        (*strptr)++;
  2086. X        return (-1);
  2087. X    }
  2088. X    return (0);
  2089. X}
  2090. X
  2091. X#ifdef LEXDEBUG
  2092. Xallprint(c)
  2093. X    char c;
  2094. X{
  2095. X    if ( c < 32 ) {
  2096. X        putc( '^', stderr );
  2097. X        c += 32;
  2098. X    } else if ( c == 127 ) {
  2099. X        putc( '^', stderr );
  2100. X        c = '?';
  2101. X    }
  2102. X    putc( c, stderr );
  2103. X}
  2104. X#endif
  2105. ________This_Is_The_END________
  2106. if test `wc -c < lexstring.c` -ne     3713; then
  2107.     echo 'shar: lexstring.c was damaged during transit (should have been     3713 bytes)'
  2108. fi
  2109. fi        ; : end of overwriting check
  2110. echo 'x - libtws.3'
  2111. if test -f libtws.3; then echo 'shar: not overwriting libtws.3'; else
  2112. sed 's/^X//' << '________This_Is_The_END________' > libtws.3
  2113. X.TH libtws 3 "08 November 1986"
  2114. X.SH NAME
  2115. Xlibtws \- alternate date and time routines including parsing
  2116. X.SH SYNOPSIS
  2117. X.nf
  2118. X.fc ^ ~
  2119. X.ta \w'char *dtimezone( offset, flags );  'u
  2120. Xinclude "tws.h"
  2121. X.PP
  2122. X^struct tws *dlocaltime( clock );~^/* local clock into tws */
  2123. Xlong *clock;
  2124. X.PP
  2125. X^struct tws *gmtime( clock );~^/* GMT clock into tws */
  2126. Xlong *clock;
  2127. X.PP
  2128. X^char *dtime( clock );~^/* clock into string */
  2129. Xlong *clock;
  2130. X.PP
  2131. X^long twclock( t );~^/* tws into clock */
  2132. Xstruct tws *t;
  2133. X.PP
  2134. X^long twjuliandate( t );~^/* tws into Julian day number */
  2135. Xstruct tws *t;
  2136. X.PP
  2137. X^struct tws *dparsetime( str );~^/* string into tws */
  2138. Xchar *str;
  2139. X.PP
  2140. X^char *dctime( t );~^/* tws into string */
  2141. Xstruct tws *t;
  2142. X.PP
  2143. X^char *dasctime( t, flags );~^/* tws into string */
  2144. Xstruct tws *t;
  2145. Xint flags;
  2146. X.PP
  2147. X^char *dtimezone( offset, flags );~^/* timezone into string */
  2148. Xint offset, flags;
  2149. X.PP
  2150. X^char *dtwszone( t );~^/* tws's timezone into string */
  2151. Xstruct tws *t;
  2152. X.PP
  2153. X^char *dtimemow( );~^/* current time into string */
  2154. X.PP
  2155. X^struct tws *dtwstime( );~^/* current time into tws */
  2156. X.PP
  2157. X^void twscopy( tot, fromt );~^/* copy a tws */
  2158. Xstruct tws *tot, *fromt;
  2159. X.PP
  2160. X^int twsort( t1, t2 );~^/* compare two tws's */
  2161. Xstruct tws *t1, *t2;
  2162. X.PP
  2163. X^long twsubtract( t1, t2 );~^/* seconds between t2 and t1 */
  2164. Xstruct tws *t1, *t2;
  2165. X.fi
  2166. X.SH DESCRIPTION
  2167. X.I Libtws
  2168. Xis a fairly complete date/time library.
  2169. XUnlike the standard Unix* date/time routines,
  2170. X.I libtws
  2171. Xwill parse date/time strings into internal form.
  2172. XThe format for specifying date/time strings is pretty loose - basically
  2173. Xthe same as the format for date/times in network mail.
  2174. X.PP
  2175. XMost of the routines do not use the Unix* "clock" time
  2176. Xformat, and therefore are not limited to dates after 01 January 1970.
  2177. XIn particular, twsubtract() lets you subtract two dates without
  2178. Xconverting them to "clock" form.
  2179. X.SH "SEE\ ALSO"
  2180. X.IR ctime(3),
  2181. X.IR time(3)
  2182. X.SH AUTHOR
  2183. XMost of
  2184. X.I libtws
  2185. Xcame from version 6.5 of the MH message
  2186. Xhandling system, courtesy of Marshall Rose.
  2187. XSome improvements (?) were added by Jef Poskanzer.
  2188. X.SH BUGS
  2189. XThe return values point to static data whose contents are overwritten
  2190. Xby the next call.
  2191. X.PP
  2192. XThe basic Unix* time format (clock) only goes back to 1970, limiting
  2193. Xapplications somewhat.
  2194. X.SH NOTE
  2195. X* Unix is a virus from outer space.
  2196. ________This_Is_The_END________
  2197. if test `wc -c < libtws.3` -ne     2241; then
  2198.     echo 'shar: libtws.3 was damaged during transit (should have been     2241 bytes)'
  2199. fi
  2200. fi        ; : end of overwriting check
  2201. echo 'x - marc.c'
  2202. if test -f marc.c; then echo 'shar: not overwriting marc.c'; else
  2203. sed 's/^X//' << '________This_Is_The_END________' > marc.c
  2204. X/*
  2205. X * $Header: marc.c,v 1.2 88/06/06 01:05:02 hyc Locked $
  2206. X */
  2207. X
  2208. X/*  MARC - Archive merge utility
  2209. X
  2210. X    Version 5.21, created on 04/22/87 at 15:05:10
  2211. X
  2212. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  2213. X
  2214. X    By:     Thom Henderson
  2215. X
  2216. X    Description:
  2217. X     This program is used to "merge" archives.  That is, to move
  2218. X     files from one archive to another with no data conversion.
  2219. X     Please refer to the ARC source for a description of archives
  2220. X     and archive formats.
  2221. X
  2222. X    Instructions:
  2223. X     Run this program with no arguments for complete instructions.
  2224. X
  2225. X    Language:
  2226. X     Computer Innovations Optimizing C86
  2227. X*/
  2228. X#include <stdio.h>
  2229. X#include "arc.h"
  2230. X
  2231. XFILE *src;                   /* source archive */
  2232. Xchar srcname[STRLEN];               /* source archive name */
  2233. X
  2234. Xstatic char **lst;               /* files list */
  2235. Xstatic int lnum;               /* length of files list */
  2236. X
  2237. X
  2238. Xmain(nargs,arg)                   /* system entry point */
  2239. Xint nargs;                   /* number of arguments */
  2240. Xchar *arg[];                   /* pointers to arguments */
  2241. X{
  2242. X    char *makefnam();               /* filename fixup routine */
  2243. X    char *calloc();               /* memory manager */
  2244. X    char *envfind();
  2245. X#if    !MTS
  2246. X    char *arctemp2, *mktemp();        /* temp file stuff */
  2247. X#endif
  2248. X#if    GEMDOS
  2249. X    void exitpause();
  2250. X#endif
  2251. X    int n;                   /* index */
  2252. X
  2253. X    if(nargs<3)
  2254. X    {     printf("MARC - Archive merger, Version 5.21, created on 04/22/87 at 15:05:10\n");
  2255. X/*     printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
  2256. X     printf(" ALL RIGHTS RESERVED\n\n");
  2257. X     printf("Please refer all inquiries to:\n\n");
  2258. X     printf("    System Enhancement Associates\n");
  2259. X     printf("    21 New Street, Wayne NJ 07470\n\n");
  2260. X     printf("You may copy and distribute this program freely,");
  2261. X     printf(" provided that:\n");
  2262. X     printf("    1)      No fee is charged for such copying and");
  2263. X     printf(" distribution, and\n");
  2264. X     printf("    2)      It is distributed ONLY in its original,");
  2265. X     printf(" unmodified state.\n\n");
  2266. X     printf("If you like this program, and find it of use, then your");
  2267. X     printf(" contribution will\n");
  2268. X     printf("be appreciated.  You may not use this product in a");
  2269. X     printf(" commercial environment\n");
  2270. X     printf("or a governmental organization without paying a license");
  2271. X     printf(" fee of $35.  Site\n");
  2272. X     printf("licenses and commercial distribution licenses are");
  2273. X     printf(" available.  A program\n");
  2274. X     printf("disk and printed documentation are available for $50.\n");
  2275. X     printf("\nIf you fail to abide by the terms of this license, ");
  2276. X     printf(" then your conscience\n");
  2277. X     printf("will haunt you for the rest of your life.\n\n");
  2278. X*/
  2279. X     printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
  2280. X     printf("Where: <tgtarc> is the archive to add files to,\n");
  2281. X     printf("    <srcarc> is the archive to get files from, and\n");
  2282. X     printf("    <filename> is zero or more file names to get.\n");
  2283. X     printf("\nAdapted from MSDOS by Howard Chu\n");
  2284. X#if    GEMDOS
  2285. X     exitpause();
  2286. X#endif
  2287. X     return 1;
  2288. X    }
  2289. X
  2290. X    /* see where temp files go */
  2291. X#if    !MTS
  2292. X    arctemp = calloc(1, STRLEN);
  2293. X    if (!(arctemp2 = envfind("ARCTEMP")))
  2294. X        arctemp2 = envfind("TMPDIR");
  2295. X    if (arctemp2) {
  2296. X        strcpy(arctemp, arctemp2);
  2297. X        n = strlen(arctemp);
  2298. X        if (arctemp[n - 1] != CUTOFF)
  2299. X            arctemp[n] = CUTOFF;
  2300. X    }
  2301. X#if    !MSDOS
  2302. X    strcat(arctemp, mktemp("AXXXXXX"));
  2303. X#else
  2304. X    strcat(arctemp, "$ARCTEMP");
  2305. X#endif
  2306. X#else
  2307. X    guinfo("SHFSEP    ", gotinf);
  2308. X    sepchr[0] = gotinf[0];
  2309. X    guinfo("SCRFCHAR", gotinf);
  2310. X    tmpchr[0] = gotinf[0];
  2311. X    arctemp = "-$$$";
  2312. X    arctemp[0] = tmpchr[0];
  2313. X#endif
  2314. X
  2315. X    makefnam(arg[1],".arc",arcname);   /* fix up archive names */
  2316. X    makefnam(arg[2],".arc",srcname);
  2317. X/*    makefnam(".$$$",arcname,newname);*/
  2318. X    sprintf(newname,"%s.arc",arctemp);
  2319. X
  2320. X#if    !UNIX
  2321. X    upper(arcname); upper(srcname); upper(newname);
  2322. X#endif
  2323. X
  2324. X    arc = fopen(arcname,"rb");           /* open the archives */
  2325. X    if(!(src=fopen(srcname,"rb")))
  2326. X     abort("Cannot read source archive %s",srcname);
  2327. X    if(!(new=fopen(newname,"wb")))
  2328. X     abort("Cannot create new archive %s",newname);
  2329. X
  2330. X    if(!arc)
  2331. X     printf("Creating new archive %s\n",arcname);
  2332. X
  2333. X    /* get the files list set up */
  2334. X
  2335. X    lnum = nargs-3;               /* initial length of list */
  2336. X    if(lnum<1)                   /* phoney for default case */
  2337. X    {     lnum = 1;
  2338. X     lst = (char **) calloc(1,sizeof(char *));
  2339. X     lst[0] = "*.*";
  2340. X    }
  2341. X    else                   /* else use filenames given */
  2342. X    {     lst = (char **) calloc(lnum,sizeof(char *));
  2343. X     for(n=3; n<nargs; n++)
  2344. X          lst[n-3] = arg[n];
  2345. X
  2346. X     for(n=0; n<lnum; )           /* expand indirect references */
  2347. X     {    if(*lst[n] == '@')
  2348. X           expandlst(n);
  2349. X          else n++;
  2350. X     }
  2351. X    }
  2352. X
  2353. X    merge(lnum,lst);               /* merge desired files */
  2354. X
  2355. X    if(arc) fclose(arc);           /* close the archives */
  2356. X    fclose(src);
  2357. X    fclose(new);
  2358. X
  2359. X    if(arc)                   /* make the switch */
  2360. X     if(unlink(arcname))
  2361. X          abort("Unable to delete old copy of %s",arcname);
  2362. X    if(move(newname,arcname))
  2363. X     abort("Unable to rename %s to %s",newname,arcname);
  2364. X
  2365. X    setstamp(arcname,arcdate,arctime);     /* new arc matches newest file */
  2366. X
  2367. X#if    GEMDOS
  2368. X    exitpause();
  2369. X#endif
  2370. X    return nerrs;
  2371. X}
  2372. X
  2373. Xmerge(nargs,arg)               /* merge two archives */
  2374. Xint nargs;                   /* number of filename templates */
  2375. Xchar *arg[];                   /* pointers to names */
  2376. X{
  2377. X    struct heads srch;               /* source archive header */
  2378. X    struct heads arch;               /* target archive header */
  2379. X    int gotsrc, gotarc;               /* archive entry versions (0=end) */
  2380. X    int copy;                   /* true to copy file from source */
  2381. X    int n;                   /* index */
  2382. X
  2383. X    gotsrc = gethdr(src,&srch);           /* get first source file */
  2384. X    gotarc = gethdr(arc,&arch);           /* get first target file */
  2385. X
  2386. X    while(gotsrc || gotarc)           /* while more to merge */
  2387. X    {     if(strcmp(srch.name,arch.name)>0)
  2388. X     {    copyfile(arc,&arch,gotarc);
  2389. X          gotarc = gethdr(arc,&arch);
  2390. X     }
  2391. X
  2392. X     else if(strcmp(srch.name,arch.name)<0)
  2393. X     {    copy = 0;
  2394. X          for(n=0; n<nargs; n++)
  2395. X          {       if(match(srch.name,arg[n]))
  2396. X           {    copy = 1;
  2397. X            break;
  2398. X           }
  2399. X          }
  2400. X          if(copy)               /* select source or target */
  2401. X          {       printf("Adding file:      %s\n",srch.name);
  2402. X           copyfile(src,&srch,gotsrc);
  2403. X          }
  2404. X          else fseek(src,srch.size,1);
  2405. X          gotsrc = gethdr(src,&srch);
  2406. X     }
  2407. X
  2408. X     else                   /* duplicate names */
  2409. X     {    copy = 0;
  2410. X          {       if((srch.date>arch.date)
  2411. X           || (srch.date==arch.date && srch.time>arch.time))
  2412. X           {    for(n=0; n<nargs; n++)
  2413. X            {    if(match(srch.name,arg[n]))
  2414. X                 {      copy = 1;
  2415. X                  break;
  2416. X                 }
  2417. X            }
  2418. X           }
  2419. X          }
  2420. X          if(copy)               /* select source or target */
  2421. X          {       printf("Updating file: %s\n",srch.name);
  2422. X           copyfile(src,&srch,gotsrc);
  2423. X           gotsrc = gethdr(src,&srch);
  2424. X           if(gotarc)
  2425. X           {    fseek(arc,arch.size,1);
  2426. X            gotarc = gethdr(arc,&arch);
  2427. X           }
  2428. X          }
  2429. X          else
  2430. X          {       copyfile(arc,&arch,gotarc);
  2431. X           gotarc = gethdr(arc,&arch);
  2432. X           if(gotsrc)
  2433. X           {    fseek(src,srch.size,1);
  2434. X            gotsrc = gethdr(src,&srch);
  2435. X           }
  2436. X          }
  2437. X     }
  2438. X    }
  2439. X
  2440. X    hdrver = 0;                   /* end of archive marker */
  2441. X    writehdr(&arch,new);           /* mark the end of the archive */
  2442. X}
  2443. X
  2444. Xint gethdr(f,hdr)               /* special read header for merge */
  2445. XFILE *f;                   /* file to read from */
  2446. Xstruct heads *hdr;               /* storage for header */
  2447. X{
  2448. X    char *i = hdr->name;           /* string index */
  2449. X    int n;                   /* index */
  2450. X
  2451. X    for(n=0; n<FNLEN; n++)           /* fill name field */
  2452. X     *i++ = 0176;               /* impossible high value */
  2453. X    *--i = '\0';               /* properly end the name */
  2454. X
  2455. X    hdrver = 0;                   /* reset header version */
  2456. X    if(readhdr(hdr,f))               /* use normal reading logic */
  2457. X     return hdrver;               /* return the version */
  2458. X    else return 0;               /* or fake end of archive */
  2459. X}
  2460. X
  2461. Xcopyfile(f,hdr,ver)               /* copy a file from an archive */
  2462. XFILE *f;                   /* archive to copy from */
  2463. Xstruct heads *hdr;               /* header data for file */
  2464. Xint ver;                   /* header version */
  2465. X{
  2466. X    hdrver = ver;               /* set header version */
  2467. X    writehdr(hdr,new);               /* write out the header */
  2468. X    filecopy(f,new,hdr->size);           /* copy over the data */
  2469. X}
  2470. X
  2471. Xstatic expandlst(n)               /* expand an indirect reference */
  2472. Xint n;                       /* number of entry to expand */
  2473. X{
  2474. X    FILE *lf, *fopen();               /* list file, opener */
  2475. X    char *malloc(), *realloc();           /* memory managers */
  2476. X    char buf[100];               /* input buffer */
  2477. X    int x;                   /* index */
  2478. X    char *p = lst[n]+1;               /* filename pointer */
  2479. X
  2480. X    if(*p)                   /* use name if one was given */
  2481. X    {     makefnam(p,".CMD",buf);
  2482. X     upper(buf);
  2483. X     if(!(lf=fopen(buf,"r")))
  2484. X          abort("Cannot read list of files in %s",buf);
  2485. X    }
  2486. X    else lf = stdin;               /* else use standard input */
  2487. X
  2488. X    for(x=n+1; x<lnum; x++)           /* drop reference from the list */
  2489. X     lst[x-1] = lst[x];
  2490. X    lnum--;
  2491. X
  2492. X    while(fscanf(lf,"%99s",buf)>0)     /* read in the list */
  2493. X    {     if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
  2494. X          abort("too many file references");
  2495. X
  2496. X     lst[lnum] = malloc(strlen(buf)+1);
  2497. X     strcpy(lst[lnum],buf);           /* save the name */
  2498. X     lnum++;
  2499. X    }
  2500. X
  2501. X    if(lf!=stdin)               /* avoid closing standard input */
  2502. X     fclose(lf);
  2503. X}
  2504. ________This_Is_The_END________
  2505. if test `wc -c < marc.c` -ne     9053; then
  2506.     echo 'shar: marc.c was damaged during transit (should have been     9053 bytes)'
  2507. fi
  2508. fi        ; : end of overwriting check
  2509. exit 0
  2510.  
  2511.