PageRenderTime 28ms CodeModel.GetById 13ms app.highlight 6ms RepoModel.GetById 2ms app.codeStats 0ms

/usr.bin/colldef/parse.y

https://bitbucket.org/freebsd/freebsd-head/
Happy | 384 lines | 357 code | 27 blank | 0 comment | 0 complexity | 6026bca0e1588ade8b5bf662178491bd MD5 | raw file
  1%{
  2/*-
  3 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
  4 *		at Electronni Visti IA, Kiev, Ukraine.
  5 *			All rights reserved.
  6 *
  7 * Redistribution and use in source and binary forms, with or without
  8 * modification, are permitted provided that the following conditions
  9 * are met:
 10 * 1. Redistributions of source code must retain the above copyright
 11 *    notice, this list of conditions and the following disclaimer.
 12 * 2. Redistributions in binary form must reproduce the above copyright
 13 *    notice, this list of conditions and the following disclaimer in the
 14 *    documentation and/or other materials provided with the distribution.
 15 *
 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 26 * SUCH DAMAGE.
 27 */
 28
 29#include <sys/cdefs.h>
 30__FBSDID("$FreeBSD$");
 31
 32#include <sys/types.h>
 33#include <arpa/inet.h>
 34#include <err.h>
 35#include <stdarg.h>
 36#include <stdio.h>
 37#include <string.h>
 38#include <unistd.h>
 39#include <sysexits.h>
 40#include "collate.h"
 41#include "common.h"
 42
 43extern FILE *yyin;
 44void yyerror(const char *fmt, ...) __printflike(1, 2);
 45int yyparse(void);
 46int yylex(void);
 47static void usage(void);
 48static void collate_print_tables(void);
 49
 50char map_name[FILENAME_MAX] = ".";
 51char curr_chain[STR_LEN];
 52
 53char __collate_version[STR_LEN];
 54u_char charmap_table[UCHAR_MAX + 1][CHARMAP_SYMBOL_LEN];
 55
 56#undef __collate_substitute_table
 57u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
 58#undef __collate_char_pri_table
 59struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
 60struct __collate_st_chain_pri *__collate_chain_pri_table;
 61
 62int chain_index = 0;
 63int prim_pri = 1, sec_pri = 1;
 64#ifdef COLLATE_DEBUG
 65int debug;
 66#endif
 67
 68const char *out_file = "LC_COLLATE";
 69%}
 70%union {
 71	u_char ch;
 72	u_char str[BUFSIZE];
 73}
 74%token SUBSTITUTE WITH ORDER RANGE
 75%token <str> STRING
 76%token <str> DEFN
 77%token <ch> CHAR
 78%%
 79collate : statment_list
 80;
 81statment_list : statment
 82	| statment_list '\n' statment
 83;
 84statment :
 85	| charmap
 86	| substitute
 87	| order
 88;
 89charmap : DEFN CHAR {
 90	if (strlen($1) + 1 > CHARMAP_SYMBOL_LEN)
 91		yyerror("Charmap symbol name '%s' is too long", $1);
 92	strcpy(charmap_table[$2], $1);
 93}
 94;
 95substitute : SUBSTITUTE CHAR WITH STRING {
 96	if ($2 == '\0')
 97		yyerror("NUL character can't be substituted");
 98	if (strchr($4, $2) != NULL)
 99		yyerror("Char 0x%02x substitution is recursive", $2);
100	if (strlen($4) + 1 > STR_LEN)
101		yyerror("Char 0x%02x substitution is too long", $2);
102	strcpy(__collate_substitute_table[$2], $4);
103}
104;
105order : ORDER order_list {
106	FILE *fp;
107	int ch, substed, ordered;
108	uint32_t u32;
109
110	for (ch = 0; ch < UCHAR_MAX + 1; ch++) {
111		substed = (__collate_substitute_table[ch][0] != ch);
112		ordered = !!__collate_char_pri_table[ch].prim;
113		if (!ordered && !substed)
114			yyerror("Char 0x%02x not found", ch);
115		if (substed && ordered)
116			yyerror("Char 0x%02x can't be ordered since substituted", ch);
117	}
118
119	if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table,
120	     sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL)
121		yyerror("can't grow chain table");
122	(void)memset(&__collate_chain_pri_table[chain_index], 0,
123		     sizeof(__collate_chain_pri_table[0]));
124	chain_index++;
125
126#ifdef COLLATE_DEBUG
127	if (debug)
128		collate_print_tables();
129#endif
130	if ((fp = fopen(out_file, "w")) == NULL)
131		err(EX_UNAVAILABLE, "can't open destination file %s",
132		    out_file);
133
134	strcpy(__collate_version, COLLATE_VERSION1_2);
135	if (fwrite(__collate_version, sizeof(__collate_version), 1, fp) != 1)
136		err(EX_IOERR,
137		"IO error writting collate version to destination file %s",
138		    out_file);
139	u32 = htonl(chain_index);
140	if (fwrite(&u32, sizeof(u32), 1, fp) != 1)
141		err(EX_IOERR,
142		"IO error writting chains number to destination file %s",
143		    out_file);
144	if (fwrite(__collate_substitute_table,
145		   sizeof(__collate_substitute_table), 1, fp) != 1)
146		err(EX_IOERR,
147		"IO error writting substitute table to destination file %s",
148		    out_file);
149	for (ch = 0; ch < UCHAR_MAX + 1; ch++) {
150		__collate_char_pri_table[ch].prim =
151		    htonl(__collate_char_pri_table[ch].prim);
152		__collate_char_pri_table[ch].sec =
153		    htonl(__collate_char_pri_table[ch].sec);
154	}
155	if (fwrite(__collate_char_pri_table,
156		   sizeof(__collate_char_pri_table), 1, fp) != 1)
157		err(EX_IOERR,
158		"IO error writting char table to destination file %s",
159		    out_file);
160	for (ch = 0; ch < chain_index; ch++) {
161		__collate_chain_pri_table[ch].prim =
162		    htonl(__collate_chain_pri_table[ch].prim);
163		__collate_chain_pri_table[ch].sec =
164		    htonl(__collate_chain_pri_table[ch].sec);
165	}
166	if (fwrite(__collate_chain_pri_table,
167		   sizeof(*__collate_chain_pri_table), chain_index, fp) !=
168		   (size_t)chain_index)
169		err(EX_IOERR,
170		"IO error writting chain table to destination file %s",
171		    out_file);
172	if (fclose(fp) != 0)
173		err(EX_IOERR, "IO error closing destination file %s",
174		    out_file);
175	exit(EX_OK);
176}
177;
178order_list : item
179	| order_list ';' item
180;
181chain : CHAR CHAR {
182	curr_chain[0] = $1;
183	curr_chain[1] = $2;
184	if (curr_chain[0] == '\0' || curr_chain[1] == '\0')
185		yyerror("\\0 can't be chained");
186	curr_chain[2] = '\0';
187}
188	| chain CHAR {
189	static char tb[2];
190
191	tb[0] = $2;
192	if (tb[0] == '\0')
193		yyerror("\\0 can't be chained");
194	if (strlen(curr_chain) + 2 > STR_LEN)
195		yyerror("Chain '%s' grows too long", curr_chain);
196	(void)strcat(curr_chain, tb);
197}
198;
199item :  CHAR {
200	if (__collate_char_pri_table[$1].prim)
201		yyerror("Char 0x%02x duplicated", $1);
202	__collate_char_pri_table[$1].prim = prim_pri++;
203}
204	| chain {
205	if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table,
206	     sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL)
207		yyerror("can't grow chain table");
208	(void)memset(&__collate_chain_pri_table[chain_index], 0,
209		     sizeof(__collate_chain_pri_table[0]));
210	(void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain);
211	__collate_chain_pri_table[chain_index].prim = prim_pri++;
212	chain_index++;
213}
214	| CHAR RANGE CHAR {
215	u_int i;
216
217	if ($3 <= $1)
218		yyerror("Illegal range 0x%02x -- 0x%02x", $1, $3);
219
220	for (i = $1; i <= $3; i++) {
221		if (__collate_char_pri_table[(u_char)i].prim)
222			yyerror("Char 0x%02x duplicated", (u_char)i);
223		__collate_char_pri_table[(u_char)i].prim = prim_pri++;
224	}
225}
226	| '{' prim_order_list '}' {
227	prim_pri++;
228}
229	| '(' sec_order_list ')' {
230	prim_pri++;
231	sec_pri = 1;
232}
233;
234prim_order_list : prim_sub_item
235	| prim_order_list ',' prim_sub_item 
236;
237sec_order_list : sec_sub_item
238	| sec_order_list ',' sec_sub_item 
239;
240prim_sub_item : CHAR {
241	if (__collate_char_pri_table[$1].prim)
242		yyerror("Char 0x%02x duplicated", $1);
243	__collate_char_pri_table[$1].prim = prim_pri;
244}
245	| CHAR RANGE CHAR {
246	u_int i;
247
248	if ($3 <= $1)
249		yyerror("Illegal range 0x%02x -- 0x%02x",
250			$1, $3);
251
252	for (i = $1; i <= $3; i++) {
253		if (__collate_char_pri_table[(u_char)i].prim)
254			yyerror("Char 0x%02x duplicated", (u_char)i);
255		__collate_char_pri_table[(u_char)i].prim = prim_pri;
256	}
257}
258	| chain {
259	if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table,
260	     sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL)
261		yyerror("can't grow chain table");
262	(void)memset(&__collate_chain_pri_table[chain_index], 0,
263		     sizeof(__collate_chain_pri_table[0]));
264	(void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain);
265	__collate_chain_pri_table[chain_index].prim = prim_pri;
266	chain_index++;
267}
268;
269sec_sub_item : CHAR {
270	if (__collate_char_pri_table[$1].prim)
271		yyerror("Char 0x%02x duplicated", $1);
272	__collate_char_pri_table[$1].prim = prim_pri;
273	__collate_char_pri_table[$1].sec = sec_pri++;
274}
275	| CHAR RANGE CHAR {
276	u_int i;
277
278	if ($3 <= $1)
279		yyerror("Illegal range 0x%02x -- 0x%02x",
280			$1, $3);
281
282	for (i = $1; i <= $3; i++) {
283		if (__collate_char_pri_table[(u_char)i].prim)
284			yyerror("Char 0x%02x duplicated", (u_char)i);
285		__collate_char_pri_table[(u_char)i].prim = prim_pri;
286		__collate_char_pri_table[(u_char)i].sec = sec_pri++;
287	}
288}
289	| chain {
290	if ((__collate_chain_pri_table = realloc(__collate_chain_pri_table,
291	     sizeof(*__collate_chain_pri_table) * (chain_index + 1))) == NULL)
292		yyerror("can't grow chain table");
293	(void)memset(&__collate_chain_pri_table[chain_index], 0,
294		     sizeof(__collate_chain_pri_table[0]));
295	(void)strcpy(__collate_chain_pri_table[chain_index].str, curr_chain);
296	__collate_chain_pri_table[chain_index].prim = prim_pri;
297	__collate_chain_pri_table[chain_index].sec = sec_pri++;
298	chain_index++;
299}
300;
301%%
302int
303main(int ac, char **av)
304{
305	int ch;
306
307#ifdef COLLATE_DEBUG
308	while((ch = getopt(ac, av, ":do:I:")) != -1) {
309#else
310	while((ch = getopt(ac, av, ":o:I:")) != -1) {
311#endif
312		switch (ch)
313		{
314#ifdef COLLATE_DEBUG
315		  case 'd':
316			debug++;
317			break;
318#endif
319		  case 'o':
320			out_file = optarg;
321			break;
322
323		  case 'I':
324			strlcpy(map_name, optarg, sizeof(map_name));
325			break;
326
327		  default:
328			usage();
329		}
330	}
331	ac -= optind;
332	av += optind;
333	if (ac > 0) {
334		if ((yyin = fopen(*av, "r")) == NULL)
335			err(EX_UNAVAILABLE, "can't open source file %s", *av);
336	}
337	for (ch = 0; ch <= UCHAR_MAX; ch++)
338		__collate_substitute_table[ch][0] = ch;
339	yyparse();
340	return 0;
341}
342
343static void
344usage(void)
345{
346	fprintf(stderr, "usage: colldef [-I map_dir] [-o out_file] [filename]\n");
347	exit(EX_USAGE);
348}
349
350void
351yyerror(const char *fmt, ...)
352{
353	va_list ap;
354	char msg[128];
355
356	va_start(ap, fmt);
357	vsnprintf(msg, sizeof(msg), fmt, ap);
358	va_end(ap);
359	errx(EX_UNAVAILABLE, "%s near line %d", msg, line_no);
360}
361
362#ifdef COLLATE_DEBUG
363static void
364collate_print_tables(void)
365{
366	int i;
367
368	printf("Substitute table:\n");
369	for (i = 0; i < UCHAR_MAX + 1; i++)
370	    if (i != *__collate_substitute_table[i])
371		printf("\t'%c' --> \"%s\"\n", i,
372		       __collate_substitute_table[i]);
373	printf("Chain priority table:\n");
374	for (i = 0; i < chain_index - 1; i++)
375		printf("\t\"%s\" : %d %d\n",
376		    __collate_chain_pri_table[i].str,
377		    __collate_chain_pri_table[i].prim,
378		    __collate_chain_pri_table[i].sec);
379	printf("Char priority table:\n");
380	for (i = 0; i < UCHAR_MAX + 1; i++)
381		printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
382		       __collate_char_pri_table[i].sec);
383}
384#endif