home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1999 October / VPR9910A.BIN / OLS / unrar32005 / unrar32005.lzh / src / util.cxx < prev    next >
C/C++ Source or Header  |  1998-04-03  |  7KB  |  323 lines

  1. /*
  2.  *   Copyright (c) 1998 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. char *
  35. find_last_slash (const char *p)
  36. {
  37.   for (u_char *x = 0, *s = (u_char *)p; *s;)
  38.     {
  39. #ifdef KANJI
  40.       if (iskanji (*s) && s[1])
  41.         s += 2;
  42.       else
  43. #endif
  44.         {
  45.           if (*s == '/' || *s == '\\')
  46.             x = s;
  47.           s++;
  48.         }
  49.     }
  50.   return (char *)x;
  51. }
  52.  
  53. char *
  54. find_slash (const char *p)
  55. {
  56.   for (u_char *s = (u_char *)p; *s;)
  57.     {
  58. #ifdef KANJI
  59.       if (iskanji (*s) && s[1])
  60.         s += 2;
  61.       else
  62. #endif
  63.         {
  64.           if (*s == '/' || *s == '\\')
  65.             return (char *)s;
  66.           s++;
  67.         }
  68.     }
  69.   return 0;
  70. }
  71.  
  72. char *
  73. trim_root (const char *path)
  74. {
  75.   if (isalpha (u_char (*path)) && path[1] == ':')
  76.     path += 2;
  77.   for (; *path == '\\' || *path == '/'; path++)
  78.     ;
  79.   return (char *)path;
  80. }
  81.  
  82. char *
  83. stpcpy (char *d, const char *s)
  84. {
  85.   int l = strlen (s);
  86.   memcpy (d, s, l + 1);
  87.   return d + l;
  88. }
  89.  
  90. void
  91. cmdline::discard ()
  92. {
  93.   for (int i = 0; i < cl_ac; i++)
  94.     if (cl_av[i])
  95.       free (cl_av[i]);
  96.   if (cl_av)
  97.     free (cl_av);
  98.   cl_ac = 0;
  99.   cl_av = 0;
  100.   cl_max = 0;
  101. }
  102.  
  103. char *
  104. cmdline::copyarg (const u_char *s, const u_char *se, int dq)
  105. {
  106.   int l = se - s - dq;
  107.   if (!l)
  108.     return "";
  109.   char *d0 = (char *)malloc (l + 1);
  110.   if (!d0)
  111.     return 0;
  112.   for (char *d = d0; s < se; s++)
  113.     if (*s != '"')
  114.       *d++ = *s;
  115.   *d = 0;
  116.   return d0;
  117. }
  118.  
  119. int
  120. cmdline::parse (const char *cmdline, int l, int resp_ok)
  121. {
  122.   if (!cmdline)
  123.     return 0;
  124.   const u_char *cp = (const u_char *)cmdline;
  125.   const u_char *ce = cp + l;
  126.   const u_char *c0 = 0;
  127.   int dq = 0;
  128.   for (;; cp++)
  129.     {
  130.       int c = cp == ce ? EOF : *cp;
  131.       switch (c)
  132.         {
  133.         case ' ':
  134.         case '\t':
  135.           if (dq & 1)
  136.             goto normal_char;
  137.           /* fall thru... */
  138.         case EOF:
  139.         case '\r':
  140.         case '\n':
  141.           if (c0)
  142.             {
  143.               char *arg = copyarg (c0, cp, dq);
  144.               if (!arg)
  145.                 return ERROR_ENOUGH_MEMORY;
  146.               if (resp_ok && *arg == '@')
  147.                 {
  148.                   mapf mf;
  149.                   int e = mf.open (arg + 1);
  150.                   free (arg);
  151.                   if (!e)
  152.                     return ERROR_RESPONSE_READ;
  153.                   e = parse ((const char *)mf.base (), mf.size (), 0);
  154.                   if (e)
  155.                     return e;
  156.                 }
  157.               else if (*arg)
  158.                 {
  159.                   if (cl_ac == cl_max)
  160.                     {
  161.                       cl_max += 32;
  162.                       char **x = (char **)realloc (cl_av, sizeof *x * cl_max);
  163.                       if (!x)
  164.                         {
  165.                           free (arg);
  166.                           return ERROR_ENOUGH_MEMORY;
  167.                         }
  168.                       cl_av = x;
  169.                     }
  170.                   cl_av[cl_ac++] = arg;
  171.                 }
  172.               dq = 0;
  173.               c0 = 0;
  174.             }
  175.           if (c == EOF)
  176.             return 0;
  177.           break;
  178.  
  179.         case '"':
  180.           dq++;
  181.           /* fall thru... */
  182.         default:
  183.         normal_char:
  184.           if (!c0)
  185.             c0 = cp;
  186.           break;
  187.         }
  188.     }
  189. }
  190.  
  191. int
  192. glob::match (const char *pat, const char *str)
  193. {
  194.   const u_char *p = (const u_char *)pat;
  195.   const u_char *s = (const u_char *)str;
  196.  
  197.   while (1)
  198.     {
  199.       int c = *p++;
  200.       switch (c)
  201.         {
  202.         case 0:
  203.           return !*s;
  204.  
  205.         case '?':
  206.           if (!*s || *s == '/' || *s == '\\')
  207.             return 0;
  208. #ifdef KANJI
  209.           if (iskanji (*s) && s[1])
  210.             s++;
  211. #endif
  212.           s++;
  213.           break;
  214.  
  215.         case '*':
  216.           for (; *p == '*'; p++)
  217.             ;
  218.           if (!*p)
  219.             return !find_slash ((const char *)s);
  220.           while (1)
  221.             {
  222.               if (match ((const char *)p, (const char *)s))
  223.                 return 1;
  224.               if (!*s || *s == '/' || *s == '\\')
  225.                 return 0;
  226. #ifdef KANJI
  227.               if (iskanji (*s) && s[1])
  228.                 s++;
  229. #endif
  230.               s++;
  231.             }
  232.  
  233.         case '/':
  234.         case '\\':
  235.           if (*s != '/' && *s != '\\')
  236.             return 0;
  237.           s++;
  238.           break;
  239.  
  240.         default:
  241. #ifdef KANJI
  242.           if (iskanji (c) && *p)
  243.             {
  244.               if (u_char (c) != *s++)
  245.                 return 0;
  246.               if (*p++ != *s++)
  247.                 return 0;
  248.             }
  249.           else
  250. #endif
  251.             {
  252.               if (translate (c) != translate (*s))
  253.                 return 0;
  254.               s++;
  255.             }
  256.         }
  257.     }
  258. }
  259.  
  260. int
  261. glob::match (const char *file, int strict) const
  262. {
  263.   if (!g_npat)
  264.     return 1;
  265.   if (strict)
  266.     {
  267.       for (int i = 0; i < g_npat; i++)
  268.         if (match (g_pat[i], file))
  269.           return 1;
  270.     }
  271.   else
  272.     {
  273.       const char *name = find_last_slash (file);
  274.       name = name ? name + 1 : file;
  275.       for (int i = 0; i < g_npat; i++)
  276.         if (match (g_pat[i], find_slash (g_pat[i]) ? file : name))
  277.           return 1;
  278.     }
  279.   return 0;
  280. }
  281.  
  282. int
  283. check_kanji_trail (const char *string, u_int off)
  284. {
  285.   for (const u_char *s0 = (u_char *)string, *se = s0 + off, *s = se;
  286.        s-- > s0 && iskanji (*s);)
  287.     ;
  288.   return !((se - s) & 1);
  289. }
  290.  
  291. int
  292. ostrbuf::formatv (const char *fmt, va_list ap)
  293. {
  294.   if (space () <= 0)
  295.     return 0;
  296.   int l = _vsnprintf (os_buf, space (), fmt, ap);
  297.   if (l > 0)
  298.     {
  299.       os_buf += l;
  300.       os_size -= l;
  301.       *os_buf = 0;
  302.     }
  303.   else
  304.     {
  305.       l = space ();
  306.       if (check_kanji_trail (os_buf, l))
  307.         l--;
  308.       os_buf[l] = 0;
  309.       os_size = 0;
  310.     }
  311.   return space () > 0;
  312. }
  313.  
  314. int
  315. ostrbuf::format (const char *fmt, ...)
  316. {
  317.   va_list ap;
  318.   va_start (ap, fmt);
  319.   int x = formatv (fmt, ap);
  320.   va_end (ap);
  321.   return x;
  322. };
  323.