File: gdecl.awk

package info (click to toggle)
mawk 1.3.4.20260129-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,244 kB
  • sloc: ansic: 19,998; sh: 4,627; yacc: 1,182; awk: 903; makefile: 301
file content (127 lines) | stat: -rwxr-xr-x 2,953 bytes parent folder | download | duplicates (2)
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
#!/usr/bin/mawk -f
# $MawkId: gdecl.awk,v 1.6 2020/09/19 14:04:25 tom Exp $

# 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,  xg)
{
  sub( /^ /, "", line)  # eat SPACE if any

  # surround s with parenthesis to make sure ^ acts on the
  # whole thing

  if ( match(line, "^" "(" s ")") > 0 ) {
    xg = substr(line, 1, RLENGTH)
    line = (RLENGTH < length(line)) ? substr(line, RLENGTH+1) : ""
    return xg
  } else {
    return ""
  }
}

function ptr_to(n,  xp)  # print "pointer to" , n times
{ n = int(n)
  if ( n <= 0 )  return ""
  xp = "pointer to" ; n--
  while ( n-- )  xp = xp " pointer to"
  return xp
}

#recursively get a decl
# returns an english description of the declaration or
# "" if not a C declaration.
function  decl(   xd, t, ptr_part)
{

  xd = gobble("[* ]+")   # get list of *** ...
  gsub(/ /, "", xd)   # remove all SPACES
  ptr_part = ptr_to( length(xd) )

  # 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 ( (xd = decl()) == "" || gobble( "\\)" ) == "" ) return ""

  }
  else  #  expecting an identifier
  {
    if ( (xd = gobble(id)) == "" )  return ""
    xd = xd ":"
  }

  # finally look for ()
  # or  [ opt_size ]

  while ( 1 )
     if ( gobble( funct_mark ) )  xd = xd " function returning"
     else
     if ( ( t = gobble( array_mark ) ) != "" )
     { gsub(/ /, "", t)
       xd = xd " array" t " of"
     }
     else  break


   xd = xd " "  ptr_part
   return xd
}


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
    }

}