Use val_to_str_const().
[obnox/wireshark/wip.git] / epan / diam_dict.l
1 /*
2  * We don't read from the terminal.
3  */
4 %option never-interactive
5
6 /*
7  * The language we're scanning is case-insensitive.
8  */
9 %option caseless
10
11 /*
12  * We use start condition stacks.
13  */
14 %option stack
15
16 /*
17  * Prefix scanner routines with "DiamDict" rather than "yy", so this scanner
18  * can coexist with other scanners.
19  */
20 %option prefix="DiamDict"
21
22 %option outfile="diam_dict.c"
23
24 %{
25         /*
26          ** diam_dict.h
27          ** Diameter Dictionary Import Routines
28          **
29          ** $Id$
30          **
31          ** (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
32          **
33          ** This library is free software; you can redistribute it and/or
34          ** modify it under the terms of the GNU Library General Public
35          ** License as published by the Free Software Foundation; either
36          ** version 2 of the License, or (at your option) any later version.
37          **
38          ** This library is distributed in the hope that it will be useful,
39          ** but WITHOUT ANY WARRANTY; without even the implied warranty of
40          ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
41          ** Library General Public License for more details.
42          **
43          ** You should have received a copy of the GNU Library General Public
44          ** License along with this library; if not, write to the Free Software
45          ** Foundation, Inc., 51 Franklin Street, Fifth Floor,
46          ** Boston, MA  02110-1301, USA.
47          */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <glib.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <errno.h>
57 #include <stdlib.h>
58 #include <stdarg.h>
59 #include "diam_dict.h"
60 #include "diam_dict_lex.h"
61 #include <wsutil/file_util.h>
62
63 typedef struct entity_t {
64         char* name;
65         char* file;
66         struct entity_t* next;
67 } entity_t;
68
69 #define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); attr_uint = &(cont); yy_push_state(GET_UINT_ATTR); } while(0)
70 #define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); attr_str = &(cont); yy_push_state(GET_ATTR); } while(0)
71 #define IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR); } while(0)
72
73 #define D(args) ddict_debug args
74
75 #define MAX_INCLUDE_DEPTH 10
76 #define YY_INPUT(buf,result,max_size) { result = current_yyinput(buf,max_size); }
77 #define ECHO
78 #define APPEND(txt,len) append_to_buffer(txt,len)
79
80 static entity_t ents;
81 static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
82 static int include_stack_ptr = 0;
83 static size_t (*current_yyinput)(char*,size_t);
84 static const char* sys_dir;
85 static ddict_t* dict;
86 static ddict_application_t* appl;
87 static ddict_avp_t* avp;
88 static ddict_enum_t* enumitem;
89 static ddict_gavp_t* gavp;
90 static ddict_typedefn_t* typedefn;
91 static ddict_cmd_t* cmd;
92 static ddict_vendor_t* vnd;
93 static ddict_xmlpi_t* xmlpi;
94
95 static ddict_application_t* last_appl;
96 static ddict_avp_t* last_avp;
97 static ddict_enum_t* last_enumitem;
98 static ddict_gavp_t* last_gavp;
99 static ddict_typedefn_t* last_typedefn;
100 static ddict_cmd_t* last_cmd;
101 static ddict_vendor_t* last_vnd;
102 static ddict_xmlpi_t* last_xmlpi;
103
104 static char** attr_str;
105 static unsigned* attr_uint;
106
107 static void ddict_debug(const char* fmt, ...);
108 static void append_to_buffer(char* txt, int len);
109 static FILE* ddict_open(const char*, const char*);
110
111 %}
112
113
114 xmlpi_start [[:blank:] \r\n]*<\?[[:blank:] \r\n]*
115 xmlpi_end [[:blank:] \r\n]*\?>[[:blank:] \r\n]*
116 xmlpi_key_attr [[:blank:] \r\n]*key[[:blank:] \r\n]*=[[:blank:] \r\n]*\042
117 xmlpi_value_attr [[:blank:] \r\n]*value[[:blank:] \r\n]*=[[:blank:] \r\n]*\042
118
119 comment_start [[:blank:] \r\n]*<!--[[:blank:] \r\n]*
120 comment_end [[:blank:] \r\n]*-->[[:blank:] \r\n]*
121 open_tag [[:blank:] \r\n]*<[[:blank:] \r\n]*
122 end_tag [[:blank:] \r\n]*\/>[[:blank:] \r\n]*
123 close_tag [[:blank:] \r\n]*>[[:blank:] \r\n]*
124 open_closetag [[:blank:] \r\n]*<\/[[:blank:] \r\n]*
125 equals [[:blank:] \r\n]*=[[:blank:] \r\n]*
126 whitespace [[:blank:] \r\n]*
127 dquoted \042[^\042]*\042
128
129 doctype [[:blank:] \r\n]*<!DOCTYPE[^\[]*\[[[:blank:] \r\n]*
130 doctype_end [[:blank:] \r\n]*\][[:blank:] \r\n]*>[[:blank:] \r\n]*
131
132 start_entity [[:blank:] \r\n]*<\!ENTITY[[:blank:] \r\n]*
133 system [[:blank:] \r\n]*SYSTEM[[:blank:] \r\n]*\042
134 entityname [a-z0-9-]+
135 ndquot [^\042]+
136 end_entity \042[[:blank:] \r\n]*>[[:blank:] \r\n]*
137
138 entity \&[a-z0-9-]+;
139
140 any .
141
142
143
144
145 stop >
146 stop_end \/>
147 dquot \042
148 number [-]?[0-9]*
149
150 dictionary_start <dictionary>
151 dictionary_end <\/dictionary>
152
153 base_start <base[^>*]*>
154 base_end <\/base>
155
156 application_start <application
157 application_end<\/application>
158
159 command_start <command
160 command_end<\/command>
161
162 typedefn_start <typedefn
163
164 avp_start <avp
165 avp_end <\/avp>
166
167 type_start <type
168 enum_start <enum
169
170 grouped_start <grouped>
171 grouped_end <\/grouped>
172
173 vendor_start <vendor
174 gavp_start <gavp
175
176 ignored_attr [a-z0-9-]+=
177 ignored_quoted \042[^\042]*\042
178
179 name_attr name=\042
180 id_attr id=\042
181 code_attr code=\042
182 vendor_attr vendor-id=\042
183 typename_attr type-name=\042
184 typeparent_attr type-parent=\042
185 description_attr description=\042
186
187
188
189 %S LOADING LOADING_COMMENT LOADING_XMLPI ENTITY GET_SYSTEM GET_FILE END_ENTITY
190 %S GET_ATTR GET_UINT_ATTR END_ATTR OUTSIDE IN_DICT IN_APPL IN_AVP APPL_ATTRS IGNORE_ATTR
191 %S TYPE_ATTRS GAVP_ATTRS ENUM_ATTRS AVP_ATTRS VENDOR_ATTRS COMMAND_ATTRS TYPEDEFN_ATTRS
192 %S XMLPI_ATTRS XMLPI_GETKEY XMLPI_GETVAL XMLPI_ENDATTR
193 %%
194 <LOADING>{doctype} ;
195 <LOADING>{doctype_end} ;
196
197 <LOADING>{comment_start} BEGIN LOADING_COMMENT;
198 <LOADING_COMMENT>. ;
199 <LOADING_COMMENT>{comment_end} BEGIN LOADING;
200
201 <LOADING>{xmlpi_start} BEGIN LOADING_XMLPI;
202 <LOADING_XMLPI>{whitespace} ;
203 <LOADING_XMLPI>{entityname} {
204         xmlpi = g_malloc(sizeof(ddict_xmlpi_t));
205         xmlpi->name = g_strdup(yytext);
206         xmlpi->key = NULL;
207         xmlpi->value = NULL;
208         xmlpi->next = NULL;
209
210         if (!dict->xmlpis) last_xmlpi = dict->xmlpis = xmlpi;
211         else last_xmlpi = last_xmlpi->next = xmlpi;
212
213         BEGIN XMLPI_ATTRS;
214 }
215
216 <XMLPI_ATTRS>{xmlpi_key_attr} BEGIN XMLPI_GETKEY;
217 <XMLPI_GETKEY>{ndquot} { xmlpi->key = strdup(yytext); BEGIN XMLPI_ATTRS; }
218
219 <XMLPI_ATTRS>{xmlpi_value_attr} BEGIN XMLPI_GETVAL;
220 <XMLPI_GETVAL>{ndquot} { xmlpi->value = strdup(yytext); BEGIN XMLPI_ATTRS; }
221
222 <XMLPI_ATTRS>.
223 <XMLPI_ATTRS>{xmlpi_end} BEGIN LOADING;
224
225
226 <LOADING>{start_entity} BEGIN ENTITY;
227 <ENTITY>{entityname} {
228         entity_t* e = g_malloc(sizeof(entity_t));
229         e->name = strdup(yytext);
230         e->next = ents.next;
231         ents.next = e;
232         BEGIN GET_SYSTEM;
233         };
234 <GET_SYSTEM>{system} BEGIN GET_FILE;
235 <GET_FILE>{ndquot} {
236                 ents.next->file = strdup(yytext);
237                 BEGIN END_ENTITY;
238         }
239 <END_ENTITY>{end_entity} BEGIN LOADING;
240
241 <LOADING>{open_tag} APPEND("<",1);
242
243 <LOADING>{close_tag} APPEND(">",1);
244
245 <LOADING>{end_tag} APPEND("/>",2);
246
247 <LOADING>{open_closetag} APPEND("</",2);
248
249 <LOADING>{whitespace} APPEND(" ",1);
250
251 <LOADING>{dquoted} APPEND(yytext,yyleng);
252
253 <LOADING>{equals} APPEND("=",1);
254
255 <LOADING>{any} APPEND(yytext,yyleng);
256
257 <LOADING>{entity} {
258         char* p = ++yytext;
259         entity_t* e;
260
261         while(*p != ';') p++;
262
263         *p = '\0';
264
265         D(("looking for entity: %s\n",yytext));
266
267         if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
268                 fprintf(stderr, "included files nested to deeply\n");
269                 yyterminate();
270         }
271
272         for (e = ents.next; e; e = e->next) {
273                 if (strcmp(e->name,yytext) == 0) {
274                         yyin = ddict_open(sys_dir,e->file);
275                         D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,yyin));
276                         if (!yyin) {
277                                 if (errno) {
278                                         fprintf(stderr, "Could not open file: '%s', error: %s\n", e->file, g_strerror(errno) );
279                                         yyterminate();
280                                 }
281                         } else {
282                                 include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
283                                 yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
284                                 BEGIN LOADING;
285                         }
286                         break;
287                 }
288         }
289
290         if (!e) {
291                 fprintf(stderr, "Could not find entity: '%s'\n", yytext );
292                 yyterminate();
293         }
294
295 }
296
297 <<EOF>> {
298         if (!yyin) yyterminate();
299
300         fclose(yyin);
301         D(("closing: %p %i\n",yyin,include_stack_ptr));
302
303         if ( --include_stack_ptr < 0 ) {
304                 D(("DONE READING\n"));
305                 yyin = NULL;
306                 yyterminate();
307         } else {
308                 yy_delete_buffer( YY_CURRENT_BUFFER );
309                 yy_switch_to_buffer(include_stack[include_stack_ptr]);
310                 BEGIN LOADING;
311         }
312 }
313
314
315 <GET_ATTR>{ndquot} {
316         *attr_str = strdup(yytext);
317         D(("%s\n",yytext));
318         attr_str = NULL;
319         BEGIN END_ATTR;
320 }
321
322 <GET_UINT_ATTR>{number} {
323         *attr_uint = strtoul(yytext,NULL,10);
324         D(("%s\n",yytext););
325         attr_uint = NULL;
326         BEGIN END_ATTR;
327 }
328
329 <END_ATTR>{dquot} {     yy_pop_state(); }
330
331 <IGNORE_ATTR>. {
332         /* XXX: should go?*/
333         D(("{%s}",yytext));
334 }
335
336 <IGNORE_ATTR>{ignored_quoted} {
337         D(("=>%s<=\n",yytext));
338         yy_pop_state();
339 }
340
341 <OUTSIDE>{dictionary_start} {
342         D(("dictionary_start\n"));
343
344         BEGIN IN_DICT;
345 }
346
347 <IN_DICT>{base_start} {
348         D(("base_start\n"));
349         BEGIN IN_APPL;
350 }
351
352 <IN_DICT>{application_start} {
353         D(("application_start\n"));
354
355         appl = g_malloc(sizeof(ddict_application_t));
356         appl->name = NULL;
357         appl->code = 0;
358         appl->next = NULL;
359
360         if (!dict->applications) last_appl = dict->applications = appl;
361         else last_appl = last_appl->next = appl;
362
363         BEGIN APPL_ATTRS;
364 }
365
366 <APPL_ATTRS>{name_attr} { ATTR_STR(appl->name); }
367 <APPL_ATTRS>{id_attr} { ATTR_UINT(appl->code); }
368
369 <APPL_ATTRS>{stop} BEGIN IN_APPL;
370 <APPL_ATTRS>{stop_end} BEGIN IN_DICT;
371
372 <IN_APPL>{command_end}                  ;
373
374 <IN_APPL>{command_start}                {
375         D(("command_start\n"));
376
377         cmd = g_malloc(sizeof(ddict_cmd_t));
378         cmd->name = NULL;
379         cmd->vendor = NULL;
380         cmd->code = 0;
381         cmd->next = NULL;
382
383         if (!dict->cmds) last_cmd = dict->cmds = cmd;
384         else last_cmd = last_cmd->next = cmd;
385
386         BEGIN COMMAND_ATTRS;
387 }
388
389 <COMMAND_ATTRS>{name_attr}              { ATTR_STR(cmd->name); }
390 <COMMAND_ATTRS>{vendor_attr}    { ATTR_STR(cmd->vendor); }
391 <COMMAND_ATTRS>{code_attr}              { ATTR_UINT(cmd->code); }
392 <COMMAND_ATTRS>{stop}                   |
393 <COMMAND_ATTRS>{stop_end}               { BEGIN IN_APPL; }
394
395 <IN_APPL>{vendor_start} {
396         D(("vendor_start\n"));
397
398         vnd = g_malloc(sizeof(ddict_vendor_t));
399         vnd->name = NULL;
400         vnd->code = 0;
401         vnd->next = NULL;
402
403         if (!dict->vendors) last_vnd = dict->vendors = vnd;
404         else last_vnd = last_vnd->next = vnd;
405
406         BEGIN VENDOR_ATTRS;
407 }
408
409 <VENDOR_ATTRS>{name_attr}               { ATTR_STR(vnd->desc); }
410 <VENDOR_ATTRS>{vendor_attr}             { ATTR_STR(vnd->name); }
411 <VENDOR_ATTRS>{code_attr}               { ATTR_UINT(vnd->code); }
412 <VENDOR_ATTRS>{stop}                    |
413 <VENDOR_ATTRS>{stop_end}                { BEGIN IN_APPL; }
414
415 <IN_APPL>{typedefn_start} {
416         D(("typedefn_start\n"));
417
418         typedefn = g_malloc(sizeof(ddict_typedefn_t));
419         typedefn->name = NULL;
420         typedefn->parent = NULL;
421         typedefn->next = NULL;
422
423         if (!dict->typedefns) last_typedefn = dict->typedefns = typedefn;
424         else last_typedefn = last_typedefn->next = typedefn;
425
426         BEGIN TYPEDEFN_ATTRS;
427 }
428
429 <TYPEDEFN_ATTRS>{typename_attr}         { ATTR_STR(typedefn->name); }
430 <TYPEDEFN_ATTRS>{typeparent_attr}       { ATTR_STR(typedefn->parent); }
431 <TYPEDEFN_ATTRS>{stop}                  |
432 <TYPEDEFN_ATTRS>{stop_end}              { BEGIN IN_APPL; }
433
434
435 <IN_APPL>{avp_start}    {
436         D(("avp_start\n"));
437
438         avp = g_malloc(sizeof(ddict_avp_t));
439         avp->name = NULL;
440         avp->description = NULL;
441         avp->vendor = NULL;
442         avp->code = 0;
443         avp->type = NULL;
444         avp->enums = NULL;
445         avp->gavps = NULL;
446         avp->next = NULL;
447
448         if (! dict->avps ) last_avp = dict->avps = avp;
449         else last_avp = last_avp->next = avp;
450
451         BEGIN AVP_ATTRS;
452 }
453
454 <AVP_ATTRS>{name_attr}                  { ATTR_STR(avp->name); }
455 <AVP_ATTRS>{description_attr}   { ATTR_STR(avp->description); }
456 <AVP_ATTRS>{vendor_attr}                { ATTR_STR(avp->vendor); }
457 <AVP_ATTRS>{code_attr}                  { ATTR_UINT(avp->code); }
458 <AVP_ATTRS>{stop}                               { BEGIN IN_AVP;  }
459 <AVP_ATTRS>{stop_end}                   { BEGIN IN_APPL; }
460
461
462 <IN_AVP>{grouped_start} { avp->type = strdup("Grouped"); };
463 <IN_AVP>{grouped_end} ;
464
465 <IN_AVP>{type_start} { BEGIN TYPE_ATTRS; }
466 <TYPE_ATTRS>{typename_attr}                     { ATTR_STR(avp->type); }
467
468 <IN_AVP>{gavp_start} {
469         D(("gavp_start\n"));
470
471         gavp = g_malloc(sizeof(ddict_gavp_t));
472         gavp->name = NULL;
473         gavp->code = 0;
474         gavp->next = NULL;
475
476         if (!avp->gavps) last_gavp = avp->gavps = gavp;
477         else last_gavp = last_gavp->next = gavp;
478
479         BEGIN GAVP_ATTRS;
480 }
481
482
483 <GAVP_ATTRS>{name_attr}                 { ATTR_STR(gavp->name); }
484
485
486 <IN_AVP>{enum_start} {
487         D(("enum_start\n"));
488
489         enumitem = g_malloc(sizeof(ddict_enum_t));
490         enumitem->name = NULL;
491         enumitem->code = 0;
492         enumitem->next = NULL;
493
494         if (!avp->enums) last_enumitem = avp->enums = enumitem;
495         else last_enumitem = last_enumitem->next = enumitem;
496
497         BEGIN ENUM_ATTRS;
498 }
499
500
501 <ENUM_ATTRS>{name_attr}                 { ATTR_STR(enumitem->name); }
502 <ENUM_ATTRS>{code_attr}                 { ATTR_UINT(enumitem->code); }
503
504 <TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop}                        { BEGIN IN_AVP; }
505 <TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop_end}            { BEGIN IN_AVP; }
506
507 <IN_AVP>{avp_end} { D(("avp_end")); BEGIN IN_APPL; }
508
509 <IN_APPL>{application_end} |
510 <IN_APPL>{base_end} {
511         BEGIN IN_DICT;
512 }
513
514 <IN_DICT>{dictionary_end} {
515         yyterminate();
516 }
517
518 <AVP_ATTRS,ENUM_ATTRS,GAVP_ATTRS,TYPE_ATTRS,TYPEDEFN_ATTRS,VENDOR_ATTRS,APPL_ATTRS,COMMAND_ATTRS>{ignored_attr} IGNORE();
519
520 <OUTSIDE>. ;
521
522
523
524
525
526
527 %%
528
529 static int debugging  = 0;
530
531 static void ddict_debug(const char* fmt, ...) {
532         va_list ap;
533
534         va_start(ap, fmt);
535         if (debugging) vfprintf(stderr, fmt, ap);
536         va_end(ap);
537
538         fflush(stderr);
539 }
540
541
542 static char* strbuf = NULL;
543 static char* write_ptr = NULL;
544 static char* read_ptr = NULL;
545
546 static unsigned size_strbuf = 8192;
547 static unsigned len_strbuf = 0;
548
549 extern void ddict_unused(void);
550 void ddict_unused(void) {
551         yy_top_state();
552 }
553
554 static void append_to_buffer(char* txt, int len) {
555
556         if (strbuf == NULL) {
557                 read_ptr = write_ptr = strbuf = g_malloc(size_strbuf);
558         }
559
560         if ( (len_strbuf + len) >= size_strbuf ) {
561                 read_ptr = strbuf = g_realloc(strbuf,size_strbuf *= 2);
562         }
563
564         write_ptr = strbuf + len_strbuf;
565         strncpy(write_ptr,txt,len);
566         len_strbuf += len;
567
568 }
569
570 static size_t file_input(char* buf, size_t max) {
571         size_t read;
572
573         read = fread(buf,1,max,yyin);
574
575         if ( read == max ) {
576                 return max;
577         } else if (read > 0) {
578                 return read;
579         } else {
580                 return YY_NULL;
581         }
582 }
583
584
585 static size_t string_input(char* buf, size_t max) {
586         if (read_ptr >= write_ptr ) {
587                 return YY_NULL;
588         } else if ( read_ptr + max > write_ptr ) {
589                 max = write_ptr - read_ptr;
590         }
591
592         memcpy(buf,read_ptr,max);
593         read_ptr += max;
594
595         return max;
596 }
597
598 static FILE* ddict_open(const char* system_directory, const char* filename) {
599         FILE* fh;
600         char* fname;
601         if (system_directory) {
602                 fname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
603                     system_directory,filename);
604         } else {
605                 fname = g_strdup(filename);
606         }
607
608         fh = ws_fopen(fname,"r");
609
610         D(("fname: %s fh: %p\n",fname,fh));
611
612         g_free(fname);
613
614
615         return fh;
616 }
617
618 ddict_t* ddict_scan(const char* system_directory, const char* filename, int dbg) {
619
620         debugging = dbg;
621
622         sys_dir = system_directory;
623
624         yyin = ddict_open(sys_dir,filename);
625
626         if (yyin == NULL) {
627                 D(("unable to open %s\n", filename));
628                 return NULL;
629         }
630
631         write_ptr = NULL;
632         read_ptr = NULL;
633
634         dict = g_malloc(sizeof(ddict_t));
635         dict->applications = NULL;
636         dict->cmds = NULL;
637         dict->vendors = NULL;
638         dict->typedefns = NULL;
639         dict->avps = NULL;
640         dict->xmlpis = NULL;
641
642         appl = NULL;
643         avp = NULL;
644         enumitem = NULL;
645         gavp = NULL;
646         typedefn = NULL;
647         cmd = NULL;
648         vnd = NULL;
649         xmlpi = NULL;
650
651         last_appl = NULL;
652         last_avp = NULL;
653         last_enumitem = NULL;
654         last_gavp = NULL;
655         last_typedefn = NULL;
656         last_cmd = NULL;
657         last_vnd = NULL;
658         last_xmlpi = NULL;
659
660         ents.next = NULL;
661         current_yyinput = file_input;
662         BEGIN LOADING;
663         yylex();
664
665         D(("\n---------------\n%s\n------- %d -------\n",strbuf,len_strbuf));
666
667         current_yyinput = string_input;
668
669         BEGIN OUTSIDE;
670         yylex();
671
672         g_free(strbuf);
673         strbuf = NULL;
674         size_strbuf = 8192;
675
676         return dict;
677 }
678
679 void ddict_free(ddict_t* d) {
680         ddict_application_t *p, *pn;
681         ddict_vendor_t *v, *vn;
682         ddict_cmd_t *c, *cn;
683         ddict_typedefn_t *t, *tn;
684         ddict_avp_t *a, *an;
685
686 #define FREE_NAMEANDOBJ(n) do { if(n->name) g_free(n->name); g_free(n); } while(0)
687
688         for (p = d->applications; p; p = pn ) {
689                 pn = p->next;
690                 FREE_NAMEANDOBJ(p);
691         }
692
693         for (v = d->vendors; v; v = vn) {
694                 vn = v->next;
695                 if (!v->desc)  g_free(v->desc);
696                 FREE_NAMEANDOBJ(v);
697         }
698
699         for (c = d->cmds; c; c = cn ) {
700                 cn = c->next;
701                 FREE_NAMEANDOBJ(c);
702         }
703
704         for (t = d->typedefns; t; t = tn) {
705                 tn = t->next;
706                 if (!t->parent)  g_free(t->parent);
707                 FREE_NAMEANDOBJ(t);
708         }
709
710         for (a = d->avps; a; a = an) {
711                 ddict_gavp_t* g, *gn;
712                 ddict_enum_t* e, *en;
713                 an = a->next;
714
715                 for (g = a->gavps; g; g = gn) {
716                         gn = g->next;
717                         FREE_NAMEANDOBJ(g);
718                 }
719
720                 for (e = a->enums; e; e = en) {
721                         en = e->next;
722                         FREE_NAMEANDOBJ(e);
723                 }
724
725                 if (!a->vendor)  g_free(a->vendor);
726                 if (!a->type)  g_free(a->type);
727                 if (!a->description)  g_free(a->description);
728                 FREE_NAMEANDOBJ(a);
729         }
730
731         g_free(d);
732 }
733
734 void ddict_print(FILE* fh, ddict_t* d) {
735         ddict_application_t* p;
736         ddict_vendor_t* v;
737         ddict_cmd_t* c;
738         ddict_typedefn_t* t;
739         ddict_avp_t* a;
740
741
742         for (p = d->applications; p; p = p->next) {
743                 fprintf(fh,"Application: %s[%u]:\n",
744                                 p->name ? p->name : "-",
745                                 p->code);
746         }
747
748         for (v = d->vendors; v; v = v->next) {
749                 fprintf(fh,"Vendor: %s[%u]:\n",
750                                 v->name ? v->name : "-",
751                                 v->code);
752         }
753
754         for (c = d->cmds; c; c = c->next) {
755                 fprintf(fh,"Command: %s[%u] \n",
756                                 c->name ? c->name : "-",
757                                 c->code);
758         }
759
760         for (t = d->typedefns; t; t = t->next) {
761                 fprintf(fh,"Type: %s -> %s \n",
762                                 t->name ? t->name : "-",
763                                 t->parent ? t->parent : "" );
764         }
765
766         for (a = d->avps; a; a = a->next) {
767                 ddict_gavp_t* g;
768                 ddict_enum_t* e;
769                 fprintf(fh,"AVP: %s[%u:%s] %s %s\n",
770                                 a->name ? a->name : "-",
771                                 a->code,
772                                 a->vendor ? a->vendor : "None",
773                                 a->type ? a->type : "-",
774                                 a->description ? a->description : "");
775
776                 for (g = a->gavps; g; g = g->next) {
777                         fprintf(fh,"\tGAVP: %s\n",
778                                         g->name ? g->name : "-" );
779                 }
780
781                 for (e = a->enums; e; e = e->next) {
782                         fprintf(fh,"\tEnum: %s[%u]\n",
783                                         e->name ? e->name : "-",
784                                         e->code);
785                 }
786         }
787 }
788
789 /*
790  * We want to stop processing when we get to the end of the input.
791  * (%option noyywrap is not used because if used then
792  * some flex versions (eg: 2.5.35) generate code which causes
793  * warnings by the Windows VC compiler).
794  */
795
796 int yywrap(void) {
797     return 1;
798 }
799
800 #ifdef TEST_DIAM_DICT_STANDALONE
801 int main(int argc, char** argv) {
802         ddict_t* d;
803         char* dname = NULL;
804         char* fname;
805         int i = 1;
806
807         switch (argc) {
808                 case 3:
809                         dname = argv[i++];
810                 case 2:
811                         fname = argv[i];
812                         break;
813                 default:
814                         fprintf(stderr,"%s: usage [dictionary_dir] dictionary_filename\n",argv[0]);
815                         return 1;
816         }
817
818         d = ddict_scan(dname,fname,1);
819
820         ddict_print(stdout, d);
821
822         return 0;
823 }
824 #endif