home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / ZIP19P1.ZIP / util.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  13KB  |  389 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel and Igor Mandrichenko.
  5.  Permission is granted to any individual or institution to use, copy, or
  6.  redistribute this software so long as all of the original files are included
  7.  unmodified, that it is not sold for profit, and that this copyright notice
  8.  is retained.
  9.  
  10. */
  11.  
  12. /*
  13.  *  util.c by Mark Adler.
  14.  */
  15.  
  16. #include "zip.h"
  17. #include <ctype.h>
  18.  
  19. #if defined(MSDOS) && !defined(OS2) && !defined(__GO32__) && !defined(WIN32)
  20. #  include <dos.h>
  21. #endif
  22.  
  23. uch upper[256], lower[256];
  24. /* Country-dependent case map table */
  25.  
  26.  
  27. #ifndef UTIL /* UTIL picks out namecmp code (all utils) and crc32 (zipcloak) */
  28.  
  29. /* Local functions */
  30. #ifdef PROTO
  31.   local int recmatch(char *, char *);
  32.   local unsigned ident(unsigned chr);
  33. #endif /* PROTO */
  34.  
  35. char *isshexp(p)
  36. char *p;                /* candidate sh expression */
  37. /* If p is a sh expression, a pointer to the first special character is
  38.    returned.  Otherwise, NULL is returned. */
  39. {
  40.   for (; *p; p++)
  41.     if (*p == '\\' && *(p+1))
  42.       p++;
  43. #ifdef VMS
  44.     else if (*p == '%' || *p == '*')
  45. #else /* !VMS */
  46.     else if (*p == '?' || *p == '*' || *p == '[')
  47. #endif /* ?VMS */
  48.       return p;
  49.   return NULL;
  50. }
  51.  
  52.  
  53. local int recmatch(p, s)
  54. char *p;                /* sh pattern to match */
  55. char *s;                /* string to match it to */
  56. /* Recursively compare the sh pattern p with the string s and return 1 if
  57.    they match, and 0 or 2 if they don't or if there is a syntax error in the
  58.    pattern.  This routine recurses on itself no deeper than the number of
  59.    characters in the pattern. */
  60. {
  61.   int c;                /* pattern char or start of range in [-] loop */ 
  62.  
  63.   /* Get first character, the pattern for new recmatch calls follows */
  64.   c = *p++;
  65.  
  66.   /* If that was the end of the pattern, match if string empty too */
  67.   if (c == 0)
  68.     return *s == 0;
  69.  
  70.   /* '?' (or '%') matches any character (but not an empty string) */
  71. #ifdef VMS
  72.   if (c == '%')
  73. #else /* !VMS */
  74.   if (c == '?')
  75. #endif /* ?VMS */
  76.     return *s ? recmatch(p, s + 1) : 0;
  77.  
  78.   /* '*' matches any number of characters, including zero */
  79.   if (c == '*')
  80.   {
  81.     if (*p == 0)
  82.       return 1;
  83.     for (; *s; s++)
  84.       if ((c = recmatch(p, s)) != 0)
  85.         return c;
  86.     return 2;           /* 2 means give up--shmatch will return false */
  87.   }
  88.  
  89. #ifndef VMS             /* No bracket matching in VMS */
  90.   /* Parse and process the list of characters and ranges in brackets */
  91.   if (c == '[')
  92.   {
  93.     int e;              /* flag true if next char to be taken literally */
  94.     char *q;            /* pointer to end of [-] group */
  95.     int r;              /* flag true to match anything but the range */
  96.  
  97.     if (*s == 0)                        /* need a character to match */
  98.       return 0;
  99.     p += (r = *p == '!');               /* see if reverse */
  100.     for (q = p, e = 0; *q; q++)         /* find closing bracket */
  101.       if (e)
  102.         e = 0;
  103.       else
  104.         if (*q == '\\')
  105.           e = 1;
  106.         else if (*q == ']')
  107.           break;
  108.     if (*q != ']')                      /* nothing matches if bad syntax */
  109.       return 0;
  110.     for (c = 0, e = *p == '-'; p < q; p++)      /* go through the list */
  111.     {
  112.       if (e == 0 && *p == '\\')         /* set escape flag if \ */
  113.         e = 1;
  114.       else if (e == 0 && *p == '-')     /* set start of range if - */
  115.         c = *(p-1);
  116.       else
  117.       {
  118.         if (*(p+1) != '-')
  119.           for (c = c ? c : *p; c <= *p; c++)    /* compare range */
  120.             if (case_map(c) == case_map(*s))
  121.               return r ? 0 : recmatch(q + 1, s + 1);
  122.         c = e = 0;                      /* clear range, escape flags */
  123.       }
  124.     }
  125.     return r ? recmatch(q + 1, s + 1) : 0;      /* bracket match failed */
  126.   }
  127. #endif /* !VMS */
  128.  
  129.   /* If escape ('\'), just compare next character */
  130.   if (c == '\\')
  131.     if ((c = *p++) == 0)                /* if \ at end, then syntax error */
  132.       return 0;
  133.  
  134.   /* Just a character--compare it */
  135.   return case_map(c) == case_map(*s) ? recmatch(p, ++s) : 0;
  136. }
  137.  
  138.  
  139. int shmatch(p, s)
  140. char *p;                /* sh pattern to match */
  141. char *s;                /* string to match it to */
  142. /* Compare the sh pattern p with the string s and return true if they match,
  143.    false if they don't or if there is a syntax error in the pattern. */
  144. {
  145.   return recmatch(p, s) == 1;
  146. }
  147.  
  148.  
  149. #ifdef MSDOS
  150.  
  151. int dosmatch(p, s)
  152. char *p;                /* dos pattern to match */
  153. char *s;                /* string to match it to */
  154. /* Break the pattern and string into name and extension parts and match
  155.    each separately using shmatch(). */
  156. {
  157.   char *p1, *p2;        /* pattern sections */
  158.   char *s1, *s2;        /* string sections */
  159.   int r;                /* result */
  160.  
  161.   if ((p1 = malloc(strlen(p) + 1)) == NULL ||
  162.       (s1 = malloc(strlen(s) + 1)) == NULL)
  163.   {
  164.     if (p1 != NULL)
  165.       free((voidp *)p1);
  166.     return 0;
  167.   }
  168.   strcpy(p1, p);
  169.   strcpy(s1, s);
  170.   if ((p2 = strrchr(p1, '.')) != NULL)
  171.     *p2++ = 0;
  172.   else
  173.     p2 = "";
  174.   if ((s2 = strrchr(s1, '.')) != NULL)
  175.     *s2++ = 0;
  176.   else
  177.     s2 = "";
  178.   r = shmatch(p2, s2) && shmatch(p1, s1);
  179.   free((voidp *)p1);
  180.   free((voidp *)s1);
  181.   return r;
  182. }
  183. #endif /* MSDOS */
  184.  
  185. voidp far **search(b, a, n, cmp)
  186. voidp *b;               /* pointer to value to search for */
  187. voidp far **a;          /* table of pointers to values, sorted */
  188. extent n;               /* number of pointers in a[] */
  189. int (*cmp) OF((voidp *, voidp far *));  /* comparison function for search */
  190. /* Search for b in the pointer list a[0..n-1] using the compare function
  191.    cmp(b, c) where c is an element of a[i] and cmp() returns negative if
  192.    *b < *c, zero if *b == *c, or positive if *b > *c.  If *b is found,
  193.    search returns a pointer to the entry in a[], else search() returns
  194.    NULL.  The nature and size of *b and *c (they can be different) are
  195.    left up to the cmp() function.  A binary search is used, and it is
  196.    assumed that the list is sorted in ascending order. */
  197. {
  198.   voidp far **i;        /* pointer to midpoint of current range */
  199.   voidp far **l;        /* pointer to lower end of current range */
  200.   int r;                /* result of (*cmp)() call */
  201.   voidp far **u;        /* pointer to upper end of current range */
  202.  
  203.   l = (voidp far **)a;  u = l + (n-1);
  204.   while (u >= l)
  205.     if ((r = (*cmp)(b, *(i = l + ((u - l) >> 1)))) < 0)
  206.       u = i - 1;
  207.     else if (r > 0)
  208.       l = i + 1;
  209.     else
  210.       return (voidp far **)i;
  211.   return NULL;          /* If b were in list, it would belong at l */
  212. }
  213.  
  214. #endif /* !UTIL */
  215.  
  216.  
  217. /* Table of CRC-32's of all single byte values (made by makecrc.c) */
  218. local ulg crctab[] = {
  219.   0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  220.   0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  221.   0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  222.   0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  223.   0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  224.   0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  225.   0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  226.   0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  227.   0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  228.   0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  229.   0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  230.   0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  231.   0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  232.   0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  233.   0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  234.   0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  235.   0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  236.   0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  237.   0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  238.   0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  239.   0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  240.   0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  241.   0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  242.   0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  243.   0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  244.   0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  245.   0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  246.   0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  247.   0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  248.   0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  249.   0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  250.   0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  251.   0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  252.   0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  253.   0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  254.   0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  255.   0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  256.   0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  257.   0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  258.   0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  259.   0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  260.   0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  261.   0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  262.   0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  263.   0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  264.   0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  265.   0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  266.   0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  267.   0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  268.   0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  269.   0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  270.   0x2d02ef8dL
  271. };
  272.  
  273.  
  274. ulg crc32(c, b)
  275. ulg c;                  /* current contents of crc shift register */
  276. int b;                  /* byte (eight bits) to run through */
  277. /* Return the CRC-32 c updated with the eight bits in b. */
  278. {
  279.   return crctab[((int)c ^ b) & 0xff] ^ (c >> 8);
  280. }
  281.  
  282.  
  283. #ifndef UTIL /* UTIL picks out namecmp code (all utils) and crc32 (zipcloak) */
  284.  
  285. ulg updcrc(s, n)
  286. char *s;                /* pointer to bytes to pump through */
  287. extent n;               /* number of bytes in s[] */
  288. /* Run a set of bytes through the crc shift register.  If s is a NULL
  289.    pointer, then initialize the crc shift register contents instead.
  290.    Return the current crc in either case. */
  291. {
  292.   register ulg c;       /* temporary variable */
  293.  
  294.   static ulg crc = 0xffffffffL; /* shift register contents */
  295.  
  296.   if (s == NULL)
  297.     c = 0xffffffffL;
  298.   else
  299.   {
  300.     c = crc;
  301.     while (n--)
  302.       c = crctab[((int)c ^ (*s++)) & 0xff] ^ (c >> 8);
  303.   }
  304.   crc = c;
  305.   return c ^ 0xffffffffL;       /* (instead of ~c for 64-bit machines) */
  306. }
  307.  
  308. #endif /* !UTIL */
  309.  
  310.  
  311. #if (defined(MSDOS) && !defined(OS2) && !defined(__GO32__) && !defined(WIN32))
  312.  
  313. local unsigned ident(unsigned chr)
  314. {
  315.    return chr; /* in al */
  316. }
  317.  
  318. void init_upper()
  319. {
  320.   static struct country {
  321.     uch ignore[18];
  322.     int (far *casemap)(int);
  323.     uch filler[16];
  324.   } country_info;
  325.  
  326.   struct country far *info = &country_info;
  327.   union REGS regs;
  328.   struct SREGS sregs;
  329.   int c;
  330.  
  331.   regs.x.ax = 0x3800; /* get country info */
  332.   regs.x.dx = FP_OFF(info);
  333.   sregs.ds  = FP_SEG(info);
  334.   intdosx(®s, ®s, &sregs);
  335.   for (c = 0; c < 128; c++) {
  336.     upper[c] = (uch) toupper(c);
  337.     lower[c] = (uch) c;
  338.   }
  339.   for (; c < sizeof(upper); c++) {
  340.     upper[c] = (uch) (*country_info.casemap)(ident(c));
  341.     /* ident() required because casemap takes its parameter in al */
  342.     lower[c] = (uch) c;
  343.   }
  344.   for (c = 0; c < sizeof(upper); c++ ) {
  345.     int u = upper[c];
  346.     if (u != c && lower[u] == (uch) u) {
  347.       lower[u] = (uch)c;
  348.     }
  349.   }
  350.   for (c = 'A'; c <= 'Z'; c++) {
  351.     lower[c] = (uch) (c - 'A' + 'a');
  352.   }
  353. }
  354. #else
  355. #  ifndef OS2
  356.  
  357. void init_upper()
  358. {
  359.   int c;
  360.   for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = c;
  361.   for (c = 'a'; c <= 'z';        c++) upper[c] = c - 'a' + 'A';
  362.   for (c = 'A'; c <= 'Z';        c++) lower[c] = c - 'A' + 'a';
  363. }
  364. #  endif /* OS2 */
  365.  
  366. #endif /* MSDOS && !__GO32__ && !OS2 */
  367.  
  368. int namecmp(string1, string2)
  369.   char *string1, *string2;
  370. /* Compare the two strings ignoring case, and correctly taking into
  371.  * account national language characters. For operating systems with
  372.  * case sensitive file names, this function is equivalent to strcmp.
  373.  */
  374. {
  375.   int d;
  376.  
  377.   for (;;)
  378.   {
  379.     d = (int) (unsigned char) case_map(*string1)
  380.       - (int) (unsigned char) case_map(*string2);
  381.     
  382.     if (d || *string1 == 0 || *string2 == 0)
  383.       return d;
  384.       
  385.     string1++;
  386.     string2++;
  387.   }
  388. }
  389.