1 /* asn1-gentables.c - Tool to create required ASN tables
2 * Copyright (C) 2001, 2008 g10 Code GmbH
4 * This file is part of KSBA.
6 * KSBA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * KSBA is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 #include "asn1-func.h"
29 #define PGMNAME "asn1-gentables"
31 #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
32 # define ATTR_PRINTF(a,b) __attribute__ ((format (printf,a,b)))
34 # define ATTR_PRINTF(a,b)
38 #define DEVNULL_NAME "nul"
40 #define DEVNULL_NAME "/dev/null"
44 /* keep track of parsing error */
45 static int error_counter;
50 static int check_only;
53 struct name_list_s *next;
57 static struct name_list_s *string_table, **string_table_tail;
58 static size_t string_table_offset;
60 static void print_error (const char *fmt, ... ) ATTR_PRINTF(1,2);
64 print_error (const char *fmt, ... )
68 va_start (arg_ptr, fmt);
69 fputs (PGMNAME ": ", stderr);
70 vfprintf (stderr, fmt, arg_ptr);
77 insert_string (const char *name)
79 struct name_list_s *item;
82 if (!string_table_tail)
84 string_table_tail = &string_table;
88 if (string_table_offset && !*name)
91 for (item = string_table,off = 0; item; item = item->next)
93 for (n=0; item->name[n]; n++)
94 if (!strcmp (item->name+n, name))
96 off += strlen (item->name) + 1;
99 item = xmalloc ( sizeof *item + strlen (name));
100 strcpy (item->name, name);
102 *string_table_tail = item;
103 string_table_tail = &item->next;
104 off = string_table_offset;
105 string_table_offset += strlen (name) + 1;
110 cmp_string (const void *aptr, const void *bptr)
112 const char *a = (*(const struct name_list_s **)aptr)->name;
113 const char *b = (*(const struct name_list_s **)bptr)->name;
115 const size_t len_a = strlen(a);
116 const size_t len_b = strlen(b);
126 sort_string_table (void)
128 struct name_list_s *item;
129 struct name_list_s **array;
132 if (!string_table || !string_table->next)
133 return; /* Nothing to sort. */
135 for (item = string_table,arraylen = 0; item; item = item->next)
137 array = xcalloc (arraylen, sizeof *array);
138 for (item = string_table,arraylen = 0; item; item = item->next)
139 array[arraylen++] = item;
140 qsort (array, arraylen, sizeof *array, cmp_string);
141 /* Replace table by sorted one. */
142 string_table_tail = NULL;
144 string_table_offset = 0;
145 for (i=0; i < arraylen; i++)
146 insert_string (array[i]->name);
148 /* for (item = string_table,arraylen = 0; item; item = item->next) */
149 /* fprintf (stderr, " `%s'\n", item->name); */
154 write_string_table (FILE *fp)
156 struct name_list_s *item;
164 fputs ("static const char string_table[] = {\n ", fp);
165 for (item = string_table; item; item = item->next)
167 for (s=item->name, pos=0; *s; s++)
170 fprintf (fp, "%s ", pos>1? "\n":"");
171 fprintf (fp, "'%c',", *s);
173 fputs ("'\\0',\n", fp);
176 /* (we use an extra \0 to get rid of the last comma) */
177 fprintf (fp, " '\\0' };\n/* (%d strings) */\n", count);
181 static struct name_list_s *
182 create_static_structure (AsnNode pointer, const char *file_name, FILE *fp)
185 struct name_list_s *structure_name;
186 const char *char_p, *slash_p, *dot_p;
191 while ((char_p = strchr (char_p, '/')))
198 dot_p = file_name + strlen (file_name);
200 while ((char_p = strchr (char_p, '.')))
206 structure_name = xmalloc (sizeof *structure_name + dot_p - slash_p + 100);
207 structure_name->next = NULL;
208 memcpy (structure_name->name, slash_p, dot_p - slash_p);
209 structure_name->name[dot_p - slash_p] = 0;
211 fprintf (fp, "static const static_asn %s_asn1_tab[] = {\n",
212 structure_name->name);
214 for (p = pointer; p; p = _ksba_asn_walk_tree (pointer, p))
216 /* set the help flags */
217 p->flags.help_down = !!p->down;
218 p->flags.help_right = !!p->right;
220 /* write a structure line */
223 fprintf (fp, "%u", (unsigned int)insert_string (p->name));
226 fprintf (fp, ",%u", p->type);
229 fprintf (fp, "%u", p->flags.class);
230 fputs (p->flags.explicit ? ",1":",0", fp);
231 fputs (p->flags.implicit ? ",1":",0", fp);
232 fputs (p->flags.has_imports ? ",1":",0", fp);
233 fputs (p->flags.assignment ? ",1":",0", fp);
234 fputs (p->flags.one_param ? ",1":",0", fp);
235 fputs (p->flags.has_tag ? ",1":",0", fp);
236 fputs (p->flags.has_size ? ",1":",0", fp);
237 fputs (p->flags.has_list ? ",1":",0", fp);
238 fputs (p->flags.has_min_max ? ",1":",0", fp);
239 fputs (p->flags.has_defined_by ? ",1":",0", fp);
240 fputs (p->flags.is_false ? ",1":",0", fp);
241 fputs (p->flags.is_true ? ",1":",0", fp);
242 fputs (p->flags.has_default ? ",1":",0", fp);
243 fputs (p->flags.is_optional ? ",1":",0", fp);
244 fputs (p->flags.is_implicit ? ",1":",0", fp);
245 fputs (p->flags.in_set ? ",1":",0", fp);
246 fputs (p->flags.in_choice ? ",1":",0", fp);
247 fputs (p->flags.in_array ? ",1":",0", fp);
248 fputs (p->flags.is_any ? ",1":",0", fp);
249 fputs (p->flags.not_used ? ",1":",0", fp);
250 fputs (p->flags.help_down ? ",1":",0", fp);
251 fputs (p->flags.help_right ? ",1":",0", fp);
254 if (p->valuetype == VALTYPE_CSTR)
256 (unsigned int)insert_string (p->value.v_cstr));
257 else if (p->valuetype == VALTYPE_LONG
258 && p->type == TYPE_INTEGER && p->flags.assignment)
260 snprintf (numbuf, sizeof numbuf, "%ld", p->value.v_long);
261 fprintf (fp, ",%u", (unsigned int)insert_string (numbuf));
263 else if (p->valuetype == VALTYPE_ULONG)
265 snprintf (numbuf, sizeof numbuf, "%lu", p->value.v_ulong);
266 fprintf (fp, ",%u", (unsigned int)insert_string (numbuf));
271 print_error ("can't store a value of type %d\n", p->valuetype);
277 fprintf (fp, " {0,0}\n};\n");
279 return structure_name;
284 static struct name_list_s *
285 one_file (const char *fname, int *count, FILE *fp)
287 ksba_asn_tree_t tree;
290 rc = ksba_asn_parse_file (fname, &tree, check_only);
292 print_error ("error parsing `%s': %s\n", fname, gpg_strerror (rc) );
293 else if (!check_only)
296 ksba_asn_tree_dump (tree, dump_only==2? "<":NULL, fp);
301 "#include <config.h>\n"
302 "#include <stdio.h>\n"
303 "#include <string.h>\n"
304 "#include \"ksba.h\"\n"
305 "#include \"asn1-func.h\"\n"
308 return create_static_structure (tree->parse_tree, fname, fp);
316 main (int argc, char **argv)
319 struct name_list_s *all_names = NULL, *nl;
322 if (!argc || (argc > 1 &&
323 (!strcmp (argv[1],"--help") || !strcmp (argv[1],"-h"))) )
325 fputs ("usage: asn1-gentables [--check] [--dump[-expanded]] [files.asn]\n",
331 if (argc && !strcmp (*argv,"--check"))
336 else if (argc && !strcmp (*argv,"--dump"))
341 else if (argc && !strcmp (*argv,"--dump-expanded"))
349 all_names = one_file ("-", &count, stdout);
354 /* We first parse it to /dev/null to build up the string table. */
355 nullfp = fopen (DEVNULL_NAME, "w");
358 print_error ("can't open `%s': %s\n", DEVNULL_NAME, strerror (errno));
361 for (i=0; i < argc; i++)
362 one_file (argv[i], &count, nullfp);
365 sort_string_table ();
368 for (; argc; argc--, argv++)
370 nl = one_file (*argv, &count, stdout);
373 nl->next = all_names;
379 if (all_names && !error_counter)
381 /* Write the string table. */
383 write_string_table (stdout);
384 /* Write the lookup function */
385 printf ("\n\nconst static_asn *\n"
386 "_ksba_asn_lookup_table (const char *name,"
387 " const char **stringtbl)\n"
389 " *stringtbl = string_table;\n"
391 for (nl=all_names; nl; nl = nl->next)
392 printf (" if (!strcmp (name, \"%s\"))\n"
393 " return %s_asn1_tab;\n", nl->name, nl->name);
394 printf ("\n return NULL;\n}\n");
397 return error_counter? 1:0;