summaryrefslogtreecommitdiff
path: root/epan/diam_dict.l
diff options
context:
space:
mode:
authorLuis Ontanon <luis.ontanon@gmail.com>2007-07-16 05:41:58 +0000
committerLuis Ontanon <luis.ontanon@gmail.com>2007-07-16 05:41:58 +0000
commitb0bd83c868af357fffc971157f4bae2b7060073d (patch)
treec12038bb459ae85ba796785b962a8246fb23747d /epan/diam_dict.l
parent4ec27a3f421ccd8723256ec1ee1c0c9d86790311 (diff)
downloadwireshark-b0bd83c868af357fffc971157f4bae2b7060073d.tar.gz
Rewrite of the diameter dissector to use the dictionary for creating hfids, drop libxml dependency.
The work is still incomplete (anything but strings and numbers appears as bytes) but I want others to start testing it. TODO: builders and decoders for: - (ntp) timestamps - addresses - diameteruris - diameteridentities - ipfilterrules - qosfilterrules - mipregistrationrequests svn path=/trunk/; revision=22318
Diffstat (limited to 'epan/diam_dict.l')
-rw-r--r--epan/diam_dict.l759
1 files changed, 759 insertions, 0 deletions
diff --git a/epan/diam_dict.l b/epan/diam_dict.l
new file mode 100644
index 0000000000..6c90e48fe9
--- /dev/null
+++ b/epan/diam_dict.l
@@ -0,0 +1,759 @@
+%option noyywrap
+%option nounput
+%option never-interactive
+%option prefix="DiamDict"
+%option caseless
+%option stack
+
+%option outfile="diam_dict.c"
+
+%{
+ /*
+ ** diam_dict.h
+ ** Diameter Dictionary Import Routines
+ **
+ ** $Id$
+ **
+ ** (c) 2007, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+ **
+ ** This library is free software; you can redistribute it and/or
+ ** modify it under the terms of the GNU Library General Public
+ ** License as published by the Free Software Foundation; either
+ ** version 2 of the License, or (at your option) any later version.
+ **
+ ** This library is distributed in the hope that it will be useful,
+ ** but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ ** Library General Public License for more details.
+ **
+ ** You should have received a copy of the GNU Library General Public
+ ** License along with this library; if not, write to the
+ ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ ** Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "diam_dict.h"
+
+typedef struct entity_t {
+ char* name;
+ char* file;
+ struct entity_t* next;
+} entity_t;
+
+#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); attr_uint = &(cont); yy_push_state(GET_UINT_ATTR); } while(0)
+#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); attr_str = &(cont); yy_push_state(GET_ATTR); } while(0)
+#define IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR); } while(0)
+
+#ifdef DEBUG_DIAM_DICT
+#define D(args) do { printf args ; fflush(stdout); } while(0)
+#else
+#define D(args)
+#endif
+
+#ifdef _WIN32
+#define DDICT_DIRSEP "\\"
+#else
+#define DDICT_DIRSEP "/"
+#endif
+
+#define MAX_INCLUDE_DEPTH 10
+#define YY_INPUT(buf,result,max_size) { result = current_yyinput(buf,max_size); }
+#define ECHO
+#define APPEND(txt,len) append_to_buffer(txt,len)
+
+static entity_t ents;
+static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
+static int include_stack_ptr = 0;
+static size_t (*current_yyinput)(char*,size_t);
+static const char* sys_dir;
+static ddict_t* dict;
+static ddict_application_t* appl;
+static ddict_avp_t* avp;
+static ddict_enum_t* enumitem;
+static ddict_gavp_t* gavp;
+static ddict_typedefn_t* typedefn;
+static ddict_cmd_t* cmd;
+static ddict_vendor_t* vnd;
+
+static ddict_application_t* last_appl;
+static ddict_avp_t* last_avp;
+static ddict_enum_t* last_enumitem;
+static ddict_gavp_t* last_gavp;
+static ddict_typedefn_t* last_typedefn;
+static ddict_cmd_t* last_cmd;
+static ddict_vendor_t* last_vnd;
+
+static char** attr_str;
+static unsigned* attr_uint;
+
+static void append_to_buffer(char* txt, int len);
+static FILE* ddict_open(const char*, const char*);
+
+%}
+
+
+xmlpi_start [[:blank:] \r\n]*<\?[[:blank:] \r\n]*
+xmlpi_end [[:blank:] \r\n]*\?>[[:blank:] \r\n]*
+
+comment_start [[:blank:] \r\n]*<!--[[:blank:] \r\n]*
+comment_end [[:blank:] \r\n]*-->[[:blank:] \r\n]*
+open_tag [[:blank:] \r\n]*<[[:blank:] \r\n]*
+end_tag [[:blank:] \r\n]*\/>[[:blank:] \r\n]*
+close_tag [[:blank:] \r\n]*>[[:blank:] \r\n]*
+open_closetag [[:blank:] \r\n]*<\/[[:blank:] \r\n]*
+equals [[:blank:] \r\n]*=[[:blank:] \r\n]*
+whitespace [[:blank:] \r\n]*
+dquoted \042[^\042]*\042
+
+doctype [[:blank:] \r\n]*<!DOCTYPE[^\[]*\[[[:blank:] \r\n]*
+doctype_end [[:blank:] \r\n]*\][[:blank:] \r\n]*>[[:blank:] \r\n]*
+
+start_entity [[:blank:] \r\n]*<\!ENTITY[[:blank:] \r\n]*
+system [[:blank:] \r\n]*SYSTEM[[:blank:] \r\n]*\042
+entityname [a-z0-9]+
+ndquot [^\042]+
+end_entity \042[[:blank:] \r\n]*>[[:blank:] \r\n]*
+
+entity \&[a-z0-9]+;
+
+any .
+
+
+
+
+stop >
+stop_end \/>
+dquot \042
+number [-]?[0-9]*
+
+dictionary_start <dictionary>
+dictionary_end <\/dictionary>
+
+base_start <base[^>*]*>
+base_end <\/base>
+
+applictation_start <application
+application_end<\/application>
+
+command_start <command
+command_end<\/command>
+
+typedefn_start <typedefn
+
+avp_start <avp
+avp_end <\/avp>
+
+type_start <type
+enum_start <enum
+
+grouped_start <grouped>
+grouped_end <\/grouped>
+
+vendor_start <vendor
+gavp_start <gavp
+
+ignored_attr [a-z0-9-]+=
+ignored_quoted \042[^\042]*\042
+
+name_attr name=\042
+id_attr id=\042
+code_attr code=\042
+vendor_attr vendor-id=\042
+typename_attr type-name=\042
+typeparent_attr type-parent=\042
+description_attr description=\042
+
+
+
+%S LOADING LOADING_COMMENT LOADING_XMLPI ENTITY GET_SYSTEM GET_FILE END_ENTITY
+%S GET_ATTR GET_UINT_ATTR END_ATTR OUTSIDE IN_DICT IN_APPL IN_AVP APPL_ATTRS IGNORE_ATTR
+%S TYPE_ATTRS GAVP_ATTRS ENUM_ATTRS AVP_ATTRS VENDOR_ATTRS COMMAND_ATTRS TYPEDEFN_ATTRS
+
+%%
+<LOADING>{doctype} ;
+<LOADING>{doctype_end} ;
+
+<LOADING>{comment_start} BEGIN LOADING_COMMENT;
+<LOADING_COMMENT>. ;
+<LOADING_COMMENT>{comment_end} BEGIN LOADING;
+
+<LOADING>{xmlpi_start} BEGIN LOADING_XMLPI;
+<LOADING_XMLPI>. ;
+<LOADING_XMLPI>{xmlpi_end} BEGIN LOADING;
+
+<LOADING>{start_entity} BEGIN ENTITY;
+<ENTITY>{entityname} {
+ entity_t* e = malloc(sizeof(entity_t));
+ e->name = strdup(yytext);
+ e->next = ents.next;
+ ents.next = e;
+ BEGIN GET_SYSTEM;
+ };
+<GET_SYSTEM>{system} BEGIN GET_FILE;
+<GET_FILE>{ndquot} {
+ ents.next->file = strdup(yytext);
+ BEGIN END_ENTITY;
+ }
+<END_ENTITY>{end_entity} BEGIN LOADING;
+
+<LOADING>{open_tag} APPEND("<",1);
+
+<LOADING>{close_tag} APPEND(">",1);
+
+<LOADING>{end_tag} APPEND("/>",2);
+
+<LOADING>{open_closetag} APPEND("</",2);
+
+<LOADING>{whitespace} APPEND(" ",1);
+
+<LOADING>{dquoted} APPEND(yytext,yyleng);
+
+<LOADING>{equals} APPEND("=",1);
+
+<LOADING>{any} APPEND(yytext,yyleng);
+
+<LOADING>{entity} {
+ char* p = ++yytext;
+ entity_t* e;
+
+ while(*p != ';') p++;
+
+ *p = '\0';
+
+ D(("looking for entity: %s\n",yytext));
+
+ if ( include_stack_ptr >= MAX_INCLUDE_DEPTH ) {
+ fprintf(stderr, "included files nested to deeply\n");
+ yyterminate();
+ }
+
+ include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
+
+
+ for (e = ents.next; e; e = e->next) {
+ if (strcmp(e->name,yytext) == 0) {
+ yyin = ddict_open(sys_dir,e->file);
+ D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,yyin));
+ if (!yyin) {
+ if (errno) {
+ fprintf(stderr, "Could not open file: '%s', error: %s\n", e->file, strerror(errno) );
+ yyterminate();
+ }
+ } else {
+ yy_switch_to_buffer(yy_create_buffer( yyin, YY_BUF_SIZE ) );
+ BEGIN LOADING;
+ }
+ break;
+ }
+ }
+
+ if (!e) {
+ fprintf(stderr, "Could not find entity: '%s'", e->name );
+ yyterminate();
+ }
+
+}
+
+<<EOF>> {
+ if (!yyin) yyterminate();
+
+ fclose(yyin);
+ D(("closing: %p %i\n",yyin,include_stack_ptr));
+
+ if ( --include_stack_ptr < 0 ) {
+ D(("DONE READING\n"));
+ yyin = NULL;
+ yyterminate();
+ } else {
+ yy_delete_buffer( YY_CURRENT_BUFFER );
+ yy_switch_to_buffer(include_stack[include_stack_ptr]);
+ BEGIN LOADING;
+ }
+}
+
+
+<GET_ATTR>{ndquot} {
+ *attr_str = strdup(yytext);
+ D(("%s\n",yytext));
+ attr_str = NULL;
+ BEGIN END_ATTR;
+}
+
+<GET_UINT_ATTR>{number} {
+ *attr_uint = strtoul(yytext,NULL,10);
+ D(("%s\n",yytext););
+ attr_uint = NULL;
+ BEGIN END_ATTR;
+}
+
+<END_ATTR>{dquot} { yy_pop_state(); }
+
+<IGNORE_ATTR>. {
+ /* XXX: should go?*/
+ D(("{%s}",yytext));
+}
+
+<IGNORE_ATTR>{ignored_quoted} {
+ D(("=>%s<=\n",yytext));
+ yy_pop_state();
+}
+
+<OUTSIDE>{dictionary_start} {
+ D(("dictionary_start\n"));
+ dict = malloc(sizeof(ddict_t));
+ dict->applications = NULL;
+ dict->cmds = NULL;
+ dict->vendors = NULL;
+ dict->typedefns = NULL;
+ dict->avps = NULL;
+
+ BEGIN IN_DICT;
+}
+
+<IN_DICT>{base_start} {
+ D(("base_start\n"));
+ BEGIN IN_APPL;
+}
+
+<IN_DICT>{applictation_start} {
+ D(("applictation_start\n"));
+
+ appl = malloc(sizeof(ddict_application_t));
+ appl->name = NULL;
+ appl->code = 0;
+ appl->next = NULL;
+
+ if (!dict->applications) last_appl = dict->applications = appl;
+ else last_appl = last_appl->next = appl;
+
+ BEGIN APPL_ATTRS;
+}
+
+<APPL_ATTRS>{name_attr} { ATTR_STR(appl->name); }
+<APPL_ATTRS>{id_attr} { ATTR_UINT(appl->code); }
+
+<APPL_ATTRS>{stop} BEGIN IN_APPL;
+<APPL_ATTRS>{stop_end} BEGIN IN_DICT;
+
+<IN_APPL>{command_end} ;
+
+<IN_APPL>{command_start} {
+ D(("command_start\n"));
+
+ cmd = malloc(sizeof(ddict_cmd_t));
+ cmd->name = NULL;
+ cmd->vendor = NULL;
+ cmd->code = 0;
+ cmd->next = NULL;
+
+ if (!dict->cmds) last_cmd = dict->cmds = cmd;
+ else last_cmd = last_cmd->next = cmd;
+
+ BEGIN COMMAND_ATTRS;
+}
+
+<COMMAND_ATTRS>{name_attr} { ATTR_STR(cmd->name); }
+<COMMAND_ATTRS>{vendor_attr} { ATTR_STR(cmd->vendor); }
+<COMMAND_ATTRS>{code_attr} { ATTR_UINT(cmd->code); }
+<COMMAND_ATTRS>{stop} |
+<COMMAND_ATTRS>{stop_end} { BEGIN IN_APPL; }
+
+<IN_APPL>{vendor_start} {
+ D(("vendor_start\n"));
+
+ vnd = malloc(sizeof(ddict_vendor_t));
+ vnd->name = NULL;
+ vnd->code = 0;
+ vnd->next = NULL;
+
+ if (!dict->vendors) last_vnd = dict->vendors = vnd;
+ else last_vnd = last_vnd->next = vnd;
+
+ BEGIN VENDOR_ATTRS;
+}
+
+<VENDOR_ATTRS>{name_attr} { ATTR_STR(vnd->desc); }
+<VENDOR_ATTRS>{vendor_attr} { ATTR_STR(vnd->name); }
+<VENDOR_ATTRS>{code_attr} { ATTR_UINT(vnd->code); }
+<VENDOR_ATTRS>{stop} |
+<VENDOR_ATTRS>{stop_end} { BEGIN IN_APPL; }
+
+<IN_APPL>{typedefn_start} {
+ D(("typedefn_start\n"));
+
+ typedefn = malloc(sizeof(ddict_typedefn_t));
+ typedefn->name = NULL;
+ typedefn->parent = NULL;
+ typedefn->next = NULL;
+
+ if (!dict->typedefns) last_typedefn = dict->typedefns = typedefn;
+ else last_typedefn = last_typedefn->next = typedefn;
+
+ BEGIN TYPEDEFN_ATTRS;
+}
+
+<TYPEDEFN_ATTRS>{typename_attr} { ATTR_STR(typedefn->name); }
+<TYPEDEFN_ATTRS>{typeparent_attr} { ATTR_STR(typedefn->parent); }
+<TYPEDEFN_ATTRS>{stop} |
+<TYPEDEFN_ATTRS>{stop_end} { BEGIN IN_APPL; }
+
+
+<IN_APPL>{avp_start} {
+ D(("avp_start\n"));
+
+ avp = malloc(sizeof(ddict_avp_t));
+ avp->name = NULL;
+ avp->vendor = NULL;
+ avp->code = 0;
+ avp->type = NULL;
+ avp->enums = NULL;
+ avp->gavps = NULL;
+ avp->next = NULL;
+
+ if (! dict->avps ) last_avp = dict->avps = avp;
+ else last_avp = last_avp->next = avp;
+
+ BEGIN AVP_ATTRS;
+}
+
+<AVP_ATTRS>{name_attr} { ATTR_STR(avp->name); }
+<AVP_ATTRS>{description_attr} { ATTR_STR(avp->description); }
+<AVP_ATTRS>{vendor_attr} { ATTR_STR(avp->vendor); }
+<AVP_ATTRS>{code_attr} { ATTR_UINT(avp->code); }
+<AVP_ATTRS>{stop} { BEGIN IN_AVP; }
+<AVP_ATTRS>{stop_end} { BEGIN IN_APPL; }
+
+
+<IN_AVP>{grouped_start} { avp->type = strdup("Grouped"); };
+<IN_AVP>{grouped_end} ;
+
+<IN_AVP>{type_start} { BEGIN TYPE_ATTRS; }
+<TYPE_ATTRS>{typename_attr} { ATTR_STR(avp->type); }
+
+<IN_AVP>{gavp_start} {
+ D(("gavp_start\n"));
+
+ gavp = malloc(sizeof(ddict_gavp_t));
+ gavp->name = NULL;
+ gavp->code = 0;
+ gavp->next = NULL;
+
+ if (!avp->gavps) last_gavp = avp->gavps = gavp;
+ else last_gavp = last_gavp->next = gavp;
+
+ BEGIN GAVP_ATTRS;
+}
+
+
+<GAVP_ATTRS>{name_attr} { ATTR_STR(gavp->name); }
+
+
+<IN_AVP>{enum_start} {
+ D(("enum_start\n"));
+
+ enumitem = malloc(sizeof(ddict_enum_t));
+ enumitem->name = NULL;
+ enumitem->code = 0;
+ enumitem->next = NULL;
+
+ if (!avp->enums) last_enumitem = avp->enums = enumitem;
+ else last_enumitem = last_enumitem->next = enumitem;
+
+ BEGIN ENUM_ATTRS;
+}
+
+
+<ENUM_ATTRS>{name_attr} { ATTR_STR(enumitem->name); }
+<ENUM_ATTRS>{code_attr} { ATTR_UINT(enumitem->code); }
+
+<TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop} { BEGIN IN_AVP; }
+<TYPE_ATTRS,GAVP_ATTRS,ENUM_ATTRS>{stop_end} { BEGIN IN_AVP; }
+
+<IN_AVP>{avp_end} { D(("avp_end")); BEGIN IN_APPL; }
+
+<IN_APPL>{application_end} |
+<IN_APPL>{base_end} {
+ BEGIN IN_DICT;
+}
+
+<IN_DICT>{dictionary_end} {
+ yyterminate();
+}
+
+<AVP_ATTRS,ENUM_ATTRS,GAVP_ATTRS,TYPE_ATTRS,TYPEDEFN_ATTRS,VENDOR_ATTRS,APPL_ATTRS,COMMAND_ATTRS>{ignored_attr} IGNORE();
+
+<OUTSIDE>. ;
+
+
+
+
+
+
+%%
+
+static char* strbuf = NULL;
+static char* write_ptr = NULL;
+static char* read_ptr = NULL;
+
+static unsigned size_strbuf = 8192;
+static unsigned len_strbuf = 0;
+
+extern void ddict_unused(void);
+void ddict_unused(void) {
+ yy_top_state();
+}
+
+static void append_to_buffer(char* txt, int len) {
+
+ if (strbuf == NULL) {
+ read_ptr = write_ptr = strbuf = malloc(size_strbuf);
+ }
+
+ if ( (len_strbuf + len) >= size_strbuf ) {
+ read_ptr = strbuf = realloc(strbuf,size_strbuf *= 2);
+ }
+
+ write_ptr = strbuf + len_strbuf;
+ strncpy(write_ptr,txt,len);
+ len_strbuf += len;
+
+}
+
+static size_t file_input(char* buf, size_t max) {
+ size_t read;
+
+ read = fread(buf,1,max,yyin);
+
+ if ( read == max ) {
+ return max;
+ } else if (read > 0) {
+ return read;
+ } else {
+ return YY_NULL;
+ }
+}
+
+
+static size_t string_input(char* buf, size_t max) {
+ if (read_ptr >= write_ptr ) {
+ return YY_NULL;
+ } else if ( read_ptr + max > write_ptr ) {
+ max = write_ptr - read_ptr;
+ }
+
+ memcpy(buf,read_ptr,max);
+ read_ptr += max;
+
+ return max;
+}
+
+static FILE* ddict_open(const char* system_directory, const char* filename) {
+ FILE* fh;
+ char* fname;
+
+ if (system_directory) {
+ int len = strlen(system_directory) + strlen(filename) + strlen(DDICT_DIRSEP) + 1;
+ fname = malloc(len);
+ snprintf(fname, len, "%s%s%s",system_directory,DDICT_DIRSEP,filename);
+ } else {
+ fname = strdup(filename);
+ }
+
+ fh = fopen(fname,"r");
+
+ D(("fname: %s fh: %p\n",fname,fh));
+
+ free(fname);
+
+
+ return fh;
+}
+
+ddict_t* ddict_scan(const char* system_directory, const char* filename) {
+
+ sys_dir = system_directory;
+
+ yyin = ddict_open(sys_dir,filename);
+
+ write_ptr = NULL;
+ read_ptr = NULL;
+
+ ents.next = NULL;
+ current_yyinput = file_input;
+ BEGIN LOADING;
+ yylex();
+
+ D(("\n---------------\n%s\n------- %d -------\n",strbuf,len_strbuf));
+
+ dict = NULL;
+ appl = NULL;
+ avp = NULL;
+ enumitem = NULL;
+ gavp = NULL;
+ typedefn = NULL;
+ cmd = NULL;
+ vnd = NULL;
+
+ last_appl = NULL;
+ last_avp = NULL;
+ last_enumitem = NULL;
+ last_gavp = NULL;
+ last_typedefn = NULL;
+ last_cmd = NULL;
+ last_vnd = NULL;
+
+ current_yyinput = string_input;
+
+ BEGIN OUTSIDE;
+ yylex();
+
+ free(strbuf);
+ strbuf = NULL;
+ size_strbuf = 8192;
+
+ return dict;
+}
+
+void ddict_free(ddict_t* d) {
+ ddict_application_t *p, *pn;
+ ddict_vendor_t *v, *vn;
+ ddict_cmd_t *c, *cn;
+ ddict_typedefn_t *t, *tn;
+ ddict_avp_t *a, *an;
+
+#define FREE_NAMEANDOBJ(n) do { if(n->name) free(n->name); free(n); } while(0)
+
+ for (p = d->applications; p; p = pn ) {
+ pn = p->next;
+ FREE_NAMEANDOBJ(p);
+ }
+
+ for (v = d->vendors; v; v = vn) {
+ vn = v->next;
+ if (!v->desc) free(v->desc);
+ FREE_NAMEANDOBJ(v);
+ }
+
+ for (c = d->cmds; c; c = cn ) {
+ cn = c->next;
+ FREE_NAMEANDOBJ(c);
+ }
+
+ for (t = d->typedefns; t; t = tn) {
+ tn = t->next;
+ if (!t->parent) free(t->parent);
+ FREE_NAMEANDOBJ(t);
+ }
+
+ for (a = d->avps; a; a = an) {
+ ddict_gavp_t* g, *gn;
+ ddict_enum_t* e, *en;
+ an = a->next;
+
+ for (g = a->gavps; g; g = gn) {
+ gn = g->next;
+ FREE_NAMEANDOBJ(g);
+ }
+
+ for (e = a->enums; e; e = en) {
+ en = e->next;
+ FREE_NAMEANDOBJ(e);
+ }
+
+ if (!a->vendor) free(a->vendor);
+ if (!a->type) free(a->type);
+ if (!a->description) free(a->description);
+ FREE_NAMEANDOBJ(a);
+ }
+
+ free(d);
+}
+
+void ddict_print(FILE* fh, ddict_t* d) {
+ ddict_application_t* p;
+ ddict_vendor_t* v;
+ ddict_cmd_t* c;
+ ddict_typedefn_t* t;
+ ddict_avp_t* a;
+
+
+ for (p = d->applications; p; p = p->next) {
+ fprintf(fh,"Application: %s[%u]:\n",
+ p->name ? p->name : "-",
+ p->code);
+ }
+
+ for (v = d->vendors; v; v = v->next) {
+ fprintf(fh,"Vendor: %s[%u]:\n",
+ v->name ? v->name : "-",
+ v->code);
+ }
+
+ for (c = d->cmds; c; c = c->next) {
+ fprintf(fh,"Command: %s[%u] \n",
+ c->name ? c->name : "-",
+ c->code);
+ }
+
+ for (t = d->typedefns; t; t = t->next) {
+ fprintf(fh,"Type: %s -> %s \n",
+ t->name ? t->name : "-",
+ t->parent ? t->parent : "" );
+ }
+
+ for (a = d->avps; a; a = a->next) {
+ ddict_gavp_t* g;
+ ddict_enum_t* e;
+ fprintf(fh,"AVP: %s[%u:%s] %s %s\n",
+ a->name ? a->name : "-",
+ a->code,
+ a->vendor ? a->vendor : "None",
+ a->type ? a->type : "-",
+ a->description ? a->description : "");
+
+ for (g = a->gavps; g; g = g->next) {
+ fprintf(fh,"\tGAVP: %s\n",
+ g->name ? g->name : "-" );
+ }
+
+ for (e = a->enums; e; e = e->next) {
+ fprintf(fh,"\tEnum: %s[%u]\n",
+ e->name ? e->name : "-",
+ e->code);
+ }
+ }
+}
+
+#ifdef TEST_DIAM_DICT_STANDALONE
+int main(int argc, char** argv) {
+ ddict_t* d;
+ char* dname = NULL;
+ char* fname;
+ int i = 1;
+
+ switch (argc) {
+ case 3:
+ dname = argv[i++];
+ case 2:
+ fname = argv[i];
+ break;
+ default:
+ fprintf(stderr,"%s: usage [dictionary_dir] dictionary_filename\n",argv[0]);
+ return 1;
+ }
+
+ d = ddict_scan(dname,fname);
+
+ ddict_print(stdout, d);
+
+ return 0;
+}
+#endif