# # makepro.awk - generate prototype lists # BEGIN { aborting = 0 # arg 1 is the name of the file to process # arg 2 is the name of the subdirectory it is in if(ARGC != 3) { aborting = 1 exit 1 } name = ARGV[1] gsub(/^.*\//, "", name) gsub(/\.c$/, "", name) name = ARGV[2] "_" name gsub(/\//, "_", name) ARGC-- printf "E#ifndef have_%s_globals\n", name printf "E#define have_%s_globals\n", name printf "E\n" } # all relevant declarations are preceded by "/**/" on a line by itself /^\/\*\*\/$/ { # The declaration is on following lines. The interesting part might # be terminated by a `{' (`int foo(void) { }' or `int bar[] = {') # or `;' (`int x;'). line = "" isfunc = 0 while(1) { if(getline <= 0) { aborting = 1 exit 1 } if (line == "" && $0 ~ /^[ \t]*#/) { # Directly after the /**/ was a preprocessor line. # Spit it out and re-start the outer loop. printf "E%s\n", $0 printf "L%s\n", $0 next } gsub(/\t/, " ") line = line " " $0 gsub(/\/\*([^*]|\*+[^*\/])*\*+\//, " ", line) if(line ~ /\/\*/) continue # If it is a function definition, note so. if(line ~ /\) *[{].*$/) #} isfunc = 1 if(sub(/ *[{;].*$/, "", line)) #} break } # Put spaces around each identifier. while(match(line, /[^_0-9A-Za-z ][_0-9A-Za-z]/) || match(line, /[_0-9A-Za-z][^_0-9A-Za-z ]/)) line = substr(line, 1, RSTART) " " substr(line, RSTART+1) # Separate declarations into a type and a list of declarators. # In each declarator, "@{" and "@}" are used in place of parens to # mark function parameter lists, and "@!" is used in place of commas # in parameter lists. "@<" and "@>" are used in place of # non-parameter list parens. gsub(/ _ +/, " _ ", line) while(1) { if(isfunc && match(line, /\([^()]*\)$/)) line = substr(line, 1, RSTART-1) " _ (" substr(line, RSTART) ")" else if(match(line, / _ \(\([^,()]*,/)) line = substr(line, 1, RSTART+RLENGTH-2) "@!" substr(line, RSTART+RLENGTH) else if(match(line, / _ \(\([^,()]*\)\)/)) line = substr(line, 1, RSTART-1) "@{" substr(line, RSTART+5, RLENGTH-7) "@}" substr(line, RSTART+RLENGTH) else if(match(line, /\([^,()]*\)/)) line = substr(line, 1, RSTART-1) "@<" substr(line, RSTART+1, RLENGTH-2) "@>" substr(line, RSTART+RLENGTH) else break } sub(/^ */, "", line) match(line, /^((const|enum|mod_export|static|struct|union) +)*([_0-9A-Za-z]+ +|((char|double|float|int|long|short|unsigned|void) +)+)((const|static) +)*/) dtype = substr(line, 1, RLENGTH) sub(/ *$/, "", dtype) if(" " dtype " " ~ / static /) locality = "L" else locality = "E" exported = " " dtype " " ~ / mod_export / line = substr(line, RLENGTH+1) "," # Handle each declarator. while(match(line, /^[^,]*,/)) { # Separate out the name from the declarator. Use "@+" and "@-" # to bracket the name within the declarator. Strip off any # initialiser. dcltor = substr(line, 1, RLENGTH-1) line = substr(line, RLENGTH+1) sub(/\=.*$/, "", dcltor) match(dcltor, /^([^_0-9A-Za-z]| const )*/) dcltor = substr(dcltor, 1, RLENGTH) "@+" substr(dcltor, RLENGTH+1) match(dcltor, /^.*@\+[_0-9A-Za-z]+/) dcltor = substr(dcltor, 1, RLENGTH) "@-" substr(dcltor, RLENGTH+1) dnam = dcltor sub(/^.*@\+/, "", dnam) sub(/@-.*$/, "", dnam) # Put parens etc. back gsub(/@[{]/, " _((", dcltor) gsub(/@}/, "))", dcltor) gsub(/@/, ")", dcltor) gsub(/@!/, ",", dcltor) # If this is exported, add it to the exported symbol list. if(exported) printf "X%s\n", dnam # Format the declaration for output dcl = dtype " " dcltor ";" if(locality ~ /E/) dcl = "extern " dcl gsub(/@[+-]/, "", dcl) gsub(/ +/, " ", dcl) while(match(dcl, /[^_0-9A-Za-z] ./) || match(dcl, /. [^_0-9A-Za-z]/)) dcl = substr(dcl, 1, RSTART) substr(dcl, RSTART+2) printf "%s%s\n", locality, dcl } } END { if(aborting) exit 1 printf "E\n" printf "E#endif /* !have_%s_globals */\n", name }