#!/usr/bin/perl -w
#
# $Id: refdes_renum,v 1.2 2005/12/21 00:09:56 danmc Exp $
#
# Copyright (C) 2003 Dan McMahill
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


# This script is used to renumber devices in a gschem (part of gEDA)
# schematic.  This program works on single as well as multi-sheet 
# schematics.
#
# Usage:
#    renum.pl file1.sch [file2.sch [file3.sch ...]]
#

# for parsing input options
use Getopt::Long;

# for ceil function
use POSIX;

# don't allow -he to be interpreted as --help
$Getopt::Long::autoabbrev=0;

&GetOptions(("help" => \&usage, 
	     "nocopy" => \$nocopy,
	     "pgskip:i" => \$pgskip,
	     "verbose" => \$verbose,
	     "version" => \&version
	     ));

usage() if $Getopt::Long::error;

# set the default increment for sheets
unless( $pgskip ) { $pgskip = 100; }

usage() unless @ARGV;



# make sure the input schematic exists and we can read it
$i=0;
while(@ARGV) {
  $fname[$i]=shift(@ARGV);
  die "Schematic file $fname[$i] does not exist or can not be read"
    unless -r $fname[$i];
  $i++;
}

$filecnt = $i;

for($i=0; $i < $filecnt; $i++) {
  print "Processing input file #",$i+1,": $fname[$i]\n";
  open(NETLIST,"$fname[$i]") or die "Can't open $fname[$i]: $!\n";

  # open output netlist
  $outfname="$fname[$i].renum";
  open(OUTNET,">$outfname") or die "Can't open $outfname: $!\n";

  while($line = <NETLIST>) {
    unless( $line =~ /^refdes/) {
      print OUTNET $line;
      next;
    }
    # eat the newline
    $line =~ s/\n//;

    # for lines like "refdes=CR37" pick out the "CR" part.
    # There's probably a more concise way, but the perl book
    # is at work right now.
    $pre = $line;
    $pre =~ s/^refdes=//;
    $pre =~ s/[0-9\?]*$//;
    print "Refdes line \"$line\" has pre=\"$pre\"\n" if($verbose);

    # if we're skipping numbers, then start at 100 for page 1
    # and we'll jump to 200 for page 2, etc.
    if( ! $devcnt{$pre} ) { $devcnt{$pre} = $pgskip ? ($i+1)*$pgskip : 0; }
    $devcnt{$pre}++;
    print "Renumbering $line to $pre$devcnt{$pre}\n" if($verbose);
    print OUTNET "refdes=$pre$devcnt{$pre}\n";
  }
  close(NETLIST);
  close(OUTNET);

  # round each element up to the next 100 to help identify what
  # schematic page a component is on by the refdes.
  if( $pgskip ) {
      foreach $dev (keys %devcnt) {
	  my $new_cnt = ($i + 2)*$pgskip;
	  if( $new_cnt < $devcnt{$dev} ) {
	      print STDERR "ERROR:  You have more than $pgskip elements with\n";
	      print STDERR "prefix $dev on this sheet.  You will need to either\n";
	      print STDERR "reduce this number or specify a larger step with the\n";
	      print STDERR "--pgskip argument.\n";
	      exit( 1 );
	  }
	  $devcnt{$dev} = $new_cnt;
	  print "Incremented \"$dev\" counter to $devcnt{$dev}\n" if($verbose);
      }
  }

  # make this an option to not overwrite the original
  if( $nocopy ) {
      print "Leaving page #",$i+1," output in $outfname\n";
      }
  else {
      system("mv $outfname $fname[$i]");
  }
}

exit;


#######################################################################
#
# Subroutines
#
#######################################################################

#---------------------------------
# usage()
#
# prints program usage
#---------------------------------

sub usage {
  my $pname = $0;
  $pname =~ s/.*\///g;

  print "Usage:\n\n";
  print "\t$pname [--nocopy] [--pgskip [number] ] file1 [file2 [file3 ... ] ]\n";
  print "\t$pname --help\n";
  print "\t$pname --version\n";
  print "\n";
  print "$pname reads a gschem schematic file or files and renumbers all reference\n";
  print "designators.  The reference designators are numbered starting with 1 and the\n";
  print "old schematic file is replaced by the modified schematic file.\n";
  print "\n";
  print "$pname accepts the following options:\n";
  print "\n";
  print "    --help      Displays this help message.\n";
  print "\n";
  print "    --nocopy    If given, this flag leaves the modified files in new files\n";
  print "                whose names are generated by appending a \".renum\" to the\n";
  print "                original file names.  The default is to overwrite the original.\n";
  print "\n";
  print "    --pgskip    When this flag is used, components on the first schematic sheet\n";
  print "                are numbered starting with 101.  On the second sheet, they start\n";
  print "                with 201, etc  Specifying a value gives the step between pages.\n";
  print "                For example --pgskip 10 will start with 11, 21, 31, etc.\n";
  print "\n";
  print "    --verbose   Enables verbose output.\n";
  print "\n";
  print "    --version   Shows the version of this program.\n";
  print "\n\n";
  print "Example:\n\n";
  print "\t$pname mysch.sch\n";
  print "\t$pname --pgskip pg1.sch pg2.sch pg3.sch\n";
  print "\n\n";
  print "$pname was written by Dan McMahill <dmcmahill\@netbsd.org>\n";
  print "\n\n";
  exit;
}

#---------------------------------
# version()
#
# prints program version
#---------------------------------

sub version {
  open(PROG,"$0") or die "Could not open \"$0\" to find version\n\n";
  my $pname = $0;
  $pname =~ s/.*\///g;

  while($line = <PROG>) {
    if( $line =~ /^#\s*\$Id.*\$/) {
      @words = split ' ',,$line;
      $version = $words[3];
      $date = $words[4];
      print "$pname ($0):  Version $version, $date\n";
      exit;
    }
  }
  print "Could not determine version of \"$0\"\n\n";
  exit;
}

# ----------------------------------------------
#
# Change Log
#
# $Log: refdes_renum,v $
# Revision 1.2  2005/12/21 00:09:56  danmc
# - Fix a bug where when using the --pgskip option, components which were
#   present on page n, but not on pages n+1 through n+j, and present again
#   on page n+j+1 got numbered in a strange way.  For example, J101 on page
#   1, no connectors on page 2, J201 on page 3 instead of J301.  Noted by
#   Stuart Brorson.
#
# - While here allow the user to change the default increment from 100 to whatever
#   they want.
#
# - Also fix a bug where exactly 101 components with the same refdes prefix
#   would cause a duplicate refdes on the next page.
#
# Revision 1.1  2003/02/21 03:21:12  ahvezda
# Added scripts/refdes_renum written by Dan McMahill
#
#
#
