1 1.1 tron #!/usr/bin/perl 2 1.1 tron 3 1.1 tron use Getopt::Std; 4 1.1 tron 5 1.1 tron # Usage: fixman [-f] postconf.proto filename.c >filename.c.new 6 1.1 tron 7 1.1 tron # fixman - fix parameter text in embedded man pages 8 1.1 tron 9 1.1 tron # Basic operation: 10 1.1 tron # 11 1.1 tron # - Read definitions fron postconf.proto like file 12 1.1 tron # 13 1.1 tron # - Read source file with embedded manual page 14 1.1 tron # 15 1.1 tron # - Write to stdout the updated source file. 16 1.1 tron # 17 1.1 tron 18 1.1 tron #use Getopt::Std; 19 1.1 tron 20 1.1 tron #$opt_h = undef; 21 1.1 tron #$opt_v = undef; 22 1.1 tron #getopts("hv"); 23 1.1 tron 24 1.1 tron #push @ARGV, "/dev/null"; # XXX 25 1.1 tron 26 1.1 tron $opt_f = undef; 27 1.1 tron $opt_v = undef; 28 1.1 tron getopts("fv"); 29 1.1 tron 30 1.1 tron die "Usage: $0 [-fv] protofile [sourcefile...] 31 1.1 tron -f: include full parameter description instead of one-line summary 32 1.1 tron -v: verbose mode\n" 33 1.1 tron unless $protofile = shift(@ARGV); 34 1.1 tron 35 1.1 tron # Save one definition. 36 1.1 tron 37 1.1 tron sub save_text 38 1.1 tron { 39 1.1 tron if ($category eq "PARAM") { 40 1.1 tron $text =~ s/\.\s.*/.\n/s unless $opt_f; 41 1.1 tron $param_text{$name} = $text; 42 1.1 tron $defval = "empty" unless $defval ne ""; 43 1.1 tron $defval_text{$name} = $defval; 44 1.1 tron if ($opt_v) { 45 1.1 tron printf "saving entry %s %.20s..\n", $name, $text; 46 1.1 tron } 47 1.1 tron } elsif ($category eq "CLASS") { 48 1.1 tron $class_text{$name} = $text; 49 1.1 tron if ($opt_v) { 50 1.1 tron printf "saving class %s %.20s..\n", $name, $text; 51 1.1 tron } 52 1.1 tron } else { 53 1.1 tron die "Unknown category: $category. Need PARAM or CLASS.\n"; 54 1.1 tron } 55 1.1 tron } 56 1.1 tron 57 1.1 tron # Emit one parameter name and text 58 1.1 tron 59 1.1 tron sub emit_text 60 1.1 tron { 61 1.1 tron my ($delim) = @_; 62 1.1 tron if ($block = $param_text{$name}) { 63 1.1 tron print "$delim .IP \"\\fB$name ($defval_text{$name})\\fR\"\n"; 64 1.1 tron $wantpp = 0; 65 1.1 tron $block =~ s/<a [^>]*>//g; 66 1.1 tron $block =~ s/<\/a>//g; 67 1.1 tron $block =~ s/<b>/\\fB/g; 68 1.1 tron $block =~ s/<i>/\\fI/g; 69 1.1 tron $block =~ s/<\/b>/\\fR/g; 70 1.1 tron $block =~ s/<\/i>/\\fR/g; 71 1.1 tron $block =~ s/\n(<p(re)?>)/\n.sp\n\1/g ; # if ($wantpp); 72 1.1 tron $block =~ s/^(<p(re)?>)/.sp\n\1/ ; # if ($wantpp); 73 1.1 tron $block =~ s/<p> */\n/g; 74 1.1 tron $block =~ s/<\/p>/\n/g; 75 1.1 tron $block =~ s/<pre>/\n.nf\n.na\n.ft C\n/g; 76 1.1 tron $block =~ s/<\/pre>/\n.fi\n.ad\n.ft R\n/g; 77 1.1 tron $block =~ s/<dl[^>]*>/\n.RS\n/g; 78 1.1 tron $block =~ s/<ul>/\n.RS\n/g; 79 1.1 tron #$block =~ s/<\/dl>/\n.PP\n/g; 80 1.1 tron #$block =~ s/<\/ul>/\n.PP\n/g; 81 1.1 tron $block =~ s/<\/dl>/\n.RE\n.IP ""\n/g; 82 1.1 tron $block =~ s/<\/ul>/\n.RE\n.IP ""\n/g; 83 1.1 tron $block =~ s/<dd>/\n/g; 84 1.1 tron $block =~ s/<\/dd>/\n/g; 85 1.1 tron $block =~ s/<li>\s*/\n.IP \\(bu\n/g; 86 1.1 tron $block =~ s/<dt>\s*/\n.IP "/g; 87 1.1 tron $block =~ s/\s*<\/dt>/"/g; 88 1.1 tron $block =~ s/<blockquote>/\n.na\n.nf\n.in +4\n/g; 89 1.1 tron $block =~ s/<\/blockquote>/\n.in -4\n.fi\n.ad\n/g; 90 1.1 tron $block =~ s/\n<br>/\n.br\n/g; 91 1.1 tron $block =~ s/<br>\s*/\n.br\n/g; 92 1.1.1.2 christos $block =~ s/≤/<=/g; 93 1.1.1.2 christos $block =~ s/≥/>=/g; 94 1.1 tron $block =~ s/</</g; 95 1.1 tron $block =~ s/>/>/g; 96 1.1.1.4 christos $block =~ s/<sup>/^/g; 97 1.1.1.4 christos $block =~ s;</sup>;;g; 98 1.1 tron 99 1.1 tron # Peep-hole optimizer. 100 1.1 tron $block =~ s/^\s+//g; 101 1.1 tron $block =~ s/\s+\n/\n/g; 102 1.1 tron $block =~ s/^\n//g; 103 1.1 tron $block =~ s/\.IP ""\n(\.sp\n)+/.IP ""\n/g; 104 1.1 tron $block =~ s/\.IP ""\n(\.[A-Z][A-Z])/\1/g; 105 1.1 tron $block =~ s/(.IP ""\n)+$//; 106 1.1 tron $block =~ s/^(\.(PP|sp)\n)+//; 107 1.1 tron #$wantpp = !($block =~ /^\.(SH|IP)/); 108 1.1 tron 109 1.1 tron # Boldify man page references. 110 1.1 tron $block =~ s/([_a-zA-Z0-9-]+)(\([0-9]\))/\\fB\1\\fR\2/g; 111 1.1 tron 112 1.1 tron # Encapsulate as C code comment. 113 1.1 tron $block =~ s/^([^.])/$delim\t\1/; 114 1.1 tron $block =~ s/^\./$delim ./; 115 1.1 tron $block =~ s/\n([^.])/\n$delim\t\1/g; 116 1.1 tron $block =~ s/\n\./\n$delim ./g; 117 1.1 tron 118 1.1 tron print $block; 119 1.1 tron } else { 120 1.1 tron print "$delim .IP \"\\fB$name ($defval)\\fR\"\n"; 121 1.1 tron print $text; 122 1.1 tron } 123 1.1 tron $name = ""; 124 1.1 tron } 125 1.1 tron 126 1.1 tron # Read the whole file even if we want to print only one parameter. 127 1.1 tron 128 1.1 tron open(POSTCONF, $protofile) || die " cannot open $protofile: $!\n"; 129 1.1 tron 130 1.1 tron while(<POSTCONF>) { 131 1.1 tron 132 1.1 tron next if /^#/; 133 1.1 tron next unless ($name || /\S/); 134 1.1 tron 135 1.1 tron if (/^%(PARAM|CLASS)/) { 136 1.1 tron 137 1.1 tron # Save the accumulated text. 138 1.1 tron 139 1.1 tron if ($name && $text) { 140 1.1 tron save_text(); 141 1.1 tron } 142 1.1 tron 143 1.1 tron # Reset the parameter name and accumulated text. 144 1.1 tron 145 1.1 tron $name = $text = ""; 146 1.1 tron $category = $1; 147 1.1 tron 148 1.1 tron # Accumulate the parameter name and default value. 149 1.1 tron 150 1.1 tron do { 151 1.1 tron $text .= $_; 152 1.1 tron } while(($_ = <POSTCONF>) && /\S/); 153 1.1 tron ($junk, $name, $defval) = split(/\s+/, $text, 3); 154 1.1 tron 155 1.1 tron $defval =~ s/\s+/ /g; 156 1.1 tron $defval =~ s/\s+$//; 157 1.1.1.2 christos $defval =~ s/≤/<=/g; 158 1.1.1.2 christos $defval =~ s/≥/>=/g; 159 1.1 tron $defval =~ s/</</g; 160 1.1 tron $defval =~ s/>/>/g; 161 1.1 tron $defval =~ s/"/'/g; 162 1.1 tron $text = ""; 163 1.1 tron next; 164 1.1 tron } 165 1.1 tron 166 1.1 tron # Accumulate the text in the class or parameter definition. 167 1.1 tron 168 1.1 tron $text .= $_; 169 1.1 tron 170 1.1 tron } 171 1.1 tron 172 1.1 tron # Save the last definition. 173 1.1 tron 174 1.1 tron if ($name && $text) { 175 1.1 tron save_text(); 176 1.1 tron } 177 1.1 tron 178 1.1 tron # Process source file with embedded text. For now, hard-coded for C & sh. 179 1.1 tron 180 1.1 tron while(<>) { 181 1.1 tron 182 1.1 tron if (/^(\/\*|#)\+\+/) { 183 1.1 tron $incomment = 1; 184 1.1 tron $name = ""; 185 1.1 tron print; 186 1.1 tron next; 187 1.1 tron } 188 1.1 tron 189 1.1 tron if (/^(\/\*|#)--/) { 190 1.1 tron emit_text($1) if ($name ne ""); 191 1.1 tron $incomment = 0; 192 1.1 tron print; 193 1.1 tron next; 194 1.1 tron } 195 1.1 tron 196 1.1 tron if (!$incomment) { 197 1.1 tron print; 198 1.1 tron next; 199 1.1 tron } 200 1.1 tron 201 1.1 tron if (/(\/\*|#) +CONFIGURATION +PARAM/) { 202 1.1 tron $incomment = 2; 203 1.1 tron } 204 1.1 tron 205 1.1 tron # Delete text after nested itemized list. 206 1.1 tron if ($incomment == 2 && /^(\/\*|#) +\.IP ""/) { 207 1.1 tron $text .= $_; 208 1.1 tron while (<>) { 209 1.1 tron last if /^(\/\*|#) +([A-Z][A-Z][A-Z]+|\.[A-Z][A-Z])/; 210 1.1 tron $text .= $_; 211 1.1 tron } 212 1.1 tron } 213 1.1 tron 214 1.1 tron # Delete nested itemized list. 215 1.1 tron if ($incomment == 2 && /^(\/\*|#) +\.RS/) { 216 1.1 tron $text .= $_; 217 1.1 tron $rsnest++; 218 1.1 tron while (<>) { 219 1.1 tron $text .= $_; 220 1.1 tron $rsnest++ if /^(\/\*|#) +\.RS/; 221 1.1 tron $rsnest-- if /(\/\*|#) +\.RE/; 222 1.1 tron last if $rsnest == 0; 223 1.1 tron } 224 1.1 tron next; 225 1.1 tron } 226 1.1 tron 227 1.1 tron if ($incomment == 2 && /^(\/\*|#) +\.IP +"?\\fB([a-zA-Z0-9_]+)( +\((.*)\))?/) { 228 1.1 tron emit_text($1) if ($name ne ""); 229 1.1 tron $name = $2; 230 1.1 tron $defval = $4; 231 1.1 tron $text = ""; 232 1.1 tron next; 233 1.1 tron } 234 1.1 tron 235 1.1.1.3 christos if ($incomment == 2 && /^(\/\*|#) +\.IP +"?\\fI([a-zA-Z0-9_]+)\\fB([a-zA-Z0-9_]+)( +\((.*)\))?/) { 236 1.1.1.3 christos emit_text($1) if ($name ne ""); 237 1.1.1.3 christos $name = "$2$3"; 238 1.1.1.3 christos $defval = $4; 239 1.1.1.3 christos $text = ""; 240 1.1.1.3 christos next; 241 1.1.1.3 christos } 242 1.1.1.3 christos 243 1.1 tron if ($incomment == 2 && /^(\/\*|#) +([A-Z][A-Z][A-Z]+|\.[A-Z][A-Z])/) { 244 1.1 tron emit_text($1) if ($name ne ""); 245 1.1 tron $incomment = 0 if /^(\/\*|#) +(SEE +ALSO|README +FILES|LICENSE|AUTHOR)/; 246 1.1 tron print; 247 1.1 tron next; 248 1.1 tron } 249 1.1 tron 250 1.1 tron if ($name ne "") { 251 1.1 tron $text .= $_; 252 1.1 tron next; 253 1.1 tron } 254 1.1 tron 255 1.1 tron print; 256 1.1 tron next; 257 1.1 tron } 258 1.1 tron 259 1.1 tron die "Unterminated comment\n" if $incomment; 260