xref: /freebsd/contrib/libucl/utils/chargen.c (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1 /* Copyright (c) 2013, Vsevolod Stakhov
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *       * Redistributions of source code must retain the above copyright
7  *         notice, this list of conditions and the following disclaimer.
8  *       * Redistributions in binary form must reproduce the above copyright
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 /**
25  * @file this utility generates character table for ucl
26  */
27 
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <stdbool.h>
31 
32 static inline int
33 print_flag (const char *flag, bool *need_or, char *val)
34 {
35 	int res;
36 	res = sprintf (val, "%s%s", *need_or ? "|" : "", flag);
37 
38 	*need_or |= true;
39 
40 	return res;
41 }
42 
43 int
44 main (int argc, char **argv)
45 {
46 	int i, col, r;
47 	const char *name = "ucl_chartable";
48 	bool need_or;
49 	char valbuf[2048];
50 
51 	col = 0;
52 
53 	if (argc > 1) {
54 		name = argv[1];
55 	}
56 
57 	printf ("static const unsigned int %s[256] = {\n", name);
58 
59 	for (i = 0; i < 256; i ++) {
60 		need_or = false;
61 		r = 0;
62 		/* UCL_CHARACTER_VALUE_END */
63 
64 		if (i == ' ' || i == '\t') {
65 			r += print_flag ("UCL_CHARACTER_WHITESPACE", &need_or, valbuf + r);
66 		}
67 		if (isspace (i)) {
68 			r += print_flag ("UCL_CHARACTER_WHITESPACE_UNSAFE", &need_or, valbuf + r);
69 		}
70 		if (isalnum (i) || i >= 0x80 || i == '/' || i == '_') {
71 			r += print_flag ("UCL_CHARACTER_KEY_START", &need_or, valbuf + r);
72 		}
73 		if (isalnum (i) || i == '-' || i == '_' || i == '/' || i == '.' || i >= 0x80) {
74 			r += print_flag ("UCL_CHARACTER_KEY", &need_or, valbuf + r);
75 		}
76 		if (i == 0 || i == '\r' || i == '\n' || i == ']' || i == '}' || i == ';' || i == ',' || i == '#') {
77 			r += print_flag ("UCL_CHARACTER_VALUE_END", &need_or, valbuf + r);
78 		}
79 		else {
80 			if (isprint (i) || i >= 0x80) {
81 				r += print_flag ("UCL_CHARACTER_VALUE_STR", &need_or, valbuf + r);
82 			}
83 			if (isdigit (i) || i == '-') {
84 				r += print_flag ("UCL_CHARACTER_VALUE_DIGIT_START", &need_or, valbuf + r);
85 			}
86 			if (isalnum (i) || i == '.' || i == '-' || i == '+') {
87 				r += print_flag ("UCL_CHARACTER_VALUE_DIGIT", &need_or, valbuf + r);
88 			}
89 		}
90 		if (i == '"' || i == '\\' || i == '/' || i == 'b' ||
91 			i == 'f' || i == 'n' || i == 'r' || i == 't' || i == 'u') {
92 			r += print_flag ("UCL_CHARACTER_ESCAPE", &need_or, valbuf + r);
93 		}
94 		if (i == ' ' || i == '\t' || i == ':' || i == '=') {
95 			r += print_flag ("UCL_CHARACTER_KEY_SEP", &need_or, valbuf + r);
96 		}
97 		if (i == '\n' || i == '\r' || i == '\\' || i == '\b' || i == '\t' ||
98 				i == '"' || i == '\f') {
99 			r += print_flag ("UCL_CHARACTER_JSON_UNSAFE", &need_or, valbuf + r);
100 		}
101 		if (i == '\n' || i == '\r' || i == '\\' || i == '\b' || i == '\t' ||
102 				i == '"' || i == '\f' || i == '=' || i == ':' || i == '{' || i == '[' || i == ' ') {
103 			r += print_flag ("UCL_CHARACTER_UCL_UNSAFE", &need_or, valbuf + r);
104 		}
105 
106 		if (!need_or) {
107 			r += print_flag ("UCL_CHARACTER_DENIED", &need_or, valbuf + r);
108 		}
109 
110 		if (isprint (i)) {
111 			r += sprintf (valbuf + r, " /* %c */", i);
112 		}
113 		if (i != 255) {
114 			r += sprintf (valbuf + r, ", ");
115 		}
116 		col += r;
117 		if (col > 80) {
118 			printf ("\n%s", valbuf);
119 			col = r;
120 		}
121 		else {
122 			printf ("%s", valbuf);
123 		}
124 	}
125 	printf ("\n}\n");
126 
127 	return 0;
128 }
129