2 /* Include this before everything else, for various large-file definitions */
8 * We want a reentrant scanner.
13 * We don't use input, so don't generate code for it.
18 * We don't use unput, so don't generate code for it.
23 * We don't read interactively from the terminal.
25 %option never-interactive
28 * The language we're scanning is case-insensitive.
33 * We use start condition stacks.
38 * We want to stop processing when we get to the end of the input.
43 * The type for the state we keep for a scanner.
45 %option extra-type="DiamDict_scanner_state_t *"
48 * Prefix scanner routines with "DiamDict_" rather than "yy", so this scanner
49 * can coexist with other scanners.
51 %option prefix="DiamDict_"
53 %option outfile="diam_dict.c"
56 * We have to override the memory allocators so that we don't get
57 * "unused argument" warnings from the yyscanner argument (which
58 * we don't use, as we have a global memory allocator).
60 * We provide, as macros, our own versions of the routines generated by Flex,
61 * which just call malloc()/realloc()/free() (as the Flex versions do),
62 * discarding the extra argument.
71 ** Diameter Dictionary Import Routines
73 ** (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
75 ** This library is free software; you can redistribute it and/or
76 ** modify it under the terms of the GNU Library General Public
77 ** License as published by the Free Software Foundation; either
78 ** version 2 of the License, or (at your option) any later version.
80 ** This library is distributed in the hope that it will be useful,
81 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
82 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
83 ** Library General Public License for more details.
85 ** You should have received a copy of the GNU Library General Public
86 ** License along with this library; if not, write to the Free Software
87 ** Foundation, Inc., 51 Franklin Street, Fifth Floor,
88 ** Boston, MA 02110-1301, USA.
90 ** See draft-frascone-xml-dictionary for the syntax of the
100 #include "diam_dict.h"
101 #include <epan/to_str.h>
102 #include <wsutil/file_util.h>
105 * Disable diagnostics in the code generated by Flex.
109 typedef struct entity_t {
112 struct entity_t* next;
115 #define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_UINT_ATTR, yyscanner); } while(0)
116 #define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); yyextra->attr_str = &(cont); yy_push_state(GET_ATTR, yyscanner); } while(0)
117 #define IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR, yyscanner); } while(0)
119 #define D(args) ddict_debug args
121 #define MAX_INCLUDE_DEPTH 10
122 #define YY_INPUT(buf,result,max_size) { result = yyextra->current_yyinput(buf,max_size,yyscanner); }
123 #define YY_USER_INIT { \
124 DiamDict_scanner_state_t *scanner_state = DiamDict_get_extra(yyscanner); \
125 BEGIN(scanner_state->start_state); \
128 #define APPEND(txt,len) append_to_buffer(txt,len,yyextra)
137 unsigned size_strbuf;
142 ddict_application_t* appl;
144 ddict_enum_t* enumitem;
146 ddict_typedefn_t* typedefn;
149 ddict_xmlpi_t* xmlpi;
151 ddict_application_t* last_appl;
152 ddict_avp_t* last_avp;
153 ddict_enum_t* last_enumitem;
154 ddict_gavp_t* last_gavp;
155 ddict_typedefn_t* last_typedefn;
156 ddict_cmd_t* last_cmd;
157 ddict_vendor_t* last_vnd;
158 ddict_xmlpi_t* last_xmlpi;
165 size_t (*current_yyinput)(char*,size_t,yyscan_t);
166 int (*current_close)(FILE *fh);
168 YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
169 int include_stack_ptr;
172 } DiamDict_scanner_state_t;
174 static void ddict_debug(const char* fmt, ...) G_GNUC_PRINTF(1, 2);
175 static void append_to_buffer(const char* txt, unsigned len, DiamDict_scanner_state_t *statep);
176 static FILE* ddict_open(const char*, const char*);
179 * Sleazy hack to suppress compiler warnings in yy_fatal_error().
181 #define YY_EXIT_FAILURE ((void)yyscanner, 2)
184 * Macros for the allocators, to discard the extra argument.
186 #define DiamDict_alloc(size, yyscanner) (void *)malloc(size)
187 #define DiamDict_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size))
188 #define DiamDict_free(ptr, yyscanner) free((char *)ptr)
193 xmlpi_start [[:blank:] \r\n]*<\?[[:blank:] \r\n]*
194 xmlpi_end [[:blank:] \r\n]*\?>[[:blank:] \r\n]*
195 xmlpi_key_attr [[:blank:] \r\n]*key[[:blank:] \r\n]*=[[:blank:] \r\n]*\042
196 xmlpi_value_attr [[:blank:] \r\n]*value[[:blank:] \r\n]*=[[:blank:] \r\n]*\042
198 comment_start [[:blank:] \r\n]*<!--[[:blank:] \r\n]*
199 comment_end [[:blank:] \r\n]*-->[[:blank:] \r\n]*
200 open_tag [[:blank:] \r\n]*<[[:blank:] \r\n]*
201 end_tag [[:blank:] \r\n]*\/>[[:blank:] \r\n]*
202 close_tag [[:blank:] \r\n]*>[[:blank:] \r\n]*
203 open_closetag [[:blank:] \r\n]*<\/[[:blank:] \r\n]*
204 equals [[:blank:] \r\n]*=[[:blank:] \r\n]*
205 whitespace [[:blank:] \r\n]*
206 dquoted \042[^\042]*\042
208 doctype [[:blank:] \r\n]*<!DOCTYPE[^\[]*\[[[:blank:] \r\n]*
209 doctype_end [[:blank:] \r\n]*\][[:blank:] \r\n]*>[[:blank:] \r\n]*
211 start_entity [[:blank:] \r\n]*<\!ENTITY[[:blank:] \r\n]*
212 system [[:blank:] \r\n]*SYSTEM[[:blank:] \r\n]*\042
213 entityname [a-z0-9-]+
215 end_entity \042[[:blank:] \r\n]*>[[:blank:] \r\n]*
229 dictionary_start <dictionary>
230 dictionary_end <\/dictionary>
232 base_start <base[^>*]*>
235 application_start <application
236 application_end<\/application>
238 command_start <command
239 command_end<\/command>
241 typedefn_start <typedefn
249 grouped_start <grouped>
250 grouped_end <\/grouped>
257 ignored_attr [a-z0-9-]+=
258 ignored_quoted \042[^\042]*\042
263 vendor_attr vendor-id=\042
264 typename_attr type-name=\042
265 typeparent_attr type-parent=\042
266 description_attr description=\042
270 %S LOADING LOADING_COMMENT LOADING_XMLPI ENTITY GET_SYSTEM GET_FILE END_ENTITY
271 %S GET_ATTR GET_UINT_ATTR END_ATTR OUTSIDE IN_DICT IN_APPL IN_AVP APPL_ATTRS IGNORE_ATTR
272 %S TYPE_ATTRS GAVP_ATTRS ENUM_ATTRS AVP_ATTRS VENDOR_ATTRS COMMAND_ATTRS TYPEDEFN_ATTRS
273 %S XMLPI_ATTRS XMLPI_GETKEY XMLPI_GETVAL XMLPI_ENDATTR
276 <LOADING>{doctype_end} ;
278 <LOADING>{comment_start} BEGIN LOADING_COMMENT;
280 <LOADING_COMMENT>{comment_end} BEGIN LOADING;
282 <LOADING>{xmlpi_start} BEGIN LOADING_XMLPI;
283 <LOADING_XMLPI>{whitespace} ;
284 <LOADING_XMLPI>{entityname} {
285 yyextra->xmlpi = g_new(ddict_xmlpi_t,1);
286 yyextra->xmlpi->name = g_strdup(yytext);
287 yyextra->xmlpi->key = NULL;
288 yyextra->xmlpi->value = NULL;
289 yyextra->xmlpi->next = NULL;
291 if (!yyextra->dict->xmlpis)
292 yyextra->last_xmlpi = yyextra->dict->xmlpis = yyextra->xmlpi;
294 yyextra->last_xmlpi = yyextra->last_xmlpi->next = yyextra->xmlpi;
299 <XMLPI_ATTRS>{xmlpi_key_attr} BEGIN XMLPI_GETKEY;
300 <XMLPI_GETKEY>{ndquot} { yyextra->xmlpi->key = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
302 <XMLPI_ATTRS>{xmlpi_value_attr} BEGIN XMLPI_GETVAL;
303 <XMLPI_GETVAL>{ndquot} { yyextra->xmlpi->value = g_strdup(yytext); BEGIN XMLPI_ATTRS; }
306 <XMLPI_ATTRS>{xmlpi_end} BEGIN LOADING;
309 <LOADING>{start_entity} BEGIN ENTITY;
310 <ENTITY>{entityname} {
311 entity_t* e = g_new(entity_t,1);
312 e->name = g_strdup(yytext);
313 e->next = yyextra->ents;
317 <GET_SYSTEM>{system} BEGIN GET_FILE;
319 yyextra->ents->file = g_strdup(yytext);
322 <END_ENTITY>{end_entity} BEGIN LOADING;
324 <LOADING>{open_tag} APPEND("<",1);
326 <LOADING>{close_tag} APPEND(">",1);
328 <LOADING>{end_tag} APPEND("/>",2);
330 <LOADING>{open_closetag} APPEND("</",2);
332 <LOADING>{whitespace} APPEND(" ",1);
334 <LOADING>{dquoted} APPEND(yytext, (unsigned) yyleng);
336 <LOADING>{equals} APPEND("=",1);
338 <LOADING>{any} APPEND(yytext, (unsigned) yyleng);
344 while(*p != ';') p++;
348 D(("looking for entity: %s\n",yytext));
350 if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
351 fprintf(stderr, "included files nested to deeply\n");
355 for (e = yyextra->ents; e; e = e->next) {
356 if (strcmp(e->name,yytext) == 0) {
357 yyin = ddict_open(yyextra->sys_dir,e->file);
358 D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,(void*)yyin));
361 fprintf(stderr, "Could not open file: '%s', error: %s\n", e->file, g_strerror(errno) );
363 fprintf(stderr, "Could not open file: '%s', error unknown (errno == 0)\n", e->file );
366 yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER;
367 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner);
375 fprintf(stderr, "Could not find entity: '%s'\n", yytext );
382 if (!yyin) yyterminate();
384 yyextra->current_close(yyin);
385 D(("closing: %p %i\n",(void*)yyin,yyextra->include_stack_ptr));
387 if ( --yyextra->include_stack_ptr < 0 ) {
388 D(("DONE READING\n"));
392 yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner);
393 yy_switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner);
400 *(yyextra->attr_str) = g_strdup(yytext);
402 yyextra->attr_str = NULL;
406 <GET_UINT_ATTR>{number} {
407 *(yyextra->attr_uint) = (unsigned) strtoul(yytext,NULL,10);
409 yyextra->attr_uint = NULL;
413 <END_ATTR>{dquot} { yy_pop_state(yyscanner); }
420 <IGNORE_ATTR>{ignored_quoted} {
421 D(("=>%s<=\n",yytext));
422 yy_pop_state(yyscanner);
425 <OUTSIDE>{dictionary_start} {
426 D(("dictionary_start\n"));
431 <IN_DICT>{base_start} {
436 <IN_DICT>{application_start} {
437 D(("application_start\n"));
439 yyextra->appl = g_new(ddict_application_t,1);
440 yyextra->appl->name = NULL;
441 yyextra->appl->code = 0;
442 yyextra->appl->next = NULL;
444 if (!yyextra->dict->applications)
445 yyextra->last_appl = yyextra->dict->applications = yyextra->appl;
447 yyextra->last_appl = yyextra->last_appl->next = yyextra->appl;
452 <APPL_ATTRS>{name_attr} { ATTR_STR(yyextra->appl->name); }
453 <APPL_ATTRS>{id_attr} { ATTR_UINT(yyextra->appl->code); }
455 <APPL_ATTRS>{stop} BEGIN IN_APPL;
456 <APPL_ATTRS>{stop_end} BEGIN IN_DICT;
458 <IN_APPL>{command_end} ;
460 <IN_APPL>{command_start} {
461 D(("command_start\n"));
463 yyextra->cmd = g_new(ddict_cmd_t,1);
464 yyextra->cmd->name = NULL;
465 yyextra->cmd->vendor = NULL;
466 yyextra->cmd->code = 0;
467 yyextra->cmd->next = NULL;
469 if (!yyextra->dict->cmds)
470 yyextra->last_cmd = yyextra->dict->cmds = yyextra->cmd;
472 yyextra->last_cmd = yyextra->last_cmd->next = yyextra->cmd;
477 <COMMAND_ATTRS>{name_attr} { ATTR_STR(yyextra->cmd->name); }
478 <COMMAND_ATTRS>{vendor_attr} { ATTR_STR(yyextra->cmd->vendor); }
479 <COMMAND_ATTRS>{code_attr} { ATTR_UINT(yyextra->cmd->code); }
480 <COMMAND_ATTRS>{stop} |
481 <COMMAND_ATTRS>{stop_end} { BEGIN IN_APPL; }
483 <IN_DICT>{vendor_start} {
484 D(("vendor_start\n"));
486 yyextra->vnd = g_new(ddict_vendor_t,1);
487 yyextra->vnd->name = NULL;
488 yyextra->vnd->code = 0;
489 yyextra->vnd->next = NULL;
491 if (!yyextra->dict->vendors)
492 yyextra->last_vnd = yyextra->dict->vendors = yyextra->vnd;
494 yyextra->last_vnd = yyextra->last_vnd->next = yyextra->vnd;
499 <VENDOR_ATTRS>{name_attr} { ATTR_STR(yyextra->vnd->desc); }
500 <VENDOR_ATTRS>{vendor_attr} { ATTR_STR(yyextra->vnd->name); }
501 <VENDOR_ATTRS>{code_attr} { ATTR_UINT(yyextra->vnd->code); }
502 <VENDOR_ATTRS>{stop} { BEGIN IN_APPL; }
503 <VENDOR_ATTRS>{stop_end} { BEGIN IN_DICT; }
505 <IN_APPL>{typedefn_start} {
506 D(("typedefn_start\n"));
508 yyextra->typedefn = g_new(ddict_typedefn_t,1);
509 yyextra->typedefn->name = NULL;
510 yyextra->typedefn->parent = NULL;
511 yyextra->typedefn->next = NULL;
513 if (!yyextra->dict->typedefns)
514 yyextra->last_typedefn = yyextra->dict->typedefns = yyextra->typedefn;
516 yyextra->last_typedefn = yyextra->last_typedefn->next = yyextra->typedefn;
518 BEGIN TYPEDEFN_ATTRS;
521 <TYPEDEFN_ATTRS>{typename_attr} { ATTR_STR(yyextra->typedefn->name); }
522 <TYPEDEFN_ATTRS>{typeparent_attr} { ATTR_STR(yyextra->typedefn->parent); }
523 <TYPEDEFN_ATTRS>{stop} |
524 <TYPEDEFN_ATTRS>{stop_end} { BEGIN IN_APPL; }
527 <IN_APPL>{avp_start} {
530 yyextra->avp = g_new(ddict_avp_t,1);
531 yyextra->avp->name = NULL;
532 yyextra->avp->description = NULL;
533 yyextra->avp->vendor = NULL;
534 yyextra->avp->code = 0;
535 yyextra->avp->type = NULL;
536 yyextra->avp->enums = NULL;
537 yyextra->avp->gavps = NULL;
538 yyextra->avp->next = NULL;
540 if (! yyextra->dict->avps )
541 yyextra->last_avp = yyextra->dict->avps = yyextra->avp;
543 yyextra->last_avp = yyextra->last_avp->next = yyextra->avp;
548 <AVP_ATTRS>{name_attr} { ATTR_STR(yyextra->avp->name); }
549 <AVP_ATTRS>{description_attr} { ATTR_STR(yyextra->avp->description); }
550 <AVP_ATTRS>{vendor_attr} { ATTR_STR(yyextra->avp->vendor); }
551 <AVP_ATTRS>{code_attr} { ATTR_UINT(yyextra->avp->code); }
552 <AVP_ATTRS>{stop} { BEGIN IN_AVP; }
553 <AVP_ATTRS>{stop_end} { BEGIN IN_APPL; }
556 <IN_AVP>{grouped_start} { yyextra->avp->type = g_strdup("Grouped"); };
557 <IN_AVP>{grouped_end} ;
559 <IN_AVP>{type_start} { BEGIN TYPE_ATTRS; }
560 <TYPE_ATTRS>{typename_attr} { ATTR_STR(yyextra->avp->type); }
562 <IN_AVP>{gavp_start} {
565 yyextra->gavp = g_new(ddict_gavp_t,1);
566 yyextra->gavp->name = NULL;
567 yyextra->gavp->code = 0;
568 yyextra->gavp->next = NULL;
570 if (!yyextra->avp->gavps)
571 yyextra->last_gavp = yyextra->avp->gavps = yyextra->gavp;
573 yyextra->last_gavp = yyextra->last_gavp->next = yyextra->gavp;
579 <GAVP_ATTRS>{name_attr} { ATTR_STR(yyextra->gavp->name); }
582 <IN_AVP>{enum_start} {
585 yyextra->enumitem = g_new(ddict_enum_t,1);
586 yyextra->enumitem->name = NULL;
587 yyextra->enumitem->code = 0;
588 yyextra->enumitem->next = NULL;
590 if (!yyextra->avp->enums)
591 yyextra->last_enumitem = yyextra->avp->enums = yyextra->enumitem;
593 yyextra->last_enumitem = yyextra->last_enumitem->next = yyextra->enumitem;
599 <ENUM_ATTRS>{name_attr} { ATTR_STR(yyextra->enumitem->name); }
600 <ENUM_ATTRS>{code_attr} { ATTR_UINT(yyextra->enumitem->code); }
602 <TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop} { BEGIN IN_AVP; }
603 <TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop_end} { BEGIN IN_AVP; }
605 <IN_AVP>{avp_end} { D(("avp_end\n")); BEGIN IN_APPL; }
607 <IN_APPL>{application_end} {
608 D(("application_end\n")); BEGIN IN_DICT;
610 <IN_APPL>{stop_end} {
611 D(("application_stop_end\n")); BEGIN IN_DICT;
613 <IN_APPL>{vendor_end} {
614 D(("vendor_end\n")); BEGIN IN_DICT;
616 <IN_APPL>{base_end} {
617 D(("base_end\n")); BEGIN IN_DICT;
620 <IN_DICT>{dictionary_end} {
624 <AVP_ATTRS,ENUM_ATTRS,GAVP_ATTRS,TYPE_ATTRS,TYPEDEFN_ATTRS,VENDOR_ATTRS,APPL_ATTRS,COMMAND_ATTRS>{ignored_attr} IGNORE();
631 * Turn diagnostics back on, so we check the code that we've written.
635 static int debugging = 0;
637 static void ddict_debug(const char* fmt, ...) {
641 if (debugging) vfprintf(stderr, fmt, ap);
648 * Sleazy hack to avoid unused function warnings for yy_top_state.
650 extern void ddict_unused(yyscan_t yyscanner);
653 ddict_unused(yyscan_t yyscanner)
655 yy_top_state(yyscanner);
659 append_to_buffer(const char* txt, unsigned len, DiamDict_scanner_state_t *statep)
662 if (statep->strbuf == NULL) {
663 statep->strbuf = (char*)g_malloc(statep->size_strbuf);
664 statep->read_ptr = statep->strbuf;
665 statep->write_ptr = statep->strbuf;
668 if (statep->len_strbuf + len >= statep->size_strbuf) {
669 statep->strbuf = (char*)g_realloc(statep->strbuf,statep->size_strbuf *= 2);
670 statep->read_ptr = statep->strbuf;
673 statep->write_ptr = statep->strbuf + statep->len_strbuf;
674 memcpy(statep->write_ptr, txt, len + 1);
675 statep->len_strbuf += len;
679 file_input(char* buf, size_t max, yyscan_t scanner)
681 FILE *in = yyget_in(scanner);
684 read_cnt = fread(buf,1,max,in);
686 if ( read_cnt == max ) {
688 } else if (read_cnt > 0) {
697 string_input(char* buf, size_t max, yyscan_t scanner)
699 DiamDict_scanner_state_t *statep = yyget_extra(scanner);
701 if (statep->read_ptr >= statep->write_ptr ) {
703 } else if ( statep->read_ptr + max > statep->write_ptr ) {
704 max = statep->write_ptr - statep->read_ptr;
707 memcpy(buf,statep->read_ptr,max);
708 statep->read_ptr += max;
714 * If we're reading from a string, yyin is set to stdin, and we don't
715 * want to close that.
718 string_close(FILE *fh _U_)
724 ddict_open(const char* system_directory, const char* filename)
728 if (system_directory) {
729 fname = ws_strdup_printf("%s" G_DIR_SEPARATOR_S "%s",
730 system_directory,filename);
732 fname = g_strdup(filename);
735 fh = ws_fopen(fname,"r");
737 D(("fname: %s fh: %p\n",fname,(void*)fh));
746 ddict_scan(const char* system_directory, const char* filename, int dbg)
748 DiamDict_scanner_state_t state;
754 state.sys_dir = system_directory;
756 state.write_ptr = NULL;
757 state.read_ptr = NULL;
760 state.size_strbuf = 8192;
761 state.len_strbuf = 0;
763 state.dict = g_new(ddict_t,1);
764 state.dict->applications = NULL;
765 state.dict->vendors = NULL;
766 state.dict->cmds = NULL;
767 state.dict->typedefns = NULL;
768 state.dict->avps = NULL;
769 state.dict->xmlpis = NULL;
773 state.enumitem = NULL;
775 state.typedefn = NULL;
780 state.last_appl = NULL;
781 state.last_avp = NULL;
782 state.last_enumitem = NULL;
783 state.last_gavp = NULL;
784 state.last_typedefn = NULL;
785 state.last_cmd = NULL;
786 state.last_vnd = NULL;
787 state.last_xmlpi = NULL;
791 state.attr_str = NULL;
792 state.attr_uint = NULL;
797 * Reads the file, does some work, and stores a modified version
798 * of the file contents in memory.
800 state.current_yyinput = file_input;
801 state.current_close = fclose;
802 state.include_stack_ptr = 0;
804 in = ddict_open(system_directory,filename);
807 D(("unable to open %s: %s\n", filename, g_strerror(errno)));
812 if (DiamDict_lex_init(&scanner) != 0) {
813 /* Note: cannot be reached since memory allocation failure terminates early */
814 D(("Can't initialize scanner: %s\n", g_strerror(errno)));
820 DiamDict_set_in(in, scanner);
822 /* Associate the state with the scanner */
823 DiamDict_set_extra(&state, scanner);
825 state.start_state = LOADING;
826 DiamDict_lex(scanner);
828 DiamDict_lex_destroy(scanner);
830 * XXX - can the lexical analyzer terminate without closing
831 * all open input files?
834 D(("\n---------------\n%s\n------- %u -------\n",state.strbuf,state.len_strbuf));
839 * Reads the modified version of the file contents and does the
842 state.current_yyinput = string_input;
843 state.current_close = string_close;
845 if (DiamDict_lex_init(&scanner) != 0) {
846 /* Note: cannot be reached since memory allocation failure terminates early */
847 D(("Can't initialize scanner: %s\n", g_strerror(errno)));
849 g_free(state.strbuf);
853 /* Associate the state with the scanner */
854 DiamDict_set_extra(&state, scanner);
856 state.start_state = OUTSIDE;
857 DiamDict_lex(scanner);
859 DiamDict_lex_destroy(scanner);
863 for (e = state.ents; e; e = en) {
870 g_free(state.strbuf);
876 ddict_free(ddict_t* d)
878 ddict_application_t *p, *pn;
879 ddict_vendor_t *v, *vn;
881 ddict_typedefn_t *t, *tn;
883 ddict_xmlpi_t *x, *xn;
885 #define FREE_NAMEANDOBJ(n) do { g_free(n->name); g_free(n); } while(0)
887 for (p = d->applications; p; p = pn ) {
892 for (v = d->vendors; v; v = vn) {
898 for (c = d->cmds; c; c = cn ) {
904 for (t = d->typedefns; t; t = tn) {
910 for (a = d->avps; a; a = an) {
911 ddict_gavp_t* g, *gn;
912 ddict_enum_t* e, *en;
915 for (g = a->gavps; g; g = gn) {
920 for (e = a->enums; e; e = en) {
927 g_free(a->description);
931 for (x = d->xmlpis; x; x = xn) {
942 ddict_print(FILE* fh, ddict_t* d)
944 ddict_application_t* p;
951 for (p = d->applications; p; p = p->next) {
952 fprintf(fh,"Application: %s[%u]:\n",
953 p->name ? p->name : "-",
957 for (v = d->vendors; v; v = v->next) {
958 fprintf(fh,"Vendor: %s[%u]:\n",
959 v->name ? v->name : "-",
963 for (c = d->cmds; c; c = c->next) {
964 fprintf(fh,"Command: %s[%u] \n",
965 c->name ? c->name : "-",
969 for (t = d->typedefns; t; t = t->next) {
970 fprintf(fh,"Type: %s -> %s \n",
971 t->name ? t->name : "-",
972 t->parent ? t->parent : "" );
975 for (a = d->avps; a; a = a->next) {
978 fprintf(fh,"AVP: %s[%u:%s] %s %s\n",
979 a->name ? a->name : "-",
981 a->vendor ? a->vendor : "None",
982 a->type ? a->type : "-",
983 a->description ? a->description : "");
985 for (g = a->gavps; g; g = g->next) {
986 fprintf(fh,"\tGAVP: %s\n",
987 g->name ? g->name : "-" );
990 for (e = a->enums; e; e = e->next) {
991 fprintf(fh,"\tEnum: %s[%u]\n",
992 e->name ? e->name : "-",
998 #ifdef TEST_DIAM_DICT_STANDALONE
1000 main(int argc, char** argv)
1014 fprintf(stderr,"%s: usage [dictionary_dir] dictionary_filename\n",argv[0]);
1018 d = ddict_scan(dname,fname,1);
1020 fprintf(stderr, "Can't open dictionary\n");
1024 ddict_print(stdout, d);