3 # parse a C declaration by recursive descent
4 # based on a C program in KR ANSI edition
6 # run on a C file it finds the declarations
8 # restrictions: one declaration per line
9 # doesn't understand struct {...}
10 # makes assumptions about type names
13 # some awks need double escapes on strings used as
14 # regular expressions. If not run on mawk, use gdecl.awk
17 ################################################
18 # lexical scanner -- gobble()
19 # input : string s -- treated as a regular expression
20 # gobble eats SPACE, then eats longest match of s off front
21 # of global variable line.
22 # Cuts the matched part off of line
28 sub( /^ /, "", line) # eat SPACE if any
30 # surround s with parenthesis to make sure ^ acts on the
33 match(line, "^" "(" s ")")
34 x = substr(line, 1, RLENGTH)
35 line = substr(line, RLENGTH+1)
40 function ptr_to(n, x) # print "pointer to" , n times
42 if ( n <= 0 ) return ""
43 x = "pointer to" ; n--
44 while ( n-- ) x = x " pointer to"
49 #recursively get a decl
50 # returns an english description of the declaration or
51 # "" if not a C declaration.
53 function decl( x, t, ptr_part)
56 x = gobble("[* ]+") # get list of *** ...
57 gsub(/ /, "", x) # remove all SPACES
58 ptr_part = ptr_to( length(x) )
60 # We expect to see either an identifier or '('
65 # this is the recursive descent part
66 # we expect to match a declaration and closing ')'
67 # If not return "" to indicate failure
69 if ( (x = decl()) == "" || gobble( "\)" ) == "" ) return ""
72 else # expecting an identifier
74 if ( (x = gobble(id)) == "" ) return ""
82 if ( gobble( funct_mark ) ) x = x " function returning"
84 if ( t = gobble( array_mark ) )
86 x = x " array" t " of"
96 BEGIN { id = "[_A-Za-z][_A-Za-z0-9]*"
97 funct_mark = "\([ \t]*\)"
98 array_mark = "\[[ \t]*[_A-Za-z0-9]*[ \t]*\]"
100 # I've assumed types are keywords or all CAPS or end in _t
101 # Other conventions could be added.
103 type0 = "int|char|short|long|double|float|void"
104 type1 = "[_A-Z][_A-Z0-9]*" # types are CAPS
105 type2 = "[_A-Za-z][_A-Za-z0-9]*_t" # end in _t
107 types = "(" type0 "|" type1 "|" type2 ")"
113 gsub( "/\*([^*]|\*[^/])*(\*/|$)" , " ") # remove comments
114 gsub( /[ \t]+/, " ") # squeeze white space to a single space
119 scope = gobble( "extern|static" )
121 if ( type = gobble("(struct|union|enum) ") )
122 type = type gobble(id) # get the tag
126 type = gobble("(un)?signed ") gobble( types )
132 if ( (x = decl()) && gobble( ";") )
135 if ( scope ) x = x " (" scope ")"
136 gsub( / +/, " ", x) #