1 /* Functions for multi-byte support.
2    Created for gawk multi-byte extension May, 1993 by t^2 (Takahiro Tanimoto)
3    Last change: May 21, 1997 by K.Okabe  */
4 #include "awk.h"
5 
6 int
7 #ifdef __STDC__
mbstrncasecmp(const char * s1,const char * s2,size_t n)8 mbstrncasecmp(const char *s1, const char *s2, size_t n)
9 #else
10 mbstrncasecmp(s1, s2, n)
11      const char *s1, *s2;
12      size_t n;
13 #endif
14 {
15   int c1;
16 
17   while (n--) {
18     if ((c1 = (unsigned char)*s1++) == 0)
19       return -(unsigned char)*s2;
20     if (!ismbchar(c1)) {
21       if ((c1 = ((unsigned char)casetable[c1]
22 		 - (unsigned char)casetable[(unsigned char)*s2++])) != 0)
23 	return c1;
24     }
25     else {
26       size_t len = mbclen(c1) - 1;
27 
28       if ((c1 -= (unsigned char)*s2++) != 0)
29 	return c1;
30 
31       while (len--) {
32 	if (!n--)
33 	  return 0;
34 	if ((c1 = (unsigned char)*s1++) == 0)
35 	  return -(unsigned char)*s2;
36 	if ((c1 -= (unsigned char)*s2++) != 0)
37 	  return c1;
38       }
39     }
40   }
41   return 0;
42 }
43 
44 int
45 #ifdef __STDC__
mbmemcmp(const void * p1,size_t n1,const void * p2,size_t n2)46 mbmemcmp(const void *p1, size_t n1, const void *p2, size_t n2)
47 #else
48 mbmemcmp(p1, n1, p2, n2)
49      const void *p1, *p2;
50      size_t n1, n2;
51 #endif
52 {
53   const unsigned char *s1 = p1, *s2 = p2;
54   unsigned char c1;
55   size_t n;
56 
57   for (;;) {
58     if (!n1--)
59       return n2 ? -1 : 0;
60     if (!n2--)
61       return 1;
62     if ((c1 = *s1++) != *s2++) {
63       s2--;
64       return ismbchar(c1) ? (ismbchar(*s2) ? (int)c1 - *s2 : 1):
65 	(ismbchar(*s2) ? -1 : (int)c1 - *s2);
66     }
67 
68     if (!ismbchar(c1))
69       continue;
70     for (n = mbclen(c1) - 1; n > 0; n--) {
71       if (!n1--)
72 	return n2 ? -1 : 0;
73       if (!n2--)
74 	return 1;
75       if (*s1++ != *s2++)
76 	return (int)*--s1 - *--s2;
77     }
78   }
79 }
80 
81 size_t
82 #ifdef __STDC__
mblength(const char * s,size_t len)83 mblength(const char *s, size_t len)
84 #else
85 mblength(s, len)
86      const char *s;
87      size_t len;
88 #endif
89 {
90   const char *send;
91 
92   send = s + len;
93   len = 0;
94   while ((s += mbclen(*s)) <= send)
95     len++;
96   return len;
97 }
98 
99 size_t
100 #ifdef __STDC__
mbbyte(const char * s,size_t len)101 mbbyte(const char *s, size_t len)
102 #else
103 mbbyte(s, len)
104      const char *s;
105      size_t len;
106 #endif
107 {
108   const char *s0, *s1;
109 
110   if (current_mbctype == MBCTYPE_UTF8) {
111     if (len == 0)
112       return 0;
113 
114     s0 = s;
115     s1 = s + len;
116     s = s1 - 1;
117     while (s > s0 && ! ismbchar (*s) && ! ((unsigned char) *s < 0x80))
118       s--;
119     return (s + mbclen(*s) == s1) ? len : s - s0 ;
120   } else {
121     s0 = s;
122     s1 = s + len;
123     for (s = s1; s-- > s0 && ismbchar (*s);)
124       ;
125     if (! ((s1 - s) & 1))
126       len--;
127     return len;
128   }
129 }
130