]> mj.ucw.cz Git - moe.git/blob - sherlock/conf-parse.c
Box: Use read_user_mem() where possible
[moe.git] / sherlock / conf-parse.c
1 /*
2  *      Sherlock Library -- Configuration Parsing Helpers
3  *
4  *      (c) 2006 Martin Mares <mj@ucw.cz>
5  *      (c) 2006 Robert Spalek <robert@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "sherlock/sherlock.h"
12 #include "sherlock/object.h"
13 #include "ucw/chartype.h"
14 #include "ucw/fastbuf.h"
15 #include "ucw/ff-unicode.h"
16 #include "ucw/unicode.h"
17 #include "sherlock/conf.h"
18
19 /*** Attribute names ***/
20
21 static byte *
22 attr_sub_parser(byte *c, uns *ptr)
23 {
24   if (c[0] && !c[1])
25     *ptr = c[0];
26   else if (c[0] == '(' && c[1] && c[1] != ')' && c[2] == ')' && !c[3])
27     *ptr = OBJ_ATTR_SON + c[1];
28   else
29     return "Invalid attribute name";
30   return NULL;
31 }
32
33 static byte *
34 attr_parser(byte *c, uns *ptr)
35 {
36   byte *err;
37   if (err = attr_sub_parser(c, ptr))
38     return err;
39   if (*ptr >= OBJ_ATTR_SON)
40     return "Names of sub-objects are not allowed here";
41   return NULL;
42 }
43
44 static void
45 attr_sub_dumper(struct fastbuf *b, uns *ptr)
46 {
47   if (!*ptr)
48     bprintf(b, "<none> ");
49   else if (*ptr < OBJ_ATTR_SON)
50     bprintf(b, "%c ", *ptr);
51   else
52     bprintf(b, "(%c) ", *ptr - OBJ_ATTR_SON);
53 }
54
55 struct cf_user_type cf_type_attr = {
56   .size = sizeof(uns),
57   .name = "attr",
58   .parser = (cf_parser1 *) attr_parser,
59   .dumper = (cf_dumper1 *) attr_sub_dumper
60 };
61
62 struct cf_user_type cf_type_attr_sub = {
63   .size = sizeof(uns),
64   .name = "attr_sub",
65   .parser = (cf_parser1 *) attr_sub_parser,
66   .dumper = (cf_dumper1 *) attr_sub_dumper
67 };
68
69 /*** Unicode characters ***/
70
71 static uns
72 uni_parser(byte *c, u16 *up)
73 {
74   uns u;
75   byte *cc = (byte*)utf8_get(c, &u);
76   if (*cc || u == UNI_REPLACEMENT)
77     {
78       for (uns i=0; i<4; i++)
79         if (!Cxdigit(c[i]))
80           return 1;
81         else
82           u = (u << 4) | Cxvalue(c[i]);
83       if (c[4])
84         return 1;
85     }
86   *up = u;
87   return 0;
88 }
89
90 static byte *
91 unichar_parser(byte *c, uns *up)
92 {
93   u16 u;
94   if (uni_parser(c, &u))
95     return "Expecting one UTF-8 character or its code";
96   *up = u;
97   return 0;
98 }
99
100 static void
101 unichar_dumper(struct fastbuf *b, uns *up)
102 {
103   bput_utf8(b, *up);
104   bputc(b, ' ');
105 }
106
107 struct cf_user_type cf_type_unichar = {
108   .size = sizeof(uns),
109   .name = "unichar",
110   .parser = (cf_parser1 *) unichar_parser,
111   .dumper = (cf_dumper1 *) unichar_dumper
112 };
113
114 /*** Unicode ranges ***/
115
116 static byte *
117 unirange_parser(byte *s, struct unirange *ur)
118 {
119   byte *c;
120   if ((c = strchr(s, '-')) && c > s)
121     {
122       *c++ = 0;
123       if (uni_parser(s, &ur->min) || uni_parser(c, &ur->max))
124         goto err;
125     }
126   else
127     {
128       if (uni_parser(s, &ur->min))
129         goto err;
130       ur->max = ur->min;
131     }
132   if (ur->min > ur->max)
133     return "Invalid code range (min>max)";
134   return NULL;
135
136  err:
137   return "Incorrect syntax of a code range";
138 }
139
140 static void
141 unirange_dumper(struct fastbuf *b, struct unirange *ur)
142 {
143   bprintf(b, (ur->min == ur->max ? "%04x " : "%04x-%04x "), ur->min, ur->max);
144 }
145
146 struct cf_user_type cf_type_unirange = {
147   .size = sizeof(struct unirange),
148   .name = "unirange",
149   .parser = (cf_parser1 *) unirange_parser,
150   .dumper = (cf_dumper1 *) unirange_dumper
151 };
152
153 /*** Unsigned integer ranges ***/
154
155 static byte *
156 unsrange_parser(byte *s, struct unsrange *r)
157 {
158   byte *c, *msg;
159   if ((c = strchr(s, '-')) && c > s)
160     {
161       *c++ = 0;
162       if (*c == '-')
163         return "Incorrect syntax of an unsigned range";
164       if ((msg = cf_parse_int(s, &r->min)) || (msg = cf_parse_int(c, &r->max)))
165         return msg;
166     }
167   else
168     {
169       if (msg = cf_parse_int(s, &r->min))
170         return msg;
171       r->max = r->min;
172     }
173   if (r->min > r->max)
174     return "Invalid unsigned range (min>max)";
175   return NULL;
176 }
177
178 static void
179 unsrange_dumper(struct fastbuf *b, struct unsrange *r)
180 {
181   bprintf(b, (r->min == r->max ? "%u " : "%u-%u "), r->min, r->max);
182 }
183
184 struct cf_user_type cf_type_unsrange = {
185   .size = sizeof(struct unsrange),
186   .name = "gerr_range",
187   .parser = (cf_parser1 *) unsrange_parser,
188   .dumper = (cf_dumper1 *) unsrange_dumper
189 };
190
191 /* Configuration sections for (word|meta|string)-types */
192
193 static byte *
194 parse_u8(byte *s, uns *w)
195 {
196   CF_JOURNAL_VAR(*w);
197   byte *msg = cf_parse_int(s, (int *)w);
198   if (msg)
199     return msg;
200   if (*w > 255)
201     return "Weights are limited to 0..255";
202   return NULL;
203 }
204
205 static void
206 dump_u8(struct fastbuf *fb, uns *ptr)
207 {
208   bprintf(fb, "%d ", *ptr);
209 }
210
211 static struct cf_user_type weight_type = {
212   .size = sizeof(uns),
213   .name = "weight",
214   .parser = (cf_parser1*) parse_u8,
215   .dumper = (cf_dumper1*) dump_u8
216 };
217
218 void
219 cf_generate_word_type_config(struct cf_section *sec, byte **names, uns multiple, uns just_u8)
220 {
221   uns number = 0;
222   while (names[number])
223     number++;
224   struct cf_item *items = sec->cfg = xmalloc((number + 1) * sizeof(struct cf_item));
225   for (uns i = 0; i < number; i++) {
226     if (just_u8)
227       items[i] = (struct cf_item) CF_USER_ARY(names[i], ((uns*) NULL) + i*multiple, &weight_type, multiple);
228     else
229       items[i] = (struct cf_item) CF_UNS_ARY(names[i], ((uns*) NULL) + i*multiple, multiple);
230   }
231   items[number] = (struct cf_item) CF_END;
232 }