1
# ntop xml output generator -- tools
3
# Written by and copyright (c) 2002, Burton M. Strauss III
5
# Distributed as part of ntop, http://www.ntop.org
7
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
9
# This program is free software; you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation; either version 2 of the License, or
12
# (at your option) any later version.
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
19
# You should have received a copy of the GNU General Public License
20
# along with this program; if not, write to the Free Software Foundation,
21
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
25
# This tool is part of the ntop xml output system, but it is in fact
26
# not normally executed by persons compiling ntop.
28
# It is designed for the developer of ntop to create a skeleton of
29
# certain files used by xmldump.c
31
# Usage: awk -f processstruct.awk xxx.h
33
# This program processes a c language .h file and attempts to extract
34
# the structure definitions (typedef struct) so that it can create
35
# (skeleton) subroutines for insertion into xmldump.c
37
# It also creates /*XML lines for xmldump.awk to process to create
38
# the c language code that populates the DOM mode in xmldump.awk
40
# Understand the limitations - this is not a c parser, it's just dumb
41
# token matching. The output is probably pretty good, but it's only
42
# a start. If there are inteligent groupings of the fields, that's
43
# not in the struct, well, it won't figure them out.
45
# However, if you add a bunch of stuff to a structure, or add a new
46
# structure, this should save you from manually creating everything.
53
# Append - stripping trailing blanks and comments.
54
# This is used to build up a single awk string that contains an entire C statement,
55
# even if it crosses line boundaries.
57
function specialappend(inputline, append) {
58
outputline = inputline " " append
59
if ( (i=index(outputline, "/*")) > 0) {
60
if ( (j = index(outputline, "*/")) > 0) {
62
printf("/*XMLNOTE mis-matched comments, may fail */\n")
64
outputline=substr(outputline, 1, i-1) " " substr(outputline, j+2)
68
gsub(/ +$/, "", outputline)
73
programname="processstruct.awk"
75
datestamp = strftime("%Y-%m-%dT%H:%M:%S", systime() )
77
# export debug=anything to turn on debug
78
debug=ENVIRON["XMLDUMPDEBUG"]
81
if ((i=index(outputfile, ".")) > 0) { outputfile = substr(outputfile, 1, i-1) }
82
outputfile=outputfile ".skeleton"
84
if (tolower(substr(ARGV[1], 1, 1)) == "globals-structtypes.h") {
87
xmlprefix=tolower(substr(ARGV[1], 1, 1))
90
printf("/*XMLNOTE %s %s running */\n", datestamp, programname)
91
printf("/*XMLNOTE Processing %s -> %s */\n", ARGV[1], outputfile)
93
printf("/*XMLNOTE %s created on %s from %s */\n\n", outputfile, datestamp, ARGV[1]) >outputfile
100
xmlprefix=tolower(substr(ARGV[1], 1, 1))
103
# This is the translation from c types to /*XML typeflag values
104
# e.g. a float is n:f (numeric, format %f)
106
typewords["float"]="n:f"
108
typewords["short"]="n"
109
typewords["long"]="n:l"
110
typewords["unsigned"]="n:u"
111
typewords["u_char"]="n:u"
112
typewords["u_int"]="n:u"
113
typewords["u_short"]="n:u"
114
typewords["char"]="s"
115
typewords["volatile"]=""
116
typewords["u_int16_t"]="n:u"
117
typewords["u_int32_t"]="n:u"
118
typewords["u_int"]="n:u"
119
typewords["u_long"]="n:lu"
122
# This is used for modifiers (e.g. unsigned int) so that we can merge them.
124
priority_typewords["unsigned"]="u"
127
# These are used to list know typeflag values, so we don't output them (optionally, debug)
134
codewords["n:lu"]="y"
135
codewords["n:llu"]="y"
138
# These are hard-coded opaque types which we studiously ignore
140
ignore_types["pthread_mutex_t"]="yes"
141
ignore_types["pthread_cond_t"]="yes"
142
ignore_types["gdbm_file"]="yes"
143
ignore_types["file"]="yes"
144
ignore_types["ssl"]="yes"
145
ignore_types["mycode"]="yes"
148
# Current .inc output count
149
# Since the name is only valid at the end, we store the generated lines...
157
# Line counter and compress out tabs
165
# Skip cpp directives... unless we're in the middle, then just echo...
167
substr($1, 1, 1) == "#" {
168
if ( (found_typedef == "Y") &&
174
($1 == "#endif") ) ) {
175
outputecho[ocount] = $0
182
$1 == "/*XMLSKIPBEGIN" {
187
$1 == "/*XMLSKIPEND" {
194
# If all we have is a comment or a blank line, ignore it
195
$1 == "/*" && $NF == "*/" { next }
199
# Comment opening ... skip until the end ... yeah, this is crude...
201
while (getline > 0) {
203
if (index($0, "*/") > 0) {
211
# Stuff we care about begins:
212
# typedef struct [optionalcomment] {
215
# Lets skip the simplest ones .... typedef xyz int;
216
if (index($0, ";") > 0) { next }
217
if ($2 != "struct") { next }
221
printf(" /*XMLNOTE Starting typedef at line %d */\n", lines)
222
printf("/*XMLNOTE automatically created from %s starting at line %d */\n",
223
filename, lines) >>outputfile
236
# Create working names... (stripping the ;)
237
# fname is the name, lfname is lower case and pfname is 1st upper, rest lower
239
gsub(/ *;$/, "", fname)
240
lfname = tolower(fname)
241
pfname = toupper(substr(lfname, 1, 1)) substr(lfname, 2)
242
typewords[fname]=lfname
244
# Output the header lines
245
printf(" /*XMLNOTE Creating %s.inc */\n", lfname)
246
printf("/*XMLSECTIONBEGIN xml/%s_%s.inc parent input */\n", xmlprefix, lfname) >>outputfile
247
printf(" /*XML e %-30s %-20s \"\" */\n", fname, "parent:Work") >>outputfile
249
# Output the stored lines
250
for (i=0; i<ocount; i++) {
251
if (i in outputecho) {
252
printf("%s\n", outputecho[i]) >>outputfile
256
otype=tolower(outputtype[i])
257
gsub(/\*/, "", otype)
258
if (i in outputindex) {
259
printf(" /*XMLFOR i 0 %s */\n", outputindex[i]) >>outputfile
264
if (otype != outputfield[i]) {
265
printf("%s /*XML%s %-6s %-30s %-20s \"\" */\n",
267
otype in ignore_types ? "NOTE - IGNORE " : "",
269
outputfield[i] (i in outputindex ? "[i]" : ""),
272
if (i in outputindex) {
273
printf(" /*XMLROF */\n") >>outputfile
274
delete outputindex[i]
276
delete outputfield[i]
278
printf("/*XMLSECTIONEND */\n\n\n") >>outputfile
280
printf("/* ********************************** */\n") >>outputfile
281
printf("/* *Generated skeleton for xmldump.c* */\n") >>outputfile
282
printf("/* * created from %-17s * */\n", filename) >>outputfile
283
printf("/* * at line %4d * */\n", lines) >>outputfile
284
printf("/* * at %-22s * */\n", datestamp) >>outputfile
285
printf("/* ********************************** */\n\n") >>outputfile
286
printf("GdomeElement * newxml_%s(GdomeElement * parent,\n", lfname) >>outputfile
287
printf(" char * nodename,\n") >>outputfile
288
printf(" %s * input,\n", fname) >>outputfile
289
printf(" char * description);\n\n") >>outputfile
290
printf("GdomeElement * newxml_%s(GdomeElement * parent,\n", lfname) >>outputfile
291
printf(" char * nodename,\n") >>outputfile
292
printf(" %s * input,\n", fname) >>outputfile
293
printf(" char * description) {\n\n") >>outputfile
294
printf(" GdomeElement *elWork;\n") >>outputfile
295
printf(" GdomeException exc;\n\n") >>outputfile
296
printf("#if (XMLDUMP_DEBUG >= 3)\n") >>outputfile
297
printf(" traceEvent(CONST_TRACE_INFO, \"XMLDUMP_DEBUG: Starting newxml_%s\\n\");\n", lfname) >>outputfile
298
printf("#endif\n\n") >>outputfile
299
printf(" /* Insert the generated block of code */\n") >>outputfile
300
printf(" #include \"xml/%s_%s.inc\"\n\n", xmlprefix, lfname) >>outputfile
301
printf("#if (XMLDUMP_DEBUG >= 3)\n") >>outputfile
302
printf(" traceEvent(CONST_TRACE_INFO, \"XMLDUMP_DEBUG: Ending newxml_%s\\n\");\n", lfname) >>outputfile
303
printf("#endif\n\n") >>outputfile
304
printf(" return elWork;\n") >>outputfile
305
printf("}\n\n") >>outputfile
306
printf("/* ********************************** */\n") >>outputfile
307
printf("/* ********************************** */\n\n") >>outputfile
309
# Store the name of the type for later, reset the counter and continue on...
316
# If we are NOT in the middle of a typedef, then we skip the line...
318
found_typedef == "N" { next }
321
# Otherwise, it's a definition in our struct and we process it...
325
# First, read up to the ; dropping comments
328
inputline = specialappend(inputline, $0)
329
gsub(/ +$/, "", inputline)
330
while (substr(inputline, length(inputline), 1) != ";") {
333
inputline = specialappend(inputline, $0)
334
} else if (substr($1, 1, 1) == "#") {
337
printf("/*XMLNOTE no closing ; - assuming, may fail '%s' */\n", inputline)
338
inputline=inputline ";"
341
gsub(/ +$/, "", inputline)
343
while ( (i=index(inputline, "/*")) > 0) {
344
j = index(inputline, "*/")
346
printf("/*XMLNOTE mis-matched comments, may fail */\n")
349
inputline=substr(inputline, 1, i-1) " " substr(inputline, j+2)
351
gsub(/ *; *$/, "", inputline)
352
if (debug != "") printf("DEBUG: inputline='%s', NF=%d\n", inputline, NF)
354
# This gives us an entire C declaration statement. We'll set $0 to it so we can
355
# use the automatic split and $n variables.
358
# Process the first field(s) to grab the type.
359
# typetype: We look up the type in the table above until we find the
360
# first conversion to /*XML typeflag
361
# prioritytypetype is the "u" suffix if needed, again from table above.
362
# This allows us to convert "unsigned int" to n:u while "int" is just "n"
363
# ActualTypeName is just a concat of the words (unsigned long long -> unsignedlonglong)
364
# Used below to see if this is a char xx[n] that we should treat as a string.
368
for (i=1; i<=NF; i++) {
370
gsub(/\*$/, "", typeword)
371
if (typeword == "struct") {
372
ActualTypeName=ActualTypeName $i
374
} else if (typeword in typewords) {
375
ActualTypeName=ActualTypeName $i
376
if ( (typetype == "") && (typeword in typewords) && (typewords[typeword] != "") ) {
377
typetype = typewords[typeword]
379
if ( (prioritytypetype == "") && (typeword in prioritytypewords) ) {
380
prioritytypetype = prioritytypewords[typeword]
383
# Not a type word? Must be the field... stop mucking with types.
387
if (typetype == "" ) { typetype = $i }
388
if (prioritytypetype != "") {
389
if (index(typetype, ":") == 0) { typetype = typetype ":" }
390
typetype = typetype prioritytypetype
392
if (debug != "") printf("DEBUG: typetype='%s'\n", typetype)
394
# Process the remaining field(s) as variables of the associated type...
395
if (debug != "") printf("DEBUG: i=%d, NF=%d\n", i, NF)
397
if (debug != "") printf("DEBUG: processing field '%s'\n", $i)
399
if (substr($i, 1, 2) == "**") {
400
$i = substr($i, 3) "[?]"
401
ActualTypeName="forcedarray"
403
# If it's got an index value, we need to know for the XMLFOR later on...
406
field=substr($i, 1, j-1)
407
findex=substr($i, j+1)
408
gsub(/\]/, "", findex)
413
# Strip off bit masks, leading *'s, trailing commas
414
gsub(/^:[0-9]*/, "", field)
415
gsub(/^\*+/, "", field)
416
gsub(/\*+$/, "", field)
417
gsub(/,$/, "", field)
418
if (debug != "") printf("DEBUG: Field %s, type %s\n", field, typetype)
420
if (tolower(field) in ignore_types) {
421
} else if (field != "") {
422
# Store the output data for when we find the }
423
outputtype[ocount] = typetype
424
outputfield[ocount]= field
426
if (ActualTypeName ~ /char/) {
427
# char xxx[size] -- treat as string
429
outputindex[ocount] = findex
439
datestamp = strftime("%Y-%m-%dT%H:%M:%S", systime() )
440
## # Note we explicitly APPEND to the list, in case we have multiple files to process...
441
## print "# processstruct.list created " datestamp >>"processstruct.list"
442
## print "# by processstruct.awk " >>"processstruct.list"
443
## print "# from " ARGV[1] >>"processstruct.list"
444
## print "#" >>"processstruct.list"
446
# Output a list of all the unknown types we've found for xmldump.awk
447
## for (i in typelist) {
448
## if (i in typewords) {
449
## printf("# typewords %s\n", i) >>"processstruct.list"
450
## } else if (i in codewords) {
451
## printf("# codewords %s\n", i) >>"processstruct.list"
453
## printf("struct %s\n", i) >>"processstruct.list"
456
printf("\n\n/*XMLNOTE %s %s finished */\n\n\n", datestamp, programname)