home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume36 / chiaro / part16 < prev    next >
Text File  |  1993-03-26  |  56KB  |  1,795 lines

  1. Newsgroups: comp.sources.misc
  2. From: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  3. Subject: v36i086:  chiaro - Image Utilities, Part16/18
  4. Message-ID: <1993Mar26.202947.15113@sparky.imd.sterling.com>
  5. X-Md4-Signature: 0ce527b864af74accede3a338ea6412b
  6. Date: Fri, 26 Mar 1993 20:29:47 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  10. Posting-number: Volume 36, Issue 86
  11. Archive-name: chiaro/part16
  12. Environment: UNIX, Sun, DECstation, 3B1
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  src/comsrch.c src/gifcheck.c src/mf.h
  19. # Wrapped by kent@sparky on Thu Mar 25 11:20:07 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 16 (of 18)."'
  23. if test -f 'src/comsrch.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/comsrch.c'\"
  25. else
  26.   echo shar: Extracting \"'src/comsrch.c'\" \(24372 characters\)
  27.   sed "s/^X//" >'src/comsrch.c' <<'END_OF_FILE'
  28. X/***************************************************************************
  29. X*   comsrch.C                                                              *
  30. X*   MODULE:  -                                                             *
  31. X*   OS:      UNIX                                                          *
  32. X*                                                                          *
  33. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  34. X*                                                                          *
  35. X*   This file contains the code for parsing complex search strings and     *
  36. X*   performing the search.                                                 *
  37. X*                                                                          *
  38. X*   $Id: comsrch.c,v 1.8 1993/03/13 02:57:12 jwbirdsa Exp $
  39. X*                                                                          *
  40. X***************************************************************************/
  41. X
  42. X#include "config.h"
  43. X
  44. X/*
  45. X** system includes <>
  46. X*/
  47. X
  48. X#ifndef NO_STDLIB
  49. X#include <stdlib.h>
  50. X#endif
  51. X#ifndef NO_STR_INC
  52. X#ifdef STRING_PLURAL
  53. X#include <strings.h>
  54. X#else
  55. X#include <string.h>
  56. X#endif
  57. X#endif
  58. X#include <ctype.h>
  59. X#include <setjmp.h>
  60. X
  61. X
  62. X/*
  63. X** custom includes ""
  64. X*/
  65. X
  66. X#include "depend.h"
  67. X
  68. X#include "formats.h"
  69. X#include "comsrch.h"
  70. X
  71. X
  72. X/*
  73. X** local #defines
  74. X*/
  75. X
  76. X/* Token types returned by gettok(). */
  77. X
  78. X#define BAD_TOKEN       -1
  79. X
  80. X#define LEFT_PAREN      0
  81. X#define RIGHT_PAREN     1
  82. X#define GREATER_THAN    2
  83. X#define LESS_THAN       3
  84. X#define EQUALITY        4
  85. X#define GTR_EQUALS      5
  86. X#define LESS_EQUALS     6
  87. X#define LOGICAL_AND     7
  88. X#define LOGICAL_OR      8
  89. X#define END_OF_LINE     9
  90. X#define FORMAT_ID       10
  91. X#define NUMBER          11
  92. X
  93. X/* Length of stack. */
  94. X
  95. X#define STACK_LEN       25
  96. X
  97. X
  98. X/*
  99. X** misc: copyright strings, version macros, etc.
  100. X*/
  101. X
  102. Xstatic char CONST rcsid[] = "$Id: comsrch.c,v 1.8 1993/03/13 02:57:12 jwbirdsa Exp $";
  103. X
  104. X
  105. X/*
  106. X** typedefs
  107. X*/
  108. X
  109. Xtypedef struct {
  110. X    int tokentype;
  111. X    union {
  112. X        fsearch *format;
  113. X        ULONG number;
  114. X    } tokendata;
  115. X} token;
  116. X
  117. X
  118. X/*
  119. X** global variables
  120. X*/
  121. X
  122. X/*
  123. X** static globals
  124. X*/
  125. X
  126. Xint com_errorflag;
  127. X
  128. Xstatic ULONG s_height;
  129. Xstatic ULONG s_width;
  130. Xstatic ULONG s_colors;
  131. Xstatic ULONG s_format;
  132. Xstatic ULONG s_filelen;
  133. X
  134. Xstatic int stack[STACK_LEN];
  135. Xstatic int stack_ptr;
  136. X
  137. Xstatic jmp_buf jumpb;
  138. X
  139. X
  140. X/*
  141. X** function prototypes
  142. X*/
  143. X
  144. X#ifdef  __STDC__
  145. X# define P_(s) s
  146. X#else
  147. X# define P_(s) ()
  148. X#endif
  149. X
  150. Xstatic char *eval P_((char *string, int level));
  151. Xstatic token *gettok P_((char **string));
  152. X
  153. Xstatic VOID push P_((int x));
  154. Xstatic int pop();
  155. X
  156. X#undef P_
  157. X
  158. X#ifdef NO_STR_INC
  159. Xextern int strlen();
  160. X#endif
  161. X
  162. X
  163. X/*
  164. X** functions
  165. X*/
  166. X
  167. X
  168. X/***************************************************************************
  169. X*   FUNCTION: COMCHECK                                                     *
  170. X*                                                                          *
  171. X*   DESCRIPTION:                                                           *
  172. X*                                                                          *
  173. X*       This function checks a search string to make sure all tokens are   *
  174. X*       valid and in a valid order.                                        *
  175. X*                                                                          *
  176. X*   ENTRY:                                                                 *
  177. X*                                                                          *
  178. X*       searchstr - string to be checked                                   *
  179. X*                                                                          *
  180. X*   EXIT:                                                                  *
  181. X*                                                                          *
  182. X*       Returns 1 for a good string, 0 for a bad string.                   *
  183. X*                                                                          *
  184. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  185. X*                                                                          *
  186. X***************************************************************************/
  187. Xint
  188. X#ifdef __STDC__
  189. Xcomcheck(char *searchstr)
  190. X#else
  191. Xcomcheck(searchstr)
  192. Xchar *searchstr;
  193. X#endif
  194. X{
  195. X    /* Clear error flag. */
  196. X
  197. X    com_errorflag = 0;
  198. X
  199. X    /* Do parse with dummy values. */
  200. X
  201. X    comsearch(1L, 1L, 1L, 0L, 0L, searchstr);
  202. X
  203. X    /* If error flag is set, there is a problem. */
  204. X
  205. X    return ((com_errorflag != 0) ? 0 : 1);
  206. X} /* end of comcheck() */
  207. X
  208. X
  209. X/***************************************************************************
  210. X*   FUNCTION: COMSEARCH                                                    *
  211. X*                                                                          *
  212. X*   DESCRIPTION:                                                           *
  213. X*                                                                          *
  214. X*       This function is the interface to the outside world. It sets up    *
  215. X*       static global variables for the use of the parsing functions, sets *
  216. X*       up the stack, and starts the search. When the search is complete,  *
  217. X*       it reads the final value off the stack and returns it.             *
  218. X*                                                                          *
  219. X*       If there is an error in the pattern, a match is assumed.           *
  220. X*                                                                          *
  221. X*   ENTRY:                                                                 *
  222. X*                                                                          *
  223. X*       height    - height of image                                        *
  224. X*       width     - width of image                                         *
  225. X*       colors    - colors in image                                        *
  226. X*       format    - format of image                                        *
  227. X*       searchstr - the complex search string                              *
  228. X*                                                                          *
  229. X*   EXIT:                                                                  *
  230. X*                                                                          *
  231. X*       Returns 1 on match, 0 on no match.                                 *
  232. X*                                                                          *
  233. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  234. X*                                                                          *
  235. X***************************************************************************/
  236. Xint
  237. X#ifdef __STDC__
  238. Xcomsearch(ULONG height, ULONG width, ULONG colors, ULONG format, ULONG filelen,
  239. X          char *searchstr)
  240. X#else
  241. Xcomsearch(height, width, colors, format, filelen, searchstr)
  242. XULONG height;
  243. XULONG width;
  244. XULONG colors;
  245. XULONG format;
  246. XULONG filelen;
  247. Xchar *searchstr;
  248. X#endif
  249. X{
  250. X    /* Clear error flag. */
  251. X
  252. X    com_errorflag = 0;
  253. X
  254. X    /* Set global variables. */
  255. X
  256. X    s_height = height;
  257. X    s_width = width;
  258. X    s_colors = colors;
  259. X    s_format = format;
  260. X    s_filelen = filelen;
  261. X
  262. X    /* Set up stack. */
  263. X
  264. X    stack_ptr = STACK_LEN - 1;
  265. X
  266. X    /* Set up for emergency return if necessary. */
  267. X
  268. X    if (setjmp(jumpb) != 0)
  269. X    {
  270. X        /* Handle emergency return by returning 1. */
  271. X
  272. X        com_errorflag = 1;
  273. X        return 1;
  274. X    }
  275. X
  276. X    /* Call parser. */
  277. X
  278. X    eval(searchstr, 0);
  279. X
  280. X    /* There should be one and exactly one value on the stack. */
  281. X
  282. X    if (stack_ptr != (STACK_LEN - 2))
  283. X    {
  284. X        /* Handle error by returning 1. */
  285. X
  286. X        com_errorflag = 1;
  287. X        return 1;
  288. X    }
  289. X
  290. X    /* Otherwise return top of stack. */
  291. X
  292. X    return (stack[STACK_LEN - 1]);
  293. X} /* end of comsearch() */
  294. X
  295. X
  296. X/***************************************************************************
  297. X*   FUNCTION: EVAL (STATIC)                                                *
  298. X*                                                                          *
  299. X*   DESCRIPTION:                                                           *
  300. X*                                                                          *
  301. X*       This function evaluates the search string.                         *
  302. X*                                                                          *
  303. X*   ENTRY:                                                                 *
  304. X*                                                                          *
  305. X*       searchstr - string to be evaluated                                 *
  306. X*       level     - current level of recursion                             *
  307. X*                                                                          *
  308. X*   EXIT:                                                                  *
  309. X*                                                                          *
  310. X*       Returns string pointer after last token evaluated.                 *
  311. X*                                                                          *
  312. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  313. X*                                                                          *
  314. X*       May change contents of stack[] and value of stack_ptr. May never   *
  315. X*       return if error encountered.                                       *
  316. X*                                                                          *
  317. X***************************************************************************/
  318. Xstatic char *
  319. X#ifdef __STDC__
  320. Xeval(char *string, int level)
  321. X#else
  322. Xeval(string, level)
  323. Xchar *string;
  324. Xint level;
  325. X#endif
  326. X{
  327. X    token *tok;
  328. X    ULONG x, y;
  329. X    int op;
  330. X
  331. X    /* Get first token. */
  332. X
  333. X    tok = gettok(&string);
  334. X
  335. X    /* Start looping. */
  336. X
  337. X    while (tok->tokentype != END_OF_LINE)
  338. X    {
  339. X        switch (tok->tokentype)
  340. X        {
  341. X            case LEFT_PAREN:
  342. X                /* Evaluate expression to right of paren. */
  343. X
  344. X                string = eval(string, (level + 1));
  345. X
  346. X                /* If not level 0, return. */
  347. X
  348. X                if (level != 0)
  349. X                {
  350. X                    return string;
  351. X                }
  352. X                break;
  353. X  
  354. X            case RIGHT_PAREN:
  355. X            case END_OF_LINE:
  356. X                /* Check for nesting and length OK. */
  357. X
  358. X                if ((0 == level) && (stack_ptr != (STACK_LEN - 1)) &&
  359. X                     (END_OF_LINE == tok->tokentype))
  360. X                {
  361. X                    /* Some sort of nesting error. */
  362. X
  363. X                    com_errorflag = 1;
  364. X                    longjmp(jumpb, 1);
  365. X                }
  366. X
  367. X                /* If OK, just return. */
  368. X
  369. X                return string;
  370. X  
  371. X            case LOGICAL_AND:
  372. X            case LOGICAL_OR:
  373. X                /* Save token type. */
  374. X
  375. X                op = tok->tokentype;
  376. X
  377. X                /* Evaluate expression to right of operator. */
  378. X
  379. X                string = eval(string, (level + 1));
  380. X
  381. X                /* Pop top two values. */
  382. X
  383. X                x = pop();
  384. X                y = pop();
  385. X
  386. X                /* Do the operation and push the result. */
  387. X
  388. X                push(((LOGICAL_AND == op) ? (x && y) : (x || y)));
  389. X
  390. X                /* If not level 0, return. */
  391. X
  392. X                if (level != 0)
  393. X                {
  394. X                    return string;
  395. X                }
  396. X                break;
  397. X  
  398. X            case FORMAT_ID:
  399. X                /* Check for format match. */
  400. X
  401. X                if ((s_format & tok->tokendata.format->value.mask) ==
  402. X                    tok->tokendata.format->value.value)
  403. X                {
  404. X                    /* If match, push true. */
  405. X
  406. X                    push(1);
  407. X                }
  408. X                else
  409. X                {
  410. X                    /* No match, push false. */
  411. X
  412. X                    push(0);
  413. X                }
  414. X                break;
  415. X  
  416. X            case NUMBER:
  417. X                /* Save this number. */
  418. X
  419. X                x = tok->tokendata.number;
  420. X
  421. X                /* Get next token. */
  422. X
  423. X                tok = gettok(&string);
  424. X
  425. X                /* If it is not an comparison operator, error. */
  426. X
  427. X                op = tok->tokentype;
  428. X                if ((op != LESS_THAN) && (op != GREATER_THAN) &&
  429. X                    (op != EQUALITY) && (op != GTR_EQUALS) &&
  430. X                    (op != LESS_EQUALS))
  431. X                {
  432. X                    com_errorflag = 1;
  433. X                    longjmp(jumpb, 1);
  434. X                }
  435. X
  436. X                /* Get next token. */
  437. X
  438. X                tok = gettok(&string);
  439. X
  440. X                /* If it is not another number, error. */
  441. X
  442. X                if (tok->tokentype != NUMBER)
  443. X                {
  444. X                   com_errorflag = 1;
  445. X                   longjmp(jumpb, 1);
  446. X                }
  447. X
  448. X                /* Do the operation and push the result. */
  449. X
  450. X                y = tok->tokendata.number;
  451. X                switch (op)
  452. X                {
  453. X                    case LESS_THAN:
  454. X                        push((x < y));
  455. X                        break;
  456. X
  457. X                    case GREATER_THAN:
  458. X                        push((x > y));
  459. X                        break;
  460. X
  461. X                    case EQUALITY:
  462. X                        push((x == y));
  463. X                        break;
  464. X
  465. X                    case LESS_EQUALS:
  466. X                        push((x <= y));
  467. X                        break;
  468. X
  469. X                    case GTR_EQUALS:
  470. X                        push((x >= y));
  471. X                        break;
  472. X
  473. X                    default:
  474. X                        /* Internal error. */
  475. X
  476. X                        com_errorflag = 1;
  477. X                        longjmp(jumpb, 1);
  478. X                }
  479. X                break;
  480. X  
  481. X            default:
  482. X                /* Bad token. */
  483. X
  484. X                com_errorflag = 1;
  485. X                longjmp(jumpb, 1);
  486. X        }
  487. X        /* Get next token and loop around. */
  488. X
  489. X        tok = gettok(&string);
  490. X    }
  491. X
  492. X    return string;
  493. X} /* end of static eval() */
  494. X
  495. X
  496. X/***************************************************************************
  497. X*   FUNCTION: GETTOK (STATIC)                                              *
  498. X*                                                                          *
  499. X*   DESCRIPTION:                                                           *
  500. X*                                                                          *
  501. X*       This function extracts the next token from the string. The string  *
  502. X*       pointer is advanced.                                               *
  503. X*                                                                          *
  504. X*   ENTRY:                                                                 *
  505. X*                                                                          *
  506. X*       string - pointer to string pointer                                 *
  507. X*                                                                          *
  508. X*   EXIT:                                                                  *
  509. X*                                                                          *
  510. X*       Returns pointer to token. This data is kept in static internal     *
  511. X*       structure and will be destroyed by subsequent calls!               *
  512. X*                                                                          *
  513. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  514. X*                                                                          *
  515. X***************************************************************************/
  516. Xstatic token *
  517. X#ifdef __STDC__
  518. Xgettok(char **string)
  519. X#else
  520. Xgettok(string)
  521. Xchar **string;
  522. X#endif
  523. X{
  524. X    static token storage;
  525. X    char buffer[15];
  526. X    int bufind;
  527. X    int loop;
  528. X    int length;
  529. X    int maxlen;
  530. X    int maxmatch;
  531. X    /* Switch by first character of token. */
  532. X
  533. X    switch ((*string)[0])
  534. X    {
  535. X        case '(':
  536. X            storage.tokentype = LEFT_PAREN;
  537. X            (*string)++;
  538. X            break;
  539. X   
  540. X        case ')':
  541. X            storage.tokentype = RIGHT_PAREN;
  542. X            (*string)++;
  543. X            break;
  544. X   
  545. X        case '=':
  546. X            storage.tokentype = EQUALITY;
  547. X            (*string)++;
  548. X            break;
  549. X   
  550. X#ifdef DOS_COMSRCH
  551. X        case '+':
  552. X#else
  553. X        case '&':
  554. X#endif
  555. X            storage.tokentype = LOGICAL_AND;
  556. X            (*string)++;
  557. X            break;
  558. X   
  559. X#ifdef DOS_COMSRCH
  560. X        case ',':
  561. X#else
  562. X        case '|':
  563. X#endif
  564. X            storage.tokentype = LOGICAL_OR;
  565. X            (*string)++;
  566. X            break;
  567. X   
  568. X        case '\0':
  569. X            storage.tokentype = END_OF_LINE;
  570. X            break;
  571. X   
  572. X#ifdef DOS_COMSRCH
  573. X        case '}':
  574. X#else
  575. X        case '>':
  576. X#endif
  577. X            if ('=' == (*string)[1])
  578. X            {
  579. X               storage.tokentype = GTR_EQUALS;
  580. X               *string += 2;
  581. X               break;
  582. X            }
  583. X            storage.tokentype = GREATER_THAN;
  584. X            (*string)++;
  585. X            break;
  586. X   
  587. X#ifdef DOS_COMSRCH
  588. X        case '{':
  589. X#else
  590. X        case '<':
  591. X#endif
  592. X            if ('=' == (*string)[1])
  593. X            {
  594. X               storage.tokentype = LESS_EQUALS;
  595. X               *string += 2;
  596. X               break;
  597. X            }
  598. X            storage.tokentype = LESS_THAN;
  599. X            (*string)++;
  600. X            break;
  601. X   
  602. X        default:
  603. X            if ((('H' == (*string)[0]) || ('W' == (*string)[0]) ||
  604. X                 ('C' == (*string)[0]) || ('F' == (*string)[0])) &&
  605. X                (isalnum((*string)[1]) == 0))
  606. X            {
  607. X                /*
  608. X                ** Token starts with H, W, C, or F, and the next chararcter
  609. X                ** is not a letter or number, so the token can't be a format.
  610. X                ** It must be one of the symbolic constants.
  611. X                */
  612. X
  613. X                switch ((*string)[0])
  614. X                {
  615. X                    case 'H':
  616. X                        storage.tokentype = NUMBER;
  617. X                        storage.tokendata.number = s_height;
  618. X                        (*string)++;
  619. X                        break;
  620. X               
  621. X                    case 'W':
  622. X                        storage.tokentype = NUMBER;
  623. X                        storage.tokendata.number = s_width;
  624. X                        (*string)++;
  625. X                        break;
  626. X               
  627. X                    case 'C':
  628. X                        storage.tokentype = NUMBER;
  629. X                        storage.tokendata.number = s_colors;
  630. X                        (*string)++;
  631. X                        break;
  632. X               
  633. X                    case 'F':
  634. X                        storage.tokentype = NUMBER;
  635. X                        storage.tokendata.number = s_filelen;
  636. X                        (*string)++;
  637. X                        break;
  638. X                }
  639. X            }
  640. X            else if (isdigit(**string))
  641. X            {
  642. X                /* Is a number -- collect in buffer. */
  643. X
  644. X                for (bufind = 0; isdigit(buffer[bufind] = (*string)[0]);
  645. X                     (*string)++, bufind++) ;
  646. X
  647. X                /* Convert. */
  648. X
  649. X                buffer[bufind] = '\0';
  650. X                storage.tokendata.number = (ULONG) atol(buffer);
  651. X
  652. X                /* Finish. */
  653. X
  654. X                storage.tokentype = NUMBER;
  655. X                break;
  656. X            }
  657. X            else
  658. X            {
  659. X                /*
  660. X                ** Is a format or nothing. Search through table of formats
  661. X                ** for specified type, looking for longest match.
  662. X                */
  663. X
  664. X                maxlen = 0;
  665. X                for (loop = 0; formatsearch[loop].name[0] != '\0'; loop++)
  666. X                {
  667. X                    /* Check against table of strings. */
  668. X
  669. X                    length = strlen(formatsearch[loop].name);
  670. X                    if (strnicmp(formatsearch[loop].name, *string, length))
  671. X                    {
  672. X                         continue;
  673. X                    }
  674. X
  675. X                    /* String matched in order to get here. */
  676. X
  677. X                    if (length > maxlen)
  678. X                    {
  679. X                         /* If this match longer than previous, use this one. */
  680. X                         maxlen = length;
  681. X                         maxmatch = loop;
  682. X                    }
  683. X                }
  684. X
  685. X                /* Was a match found? */
  686. X
  687. X                if (0 == maxlen)
  688. X                {
  689. X                    /* No. Is bad token. */
  690. X
  691. X                    storage.tokentype = BAD_TOKEN;
  692. X                    break;
  693. X                }
  694. X
  695. X                /* Is format. */
  696. X
  697. X                storage.tokentype = FORMAT_ID;
  698. X                storage.tokendata.format = &(formatsearch[maxmatch]);
  699. X                *string += maxlen;
  700. X                break;
  701. X            }
  702. X    }
  703. X    return &storage;
  704. X} /* end of static gettok() */
  705. X
  706. X
  707. X/***************************************************************************
  708. X*   FUNCTION: PUSH (STATIC)                                                *
  709. X*                                                                          *
  710. X*   DESCRIPTION:                                                           *
  711. X*                                                                          *
  712. X*       Pushes a value on the stack. If stack overflow, performs an        *
  713. X*       emergency return.                                                  *
  714. X*                                                                          *
  715. X*   ENTRY:                                                                 *
  716. X*                                                                          *
  717. X*       x - value to push on stack                                         *
  718. X*                                                                          *
  719. X*   EXIT:                                                                  *
  720. X*                                                                          *
  721. X*       Returns nothing.                                                   *
  722. X*                                                                          *
  723. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  724. X*                                                                          *
  725. X*       Alters contents of stack[] and value of stack_ptr. May never       *
  726. X*       return.                                                            *
  727. X*                                                                          *
  728. X***************************************************************************/
  729. Xstatic VOID
  730. X#ifdef __STDC__
  731. Xpush(int x)
  732. X#else
  733. Xpush(x)
  734. Xint x;
  735. X#endif
  736. X{
  737. X    /* Put value on stack. */
  738. X
  739. X    stack[stack_ptr--] = x;
  740. X    /* If stack overflow, emergency return. */
  741. X
  742. X    if (stack_ptr < 0)
  743. X    {
  744. X        com_errorflag = 1;
  745. X        longjmp(jumpb, 1);
  746. X    }
  747. X    return;
  748. X} /* end of static push() */
  749. X
  750. X
  751. X/***************************************************************************
  752. X*   FUNCTION: POP  (STATIC)                                                *
  753. X*                                                                          *
  754. X*   DESCRIPTION:                                                           *
  755. X*                                                                          *
  756. X*       Pops a value from the stack. If stack underflow, performs an       *
  757. X*       emergency return.                                                  *
  758. X*                                                                          *
  759. X*   ENTRY:                                                                 *
  760. X*                                                                          *
  761. X*       void                                                               *
  762. X*                                                                          *
  763. X*   EXIT:                                                                  *
  764. X*                                                                          *
  765. X*       Returns the value popped from the stack.                           *
  766. X*                                                                          *
  767. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  768. X*                                                                          *
  769. X*       Alters contents of stack[] and value of stack_ptr. May never       *
  770. X*       return.                                                            *
  771. X*                                                                          *
  772. X***************************************************************************/
  773. Xstatic int
  774. X#ifdef __STDC__
  775. Xpop(VOID)
  776. X#else
  777. Xpop()
  778. X#endif
  779. X{
  780. X    /* Check for stack underflow. */
  781. X
  782. X    if ((STACK_LEN - 1) == stack_ptr)
  783. X    {
  784. X        /* Stack is going to underflow on this pop, do emergency return. */
  785. X
  786. X        com_errorflag = 1;
  787. X        longjmp(jumpb, 1);
  788. X    }
  789. X
  790. X    /* Else return value from stack. */
  791. X
  792. X    return (stack[++stack_ptr]);
  793. X} /* end of static pop() */
  794. X
  795. END_OF_FILE
  796.   if test 24372 -ne `wc -c <'src/comsrch.c'`; then
  797.     echo shar: \"'src/comsrch.c'\" unpacked with wrong size!
  798.   fi
  799.   # end of 'src/comsrch.c'
  800. fi
  801. if test -f 'src/gifcheck.c' -a "${1}" != "-c" ; then 
  802.   echo shar: Will not clobber existing file \"'src/gifcheck.c'\"
  803. else
  804.   echo shar: Extracting \"'src/gifcheck.c'\" \(25104 characters\)
  805.   sed "s/^X//" >'src/gifcheck.c' <<'END_OF_FILE'
  806. X/***************************************************************************
  807. X*   GIFCHECK.C                                                             *
  808. X*   MODULE:  -                                                             *
  809. X*   OS:      UNIX                                                          *
  810. X*                                                                          *
  811. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  812. X*                                                                          *
  813. X*   The Graphics Interchange Format(c) is the Copyright property of        *
  814. X*   CompuServe Incorporated. GIF(sm) is a Service Mark property of         *
  815. X*   CompuServe Incorporated.                                               *
  816. X*                                                                          *
  817. X*   GIF and "Graphic Interchange Format" are trademarks (tm) of            *
  818. X*   CompuServe, Inc., an H&R Block company.                                *
  819. X*                                                                          *
  820. X*   $Id: gifcheck.c,v 1.8 1993/03/08 00:22:02 jwbirdsa Exp $
  821. X*                                                                          *
  822. X***************************************************************************/
  823. X
  824. X#include "config.h"
  825. X
  826. X/*
  827. X** system includes <>
  828. X*/
  829. X
  830. X#include <stdio.h>
  831. X#include <ctype.h>
  832. X#ifndef NO_STDLIB
  833. X#include <stdlib.h>
  834. X#endif
  835. X#ifndef NO_MALLOCHDR
  836. X#include <malloc.h>
  837. X#endif
  838. X#ifndef NO_STR_INC
  839. X#ifdef STRING_PLURAL
  840. X#include <strings.h>
  841. X#else
  842. X#include <string.h>
  843. X#endif
  844. X#endif
  845. X
  846. X
  847. X/*
  848. X** custom includes ""
  849. X*/
  850. X
  851. X#include "depend.h"
  852. X
  853. X#include "fb.h"
  854. X
  855. X#include "formats.h"
  856. X#include "gif.h"
  857. X#include "gld.h"
  858. X
  859. X#include "colors.h"
  860. X
  861. X#include "gifcheck.h"
  862. X#include "blocproc.h"
  863. X
  864. X#include "stdinarg.h"
  865. X
  866. X#include "patchlevel.h"
  867. X
  868. X
  869. X/*
  870. X** local #defines
  871. X*/
  872. X
  873. X#define FB_TABLESIZE         5
  874. X#ifdef SMALL_MEM
  875. X#define FB_BUFSIZE           4096
  876. X#else
  877. X#define FB_BUFSIZE           30000
  878. X#endif
  879. X
  880. X#define TBUFSIZ              15
  881. X
  882. X
  883. X/*
  884. X** misc: copyright strings, version macros, etc.
  885. X*/
  886. X
  887. Xstatic char CONST copyright[] = "Copyright (c) 1992 James W. Birdsall. All Rights Reserved";
  888. Xstatic char CONST rcsid[] = "$Id: gifcheck.c,v 1.8 1993/03/08 00:22:02 jwbirdsa Exp $";
  889. X
  890. X#define VERS                 "1.0"
  891. X
  892. X
  893. X/*
  894. X** typedefs
  895. X*/
  896. X
  897. X/*
  898. X** global variables
  899. X*/
  900. X
  901. X/* Default: allow leading junk. */
  902. X
  903. Xint lead = 1;
  904. X
  905. X/* Default: do decompression. */
  906. X
  907. Xint decomp = 1;
  908. X
  909. X/* Default: don't dump color tables. */
  910. X
  911. Xint do_colordump = 0;
  912. X
  913. X/* Default: display FASCINATING and above, abort on VIOLATION and above. */
  914. X
  915. Xint dlevel = DLEVEL_FASCINATING;
  916. Xint elevel = ELEVEL_VIOLATION;
  917. X
  918. X/* Default: terse displays. */
  919. X
  920. Xint verbose = 0;
  921. X
  922. X/* Default: don't do hex dump of PTEs, comments, app & generic extensions. */
  923. X
  924. Xint do_hexdump = 0;
  925. X
  926. X/* Default: display progress indicator, if compiled in. */
  927. X
  928. X#ifdef PROGRESS_IND
  929. Xint prog_ind = 1;
  930. X#endif
  931. X
  932. X/* File handles for standard and error output. */
  933. X
  934. XFILE *outstr = stdout;
  935. XFILE *outerr = stdout;
  936. X
  937. X/* Global scratch space. */
  938. X
  939. Xchar scratch[132];
  940. X
  941. X
  942. X/* Global color table. */
  943. X
  944. Xextern RGB_TRIPLET *gct;
  945. X
  946. X/* Last state. */
  947. X
  948. Xextern int laststate;
  949. X
  950. X
  951. X/*
  952. X** static globals
  953. X*/
  954. X
  955. X/*
  956. X** function prototypes
  957. X*/
  958. X
  959. X#ifdef  __STDC__
  960. X# define P_(s) s
  961. X#else
  962. X# define P_(s) ()
  963. X#endif
  964. X
  965. Xstatic int check P_((char *filename));
  966. X
  967. Xstatic VOID usage();
  968. X
  969. X#undef P_
  970. X
  971. X#ifdef NO_STR_INC
  972. X#ifndef NO_STRDUP
  973. Xextern char *strdup();
  974. X#endif
  975. X#endif
  976. X
  977. X
  978. X/*
  979. X** functions
  980. X*/
  981. X
  982. X
  983. X/***************************************************************************
  984. X *   FUNCTION MAIN                                                         *
  985. X ***************************************************************************/
  986. X#ifdef __STDC__
  987. Xmain(int argc, char *argv[])
  988. X#else
  989. Xmain(argc, argv)
  990. Xint argc;
  991. Xchar *argv[];
  992. X#endif
  993. X{
  994. X    int loop, loop2;
  995. X    int onlyflags = 1;
  996. X    int argcc;
  997. X    char **argvv;
  998. X    char **namelist;
  999. X    int stdinkey = 1;     /* Nonzero = stdin is keyboard, zero = redirected. */
  1000. X    int errorlevel;
  1001. X    int temp;
  1002. X
  1003. X    /* Search for option and parse if found. */
  1004. X
  1005. X    for(loop = 1; loop < argc; loop++)
  1006. X    {
  1007. X        if ('-' == argv[loop][0])
  1008. X        {
  1009. X            switch (argv[loop][1])
  1010. X            {
  1011. X                /* Disable decompression to increase speed. */
  1012. X                case 'f':
  1013. X                    decomp = 0;
  1014. X                    break;
  1015. X
  1016. X                /* Batch mode option. */
  1017. X                case 'b':
  1018. X                    if ((outstr = fopen(NULL_DEVICE, "w")) == (FILE *) NULL)
  1019. X                    {
  1020. X                        fprintf(stderr, "ERROR: Cannot open %s\n", NULL_DEVICE);
  1021. X                        exit(EXIT_ERROR);
  1022. X                    }
  1023. X                    outerr = outstr;
  1024. X#ifdef PROGRESS_IND
  1025. X                    /* Turn off progress indicator automatically. */
  1026. X                    prog_ind = 0;
  1027. X#endif
  1028. X                    break;
  1029. X
  1030. X                /* Disable handling of leading junk. */
  1031. X                case 'l':
  1032. X                    lead = 0;
  1033. X                    break;
  1034. X
  1035. X                /* Redirect errors to stderr. */
  1036. X                case 'r':
  1037. X                    outerr = stderr;
  1038. X                    break;
  1039. X
  1040. X                /* Dump color tables. */
  1041. X                case 'c':
  1042. X                    do_colordump = 1;
  1043. X                    break;
  1044. X
  1045. X                /* Do hex dumps of PTEs, comments. */
  1046. X                case 'H':
  1047. X                    do_hexdump = 1;
  1048. X                    break;
  1049. X
  1050. X#ifdef PROGRESS_IND
  1051. X                /* Turn off progress indicator. */
  1052. X                case 'p':
  1053. X                    prog_ind = 0;
  1054. X                    break;
  1055. X#endif
  1056. X
  1057. X                /* Verbose option. */
  1058. X                case 'v':
  1059. X                    verbose = 1;
  1060. X                    break;
  1061. X
  1062. X                /* Set warning display level. */
  1063. X                case 'd':
  1064. X                    temp = atoi(argv[loop] + 2);
  1065. X                    if ((temp < 0) || (temp > DLEVEL_NITPICK))
  1066. X                    {
  1067. X                        usage();
  1068. X                    }
  1069. X                    dlevel = temp;
  1070. X                    break;
  1071. X
  1072. X                /* Set warning exit level. */
  1073. X                case 'e':
  1074. X                    temp = atoi(argv[loop] + 2);
  1075. X                    if ((temp < 0) || (temp > ELEVEL_FASCINATING))
  1076. X                    {
  1077. X                        usage();
  1078. X                    }
  1079. X                    elevel = temp;
  1080. X                    break;
  1081. X
  1082. X                /* Take filenames from stdin. */
  1083. X                case '-':
  1084. X                    stdinkey = 0;
  1085. X                    break;
  1086. X                /* Help option. */
  1087. X                case 'h':
  1088. X                /* Unknown option. */
  1089. X                default:
  1090. X                    usage();
  1091. X                    break;
  1092. X            }
  1093. X        }
  1094. X        else
  1095. X        {
  1096. X            /*
  1097. X            ** onlyflags == 1 when the command line contains only options.
  1098. X            ** If this clause is executed, means there is at least one arg
  1099. X            ** which is not an option and therefore is a target.
  1100. X            */
  1101. X
  1102. X            onlyflags = 0;
  1103. X        }
  1104. X    }
  1105. X
  1106. X    /* If no target(s) specified and stdin not redirected, error. */
  1107. X
  1108. X    if ((onlyflags != 0) && (stdinkey != 0))
  1109. X    {
  1110. X        usage();
  1111. X    }
  1112. X
  1113. X    /* Initialize file buffering package. */
  1114. X
  1115. X    if (fb_init(FB_TABLESIZE, FB_BUFSIZE) != 0)
  1116. X    {
  1117. X        fprintf(outerr, "%s\n", fb_errstring(fb_error));
  1118. X        exit(EXIT_ERROR);
  1119. X    }
  1120. X
  1121. X    /* Check for stdin redirection -- load target from stdin if redirected. */
  1122. X
  1123. X    if (stdinkey != 0)
  1124. X    {
  1125. X        argcc = argc;
  1126. X        argvv = argv;
  1127. X    }
  1128. X    else
  1129. X    {
  1130. X        argvv = stdinload(&argcc);
  1131. X        argvv[0] = argv[0];
  1132. X    }
  1133. X
  1134. X    /* Loop through targets, processing. */
  1135. X
  1136. X    for(loop = 1; loop < argcc; loop++)
  1137. X    {
  1138. X        if (argvv[loop][0] != '-')
  1139. X        {
  1140. X            /* Extract an argument from the command line and expand it. */
  1141. X
  1142. X            if ((namelist = scand(argvv[loop])) == NULL)
  1143. X            {
  1144. X                fprintf(outerr, "ERROR: bad target %s\n", argvv[loop]);
  1145. X                continue;
  1146. X            }
  1147. X            else if (NULL == namelist[0])
  1148. X            {
  1149. X                fprintf(outerr, "WARNING: no files matching %s found.\n",
  1150. X                        argvv[loop]);
  1151. X                continue;
  1152. X            }
  1153. X
  1154. X            /* Check each file. */
  1155. X
  1156. X            for(loop2 = 0; namelist[loop2]; loop2++)
  1157. X            {
  1158. X                fprintf(outstr, "\nProcessing %s...\n", namelist[loop2]);
  1159. X                errorlevel = check(namelist[loop2]);
  1160. X                if (gct != (RGB_TRIPLET *) NULL)
  1161. X                {
  1162. X                    free(gct);
  1163. X                    gct = (RGB_TRIPLET *) NULL;
  1164. X                }
  1165. X            }
  1166. X
  1167. X            /* Cleanup. */
  1168. X
  1169. X            for(loop2 = 0; namelist[loop2]; loop2++)
  1170. X            {
  1171. X                free(namelist[loop2]);
  1172. X            }
  1173. X            free(namelist);
  1174. X            if (0 == stdinkey)
  1175. X            {
  1176. X                free(argvv[loop]);
  1177. X            }
  1178. X        }
  1179. X    }
  1180. X
  1181. X    /* Cleanup. */
  1182. X
  1183. X    if (0 == stdinkey)
  1184. X    {
  1185. X        free(argvv);
  1186. X    }
  1187. X
  1188. X    exit(errorlevel);
  1189. X} /* end of main() */
  1190. X
  1191. X
  1192. X/***************************************************************************
  1193. X*   FUNCTION: errxlate                                                     *
  1194. X*                                                                          *
  1195. X*   DESCRIPTION:                                                           *
  1196. X*                                                                          *
  1197. X*       Translates an error code into a string.                            *
  1198. X*                                                                          *
  1199. X*   ENTRY:                                                                 *
  1200. X*                                                                          *
  1201. X*       errcode - code to be translated                                    *
  1202. X*                                                                          *
  1203. X*   EXIT:                                                                  *
  1204. X*                                                                          *
  1205. X*       Returns a pointer to the appropriate string.                       *
  1206. X*                                                                          *
  1207. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1208. X*                                                                          *
  1209. X***************************************************************************/
  1210. Xchar *
  1211. X#ifdef __STDC__
  1212. Xerrxlate(ULONG errcode)
  1213. X#else
  1214. Xerrxlate(errcode)
  1215. XULONG errcode;
  1216. X#endif
  1217. X{
  1218. X    char *errstring;
  1219. X    char *sever;
  1220. X
  1221. X    /* Determine severity of error. */
  1222. X
  1223. X    switch (SEVERITY(errcode))
  1224. X    {
  1225. X        case SEVERITY(ST_SUCCESS):
  1226. X            sever = "SUCCESS";
  1227. X            break;
  1228. X
  1229. X        case SEVERITY(ST_WARNING):
  1230. X            sever = "WARNING";
  1231. X            break;
  1232. X
  1233. X        case SEVERITY(ST_ERROR):
  1234. X            sever = "ERROR";
  1235. X            break;
  1236. X
  1237. X        case SEVERITY(ST_FATAL):
  1238. X        default:
  1239. X            sever = "FATAL";
  1240. X            break;
  1241. X    }
  1242. X
  1243. X    /* Get error string from module. */
  1244. X
  1245. X    switch (MODULE(errcode))
  1246. X    {
  1247. X        case MODULE(GIF_MODULE):
  1248. X            errstring = gif_errstring(errcode);
  1249. X            break;
  1250. X
  1251. X        case MODULE(FB_MODULE):
  1252. X            errstring = fb_errstring(errcode);
  1253. X            break;
  1254. X
  1255. X        case MODULE(GLD_MODULE):
  1256. X            errstring = gld_errstring(errcode);
  1257. X            break;
  1258. X
  1259. X        default:
  1260. X            errstring = NULL;
  1261. X            break;
  1262. X    }
  1263. X
  1264. X    /* Composite strings. */
  1265. X
  1266. X    if (errstring != NULL)
  1267. X    {
  1268. X        sprintf(scratch, "%s: %s", sever, errstring);
  1269. X    }
  1270. X    else
  1271. X    {
  1272. X        /* Error not recognized by any module. */
  1273. X
  1274. X        sprintf(scratch, "%s: %08lX.", sever, errcode);
  1275. X    }
  1276. X
  1277. X    return scratch;
  1278. X} /* end of errxlate() */
  1279. X
  1280. X
  1281. X/***************************************************************************
  1282. X*   FUNCTION:    check  STATIC                                             *
  1283. X*                                                                          *
  1284. X*   DESCRIPTION:                                                           *
  1285. X*                                                                          *
  1286. X*       This function verifies the named file, if necessary.               *
  1287. X*                                                                          *
  1288. X*   ENTRY:                                                                 *
  1289. X*                                                                          *
  1290. X*       filename - name of file to be verified. May include drive and/or   *
  1291. X*                  path.                                                   *
  1292. X*                                                                          *
  1293. X*   EXIT:                                                                  *
  1294. X*                                                                          *
  1295. X*       Returns EXIT_*, depending.                                         *
  1296. X*                                                                          *
  1297. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1298. X*                                                                          *
  1299. X***************************************************************************/
  1300. Xstatic int 
  1301. X#ifdef __STDC__
  1302. Xcheck(char *filename)
  1303. X#else
  1304. Xcheck(filename)
  1305. Xchar *filename;
  1306. X#endif
  1307. X{
  1308. X    FILE *origfile;
  1309. X    FB *infile;
  1310. X    ULONG status;
  1311. X    long size;
  1312. X    int mskip = 0;
  1313. X    ULONG skip;
  1314. X    long stop;
  1315. X
  1316. X    int images = 1;
  1317. X    int gens = 1;
  1318. X    int ptes = 1;
  1319. X    int gces = 1;
  1320. X    int comments = 1;
  1321. X    int apps = 1;
  1322. X
  1323. X    GIF_LSD lsd;
  1324. X    int blocktype;
  1325. X    int extype;
  1326. X    GIF_IMD imd;
  1327. X
  1328. X    /* Setup. */
  1329. X
  1330. X    gct = (RGB_TRIPLET *) NULL;
  1331. X    laststate = STATE_BEGIN;
  1332. X
  1333. X    /* Open GIF and perform other startup functions. */
  1334. X
  1335. X    if ((origfile = fopen(filename, FOPEN_READ_BINARY)) == (FILE *) NULL)
  1336. X    {
  1337. X        fprintf(outerr, "ERROR: Cannot open file %s\n", filename);
  1338. X        return EXIT_ERROR;
  1339. X    }
  1340. X
  1341. X    /* Get the size by forwarding to the end and reading offset. */
  1342. X
  1343. X    if (fseek(origfile, 0L, SEEK_END) == -1)
  1344. X    {
  1345. X        fprintf(outerr, "ERROR: Error seeking in %s\n", filename);
  1346. X        fclose(origfile);
  1347. X        return EXIT_ERROR;
  1348. X    }
  1349. X    size = ftell(origfile);
  1350. X
  1351. X    /* Get GIF logical screen descriptor. */
  1352. X
  1353. X    if (0 == lead)
  1354. X    {
  1355. X        if ((status = gif_lsdget(origfile, &lsd)) != ST_SUCCESS)
  1356. X        {
  1357. X            fprintf(outerr, "%s\n", errxlate(status));
  1358. X            fclose(origfile);
  1359. X            switch (ERRSEV(status))
  1360. X            {
  1361. X                case ERRSEV(GIF_NOTGIF_E):
  1362. X                    return EXIT_NOTGIF;
  1363. X
  1364. X                case ERRSEV(GIF_UNEOF_E):
  1365. X                    return EXIT_UNEOF;
  1366. X
  1367. X                default:
  1368. X                    return EXIT_ERROR;
  1369. X            }
  1370. X        }
  1371. X
  1372. X        /* Attach buffering to GIF file. */
  1373. X
  1374. X        infile = fb_retrofit(origfile, 'r');
  1375. X        if (fb_error != ST_SUCCESS)
  1376. X        {
  1377. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  1378. X            fclose(origfile);
  1379. X            return EXIT_ERROR;
  1380. X        }
  1381. X    }
  1382. X    else
  1383. X    {
  1384. X        /* Attach buffering to original GIF file. */
  1385. X
  1386. X        infile = fb_retrofit(origfile, 'r');
  1387. X        if (fb_error != ST_SUCCESS)
  1388. X        {
  1389. X            fprintf(outerr, "%s\n", errxlate(fb_error));
  1390. X            fclose(origfile);
  1391. X            return EXIT_ERROR;
  1392. X        }
  1393. X
  1394. X        /* Search for potentially buried LSD. */
  1395. X
  1396. X        if ((status = gif_searchlsd(infile, &lsd, &skip)) != ST_SUCCESS)
  1397. X        {
  1398. X            fprintf(outerr, "%s\n", errxlate(status));
  1399. X            fb_close(infile);
  1400. X            switch (ERRSEV(status))
  1401. X            {
  1402. X                case ERRSEV(GIF_NOTGIF_E):
  1403. X                case ERRSEV(GIF_UNEOF_E):
  1404. X                    return EXIT_NOTGIF;
  1405. X
  1406. X                default:
  1407. X                    return EXIT_ERROR;
  1408. X            }
  1409. X        }
  1410. X        if (skip != 0)
  1411. X        {
  1412. X            fprintf(outstr, "STRIP: Skipped %lu leading junk bytes.\n", skip);
  1413. X            mskip = 1;
  1414. X        }
  1415. X    }
  1416. X
  1417. X    /* Print out info from logical screen descriptor. */
  1418. X
  1419. X    if ((status = global_printout(infile, filename, &lsd, size)) != EXIT_OK)
  1420. X    {
  1421. X        return (int) status;
  1422. X    }
  1423. X
  1424. X    /* Loop through data blocks. */
  1425. X
  1426. X    blocktype = 0;
  1427. X    while (blocktype != GIF_TERMINATOR)
  1428. X    {
  1429. X        /* Find next block. */
  1430. X
  1431. X        if ((status = gif_findnext(infile, &blocktype, &skip, &extype)) != 
  1432. X            ST_SUCCESS)
  1433. X        {
  1434. X            fprintf(outerr, "%s\n", errxlate(status));
  1435. X            fb_close(infile);
  1436. X            return ((GIF_UNEOF_E == status) ? EXIT_UNEOF : EXIT_ERROR);
  1437. X        }
  1438. X
  1439. X        /* If skipped characters, FYI. */
  1440. X
  1441. X        if (skip != 0)
  1442. X        {
  1443. X            if (dlevel >= DLEVEL_VIOLATION)
  1444. X            {
  1445. X                fprintf(outstr,
  1446. X                   "VIOLATION: %lu garbage characters found between blocks\n",
  1447. X                   skip);
  1448. X            }
  1449. X            if (elevel >= ELEVEL_VIOLATION)
  1450. X            {
  1451. X                fb_close(infile);
  1452. X                return EXIT_NOTGIF;
  1453. X            }
  1454. X        }
  1455. X
  1456. X        /* Process by type of block. */
  1457. X
  1458. X        switch (blocktype)
  1459. X        {
  1460. X            case GIF_IMAGE:
  1461. X                fprintf(outstr, "IMAGE %d:\n", images);
  1462. X
  1463. X                /* Check ordering. */
  1464. X
  1465. X                if ((status = follow(STATE_IMAGE)) != EXIT_OK)
  1466. X                {
  1467. X                    fb_close(infile);
  1468. X                    return (int) status;
  1469. X                }
  1470. X
  1471. X                /* Get image descriptor. */
  1472. X
  1473. X                if ((status = gif_imdget(infile, &imd)) != ST_SUCCESS)
  1474. X                {
  1475. X                    fprintf(outerr, "%s\n", errxlate(status));
  1476. X                    fb_close(infile);
  1477. X                    return ((GIF_UNEOF_E == status) ? EXIT_UNEOF : EXIT_ERROR);
  1478. X                }
  1479. X
  1480. X                /* Print out information from image descriptor. */
  1481. X
  1482. X                status = image_printout(infile, &imd, images++, lsd.version,
  1483. X                                        lsd.gct_size);
  1484. X                if (status != EXIT_OK)
  1485. X                {
  1486. X                    return (int) status;
  1487. X                }
  1488. X
  1489. X                break;
  1490. X
  1491. X            case GIF_EXTBLOCK:
  1492. X                /* Print some info. */
  1493. X
  1494. X                if (GIF_89A == lsd.version)
  1495. X                {
  1496. X                    switch (extype)
  1497. X                    {
  1498. X                        case GIF_EXT_PLAIN_TEXT:
  1499. X                            status = pte_printout(infile, ptes++);
  1500. X                            break;
  1501. X
  1502. X                        case GIF_EXT_GRAPHIC_CONTROL:
  1503. X                            status = gce_printout(infile, gces++);
  1504. X                            break;
  1505. X
  1506. X                        case GIF_EXT_COMMENT:
  1507. X                            status = comment_printout(infile, comments++);
  1508. X                            break;
  1509. X
  1510. X                        case GIF_EXT_APPLICATION:
  1511. X                            status = app_printout(infile, apps++);
  1512. X                            break;
  1513. X
  1514. X                        default:
  1515. X                            status = genext_printout(infile, extype, gens++);
  1516. X                            break;
  1517. X                    }
  1518. X                }
  1519. X                else
  1520. X                {
  1521. X                    status = genext_printout(infile, extype, gens++);
  1522. X                }
  1523. X                if (status != EXIT_OK)
  1524. X                {
  1525. X                    /* No need to close infile -- done by *_printout(). */
  1526. X
  1527. X                    return (int) status;
  1528. X                }
  1529. X
  1530. X                break;
  1531. X
  1532. X            case GIF_TERMINATOR:
  1533. X                fprintf(outstr, "GIF TERMINATOR\n");
  1534. X                if ((status = follow(STATE_TERM)) != EXIT_OK)
  1535. X                {
  1536. X                    fb_close(infile);
  1537. X                    return (int) status;
  1538. X                }
  1539. X                break;
  1540. X
  1541. X            default:
  1542. X                fprintf(outerr, "FATAL ERROR: Internal error.\n");
  1543. X                break;
  1544. X
  1545. X        } /* End of switch (blocktype). */
  1546. X    } /* End of while (blocktype != GIF_TERMINATOR). */
  1547. X
  1548. X    /* Read all good data from file, clean up. */
  1549. X
  1550. X    stop = fb_tell(infile);
  1551. X    if (fb_error != 0)
  1552. X    {
  1553. X        fprintf(outerr, "%s\n", errxlate(fb_error));
  1554. X        fb_close(infile);
  1555. X        return EXIT_ERROR;
  1556. X    }
  1557. X    if ((status = fb_close(infile)) != ST_SUCCESS)
  1558. X    {
  1559. X        fprintf(outerr, "%s\n", errxlate(status));
  1560. X        return EXIT_ERROR;
  1561. X    }
  1562. X
  1563. X    /* extype set to nonzero if trailing garbage detected. */
  1564. X    if (extype != 0)
  1565. X    {
  1566. X        fprintf(outstr, "STRIP: %ld trailing junk bytes.\n", (size - stop + 1));
  1567. X    }
  1568. X
  1569. X    /* All done, return OK. */
  1570. X
  1571. X    if (mskip != 0)
  1572. X    {
  1573. X        return EXIT_STRIPM;
  1574. X    }
  1575. X    else if (stop != size)
  1576. X    {
  1577. X        return EXIT_STRIP;
  1578. X    }
  1579. X
  1580. X    return EXIT_OK;
  1581. X} /* end of static check() */
  1582. X
  1583. X
  1584. X/***************************************************************************
  1585. X*   FUNCTION:    usage  STATIC                                             *
  1586. X*                                                                          *
  1587. X*   DESCRIPTION:                                                           *
  1588. X*                                                                          *
  1589. X*      Prints out usage message.                                           *
  1590. X*                                                                          *
  1591. X*   ENTRY:                                                                 *
  1592. X*                                                                          *
  1593. X*      None.                                                               *
  1594. X*                                                                          *
  1595. X*   EXIT:                                                                  *
  1596. X*                                                                          *
  1597. X*      Never returns.                                                      *
  1598. X*                                                                          *
  1599. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1600. X*                                                                          *
  1601. X*      Exit()s with errorlevel EXIT_ERROR.                                 *
  1602. X*                                                                          *
  1603. X***************************************************************************/
  1604. Xstatic VOID
  1605. Xusage()
  1606. X{
  1607. X    fprintf(outstr, "\n");
  1608. X    fprintf(outstr,
  1609. X            "GIFCHECK version %s, patchlevel %d by James W. Birdsall.\n", 
  1610. X             VERS, PATCHLEVEL);
  1611. X    fprintf(outstr, "   Verifies format and validity of GIF files.\n");
  1612. X    fprintf(outstr, "   usage: gifcheck [options] target [target ...]\n");
  1613. X    fprintf(outstr, "     target       filename or directory. If a directory, all files in that\n");
  1614. X    fprintf(outstr, "                   directory will be processed. If no targets are given,\n");
  1615. X    fprintf(outstr, "                   this usage message is displayed.\n");
  1616. X
  1617. X    fprintf(outstr, "     -v           VERBOSE: turns on verbose output.\n");
  1618. X    fprintf(outstr, "     -H           HEX DUMP: switches from ASCII to HEX dump for certain blocks.\n");
  1619. X    fprintf(outstr, "     -c           COLOR DUMP: dumps raw RGB values from all colormaps.\n");
  1620. X#ifdef PROGRESS_IND
  1621. X    fprintf(outstr, "     -p           Turn off progress indicator (automatically turned off by -b).\n");
  1622. X#endif
  1623. X
  1624. X    fprintf(outstr, "     -dn          SET DISPLAY WARNING LEVEL: 0 for anomalies and violations\n");
  1625. X    fprintf(outstr, "                   only, 1 (default) for those and fascinatings, 2 for all.\n");
  1626. X    fprintf(outstr, "     -en          SET EXIT WARNING LEVEL: 0 for anomalies only, 1 (default) for\n");
  1627. X    fprintf(outstr, "                   anomalies and violations, 2 for anomalies, violations, and\n");
  1628. X    fprintf(outstr, "                   fascinatings.\n");
  1629. X
  1630. X    fprintf(outstr, "     -b           BATCH: suppresses all console output. Should be first on the\n");
  1631. X    fprintf(outstr, "                   line. Returns 0 if OK, 1 if a non-GIF file was found, 2 if\n");
  1632. X    fprintf(outstr, "                   unexpected EOF in a GIF file, 3 on other error, 4 if the\n");
  1633. X    fprintf(outstr, "                   GIF is OK but needs to be stripped, and 5 if the GIF is OK\n");
  1634. X    fprintf(outstr, "                   but needs to be stripped with the -m option.\n");
  1635. X    fprintf(outstr, "     -r           Sends error messages to stderr instead of stdout.\n");
  1636. X    fprintf(outstr, "     --           Take targets from stdin. For use with -f option of CHILS.\n");
  1637. X    fprintf(outstr, "                   Targets must be separated by newlines. Directories are\n");
  1638. X    fprintf(outstr, "                   expanded but wildcards are not. Command-line targets are\n");
  1639. X    fprintf(outstr, "                   ignored if this option is given.\n");
  1640. X    fprintf(outstr, "     -l           Disables checking for leading junk characters (from a Mac,\n");
  1641. X    fprintf(outstr, "                   for example).\n");
  1642. X
  1643. X    fprintf(outstr, "     -f           FAST: disables decompression. Only block formatting is\n");
  1644. X    fprintf(outstr, "                   checked.\n");
  1645. X    fprintf(outstr, "     -h           HELP: Prints this message.\n");
  1646. X
  1647. X    fprintf(outstr, "\n");
  1648. X    fprintf(outstr, "   Options may not be combined.\n");
  1649. X    fprintf(outstr, "\n");
  1650. X
  1651. X    exit(EXIT_ERROR);
  1652. X} /* end of static usage() */
  1653. X
  1654. END_OF_FILE
  1655.   if test 25104 -ne `wc -c <'src/gifcheck.c'`; then
  1656.     echo shar: \"'src/gifcheck.c'\" unpacked with wrong size!
  1657.   fi
  1658.   # end of 'src/gifcheck.c'
  1659. fi
  1660. if test -f 'src/mf.h' -a "${1}" != "-c" ; then 
  1661.   echo shar: Will not clobber existing file \"'src/mf.h'\"
  1662. else
  1663.   echo shar: Extracting \"'src/mf.h'\" \(2483 characters\)
  1664.   sed "s/^X//" >'src/mf.h' <<'END_OF_FILE'
  1665. X/***************************************************************************
  1666. X*   MF.H                                                                   *
  1667. X*   HEADER FOR MF (MemFile) MODULE                                         *
  1668. X*   OS:      UNIX                                                          *
  1669. X*                                                                          *
  1670. X*   Copyright (c) 1993 by James W. Birdsall, all rights reserved.          *
  1671. X*                                                                          *
  1672. X*   $Id: mf.h,v 1.5 1993/02/10 01:31:18 jwbirdsa Exp $
  1673. X*                                                                          *
  1674. X*   This file specifies the external interface to the memfile module.      *
  1675. X*                                                                          *
  1676. X***************************************************************************/
  1677. X
  1678. X#ifndef DEPEND_H
  1679. X    **** ERROR **** MUST INCLUDE DEPEND.H BEFORE MF.H
  1680. X#endif
  1681. X
  1682. X#ifndef MF_H
  1683. X
  1684. X#define MF_H
  1685. X
  1686. X/*
  1687. X** system includes <>
  1688. X*/
  1689. X
  1690. X/*
  1691. X** custom includes ""
  1692. X*/
  1693. X
  1694. X#include "status.h"
  1695. X
  1696. X
  1697. X/*
  1698. X** #defines
  1699. X*/
  1700. X
  1701. X/* miscellaneous defines */
  1702. X
  1703. X#define USE_CONMEM     0x0001
  1704. X#define USE_DISKMEM    0x0008
  1705. X
  1706. X#define USE_MASK       (USE_CONMEM | USE_DISKMEM)
  1707. X
  1708. X/* error/status defines */
  1709. X
  1710. X#define MF_EOF_W       MKERR(1, MF_MODULE, ST_WARNING)
  1711. X
  1712. X#define MF_REOPEN_E    MKERR(1, MF_MODULE, ST_ERROR)
  1713. X#define MF_EMSERROR_E  MKERR(2, MF_MODULE, ST_ERROR)
  1714. X#define MF_XMSERROR_E  MKERR(3, MF_MODULE, ST_ERROR)
  1715. X#define MF_DISKERROR_E MKERR(4, MF_MODULE, ST_ERROR)
  1716. X#define MF_NOSPACE_E   MKERR(5, MF_MODULE, ST_ERROR)
  1717. X#define MF_NOTOPEN_E   MKERR(6, MF_MODULE, ST_ERROR)
  1718. X#define MF_MALLOC_E    MKERR(7, MF_MODULE, ST_ERROR)
  1719. X#define MF_UMBERROR_E  MKERR(8, MF_MODULE, ST_ERROR)
  1720. X
  1721. X#define MF_BUG_F       MKERR(1, MF_MODULE, ST_FATAL)
  1722. X#define MF_OVERFLOW_F  MKERR(2, MF_MODULE, ST_FATAL)
  1723. X
  1724. X
  1725. X/*
  1726. X** misc: copyright strings, version macros, etc.
  1727. X*/
  1728. X
  1729. Xstatic char CONST RCSmf[] = "$Id: mf.h,v 1.5 1993/02/10 01:31:18 jwbirdsa Exp $";
  1730. X
  1731. X
  1732. X/*
  1733. X** typedefs
  1734. X*/
  1735. X
  1736. X/*
  1737. X** global variables
  1738. X*/
  1739. X
  1740. Xextern int mf_locked;
  1741. X
  1742. X
  1743. X/*
  1744. X** function prototypes
  1745. X*/
  1746. X
  1747. X#ifdef  __STDC__
  1748. X# define P_(s) s
  1749. X#else
  1750. X# define P_(s) ()
  1751. X#endif
  1752. X
  1753. XULONG mf_open P_((unsigned int flags, ULONG maxsize, char *tpath));
  1754. XULONG mf_write P_((UCHAR *buffer, unsigned int length));
  1755. XULONG mf_reset();
  1756. XULONG mf_read P_((UCHAR *buffer, unsigned int length, unsigned int *lread));
  1757. XULONG mf_close();
  1758. X
  1759. Xchar *mf_errstring P_((ULONG errcode));
  1760. X
  1761. X#undef P_
  1762. X
  1763. X#endif /* MF_H */
  1764. X
  1765. END_OF_FILE
  1766.   if test 2483 -ne `wc -c <'src/mf.h'`; then
  1767.     echo shar: \"'src/mf.h'\" unpacked with wrong size!
  1768.   fi
  1769.   # end of 'src/mf.h'
  1770. fi
  1771. echo shar: End of archive 16 \(of 18\).
  1772. cp /dev/null ark16isdone
  1773. MISSING=""
  1774. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1775.     if test ! -f ark${I}isdone ; then
  1776.     MISSING="${MISSING} ${I}"
  1777.     fi
  1778. done
  1779. if test "${MISSING}" = "" ; then
  1780.     echo You have unpacked all 18 archives.
  1781.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1782. else
  1783.     echo You still must unpack the following archives:
  1784.     echo "        " ${MISSING}
  1785. fi
  1786. exit 0
  1787. exit 0 # Just in case...
  1788.