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