util.c
来自「infozip2.2源码」· C语言 代码 · 共 621 行 · 第 1/2 页
C
621 行
/* Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly, Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as all of the original files are included, that it is not sold for profit, and that this copyright notice is retained.*//* * util.c by Mark Adler. */#include "zip.h"#include "ebcdic.h"#include <ctype.h>#ifdef MSDOS16# include <dos.h>#endifuch upper[256], lower[256];/* Country-dependent case map table */#ifndef UTIL /* UTIL picks out namecmp code (all utils) *//* Local functions */local int recmatch OF((uch *, uch *));local int count_args OF((char *s));#ifdef MSDOS16 local unsigned ident OF((unsigned chr));#endif#ifdef NO_MKTIME#include "mktime.c"#endif#ifndef HAVE_FSEEKABLEint fseekable(fp)FILE *fp;{ long x; return (fp == NULL || (fseek(fp, -1L, SEEK_CUR) == 0 && (x = ftell(fp)) >= 0 && fseek(fp, 1L, SEEK_CUR) == 0 && ftell(fp) == x + 1));}#endif /* HAVE_FSEEKABLE */char *isshexp(p)char *p; /* candidate sh expression *//* If p is a sh expression, a pointer to the first special character is returned. Otherwise, NULL is returned. */{ for (; *p; p++) if (*p == '\\' && *(p+1)) p++;#ifdef VMS else if (*p == '%' || *p == '*')#else /* !VMS */ else if (*p == '?' || *p == '*' || *p == '[')#endif /* ?VMS */ return p; return NULL;}local int recmatch(p, s)uch *p; /* sh pattern to match */uch *s; /* string to match it to *//* Recursively compare the sh pattern p with the string s and return 1 if they match, and 0 or 2 if they don't or if there is a syntax error in the pattern. This routine recurses on itself no deeper than the number of characters in the pattern. */{ unsigned int c; /* pattern char or start of range in [-] loop */ /* Get first character, the pattern for new recmatch calls follows */ c = *p++; /* If that was the end of the pattern, match if string empty too */ if (c == 0) return *s == 0; /* '?' (or '%') matches any character (but not an empty string) */#ifdef VMS if (c == '%')#else /* !VMS */ if (c == '?')#endif /* ?VMS */ return *s ? recmatch(p, s + 1) : 0; /* '*' matches any number of characters, including zero */#ifdef AMIGA if (c == '#' && *p == '?') /* "#?" is Amiga-ese for "*" */ c = '*', p++;#endif /* AMIGA */ if (c == '*') { if (*p == 0) return 1; for (; *s; s++) if ((c = recmatch(p, s)) != 0) return (int)c; return 2; /* 2 means give up--shmatch will return false */ }#ifndef VMS /* No bracket matching in VMS */ /* Parse and process the list of characters and ranges in brackets */ if (c == '[') { int e; /* flag true if next char to be taken literally */ uch *q; /* pointer to end of [-] group */ int r; /* flag true to match anything but the range */ if (*s == 0) /* need a character to match */ return 0; p += (r = (*p == '!' || *p == '^')); /* see if reverse */ for (q = p, e = 0; *q; q++) /* find closing bracket */ if (e) e = 0; else if (*q == '\\') e = 1; else if (*q == ']') break; if (*q != ']') /* nothing matches if bad syntax */ return 0; for (c = 0, e = *p == '-'; p < q; p++) /* go through the list */ { if (e == 0 && *p == '\\') /* set escape flag if \ */ e = 1; else if (e == 0 && *p == '-') /* set start of range if - */ c = *(p-1); else { uch cc = case_map(*s); if (*(p+1) != '-') for (c = c ? c : *p; c <= *p; c++) /* compare range */ if (case_map(c) == cc) return r ? 0 : recmatch(q + 1, s + 1); c = e = 0; /* clear range, escape flags */ } } return r ? recmatch(q + 1, s + 1) : 0; /* bracket match failed */ }#endif /* !VMS */ /* If escape ('\'), just compare next character */ if (c == '\\') if ((c = *p++) == 0) /* if \ at end, then syntax error */ return 0; /* Just a character--compare it */ return case_map(c) == case_map(*s) ? recmatch(p, ++s) : 0;}int shmatch(p, s)char *p; /* sh pattern to match */char *s; /* string to match it to *//* Compare the sh pattern p with the string s and return true if they match, false if they don't or if there is a syntax error in the pattern. */{ return recmatch((uch *) p, (uch *) s) == 1;}#if defined(DOS) || defined(WIN32)/* XXX also suitable for OS2? Atari? Human68K? TOPS-20?? */int dosmatch(p, s)char *p; /* dos pattern to match */char *s; /* string to match it to *//* Treat filenames without periods as having an implicit trailing period */{ char *s1; /* revised string to match */ int r; /* result */ if ((s1 = malloc(strlen(s) + 2)) == NULL) return recmatch((uch *) p, (uch *) s) == 1; /* will usually be correct */ strcpy(s1, s); if (strchr(p, '.') && !strchr(s1, '.')) strcat(s1, "."); r = recmatch((uch *)p, (uch *)s1); free((zvoid *)s1); return r == 1;}#endif /* DOS || WIN32 */zvoid far **search(b, a, n, cmp)zvoid *b; /* pointer to value to search for */zvoid far **a; /* table of pointers to values, sorted */extent n; /* number of pointers in a[] */int (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function *//* Search for b in the pointer list a[0..n-1] using the compare function cmp(b, c) where c is an element of a[i] and cmp() returns negative if *b < *c, zero if *b == *c, or positive if *b > *c. If *b is found, search returns a pointer to the entry in a[], else search() returns NULL. The nature and size of *b and *c (they can be different) are left up to the cmp() function. A binary search is used, and it is assumed that the list is sorted in ascending order. */{ zvoid far **i; /* pointer to midpoint of current range */ zvoid far **l; /* pointer to lower end of current range */ int r; /* result of (*cmp)() call */ zvoid far **u; /* pointer to upper end of current range */ l = (zvoid far **)a; u = l + (n-1); while (u >= l) { i = l + ((unsigned)(u - l) >> 1); if ((r = (*cmp)(b, (char *)*(struct zlist **)i)) < 0) u = i - 1; else if (r > 0) l = i + 1; else return (zvoid far **)i; } return NULL; /* If b were in list, it would belong at l */}#endif /* !UTIL */#ifdef MSDOS16local unsigned ident(unsigned chr){ return chr; /* in al */}void init_upper(){ static struct country { uch ignore[18]; int (far *casemap)(int); uch filler[16]; } country_info; struct country far *info = &country_info; union REGS regs; struct SREGS sregs; int c; regs.x.ax = 0x3800; /* get country info */ regs.x.dx = FP_OFF(info); sregs.ds = FP_SEG(info); intdosx(®s, ®s, &sregs); for (c = 0; c < 128; c++) { upper[c] = (uch) toupper(c); lower[c] = (uch) c; } for (; c < sizeof(upper); c++) { upper[c] = (uch) (*country_info.casemap)(ident(c)); /* ident() required because casemap takes its parameter in al */ lower[c] = (uch) c; } for (c = 0; c < sizeof(upper); c++ ) { int u = upper[c]; if (u != c && lower[u] == (uch) u) { lower[u] = (uch)c; } } for (c = 'A'; c <= 'Z'; c++) { lower[c] = (uch) (c - 'A' + 'a'); }}#else /* !MSDOS16 */# ifndef OS2void init_upper(){ int c;#if defined(ATARI) || defined(CMS_MVS)#include <ctype.h>/* this should be valid for all other platforms too. (HD 11/11/95) */ for (c = 0; c< sizeof(upper); c++) { upper[c] = islower(c) ? toupper(c) : c; lower[c] = isupper(c) ? tolower(c) : c; }#else for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = c; for (c = 'a'; c <= 'z'; c++) upper[c] = c - 'a' + 'A'; for (c = 'A'; c <= 'Z'; c++) lower[c] = c - 'A' + 'a';#endif}# endif /* !OS2 */#endif /* ?MSDOS16 */int namecmp(string1, string2) char *string1, *string2;/* Compare the two strings ignoring case, and correctly taking into * account national language characters. For operating systems with * case sensitive file names, this function is equivalent to strcmp. */{ int d; for (;;) { d = (int) (uch) case_map(*string1) - (int) (uch) case_map(*string2); if (d || *string1 == 0 || *string2 == 0) return d;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?