1#
2# makepro.awk - generate prototype lists
3#
4
5BEGIN {
6    aborting = 0
7
8    # arg 1 is the name of the file to process
9    # arg 2 is the name of the subdirectory it is in
10    if(ARGC != 3) {
11	aborting = 1
12	exit 1
13    }
14    name = ARGV[1]
15    gsub(/^.*\//, "", name)
16    gsub(/\.c$/, "", name)
17    name = ARGV[2] "_" name
18    gsub(/\//, "_", name)
19    ARGC--
20
21    printf "E#ifndef have_%s_globals\n", name
22    printf "E#define have_%s_globals\n", name
23    printf "E\n"
24}
25
26# all relevant declarations are preceded by "/**/" on a line by itself
27
28/^\/\*\*\/$/ {
29    # The declaration is on following lines.  The interesting part might
30    # be terminated by a `{' (`int foo(void) { }' or `int bar[] = {')
31    # or `;' (`int x;').
32    line = ""
33    isfunc = 0
34    while(1) {
35	if(getline <= 0) {
36	    aborting = 1
37	    exit 1
38	}
39	if (line == "" && $0 ~ /^[ \t]*#/) {
40            # Directly after the /**/ was a preprocessor line.
41            # Spit it out and re-start the outer loop.
42	    printf "E%s\n", $0
43	    printf "L%s\n", $0
44	    next
45	}
46	gsub(/\t/, " ")
47	line = line " " $0
48	gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line)
49	if(line ~ /\/\*/)
50	    continue
51	# If it is a function definition, note so.
52	if(line ~ /\) *(VA_DCL )*[{].*$/) #}
53	    isfunc = 1
54	if(sub(/ *[{;].*$/, "", line)) #}
55	    break
56    }
57    if (!match(line, /VA_ALIST/)) {
58	# Put spaces around each identifier.
59	while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) ||
60	      match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/))
61	    line = substr(line, 1, RSTART) " " substr(line, RSTART+1)
62    }
63    # Separate declarations into a type and a list of declarators.
64    # In each declarator, "@{" and "@}" are used in place of parens to
65    # mark function parameter lists, and "@!" is used in place of commas
66    # in parameter lists.  "@<" and "@>" are used in place of
67    # non-parameter list parens.
68    gsub(/ _ +/, " _ ", line)
69    while(1) {
70	if(isfunc && match(line, /\([^()]*\)$/))
71	    line = substr(line, 1, RSTART-1) " _ (" substr(line, RSTART) ")"
72	else if(match(line, / _ \(\([^,()]*,/))
73	    line = substr(line, 1, RSTART+RLENGTH-2) "@!" substr(line, RSTART+RLENGTH)
74	else if(match(line, / _ \(\([^,()]*\)\)/))
75	    line = substr(line, 1, RSTART-1) "@{" substr(line, RSTART+5, RLENGTH-7) "@}" substr(line, RSTART+RLENGTH)
76	else if(match(line, /\([^,()]*\)/))
77	    line = substr(line, 1, RSTART-1) "@<" substr(line, RSTART+1, RLENGTH-2) "@>" substr(line, RSTART+RLENGTH)
78	else
79	    break
80    }
81    sub(/^ */, "", line)
82    match(line, /^((const|enum|mod_export|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/)
83    dtype = substr(line, 1, RLENGTH)
84    sub(/ *$/, "", dtype)
85    if(" " dtype " " ~ / static /)
86	locality = "L"
87    else
88	locality = "E"
89    exported = " " dtype " " ~ / mod_export /
90    line = substr(line, RLENGTH+1) ","
91    # Handle each declarator.
92    if (match(line, /VA_ALIST/)) {
93	# Already has VARARGS handling.
94
95	# Put parens etc. back
96	gsub(/@[{]/, "((", line)
97	gsub(/@}/, "))", line)
98	gsub(/@</, "(", line)
99	gsub(/@>/, ")", line)
100	gsub(/@!/, ",", line)
101	sub(/,$/, ";", line)
102	gsub(/mod_export/, "mod_import_function", dtype)
103	gsub(/VA_ALIST/, "VA_ALIST_PROTO", line)
104	sub(/ VA_DCL/, "", line)
105
106	if(locality ~ /E/)
107	    dtype = "extern " dtype
108
109	if (match(line, /[_0-9A-Za-z]+\(VA_ALIST/))
110	  dnam = substr(line, RSTART, RLENGTH-9)
111
112	# If this is exported, add it to the exported symbol list.
113	if (exported)
114	    printf "X%s\n", dnam
115
116	printf "%s%s %s\n", locality, dtype, line
117    } else {
118	while(match(line, /^[^,]*,/)) {
119		# Separate out the name from the declarator.  Use "@+" and "@-"
120		# to bracket the name within the declarator.  Strip off any
121		# initialiser.
122		dcltor = substr(line, 1, RLENGTH-1)
123		line = substr(line, RLENGTH+1)
124		sub(/\=.*$/, "", dcltor)
125		match(dcltor, /^([^_0-9A-Za-z]| const )*/)
126		dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1)
127		match(dcltor, /^.*@\+[_0-9A-Za-z]+/)
128		dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1)
129		dnam = dcltor
130		sub(/^.*@\+/, "", dnam)
131		sub(/@-.*$/, "", dnam)
132
133		# Put parens etc. back
134		gsub(/@[{]/, " _((", dcltor)
135		gsub(/@}/, "))", dcltor)
136		gsub(/@</, "(", dcltor)
137		gsub(/@>/, ")", dcltor)
138		gsub(/@!/, ",", dcltor)
139
140		# If this is exported, add it to the exported symbol list.
141		if(exported)
142		    printf "X%s\n", dnam
143
144		# Format the declaration for output
145		dcl = dtype " " dcltor ";"
146		if(locality ~ /E/)
147		    dcl = "extern " dcl
148		if(isfunc)
149		    gsub(/ mod_export /, " mod_import_function ", dcl)
150		else
151		    gsub(/ mod_export /, " mod_import_variable ", dcl)
152		gsub(/@[+-]/, "", dcl)
153		gsub(/ +/, " ", dcl)
154		while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/))
155		    dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2)
156		printf "%s%s\n", locality, dcl
157	}
158    }
159}
160
161END {
162    if(aborting)
163	exit 1
164    printf "E\n"
165    printf "E#endif /* !have_%s_globals */\n", name
166}
167