Rename djboxsym to dwboxsym
authorDan White <dan@whiteaudio.com>
Sat, 21 Jan 2012 21:45:57 +0000 (15:45 -0600)
committerDan White <dan@whiteaudio.com>
Sat, 21 Jan 2012 21:45:57 +0000 (15:45 -0600)
djboxsym [deleted file]
dwboxsym [new file with mode: 0755]

diff --git a/djboxsym b/djboxsym
deleted file mode 100755 (executable)
index 7080447..0000000
--- a/djboxsym
+++ /dev/null
@@ -1,473 +0,0 @@
-#!/usr/bin/perl
-# -*- perl -*-
-
-# Copyright (C) 2006 DJ Delorie dj@delorie.com
-# Released under the terms of the GNU General Public License, version 2
-
-# Usage: djboxsym sample.symdef > sample.sym
-
-$y{left} = 400;
-$y{right} = 400;
-$y{labels} = 600;
-$labelpin = 0;
-
-$busspace = 200;
-$groupspace = 400;
-$skipspace = 800;
-$yinvert = 300;
-$minwidth = 0;
-
-# If set, top and bottom labels are vertical.
-$vmode = 0;
-
-# Read in the file, storing information about each pin.
-
-while (<>) {
-    next if /^#/;
-    s/^\s+//;
-    s/\s+$//;
-    s/[\s\t]+/ /g;
-    s/[\r\n]+$//;
-
-    # options
-    if (/^--(\S*)\s*(.*)/) {
-       $opt = $1;
-       @args = split(' ', $2);
-       ($opt, $value) = split(' ', $opt, 2);
-       if ($opt eq "vmode") {
-           $vmode = 1;
-#          $y{left} = $y{right} = 0;
-       }
-       if ($opt eq "square") {
-           $square = 1;
-       }
-       if ($opt eq "minwidth") {
-           $minwidth = $args[0];
-       }
-       if ($opt eq "compact") {
-           $groupspace = 200;
-           $skipspace = 400;
-           $yinvert = 400;
-           $compactmode = 1;
-       }
-       next;
-    }
-
-    # Note change of section.
-    if (/^\[(.*)\]/) {
-       $side = $1;
-       $space = 0;
-       next;
-    }
-
-    # Start a bus
-    if (/^\.bus/) {
-       $busmode = 1;
-       next;
-    }
-
-    # blank lines - cancel bus, add gap.
-    if (! /\S/) {
-       if ($busmode) {
-           $y{$side} += $busspace;
-       }
-       $busmode = 0;
-       if ($space) {
-           if ($side =~ /left|right/) {
-               $y{$side} += $groupspace;
-           }
-           if ($side =~ /top|bottom/) {
-               $x{$side} += 400;
-           }
-           $space = 0;
-       }
-       next;
-    }
-
-    if (/^\.skip (\d+)/) {
-       $skip = $1;
-       $space = 0;
-       if ($side =~ /left|right/) {
-           $y{$side} += $skip;
-       }
-       next;
-    }
-
-    # Hidden labels are stored separately, because we don't care how
-    # big they are.
-    if (/! (\S.*)/ && $side eq "labels") {
-       push(@attrs, $1);
-       next;
-    }
-
-    # Visible labels are stored as pins because their size affects the
-    # size of the symbols' box.
-    if (/\S/ && $side eq "labels") {
-       $labelpin --;
-       $pinside{$labelpin} = $side;
-       $piny{$labelpin} = $y{labels};
-       $pinlabel{$labelpin} = $_;
-       $y{labels} += $groupspace;
-       $rlen{$labelpin} = &textlen($_);
-       next;
-    }
-
-    # Regular pins are handled here.
-    if (/^(\S+)\s*(.*)/) {
-       $space = 1;
-       ($pin, $rest) = ($1,$2);
-
-       if ($pin =~ /^\d+$/) {
-           $pinseq_used[$pin] = 1;
-       }
-
-       if ($saw_pin{$pin}) {
-           print STDERR "DUPLICATE PIN $pin (was $pinlabel{$pin}, now $rest)\n";
-           $errors ++;
-       }
-       $saw_pin{$pin} = 1;
-       $maxpin = $pin if $maxpin < $pin;
-
-       $pinside{$pin} = $side;
-       $pintype{$pin} = "pas";
-       next if $side eq "nc";
-       if ($rest =~ /^([!>iop]+) (.*)/) {
-           $flags = $1;
-           $pinlabel{$pin} = $2;
-           $bubble{$pin} = 1 if $flags =~ /!/;
-           $edge{$pin} = 1 if $flags =~ />/;
-           $pintype{$pin} = "in" if $flags =~ /i/;
-           $pintype{$pin} = "out" if $flags =~ /o/;
-           $pintype{$pin} = "pwr" if $flags =~ /p/;
-           $pintype{$pin} = "inout" if $flags =~ /io/;
-       } else {
-           $pinlabel{$pin} = $rest;
-       }
-       $rlen{$pin} = &textlen($pinlabel{$pin});
-
-       if ($side =~ /left|right/) {
-           $y = $piny{$pin} = $y{$side};
-           $y{$side} += ($busmode ? $busspace : $groupspace);
-       }
-       if ($side =~ /top|bottom/) {
-           $tw = &alignpin((200 + $rlen{$pin}) / 2);
-           if ($vmode) {
-               $pinx{$pin} = $w{$side};
-               $w{$side} += (($busmode || $compactmode) ? 200 : 400);
-           } else {
-               $pinx{$pin} = $w{$side} + $tw;
-               $w{$side} += $tw + $tw;
-           }
-       }
-
-    }
-
-}
-
-$pinseq = 1;
-
-$minpin = $labelpin;
-$boxwidth = $minwidth;
-%bw = ();
-
-# for each horizontal slice of the symbol, keep track of how much
-# width is used up by the left, middle, and right labels.
-for $lp (keys %pinside) {
-    next unless $pinside{$lp} =~ /left|right|label/;
-    $yb = &alignpin($piny{$lp});
-    for ($y=$yb-300; $y<=$yb+300; $y+=100) {
-       if ($bw{$y}{$pinside{$lp}} < $rlen{$lp}) {
-           $bw{$y}{$pinside{$lp}} = $rlen{$lp};
-       }
-    }
-}
-
-# Compute the height of the box. 
-for $p (keys %pinside) {
-    next unless $pinside{$p} =~ /left|right/;
-    if ($maxy < $piny{$p}) {
-       $maxy = $piny{$p};
-    }
-}
-if (! $vmode) {
-    $maxy += $groupspace;
-}
-
-# Now, use the slice widths to compute the minimum width of the box.
-for ($i=0; $i<$maxy; $i+=100) {
-    $w = $bw{$i}{left} + $bw{$i}{labels} + $bw{$i}{right};
-    if ($bw{$i}{labels}) {
-       $wl = ($bw{$i}{left} + $bw{$i}{labels}/2) * 2;
-       $w = $wl if $w < $wl;
-       $wl = ($bw{$i}{right} + $bw{$i}{labels}/2) * 2;
-       $w = $wl if $w < $wl;
-    }
-    if ($bw{$i}{left} && $bw{$i}{labels}) {
-       $w += 100;
-    } elsif ($bw{$i}{left} && $bw{$i}{right}) {
-       $w += 200;
-    }
-    if ($bw{$i}{right} && $bw{$i}{labels}) {
-       $w += 100;
-    }
-    if ($boxwidth < $w) {
-       $boxwidth = $w;
-    }
-}
-
-$boxwidth = $w{top} if $boxwidth < $w{top};
-$boxwidth = $w{bottom} if $boxwidth < $w{bottom};
-
-# Flip Y coordinates (we count from the top, but symbols coordinates
-# are from the bottom).
-for $p (keys %pinside) {
-    next unless $pinside{$p} =~ /left|right|labels/;
-    $piny{$p} = $maxy - $piny{$p} + $yinvert;
-}
-
-$boxwidth = &alignpin($boxwidth);
-$boxwidth += 200;
-
-# Adjust the position of the top/bottom pins so that, as a group,
-# they're centered.
-%maxh = ();
-for $p (keys %pinside) {
-    next unless $pinside{$p} =~ /top|bottom/;
-    $pinx{$p} += &alignpin(($boxwidth - $w{$pinside{$p}})/2) + 300;
-    if ($vmode) {
-       $pinx{$p} += 200;
-       $h = &textlen($pinlabel{$p});
-       $maxh{$pinside{$p}} = $h if $maxh{$pinside{$p}} < $h;
-    }
-}
-
-if ($vmode) {
-    $dy = &alignpin($maxh{bottom});
-    for $lp ($minpin..-1) {
-       $piny{$lp} += $dy;
-    }
-    for $p (keys %pinside) {
-       if ($pinside{$p} =~ /left|right|bottom/) {
-           $piny{$p} += $dy;
-       }
-    }
-    $maxy += $dy + &alignpin ($maxh{top});
-}
-
-if ($square) {
-    if ($boxwidth < $maxy) {
-       $delta = $maxy - $boxwidth;
-       $delta = &alignpin($delta / 2);
-       $boxwidth = $maxy;
-       for $p (keys %pinside) {
-           if ($pinside{$p} =~ /top|bottom/) {
-               $pinx{$p} += $delta;
-           }
-       }
-    }
-    if ($maxy < $boxwidth) {
-       $maxy = $boxwidth;
-    }
-}
-
-# Labels are centered in the box.
-for $lp ($minpin..-1) {
-    $pinx{$lp} = &alignpin($boxwidth/2) + 300;
-}
-
-# Version.
-print "v 20060123 1\n";
-
-# Symbol box.
-printf("B %d %d %d %d 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",
-       300, 300, $boxwidth, $maxy);
-
-# These are the hidden labels.
-$ax = 300 + $boxwidth;
-$ay = 400 + $maxy;
-for $a (reverse @attrs) {
-    printf("T %d %d 9 10 0 0 0 0 1\n%s\n",
-          $ax, $ay, $a);
-    $ay += 200;
-}
-
-sub pinsort {
-    my ($a, $b) = @_;
-    $a =~ tr/a-z/A-Z/;
-    $b =~ tr/a-z/A-Z/;
-    $a =~ s/(\d+)/sprintf("%06d", $1);/ge;
-    $b =~ s/(\d+)/sprintf("%06d", $1);/ge;
-    return $a cmp $b;
-}
-
-# Now print all the pins.
-for $p (sort {&pinsort($a,$b)} keys %pinside) {
-    next unless $pinside{$p};
-    if ($pinside{$p} eq "left") {
-       $pinx{$p} = 300;
-    }
-    if ($pinside{$p} eq "right") {
-       $pinx{$p} = 300 + $boxwidth;
-    }
-    if ($p > 0 && !$saw_pin{$p}) {
-       print STDERR "MISSING PIN $p\n";
-       $errors++;
-    } else {
-       printf STDERR ("%3s  %-6s  %4d %4d  %s\n",
-                      $p, $pinside{$p}, $pinx{$p}, $piny{$p}, $pinlabel{$p});
-    }
-
-    eval "&drawpin_$pinside{\"$p\"} (\"$p\")";
-}
-
-# what remains are helper functions; for drawing each type of pin,
-# each type of label, etc.
-
-sub drawpin_nc {
-}
-
-sub drawpin_top {
-    my($pin) = @_;
-    $y = $maxy + 300;
-    printf("P %d %d %d %d 1 0 0\n",
-          $pinx{$pin}, $y+300, $pinx{$pin}, $y);
-    print "{\n";
-    if ($vmode) {
-       &pvltext($pinx{$pin}, $y-50, 7, $pinlabel{$pin});
-    } else {
-       &pltext($pinx{$pin}, $y-50, 5, $pinlabel{$pin});
-    }
-    &ntext($pinx{$pin}+50, $y+50, 0, $pin);
-    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
-    print "}\n";
-}
-
-sub drawpin_bottom {
-    my($pin) = @_;
-    printf("P %d %d %d %d 1 0 0\n",
-          $pinx{$pin}, 0, $pinx{$pin}, 300);
-    print "{\n";
-    if ($vmode) {
-       &pvltext($pinx{$pin}, 350, 1, $pinlabel{$pin});
-    } else {
-       &pltext($pinx{$pin}, 350, 3, $pinlabel{$pin});
-    }
-    &ntext($pinx{$pin}+50, 250, 2, $pin);
-    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
-    print "}\n";
-}
-
-sub drawpin_labels {
-    my($pin) = @_;
-    &ltext($pinx{$pin}, $piny{$pin}, 3, $pinlabel{$pin});
-}
-
-sub circle {
-    my ($x, $y) = @_;
-    print "V $x $y 50 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n";
-}
-
-sub drawpin_left {
-    my($pin) = @_;
-    $x = $pinx{$pin};
-    $px = 50;
-    if ($bubble{$pin}) {
-       $x -= 100;
-       &circle($x+50, $piny{$pin});
-    }
-    if ($edge{$pin}) {
-       $px += 100;
-       printf("L %d %d %d %d 3 0 0 0 0 0\n",
-              $pinx{$pin}, $piny{$pin}-50,
-              $pinx{$pin}+100, $piny{$pin});
-       printf("L %d %d %d %d 3 0 0 0 0 0\n",
-              $pinx{$pin}+100, $piny{$pin},
-              $pinx{$pin}, $piny{$pin}+50);
-
-    }
-    printf("P %d %d %d %d 1 0 0\n",
-          $pinx{$pin} - 300, $piny{$pin}, $x, $piny{$pin});
-    print "{\n";
-    &pltext($pinx{$pin} + $px, $piny{$pin}, 1, $pinlabel{$pin});
-    &ntext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pin);
-    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
-    print "}\n";
-}
-
-sub drawpin_right {
-    my($pin) = @_;
-    $x = $pinx{$pin};
-    $px = 50;
-    if ($bubble{$pin}) {
-       $x += 100;
-       &circle($x-50, $piny{$pin});
-    }
-    if ($edge{$pin}) {
-       $px += 100;
-       printf("L %d %d %d %d 3 0 0 0 0 0\n",
-              $pinx{$pin}, $piny{$pin}-50,
-              $pinx{$pin}-100, $piny{$pin});
-       printf("L %d %d %d %d 3 0 0 0 0 0\n",
-              $pinx{$pin}-100, $piny{$pin},
-              $pinx{$pin}, $piny{$pin}+50);
-
-    }
-    printf("P %d %d %d %d 1 0 0\n",
-          $pinx{$pin} + 300, $piny{$pin}, $x, $piny{$pin});
-    print "{\n";
-    &pltext($pinx{$pin} - $px, $piny{$pin}, 7, $pinlabel{$pin});
-    &ntext($pinx{$pin} +100, $piny{$pin} + 50, 0, $pin);
-    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
-    print "}\n";
-}
-
-sub ntext {
-    my ($x, $y, $a, $s) = @_;
-    printf("T %d %d 5 8 1 1 0 %s 1\npinnumber=%s\n", $x, $y, $a, $s);
-    if ($s =~ /^\d+$/) {
-       $my_pinseq = $s;
-    } else {
-       while ($pinseq_used[$pinseq]) {
-           $pinseq ++;
-       }
-       $pinseq_used[$pinseq] = 1;
-       $my_pinseq = $pinseq;
-    }
-    printf("T %d %d 5 8 0 1 0 %s 1\npinseq=%d\n", $x, $y, $a, $my_pinseq);
-}
-
-sub pttext {
-    my ($x, $y, $a, $s) = @_;
-    printf("T %d %d 9 10 0 1 0 %s 1\npintype=%s\n", $x, $y, $a, $s);
-}
-
-sub pltext {
-    my ($x, $y, $a, $s) = @_;
-    $s = "pinlabel=$s" unless $s =~ /=/;
-    printf("T %d %d 9 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s);
-}
-
-sub pvltext {
-    my ($x, $y, $a, $s) = @_;
-    $s = "pinlabel=$s" unless $s =~ /=/;
-    printf("T %d %d 9 10 1 1 90 %s 1\n%s\n", $x, $y, $a, $s);
-}
-
-sub ltext {
-    my ($x, $y, $a, $s) = @_;
-    printf("T %d %d 9 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s);
-}
-
-sub textlen {
-    my($t) = @_;
-    $t =~ s/^[^=]*=//;
-    $t =~ s@\\_@@g;
-    return length($t) * 110;
-}
-
-sub alignpin {
-    my($v) = @_;
-    return int(($v + 99) / 100) * 100;
-}
-
-exit $errors;
diff --git a/dwboxsym b/dwboxsym
new file mode 100755 (executable)
index 0000000..7080447
--- /dev/null
+++ b/dwboxsym
@@ -0,0 +1,473 @@
+#!/usr/bin/perl
+# -*- perl -*-
+
+# Copyright (C) 2006 DJ Delorie dj@delorie.com
+# Released under the terms of the GNU General Public License, version 2
+
+# Usage: djboxsym sample.symdef > sample.sym
+
+$y{left} = 400;
+$y{right} = 400;
+$y{labels} = 600;
+$labelpin = 0;
+
+$busspace = 200;
+$groupspace = 400;
+$skipspace = 800;
+$yinvert = 300;
+$minwidth = 0;
+
+# If set, top and bottom labels are vertical.
+$vmode = 0;
+
+# Read in the file, storing information about each pin.
+
+while (<>) {
+    next if /^#/;
+    s/^\s+//;
+    s/\s+$//;
+    s/[\s\t]+/ /g;
+    s/[\r\n]+$//;
+
+    # options
+    if (/^--(\S*)\s*(.*)/) {
+       $opt = $1;
+       @args = split(' ', $2);
+       ($opt, $value) = split(' ', $opt, 2);
+       if ($opt eq "vmode") {
+           $vmode = 1;
+#          $y{left} = $y{right} = 0;
+       }
+       if ($opt eq "square") {
+           $square = 1;
+       }
+       if ($opt eq "minwidth") {
+           $minwidth = $args[0];
+       }
+       if ($opt eq "compact") {
+           $groupspace = 200;
+           $skipspace = 400;
+           $yinvert = 400;
+           $compactmode = 1;
+       }
+       next;
+    }
+
+    # Note change of section.
+    if (/^\[(.*)\]/) {
+       $side = $1;
+       $space = 0;
+       next;
+    }
+
+    # Start a bus
+    if (/^\.bus/) {
+       $busmode = 1;
+       next;
+    }
+
+    # blank lines - cancel bus, add gap.
+    if (! /\S/) {
+       if ($busmode) {
+           $y{$side} += $busspace;
+       }
+       $busmode = 0;
+       if ($space) {
+           if ($side =~ /left|right/) {
+               $y{$side} += $groupspace;
+           }
+           if ($side =~ /top|bottom/) {
+               $x{$side} += 400;
+           }
+           $space = 0;
+       }
+       next;
+    }
+
+    if (/^\.skip (\d+)/) {
+       $skip = $1;
+       $space = 0;
+       if ($side =~ /left|right/) {
+           $y{$side} += $skip;
+       }
+       next;
+    }
+
+    # Hidden labels are stored separately, because we don't care how
+    # big they are.
+    if (/! (\S.*)/ && $side eq "labels") {
+       push(@attrs, $1);
+       next;
+    }
+
+    # Visible labels are stored as pins because their size affects the
+    # size of the symbols' box.
+    if (/\S/ && $side eq "labels") {
+       $labelpin --;
+       $pinside{$labelpin} = $side;
+       $piny{$labelpin} = $y{labels};
+       $pinlabel{$labelpin} = $_;
+       $y{labels} += $groupspace;
+       $rlen{$labelpin} = &textlen($_);
+       next;
+    }
+
+    # Regular pins are handled here.
+    if (/^(\S+)\s*(.*)/) {
+       $space = 1;
+       ($pin, $rest) = ($1,$2);
+
+       if ($pin =~ /^\d+$/) {
+           $pinseq_used[$pin] = 1;
+       }
+
+       if ($saw_pin{$pin}) {
+           print STDERR "DUPLICATE PIN $pin (was $pinlabel{$pin}, now $rest)\n";
+           $errors ++;
+       }
+       $saw_pin{$pin} = 1;
+       $maxpin = $pin if $maxpin < $pin;
+
+       $pinside{$pin} = $side;
+       $pintype{$pin} = "pas";
+       next if $side eq "nc";
+       if ($rest =~ /^([!>iop]+) (.*)/) {
+           $flags = $1;
+           $pinlabel{$pin} = $2;
+           $bubble{$pin} = 1 if $flags =~ /!/;
+           $edge{$pin} = 1 if $flags =~ />/;
+           $pintype{$pin} = "in" if $flags =~ /i/;
+           $pintype{$pin} = "out" if $flags =~ /o/;
+           $pintype{$pin} = "pwr" if $flags =~ /p/;
+           $pintype{$pin} = "inout" if $flags =~ /io/;
+       } else {
+           $pinlabel{$pin} = $rest;
+       }
+       $rlen{$pin} = &textlen($pinlabel{$pin});
+
+       if ($side =~ /left|right/) {
+           $y = $piny{$pin} = $y{$side};
+           $y{$side} += ($busmode ? $busspace : $groupspace);
+       }
+       if ($side =~ /top|bottom/) {
+           $tw = &alignpin((200 + $rlen{$pin}) / 2);
+           if ($vmode) {
+               $pinx{$pin} = $w{$side};
+               $w{$side} += (($busmode || $compactmode) ? 200 : 400);
+           } else {
+               $pinx{$pin} = $w{$side} + $tw;
+               $w{$side} += $tw + $tw;
+           }
+       }
+
+    }
+
+}
+
+$pinseq = 1;
+
+$minpin = $labelpin;
+$boxwidth = $minwidth;
+%bw = ();
+
+# for each horizontal slice of the symbol, keep track of how much
+# width is used up by the left, middle, and right labels.
+for $lp (keys %pinside) {
+    next unless $pinside{$lp} =~ /left|right|label/;
+    $yb = &alignpin($piny{$lp});
+    for ($y=$yb-300; $y<=$yb+300; $y+=100) {
+       if ($bw{$y}{$pinside{$lp}} < $rlen{$lp}) {
+           $bw{$y}{$pinside{$lp}} = $rlen{$lp};
+       }
+    }
+}
+
+# Compute the height of the box. 
+for $p (keys %pinside) {
+    next unless $pinside{$p} =~ /left|right/;
+    if ($maxy < $piny{$p}) {
+       $maxy = $piny{$p};
+    }
+}
+if (! $vmode) {
+    $maxy += $groupspace;
+}
+
+# Now, use the slice widths to compute the minimum width of the box.
+for ($i=0; $i<$maxy; $i+=100) {
+    $w = $bw{$i}{left} + $bw{$i}{labels} + $bw{$i}{right};
+    if ($bw{$i}{labels}) {
+       $wl = ($bw{$i}{left} + $bw{$i}{labels}/2) * 2;
+       $w = $wl if $w < $wl;
+       $wl = ($bw{$i}{right} + $bw{$i}{labels}/2) * 2;
+       $w = $wl if $w < $wl;
+    }
+    if ($bw{$i}{left} && $bw{$i}{labels}) {
+       $w += 100;
+    } elsif ($bw{$i}{left} && $bw{$i}{right}) {
+       $w += 200;
+    }
+    if ($bw{$i}{right} && $bw{$i}{labels}) {
+       $w += 100;
+    }
+    if ($boxwidth < $w) {
+       $boxwidth = $w;
+    }
+}
+
+$boxwidth = $w{top} if $boxwidth < $w{top};
+$boxwidth = $w{bottom} if $boxwidth < $w{bottom};
+
+# Flip Y coordinates (we count from the top, but symbols coordinates
+# are from the bottom).
+for $p (keys %pinside) {
+    next unless $pinside{$p} =~ /left|right|labels/;
+    $piny{$p} = $maxy - $piny{$p} + $yinvert;
+}
+
+$boxwidth = &alignpin($boxwidth);
+$boxwidth += 200;
+
+# Adjust the position of the top/bottom pins so that, as a group,
+# they're centered.
+%maxh = ();
+for $p (keys %pinside) {
+    next unless $pinside{$p} =~ /top|bottom/;
+    $pinx{$p} += &alignpin(($boxwidth - $w{$pinside{$p}})/2) + 300;
+    if ($vmode) {
+       $pinx{$p} += 200;
+       $h = &textlen($pinlabel{$p});
+       $maxh{$pinside{$p}} = $h if $maxh{$pinside{$p}} < $h;
+    }
+}
+
+if ($vmode) {
+    $dy = &alignpin($maxh{bottom});
+    for $lp ($minpin..-1) {
+       $piny{$lp} += $dy;
+    }
+    for $p (keys %pinside) {
+       if ($pinside{$p} =~ /left|right|bottom/) {
+           $piny{$p} += $dy;
+       }
+    }
+    $maxy += $dy + &alignpin ($maxh{top});
+}
+
+if ($square) {
+    if ($boxwidth < $maxy) {
+       $delta = $maxy - $boxwidth;
+       $delta = &alignpin($delta / 2);
+       $boxwidth = $maxy;
+       for $p (keys %pinside) {
+           if ($pinside{$p} =~ /top|bottom/) {
+               $pinx{$p} += $delta;
+           }
+       }
+    }
+    if ($maxy < $boxwidth) {
+       $maxy = $boxwidth;
+    }
+}
+
+# Labels are centered in the box.
+for $lp ($minpin..-1) {
+    $pinx{$lp} = &alignpin($boxwidth/2) + 300;
+}
+
+# Version.
+print "v 20060123 1\n";
+
+# Symbol box.
+printf("B %d %d %d %d 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n",
+       300, 300, $boxwidth, $maxy);
+
+# These are the hidden labels.
+$ax = 300 + $boxwidth;
+$ay = 400 + $maxy;
+for $a (reverse @attrs) {
+    printf("T %d %d 9 10 0 0 0 0 1\n%s\n",
+          $ax, $ay, $a);
+    $ay += 200;
+}
+
+sub pinsort {
+    my ($a, $b) = @_;
+    $a =~ tr/a-z/A-Z/;
+    $b =~ tr/a-z/A-Z/;
+    $a =~ s/(\d+)/sprintf("%06d", $1);/ge;
+    $b =~ s/(\d+)/sprintf("%06d", $1);/ge;
+    return $a cmp $b;
+}
+
+# Now print all the pins.
+for $p (sort {&pinsort($a,$b)} keys %pinside) {
+    next unless $pinside{$p};
+    if ($pinside{$p} eq "left") {
+       $pinx{$p} = 300;
+    }
+    if ($pinside{$p} eq "right") {
+       $pinx{$p} = 300 + $boxwidth;
+    }
+    if ($p > 0 && !$saw_pin{$p}) {
+       print STDERR "MISSING PIN $p\n";
+       $errors++;
+    } else {
+       printf STDERR ("%3s  %-6s  %4d %4d  %s\n",
+                      $p, $pinside{$p}, $pinx{$p}, $piny{$p}, $pinlabel{$p});
+    }
+
+    eval "&drawpin_$pinside{\"$p\"} (\"$p\")";
+}
+
+# what remains are helper functions; for drawing each type of pin,
+# each type of label, etc.
+
+sub drawpin_nc {
+}
+
+sub drawpin_top {
+    my($pin) = @_;
+    $y = $maxy + 300;
+    printf("P %d %d %d %d 1 0 0\n",
+          $pinx{$pin}, $y+300, $pinx{$pin}, $y);
+    print "{\n";
+    if ($vmode) {
+       &pvltext($pinx{$pin}, $y-50, 7, $pinlabel{$pin});
+    } else {
+       &pltext($pinx{$pin}, $y-50, 5, $pinlabel{$pin});
+    }
+    &ntext($pinx{$pin}+50, $y+50, 0, $pin);
+    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
+    print "}\n";
+}
+
+sub drawpin_bottom {
+    my($pin) = @_;
+    printf("P %d %d %d %d 1 0 0\n",
+          $pinx{$pin}, 0, $pinx{$pin}, 300);
+    print "{\n";
+    if ($vmode) {
+       &pvltext($pinx{$pin}, 350, 1, $pinlabel{$pin});
+    } else {
+       &pltext($pinx{$pin}, 350, 3, $pinlabel{$pin});
+    }
+    &ntext($pinx{$pin}+50, 250, 2, $pin);
+    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
+    print "}\n";
+}
+
+sub drawpin_labels {
+    my($pin) = @_;
+    &ltext($pinx{$pin}, $piny{$pin}, 3, $pinlabel{$pin});
+}
+
+sub circle {
+    my ($x, $y) = @_;
+    print "V $x $y 50 3 0 0 0 -1 -1 0 -1 -1 -1 -1 -1\n";
+}
+
+sub drawpin_left {
+    my($pin) = @_;
+    $x = $pinx{$pin};
+    $px = 50;
+    if ($bubble{$pin}) {
+       $x -= 100;
+       &circle($x+50, $piny{$pin});
+    }
+    if ($edge{$pin}) {
+       $px += 100;
+       printf("L %d %d %d %d 3 0 0 0 0 0\n",
+              $pinx{$pin}, $piny{$pin}-50,
+              $pinx{$pin}+100, $piny{$pin});
+       printf("L %d %d %d %d 3 0 0 0 0 0\n",
+              $pinx{$pin}+100, $piny{$pin},
+              $pinx{$pin}, $piny{$pin}+50);
+
+    }
+    printf("P %d %d %d %d 1 0 0\n",
+          $pinx{$pin} - 300, $piny{$pin}, $x, $piny{$pin});
+    print "{\n";
+    &pltext($pinx{$pin} + $px, $piny{$pin}, 1, $pinlabel{$pin});
+    &ntext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pin);
+    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
+    print "}\n";
+}
+
+sub drawpin_right {
+    my($pin) = @_;
+    $x = $pinx{$pin};
+    $px = 50;
+    if ($bubble{$pin}) {
+       $x += 100;
+       &circle($x-50, $piny{$pin});
+    }
+    if ($edge{$pin}) {
+       $px += 100;
+       printf("L %d %d %d %d 3 0 0 0 0 0\n",
+              $pinx{$pin}, $piny{$pin}-50,
+              $pinx{$pin}-100, $piny{$pin});
+       printf("L %d %d %d %d 3 0 0 0 0 0\n",
+              $pinx{$pin}-100, $piny{$pin},
+              $pinx{$pin}, $piny{$pin}+50);
+
+    }
+    printf("P %d %d %d %d 1 0 0\n",
+          $pinx{$pin} + 300, $piny{$pin}, $x, $piny{$pin});
+    print "{\n";
+    &pltext($pinx{$pin} - $px, $piny{$pin}, 7, $pinlabel{$pin});
+    &ntext($pinx{$pin} +100, $piny{$pin} + 50, 0, $pin);
+    &pttext($pinx{$pin} -100, $piny{$pin} + 50, 6, $pintype{$pin});
+    print "}\n";
+}
+
+sub ntext {
+    my ($x, $y, $a, $s) = @_;
+    printf("T %d %d 5 8 1 1 0 %s 1\npinnumber=%s\n", $x, $y, $a, $s);
+    if ($s =~ /^\d+$/) {
+       $my_pinseq = $s;
+    } else {
+       while ($pinseq_used[$pinseq]) {
+           $pinseq ++;
+       }
+       $pinseq_used[$pinseq] = 1;
+       $my_pinseq = $pinseq;
+    }
+    printf("T %d %d 5 8 0 1 0 %s 1\npinseq=%d\n", $x, $y, $a, $my_pinseq);
+}
+
+sub pttext {
+    my ($x, $y, $a, $s) = @_;
+    printf("T %d %d 9 10 0 1 0 %s 1\npintype=%s\n", $x, $y, $a, $s);
+}
+
+sub pltext {
+    my ($x, $y, $a, $s) = @_;
+    $s = "pinlabel=$s" unless $s =~ /=/;
+    printf("T %d %d 9 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s);
+}
+
+sub pvltext {
+    my ($x, $y, $a, $s) = @_;
+    $s = "pinlabel=$s" unless $s =~ /=/;
+    printf("T %d %d 9 10 1 1 90 %s 1\n%s\n", $x, $y, $a, $s);
+}
+
+sub ltext {
+    my ($x, $y, $a, $s) = @_;
+    printf("T %d %d 9 10 1 1 0 %s 1\n%s\n", $x, $y, $a, $s);
+}
+
+sub textlen {
+    my($t) = @_;
+    $t =~ s/^[^=]*=//;
+    $t =~ s@\\_@@g;
+    return length($t) * 110;
+}
+
+sub alignpin {
+    my($v) = @_;
+    return int(($v + 99) / 100) * 100;
+}
+
+exit $errors;