libksba  1.6.0
About: KSBA is a library to make the tasks of working with X.509 certificates, CMS data and related objects more easy.
  Fossies Dox: libksba-1.6.0.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

asn1-gentables.c
Go to the documentation of this file.
1 /* asn1-gentables.c - Tool to create required ASN tables
2  * Copyright (C) 2001, 2008 g10 Code GmbH
3  *
4  * This file is part of KSBA.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <stdarg.h>
25 
26 #include "gen-help.h"
27 #include "asn1-func.h"
28 
29 #define PGMNAME "asn1-gentables"
30 
31 #if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ))
32 # define ATTR_PRINTF(a,b) __attribute__ ((format (printf,a,b)))
33 #else
34 # define ATTR_PRINTF(a,b)
35 #endif
36 
37 #ifdef _WIN32
38 #define DEVNULL_NAME "nul"
39 #else
40 #define DEVNULL_NAME "/dev/null"
41 #endif
42 
43 
44 /* keep track of parsing error */
45 static int error_counter;
46 
47 /* option --dump */
48 static int dump_only;
49 /* option --check */
50 static int check_only;
51 
52 struct name_list_s {
53  struct name_list_s *next;
54  char name[1];
55 };
56 
58 static size_t string_table_offset;
59 
60 static void print_error (const char *fmt, ... ) ATTR_PRINTF(1,2);
61 
62 
63 static void
64 print_error (const char *fmt, ... )
65 {
66  va_list arg_ptr ;
67 
68  va_start (arg_ptr, fmt);
69  fputs (PGMNAME ": ", stderr);
70  vfprintf (stderr, fmt, arg_ptr);
71  va_end (arg_ptr);
72  error_counter++;
73 
74 }
75 
76 static size_t
77 insert_string (const char *name)
78 {
79  struct name_list_s *item;
80  size_t off, n;
81 
82  if (!string_table_tail)
83  {
85  insert_string ("");
86  }
87 
88  if (string_table_offset && !*name)
89  return 0;
90 
91  for (item = string_table,off = 0; item; item = item->next)
92  {
93  for (n=0; item->name[n]; n++)
94  if (!strcmp (item->name+n, name))
95  return off + n;
96  off += strlen (item->name) + 1;
97  }
98 
99  item = xmalloc ( sizeof *item + strlen (name));
100  strcpy (item->name, name);
101  item->next = NULL;
102  *string_table_tail = item;
103  string_table_tail = &item->next;
104  off = string_table_offset;
105  string_table_offset += strlen (name) + 1;
106  return off;
107 }
108 
109 static int
110 cmp_string (const void *aptr, const void *bptr)
111 {
112  const char *a = (*(const struct name_list_s **)aptr)->name;
113  const char *b = (*(const struct name_list_s **)bptr)->name;
114 
115  const size_t len_a = strlen(a);
116  const size_t len_b = strlen(b);
117 
118  if (len_a < len_b)
119  return -1;
120  if (len_a > len_b)
121  return +1;
122  return strcmp(a, b);
123 }
124 
125 static void
127 {
128  struct name_list_s *item;
129  struct name_list_s **array;
130  size_t i, arraylen;
131 
132  if (!string_table || !string_table->next)
133  return; /* Nothing to sort. */
134 
135  for (item = string_table,arraylen = 0; item; item = item->next)
136  arraylen++;
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;
143  string_table = NULL;
145  for (i=0; i < arraylen; i++)
146  insert_string (array[i]->name);
147  xfree (array);
148  /* for (item = string_table,arraylen = 0; item; item = item->next) */
149  /* fprintf (stderr, " `%s'\n", item->name); */
150 }
151 
152 
153 static void
155 {
156  struct name_list_s *item;
157  const char *s;
158  int count = 0;
159  int pos;
160 
161  if (!string_table)
162  insert_string ("");
163 
164  fputs ("static const char string_table[] = {\n ", fp);
165  for (item = string_table; item; item = item->next)
166  {
167  for (s=item->name, pos=0; *s; s++)
168  {
169  if (!(pos++ % 16))
170  fprintf (fp, "%s ", pos>1? "\n":"");
171  fprintf (fp, "'%c',", *s);
172  }
173  fputs ("'\\0',\n", fp);
174  count++;
175  }
176  /* (we use an extra \0 to get rid of the last comma) */
177  fprintf (fp, " '\\0' };\n/* (%d strings) */\n", count);
178 }
179 
180 
181 static struct name_list_s *
182 create_static_structure (AsnNode pointer, const char *file_name, FILE *fp)
183 {
184  AsnNode p;
185  struct name_list_s *structure_name;
186  const char *char_p, *slash_p, *dot_p;
187  char numbuf[50];
188 
189  char_p = file_name;
190  slash_p = file_name;
191  while ((char_p = strchr (char_p, '/')))
192  {
193  char_p++;
194  slash_p = char_p;
195  }
196 
197  char_p = slash_p;
198  dot_p = file_name + strlen (file_name);
199 
200  while ((char_p = strchr (char_p, '.')))
201  {
202  dot_p = char_p;
203  char_p++;
204  }
205 
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;
210 
211  fprintf (fp, "static const static_asn %s_asn1_tab[] = {\n",
212  structure_name->name);
213 
214  for (p = pointer; p; p = _ksba_asn_walk_tree (pointer, p))
215  {
216  /* set the help flags */
217  p->flags.help_down = !!p->down;
218  p->flags.help_right = !!p->right;
219 
220  /* write a structure line */
221  fputs (" {", fp);
222  if (p->name)
223  fprintf (fp, "%u", (unsigned int)insert_string (p->name));
224  else
225  fprintf (fp, "0");
226  fprintf (fp, ",%u", p->type);
227 
228  fputs (", {", fp);
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);
252  fputs ("}", fp);
253 
254  if (p->valuetype == VALTYPE_CSTR)
255  fprintf (fp, ",%u",
256  (unsigned int)insert_string (p->value.v_cstr));
257  else if (p->valuetype == VALTYPE_LONG
258  && p->type == TYPE_INTEGER && p->flags.assignment)
259  {
260  snprintf (numbuf, sizeof numbuf, "%ld", p->value.v_long);
261  fprintf (fp, ",%u", (unsigned int)insert_string (numbuf));
262  }
263  else if (p->valuetype == VALTYPE_ULONG)
264  {
265  snprintf (numbuf, sizeof numbuf, "%lu", p->value.v_ulong);
266  fprintf (fp, ",%u", (unsigned int)insert_string (numbuf));
267  }
268  else
269  {
270  if (p->valuetype)
271  print_error ("can't store a value of type %d\n", p->valuetype);
272  fprintf (fp, ",0");
273  }
274  fputs ("},\n", fp);
275  }
276 
277  fprintf (fp, " {0,0}\n};\n");
278 
279  return structure_name;
280 }
281 
282 
283 
284 static struct name_list_s *
285 one_file (const char *fname, int *count, FILE *fp)
286 {
287  ksba_asn_tree_t tree;
288  int rc;
289 
290  rc = ksba_asn_parse_file (fname, &tree, check_only);
291  if (rc)
292  print_error ("error parsing `%s': %s\n", fname, gpg_strerror (rc) );
293  else if (!check_only)
294  {
295  if (dump_only)
296  ksba_asn_tree_dump (tree, dump_only==2? "<":NULL, fp);
297  else
298  {
299  if (!*count)
300  fprintf (fp,"\n"
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"
306  "\n");
307  ++*count;
308  return create_static_structure (tree->parse_tree, fname, fp);
309  }
310  }
311  return 0;
312 }
313 
314 
315 int
316 main (int argc, char **argv)
317 {
318  int count = 0;
319  struct name_list_s *all_names = NULL, *nl;
320  int i;
321 
322  if (!argc || (argc > 1 &&
323  (!strcmp (argv[1],"--help") || !strcmp (argv[1],"-h"))) )
324  {
325  fputs ("usage: asn1-gentables [--check] [--dump[-expanded]] [files.asn]\n",
326  stderr);
327  return 0;
328  }
329 
330  argc--; argv++;
331  if (argc && !strcmp (*argv,"--check"))
332  {
333  argc--; argv++;
334  check_only = 1;
335  }
336  else if (argc && !strcmp (*argv,"--dump"))
337  {
338  argc--; argv++;
339  dump_only = 1;
340  }
341  else if (argc && !strcmp (*argv,"--dump-expanded"))
342  {
343  argc--; argv++;
344  dump_only = 2;
345  }
346 
347 
348  if (!argc)
349  all_names = one_file ("-", &count, stdout);
350  else
351  {
352  FILE *nullfp;
353 
354  /* We first parse it to /dev/null to build up the string table. */
355  nullfp = fopen (DEVNULL_NAME, "w");
356  if (!nullfp)
357  {
358  print_error ("can't open `%s': %s\n", DEVNULL_NAME, strerror (errno));
359  exit (2);
360  }
361  for (i=0; i < argc; i++)
362  one_file (argv[i], &count, nullfp);
363  fclose (nullfp);
364 
366 
367  count = 0;
368  for (; argc; argc--, argv++)
369  {
370  nl = one_file (*argv, &count, stdout);
371  if (nl)
372  {
373  nl->next = all_names;
374  all_names = nl;
375  }
376  }
377  }
378 
379  if (all_names && !error_counter)
380  {
381  /* Write the string table. */
382  putchar ('\n');
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"
388  "{\n"
389  " *stringtbl = string_table;\n"
390  );
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");
395  }
396 
397  return error_counter? 1:0;
398 }
@ TYPE_INTEGER
AsnNode _ksba_asn_walk_tree(AsnNode root, AsnNode node)
Definition: asn1-func.c:790
@ VALTYPE_CSTR
Definition: asn1-func.h:71
@ VALTYPE_ULONG
Definition: asn1-func.h:74
@ VALTYPE_LONG
Definition: asn1-func.h:73
static int dump_only
int main(int argc, char **argv)
static int check_only
static void write_string_table(FILE *fp)
static struct name_list_s * string_table
static struct name_list_s * create_static_structure(AsnNode pointer, const char *file_name, FILE *fp)
static void sort_string_table(void)
#define PGMNAME
static int cmp_string(const void *aptr, const void *bptr)
static int error_counter
static struct name_list_s ** string_table_tail
#define ATTR_PRINTF(a, b)
static size_t string_table_offset
static size_t insert_string(const char *name)
#define DEVNULL_NAME
static struct name_list_s * one_file(const char *fname, int *count, FILE *fp)
static void print_error(const char *fmt,...)
const char * name
Definition: dn.c:47
const char * gpg_strerror(int err)
Definition: gen-help.c:98
union asn_value_u value
Definition: asn1-func.h:104
AsnNode right
Definition: asn1-func.h:111
enum asn_value_type valuetype
Definition: asn1-func.h:103
AsnNode down
Definition: asn1-func.h:110
node_type_t type
Definition: asn1-func.h:100
struct node_flag_s flags
Definition: asn1-func.h:101
AsnNode parse_tree
Definition: asn1-func.h:118
char name[1]
struct name_list_s * next
int one_param
Definition: asn1-func.h:45
int in_array
Definition: asn1-func.h:58
int in_choice
Definition: asn1-func.h:57
int has_tag
Definition: asn1-func.h:46
int implicit
Definition: asn1-func.h:42
int has_list
Definition: asn1-func.h:48
enum tag_class class
Definition: asn1-func.h:40
int is_optional
Definition: asn1-func.h:54
int has_size
Definition: asn1-func.h:47
int not_used
Definition: asn1-func.h:61
int help_down
Definition: asn1-func.h:62
int has_imports
Definition: asn1-func.h:43
int is_false
Definition: asn1-func.h:51
int in_set
Definition: asn1-func.h:56
int has_default
Definition: asn1-func.h:53
int help_right
Definition: asn1-func.h:63
int explicit
Definition: asn1-func.h:41
int assignment
Definition: asn1-func.h:44
int is_implicit
Definition: asn1-func.h:55
int has_defined_by
Definition: asn1-func.h:50
int has_min_max
Definition: asn1-func.h:49
int is_true
Definition: asn1-func.h:52
int is_any
Definition: asn1-func.h:59
long v_long
Definition: asn1-func.h:84
char * v_cstr
Definition: asn1-func.h:79
unsigned long v_ulong
Definition: asn1-func.h:85
#define xfree(a)
Definition: util.h:58
#define xcalloc(a, b)
Definition: util.h:61
#define xmalloc(a)
Definition: util.h:60
#define ksba_asn_tree_dump
Definition: visibility.h:45
#define ksba_asn_parse_file
Definition: visibility.h:44