gsch2pcb: Make --m4-file and -m4-pcbdir arguments work again.
[geda-gaf/peter-b.git] / utils / scripts / refdes_renum
blob88e1876a7ebf3c4c56ef7e7f9976635a05614212
1 #!/usr/bin/perl -w
3 # $Id$
5 # Copyright (C) 2003 Dan McMahill
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 # This script is used to renumber devices in a gschem (part of gEDA)
23 # schematic. This program works on single as well as multi-sheet
24 # schematics.
26 # Usage:
27 # renum.pl file1.sch [file2.sch [file3.sch ...]]
30 # for parsing input options
31 use Getopt::Long;
33 # for ceil function
34 use POSIX;
36 # don't allow -he to be interpreted as --help
37 $Getopt::Long::autoabbrev=0;
39 # my $clear; # reset all refdes
40 &GetOptions(("help" => \&usage,
41 "nocopy" => \$nocopy,
42 "pgskip:100" => \$pgskip,
43 "verbose" => \$verbose,
44 "version" => \&version,
45 "clear" => \$clear,
46 "gentle" => \$gentle,
47 "force" => \$force,
48 ));
50 usage() if $Getopt::Long::error;
53 # By default pgskip is empty. But if the user gives
54 # the --pgskip option with no value, then assign pgskip
55 # to 100.
56 if (defined($pgskip) && ($pgskip == 0)) {
57 $pgskip = 100;
61 # This makes --gentle the default behavior. To
62 # force refdes renumbering, use --force.
63 $gentle = 1;
64 if ( defined($force) || defined($clear) ) {
65 undef($gentle);
68 # Print usage string in event user didn't call out any args
69 usage() unless @ARGV;
71 # Make sure the input schematic exists and we can read it.
72 # Also count number of files to open.
73 $i=0;
74 while(@ARGV) {
75 $fname[$i]=shift(@ARGV);
76 die_sdb(1, "Schematic file $fname[$i] does not exist or can not be read")
77 unless -r $fname[$i];
78 $i++;
80 $filecnt = $i; # number of files to open
81 if($verbose) {print "Found $filecnt files to process\n";}
83 # To refdes an entire design, we normally just loop through all files
84 # and process each one in order. However if --gentle option is set,
85 # we need to make two passes through all files. First to create a hash
86 # of the highest refdeses used, and second to update unnumbered
87 # refdeses. The hash is used to know where to start the refdes numbering.
89 # It gets more complicated. If --pgskip is not set, then we only need
90 # to find the highest refdes overall. But if --pgskip is set, then
91 # we need to know the highest refdes on each *page*. This is accomplished
92 # on the first scan by creating the variable $highdev{$i, $pre} when --pgskip
93 # is defined, but using the variable $highdev{$pre} when it is not.
95 if (defined($gentle)) { # First scan through design to build hash
96 for($i=0; $i < $filecnt; $i++) { # $i is the file index.
97 print "Scanning input file #".($i+1).": $fname[$i]\n";
98 open(NETLIST,"$fname[$i]") or die_sdb(1, "Can't open $fname[$i]: $!\n");
100 while($line = <NETLIST>) { # Iterate over lines found in .sch file.
101 unless( $line =~ /^refdes/) {
102 next;
104 # Found refdes line. Eat the newline.
105 $line =~ s/\n//;
107 # Now extract component prefix and suffix.
108 if($verbose) {print ("Matching $line ....\n");}
109 $line =~ /refdes=([a-zA-Z_]+)(\d+|\??)/i;
110 my $pre = $1;
111 my $suf = $2 ? $2 : "?";
112 if($verbose) {print "Refdes line \"$line\" has pre=$pre suf=$suf\n";}
114 # Now put highest refdes found into $highdev hash.
115 if (defined($pgskip)) {
116 if ($suf eq "?") {
117 # Part has no pre-existing refdes.
118 # Skip to next part.
119 next;
120 } elsif (!defined($highdev{$i, $pre})) {
121 # refdes is not cached, but refdes exists on part.
122 # Create new cache entry
123 if ($suf < $pgskip) {
124 # if pgskip=100, on pg 1, and suf = 23, set highdev=123.
125 $highdev{$i, $pre} = ($i+1)*$pgskip + $suf;
126 } elsif ( ( ($i+1)*$pgskip < $suf) &&
127 ( ($i+2)*$pgskip > $suf) ) {
128 # if pgskip=100, we're on pg 2, and suf = 204, set highdev=204.
129 $highdev{$i, $pre} = $suf;
130 } else {
131 # I don't know what to do!
132 die_sdb(3, "Encountered refdes incompatable with --pgskip setting. Refdes=$pre$suf.\n");
135 } elsif ($highdev{$i, $pre} < $suf) {
136 # part has refdes and refdes is higher than cached
137 # value. Store this new value as highest value.
138 $highdev{$i, $pre} = $suf;
139 } elsif ($highdev{$i, $pre} >= $suf) {
140 # part has refdes, but refdes is lower than cached
141 # high value. Leave it alone.
142 next;
143 } else {
144 # Should never get here
145 die_sdb(4, "Invalid refdes with --pgskip set! Exiting....\n");
148 if($verbose) {
149 print "On page ".($i+1).", caching highest refdes $pre$highdev{$i, $pre}\n";
151 } else {
152 if ($suf eq "?") {
153 # Part has no pre-existing refdes.
154 next;
155 } elsif (!defined($highdev{$pre}) ) {
156 # refdes is not cached, and refdes exists on part. Create new
157 # cache entry
158 $highdev{$pre} = $suf;
159 } elsif ($highdev{$pre} < $suf) {
160 # part has refdes and refdes is higher than cached
161 # value. Store this new value as highest value.
162 $highdev{$pre} = $suf;
163 } elsif ($highdev{$pre} >= $suf) {
164 # part has refdes, but refdes is lower than cached
165 # high value. Leave it alone.
166 next;
167 } else {
168 # Should never get here
169 die_sdb(4, "Invalid refdes! Exiting....\n");
171 if($verbose) {
172 print "Caching highest refdes $pre$highdev{$pre}\n";
176 } # while($line = <NETLIST>)
177 close(NETLIST);
178 } # for($i=0; $i < $filecnt; $i++)
179 } # if (defined($gentle))
182 # OK, now we can read through the netlist file again, assign refdeses,
183 # and write the output file.
184 for($i=0; $i < $filecnt; $i++) { # $i is the file index.
185 print "Now processing input file #".($i+1).": $fname[$i]\n";
186 open(NETLIST,"$fname[$i]") or die_sdb(1, "Can't open $fname[$i]: $!\n");
188 # open output netlist
189 $outfname="$fname[$i].renum";
190 open(OUTNET,">$outfname") or die_sdb(2, "Can't open $outfname: $!\n");
192 # Iterate over lines found in .sch file.
193 while($line = <NETLIST>) {
194 unless( $line =~ /^refdes/) {
195 print OUTNET $line;
196 next;
199 # Found refdes line. Eat the newline.
200 $line =~ s/\n//;
202 # Now extract component prefix and suffix.
203 if($verbose) {print ("Processing $line ....\n");}
204 $line =~ /refdes=([a-zA-Z_]+)(\d+|\??)/i;
205 my $pre = $1;
206 my $suf = $2 ? $2 : "?";
207 if($verbose) {print "Refdes line \"$line\" has pre=$pre suf=$suf\n";}
209 # Now finally update refdes
210 if ($clear) {
211 # Just overwrite all refdeses upon clear
212 if($verbose) {print ("Clearing refdes=$pre$suf\n");}
213 print OUTNET "refdes=$pre?\n";
214 } elsif (defined($pgskip) && defined($gentle)) {
215 # If highdev exists, then start devcnt there, otherwise, start
216 # devcnt at correct value for each page.
217 if (!defined($devcnt{$i, $pre}) && defined($highdev{$i, $pre})) {
218 $devcnt{$i, $pre} = $highdev{$i, $pre};
219 } elsif (!defined($devcnt{$i, $pre}) && !defined($highdev{$i, $pre})) {
220 $devcnt{$i, $pre} = ($i+1)*$pgskip ;
223 if ($suf eq "?") {
224 $devcnt{$i, $pre}++;
225 if ($devcnt{$i, $pre} >= ($i+2)*$pgskip) {
226 print STDERR "ERROR: You are numbering more than $pgskip elements with\n";
227 print STDERR "prefix $pre on this sheet. You will need to either\n";
228 print STDERR "reduce this number or specify a larger step with the\n";
229 print STDERR "--pgskip argument.\n";
230 die_sdb(3, "");
232 print "Renumbering $line to $pre$devcnt{$i, $pre}\n" if($verbose);
233 print OUTNET "refdes=$pre$devcnt{$i, $pre}\n";
234 } else {
235 print "Leaving line=$line alone\n" if($verbose);
236 print OUTNET "refdes=$pre$suf\n";
239 } elsif (defined($pgskip) && !defined($gentle)) {
240 if (!defined($devcnt{$i, $pre})) {
241 $devcnt{$i, $pre} = ($i+1)*$pgskip ;
243 $devcnt{$i, $pre}++;
244 if ($devcnt{$i, $pre} >= ($i+2)*$pgskip) {
245 print STDERR "ERROR: You are numbering more than $pgskip elements with\n";
246 print STDERR "prefix $pre on this sheet. You will need to either\n";
247 print STDERR "reduce this number or specify a larger step with the\n";
248 print STDERR "--pgskip argument.\n";
249 die_sdb(3, "");
251 print "Renumbering $line to $pre$devcnt{$i, $pre}\n" if($verbose);
252 print OUTNET "refdes=$pre$devcnt{$i, $pre}\n";
254 } elsif (!defined($pgskip) && defined($gentle)) {
255 if (!defined($devcnt{$pre}) && defined($highdev{$pre})) {
256 $devcnt{$pre} = $highdev{$pre};
257 } elsif (!defined($devcnt{$pre}) && !defined($highdev{$pre})) {
258 $devcnt{$pre} = 0;
260 if ($suf eq "?") {
261 $devcnt{$pre}++;
262 print "Renumbering $line to $pre$devcnt{$pre}\n" if($verbose);
263 print OUTNET "refdes=$pre$devcnt{$pre}\n";
264 } else {
265 print "Leaving line=$line alone\n" if($verbose);
266 print OUTNET "refdes=$pre$suf\n";
268 } elsif (!defined($pgskip) && !defined($gentle)) {
269 if (!defined($devcnt{$pre})) {
270 $devcnt{$pre} = 0 ;
272 $devcnt{$pre}++;
273 print "Renumbering $line to $pre$devcnt{$pre}\n" if($verbose);
274 print OUTNET "refdes=$pre$devcnt{$pre}\n";
276 } else {
277 die_sdb(4, "Invalid state when trying to update refdes! Exiting.....\n");
279 } # while($line = <NETLIST>)
280 close(NETLIST);
281 close(OUTNET);
284 # make this an option to not overwrite the original
285 if( $nocopy ) {
286 print "Leaving page #",$i+1," output in $outfname\n";
288 else {
289 system("mv $outfname $fname[$i]");
293 exit(0);
296 #######################################################################
298 # Subroutines
300 #######################################################################
302 #---------------------------------
303 # usage()
305 # prints program usage
306 #---------------------------------
308 sub usage {
309 my $pname = $0;
310 $pname =~ s/.*\///g;
312 print "Usage:\n\n";
313 print "\t$pname [--nocopy] [--pgskip [number] ] file1 [file2 [file3 ... ] ]\n";
314 print "\t$pname --help\n";
315 print "\t$pname --version\n";
316 print "\n";
317 print "$pname reads a gschem schematic file or files and renumbers all reference\n";
318 print "designators. The reference designators are numbered starting with 1 and the\n";
319 print "old schematic file is replaced by the modified schematic file.\n";
320 print "\n";
321 print "$pname accepts the following options:\n";
322 print "\n";
323 print " --help Displays this help message.\n";
324 print "\n";
325 print " --nocopy If given, this flag leaves the modified files in new files\n";
326 print " whose names are generated by appending a \".renum\" to the\n";
327 print " original file names. The default is to overwrite the original.\n";
328 print "\n";
329 print " --pgskip When this flag is used, components on the first schematic sheet\n";
330 print " are numbered starting with 101. On the second sheet, they start\n";
331 print " with 201, etc Specifying a value gives the step between pages.\n";
332 print " For example --pgskip 10 will start with 11, 21, 31, etc.\n";
333 print "\n";
334 print " --gentle This flag tells refdes_renum to leave any refdeses\n";
335 print " alone if they already have numbers. Use this option to number\n";
336 print " new components in a schematic which has already been numbered.\n";
337 print " Note that --gentle is set by default!\n";
338 print "\n";
339 print " --force Set this flag to renumber all refdeses, whether they are already\n";
340 print " numbered or not.\n";
341 print "\n";
342 print " --verbose Enables verbose output.\n";
343 print "\n";
344 print " --version Shows the version of this program.\n";
345 print "\n\n";
346 print "Return codes:\n\n";
347 print "\t$pname returns the following codes to the shell upon completion:\n";
348 print "\n";
349 print " 0 Program ran successfully.\n";
350 print " 1 Error opening or reading input file.\n";
351 print " 2 Error opening or writing output file.\n";
352 print " 3 Too many components for --pgskip setting.\n";
353 print " 4 Internal error (program bug encountered).\n";
354 print "\n";
355 print "Usage examples:\n\n";
356 print "\t$pname mysch.sch\n";
357 print "\t$pname --pgskip pg1.sch pg2.sch pg3.sch\n";
358 print "\n\n";
359 print "$pname was written by Dan McMahill <dmcmahill\@netbsd.org>\n";
360 print "\n\n";
361 exit(0);
364 #---------------------------------
365 # version()
367 # prints program version
368 #---------------------------------
370 sub version {
371 open(PROG,"$0") or die_sdb(4, "Could not open \"$0\" to find version\n\n");
372 my $pname = $0;
373 $pname =~ s/.*\///g;
375 while($line = <PROG>) {
376 if( $line =~ /^#\s*\$Id.*\$/) {
377 @words = split ' ',,$line;
378 $version = $words[3];
379 $date = $words[4];
380 print "$pname ($0): Version $version, $date\n";
381 exit(0);
384 die_sdb(4, "Could not determine version of \"$0\"\n\n");
387 #-------------------------------------------
388 # die_sdb(rc, string)
390 # Local version of die. Sets return code
391 # for shell, then calls die(string)
392 #--------------------------------------------
393 sub die_sdb {
394 my $rc = $_[0];
395 my $string = $_[1];
396 $! = $rc;
397 die($string);
400 # ----------------------------------------------
402 # Change Log
404 # $Log$
405 # Revision 1.8 2007-04-17 20:19:23 pcjc2
406 # Merge changes from noscreen branch
408 # Revision 1.2.6.2 2007/04/17 16:19:01 pcjc2
409 # Sync with trunk
411 # Revision 1.7 2007/04/15 23:20:31 sdb
412 # Made --gentle the default behavior of refdes_renum.
414 # Revision 1.7 2007/04/15 SDB
415 # Made --gentle default behavior. Now user must use --force
416 # to get old behavior, which renumbers all refdeses whether
417 # already numbered or not.
419 # Revision 1.6 2007/04/15 00:42:22 sdb
420 # Added --gentle flag to refdes_renum, which won't renumber refdeses
421 # which already have a number.
423 # Revision 1.5 4.9.2007 sdb.
424 # Added --gentle flag, and include logic to handle case
425 # where user mixes --gentle with --pgskip.
427 # Revision 1.4 2007/02/24 18:43:17 pcjc2
428 # Merge changes to date from noscreen branch.
430 # Revision 1.2.6.1 2007/02/11 23:59:10 pcjc2
431 # Sync with trunc
433 # Revision 1.3 2007/02/10 20:46:17 sdb
434 # Added --clear option to clear refdeses. (* jcl *)
436 # Revision 1.2 2005/12/21 00:09:56 danmc
437 # - Fix a bug where when using the --pgskip option, components which were
438 # present on page n, but not on pages n+1 through n+j, and present again
439 # on page n+j+1 got numbered in a strange way. For example, J101 on page
440 # 1, no connectors on page 2, J201 on page 3 instead of J301. Noted by
441 # Stuart Brorson.
443 # - While here allow the user to change the default increment from 100 to whatever
444 # they want.
446 # - Also fix a bug where exactly 101 components with the same refdes prefix
447 # would cause a duplicate refdes on the next page.
449 # Revision 1.1 2003/02/21 03:21:12 ahvezda
450 # Added scripts/refdes_renum written by Dan McMahill