#!/usr/bin/perl
#
# extract-symbols - Extract symbol names from KiCad schematics
#
# Written 2012 by Werner Almesberger
# Copyright 2012 Werner Almesberger
#
# 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.
#


sub usage
{
    print STDERR "usage: $0 file.sch\n";
    exit(1);
}


&usage if $#ARGV != 0;

push @f, $ARGV[0];
($dir = $ARGV[0]) =~ s|[^/]*$||;
$dir = "." if $dir eq "";

while (@f) {
	$file = pop @f;
	$sheet = 0;
	$comp = 0;
	open(FILE, $file) || die "$file: $!";
	while (<FILE>) {
		if (/^\$Sheet/) {
			$sheet = 1;
			next;
		}
		if (/^\$EndSheet/) {
			$sheet = 0;
			next;
		}
		if (/^\$Comp/) {
			$comp = 1;
			undef $cref;
			next;
		}
		if (/^\$EndComp/) {
			$comp = 0;
			next;
		}
		if (/^F1 "([^"]*)"/ && $sheet) {
			if (-r "$1") {
				push @f, $1;
			} elsif (-r "$dir/$1") {
				push @f, "$dir/$1";
			} else {
				die "don't know where to find $1";
			}
			next;
		}
		if (/^L\s+(\S+)\s+([^# \t\n]\S*)\s*$/ && $comp) {
			die if defined $cref;
			$cref = $2;
			$sym = $1;
			next;
		}
		if (/^U\s+1\s+/ && $comp) {
			next unless defined $cref;
			die "duplicate component reference \"$cref\" ($sym)" if
			    defined $sym{$cref};
			$sym{$cref} = $sym;
			undef $cref;
			next;
		}
	}
	close FILE;
}

for (sort keys %sym) {
	print "$_ $sym{$_}\n" || die "print: $!";
}
close STDOUT || die "close: $!";