/usr/share/doc/mawk/examples/gdecl.awk is in mawk 1.3.3-17ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #!/usr/bin/mawk
# parse a C declaration by recursive descent
#
# decl.awk with extra escapes \
################################################
############################################
# lexical scanner -- gobble()
# input : string s -- treated as a regular expression
# gobble eats SPACE, then eats longest match of s off front
# of global variable line.
# Cuts the matched part off of line
#
function gobble(s, x)
{
sub( /^ /, "", line) # eat SPACE if any
# surround s with parenthesis to make sure ^ acts on the
# whole thing
match(line, "^" "(" s ")")
x = substr(line, 1, RLENGTH)
line = substr(line, RLENGTH+1)
return x
}
function ptr_to(n, x) # print "pointer to" , n times
{ n = int(n)
if ( n <= 0 ) return ""
x = "pointer to" ; n--
while ( n-- ) x = x " pointer to"
return x
}
#recursively get a decl
# returns an english description of the declaration or
# "" if not a C declaration.
function decl( x, t, ptr_part)
{
x = gobble("[* ]+") # get list of *** ...
gsub(/ /, "", x) # remove all SPACES
ptr_part = ptr_to( length(x) )
# We expect to see either an identifier or '('
#
if ( gobble("\\(") )
{
# this is the recursive descent part
# we expect to match a declaration and closing ')'
# If not return "" to indicate failure
if ( (x = decl()) == "" || gobble( "\\)" ) == "" ) return ""
}
else # expecting an identifier
{
if ( (x = gobble(id)) == "" ) return ""
x = x ":"
}
# finally look for ()
# or [ opt_size ]
while ( 1 )
if ( gobble( funct_mark ) ) x = x " function returning"
else
if ( t = gobble( array_mark ) )
{ gsub(/ /, "", t)
x = x " array" t " of"
}
else break
x = x " " ptr_part
return x
}
BEGIN { id = "[_A-Za-z][_A-Za-z0-9]*"
funct_mark = "\\([ \t]*\\)"
array_mark = "\\[[ \t]*[_A-Za-z0-9]*[ \t]*\\]"
# I've assumed types are keywords or all CAPS or end in _t
# Other conventions could be added.
type0 = "int|char|short|long|double|float|void"
type1 = "[_A-Z][_A-Z0-9]*" # types are CAPS
type2 = "[_A-Za-z][_A-Za-z0-9]*_t" # end in _t
types = "(" type0 "|" type1 "|" type2 ")"
}
{
gsub( /\/\*([^*]|\*[^\/])*(\*\/|$)/ , " ") # remove comments
gsub( /[ \t]+/, " ") # squeeze white space to a single space
line = $0
scope = gobble( "extern|static" )
if ( type = gobble("(struct|union|enum) ") )
type = type gobble(id) # get the tag
else
{
type = gobble("(un)?signed ") gobble( types )
}
if ( ! type ) next
if ( (x = decl()) && gobble( ";") )
{
x = x " " type
if ( scope ) x = x " (" scope ")"
gsub( / +/, " ", x) #
print x
}
}
|