home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2002 July / VPR0207A.ISO / OLS / UNRAR32007 / unrar32007.lzh / src.lzh / src / util.cxx < prev    next >
C/C++ Source or Header  |  2001-02-16  |  7KB  |  338 lines

  1. /*
  2.  *   Copyright (c) 1998-2001 T. Kamei (kamei@jsdlab.co.jp)
  3.  *
  4.  *   Permission to use, copy, modify, and distribute this software
  5.  * and its documentation for any purpose is hereby granted provided
  6.  * that the above copyright notice and this permission notice appear
  7.  * in all copies of the software and related documentation.
  8.  *
  9.  *                          NO WARRANTY
  10.  *
  11.  *   THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY WARRANTIES;
  12.  * WITHOUT EVEN THE IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
  13.  * FOR A PARTICULAR PURPOSE.
  14.  */
  15.  
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include "comm-arc.h"
  19. #include "util.h"
  20. #include "mapf.h"
  21.  
  22. void
  23. init_table ()
  24. {
  25.   for (int i = 0; i < 256; i++)
  26.     {
  27.       translate_table[i] = i;
  28.       mblead_table[i] = IsDBCSLeadByte (i);
  29.     }
  30.   for (i = 'a'; i <= 'z'; i++)
  31.     translate_table[i] = i - 'a' + 'A';
  32. }
  33.  
  34. #define SEPCHAR_P(C) ((C) == '/' || (C) == '\\')
  35.  
  36. char *
  37. find_last_slash (const char *p)
  38. {
  39.   for (u_char *x = 0, *s = (u_char *)p; *s;)
  40.     {
  41. #ifdef KANJI
  42.       if (iskanji (*s) && s[1])
  43.         s += 2;
  44.       else
  45. #endif
  46.         {
  47.           if (SEPCHAR_P (*s))
  48.             x = s;
  49.           s++;
  50.         }
  51.     }
  52.   return (char *)x;
  53. }
  54.  
  55. char *
  56. find_slash (const char *p)
  57. {
  58.   for (u_char *s = (u_char *)p; *s;)
  59.     {
  60. #ifdef KANJI
  61.       if (iskanji (*s) && s[1])
  62.         s += 2;
  63.       else
  64. #endif
  65.         {
  66.           if (SEPCHAR_P (*s))
  67.             return (char *)s;
  68.           s++;
  69.         }
  70.     }
  71.   return 0;
  72. }
  73.  
  74. char *
  75. trim_root (const char *path)
  76. {
  77.   if (isalpha (u_char (*path)) && path[1] == ':')
  78.     path += 2;
  79.   for (; SEPCHAR_P (*path); path++)
  80.     ;
  81.   return (char *)path;
  82. }
  83.  
  84. char *
  85. stpcpy (char *d, const char *s)
  86. {
  87.   int l = strlen (s);
  88.   memcpy (d, s, l + 1);
  89.   return d + l;
  90. }
  91.  
  92. void
  93. cmdline::discard ()
  94. {
  95.   for (int i = 0; i < cl_ac; i++)
  96.     if (cl_av[i])
  97.       free (cl_av[i]);
  98.   if (cl_av)
  99.     free (cl_av);
  100.   cl_ac = 0;
  101.   cl_av = 0;
  102.   cl_max = 0;
  103. }
  104.  
  105. char *
  106. cmdline::copyarg (const u_char *s, const u_char *se, int dq)
  107. {
  108.   int l = se - s - dq;
  109.   if (!l)
  110.     return "";
  111.   char *d0 = (char *)malloc (l + 1);
  112.   if (!d0)
  113.     return 0;
  114.   for (char *d = d0; s < se; s++)
  115.     if (*s != '"')
  116.       *d++ = *s;
  117.   *d = 0;
  118.   return d0;
  119. }
  120.  
  121. int
  122. cmdline::parse (const char *cmdline, int l, int resp_ok)
  123. {
  124.   if (!cmdline)
  125.     return 0;
  126.   const u_char *cp = (const u_char *)cmdline;
  127.   const u_char *ce = cp + l;
  128.   const u_char *c0 = 0;
  129.   int dq = 0;
  130.   for (;; cp++)
  131.     {
  132.       int c = cp == ce ? EOF : *cp;
  133.       switch (c)
  134.         {
  135.         case ' ':
  136.         case '\t':
  137.           if (dq & 1)
  138.             goto normal_char;
  139.           /* fall thru... */
  140.         case EOF:
  141.         case '\r':
  142.         case '\n':
  143.           if (c0)
  144.             {
  145.               char *arg = copyarg (c0, cp, dq);
  146.               if (!arg)
  147.                 return ERROR_ENOUGH_MEMORY;
  148.               if (resp_ok && *arg == '@')
  149.                 {
  150.                   mapf mf;
  151.                   int e = mf.open (arg + 1);
  152.                   free (arg);
  153.                   if (!e)
  154.                     return ERROR_RESPONSE_READ;
  155.                   e = parse ((const char *)mf.base (), mf.size (), 0);
  156.                   if (e)
  157.                     return e;
  158.                 }
  159.               else if (*arg)
  160.                 {
  161.                   if (cl_ac == cl_max)
  162.                     {
  163.                       cl_max += 32;
  164.                       char **x = (char **)realloc (cl_av, sizeof *x * cl_max);
  165.                       if (!x)
  166.                         {
  167.                           free (arg);
  168.                           return ERROR_ENOUGH_MEMORY;
  169.                         }
  170.                       cl_av = x;
  171.                     }
  172.                   cl_av[cl_ac++] = arg;
  173.                 }
  174.               dq = 0;
  175.               c0 = 0;
  176.             }
  177.           if (c == EOF)
  178.             return 0;
  179.           break;
  180.  
  181.         case '"':
  182.           dq++;
  183.           /* fall thru... */
  184.         default:
  185.         normal_char:
  186.           if (!c0)
  187.             c0 = cp;
  188.           break;
  189.         }
  190.     }
  191. }
  192.  
  193. int
  194. glob::match (const char *pat, const char *str, int recursive)
  195. {
  196.   const u_char *p = (const u_char *)pat;
  197.   const u_char *s = (const u_char *)str;
  198.  
  199.   while (1)
  200.     {
  201.       int c = *p++;
  202.       switch (c)
  203.         {
  204.         case 0:
  205.           return !*s || (recursive && SEPCHAR_P (*s));
  206.  
  207.         case '?':
  208.           if (!*s || SEPCHAR_P (*s))
  209.             return 0;
  210. #ifdef KANJI
  211.           if (iskanji (*s) && s[1])
  212.             s++;
  213. #endif
  214.           s++;
  215.           break;
  216.  
  217.         case '*':
  218.           for (; *p == '*'; p++)
  219.             ;
  220.           if (!*p)
  221.             return recursive || !find_slash ((const char *)s);
  222.           while (1)
  223.             {
  224.               if (match ((const char *)p, (const char *)s, recursive))
  225.                 return 1;
  226.               if (!*s || SEPCHAR_P (*s))
  227.                 return 0;
  228. #ifdef KANJI
  229.               if (iskanji (*s) && s[1])
  230.                 s++;
  231. #endif
  232.               s++;
  233.             }
  234.  
  235.         case '/':
  236.         case '\\':
  237.           if (!SEPCHAR_P (*s))
  238.             return 0;
  239.           s++;
  240.           break;
  241.  
  242.         default:
  243. #ifdef KANJI
  244.           if (iskanji (c) && *p)
  245.             {
  246.               if (u_char (c) != *s++)
  247.                 return 0;
  248.               if (*p++ != *s++)
  249.                 return 0;
  250.             }
  251.           else
  252. #endif
  253.             {
  254.               if (translate (c) != translate (*s))
  255.                 return 0;
  256.               s++;
  257.             }
  258.         }
  259.     }
  260. }
  261.  
  262. int
  263. glob::match (const char *file, int strict, int recursive) const
  264. {
  265.   if (!g_npat)
  266.     return 1;
  267.   if (strict)
  268.     {
  269.       for (int i = 0; i < g_npat; i++)
  270.         if (match (g_pat[i], file, recursive))
  271.           return 1;
  272.     }
  273.   else
  274.     {
  275.       const char *name = find_last_slash (file);
  276.       name = name ? name + 1 : file;
  277.       for (int i = 0; i < g_npat; i++)
  278.         if (match (g_pat[i], find_slash (g_pat[i]) ? file : name, recursive))
  279.           return 1;
  280.     }
  281.   return 0;
  282. }
  283.  
  284. void
  285. glob::set_pattern (int ac, char **av)
  286. {
  287.   g_npat = ac;
  288.   g_pat = av;
  289.   for (int i = 0; i < g_npat; i++)
  290.     {
  291.       char *p = find_last_slash (g_pat[i]);
  292.       if (p && !p[1])
  293.         *p = 0;
  294.     }
  295. }
  296.  
  297. int
  298. check_kanji_trail (const char *string, u_int off)
  299. {
  300.   for (const u_char *s0 = (u_char *)string, *se = s0 + off, *s = se;
  301.        s-- > s0 && iskanji (*s);)
  302.     ;
  303.   return !((se - s) & 1);
  304. }
  305.  
  306. int
  307. ostrbuf::formatv (const char *fmt, va_list ap)
  308. {
  309.   if (space () <= 0)
  310.     return 0;
  311.   int l = _vsnprintf (os_buf, space (), fmt, ap);
  312.   if (l > 0)
  313.     {
  314.       os_buf += l;
  315.       os_size -= l;
  316.       *os_buf = 0;
  317.     }
  318.   else
  319.     {
  320.       l = space ();
  321.       if (check_kanji_trail (os_buf, l))
  322.         l--;
  323.       os_buf[l] = 0;
  324.       os_size = 0;
  325.     }
  326.   return space () > 0;
  327. }
  328.  
  329. int
  330. ostrbuf::format (const char *fmt, ...)
  331. {
  332.   va_list ap;
  333.   va_start (ap, fmt);
  334.   int x = formatv (fmt, ap);
  335.   va_end (ap);
  336.   return x;
  337. };
  338.