A clone of fped (which neo900 depends on) in case qi-hardware.com goes down.

Werner Almesberger fa98e58157 fped.c (usage): fix typo "heigth" 7 years ago
examples c6312cd313 A bit of cleanup, as suggested by Chitlesh Goorah. 14 years ago
icons 6db067a90f More work on holes: added documentation and Postscript output. 14 years ago
manual c172870dfd - README: added link to the GUI manual 14 years ago
test 688f2ab934 dimensions can now be specified in micrometers (um) 7 years ago
.gitignore 0562403f30 Add .gitignore file 12 years ago
COPYING.GPLv2 887643e65a Indicated more prominently that fped is licensed under the GPLv2 and 14 years ago
Makefile 7081258910 diff for gEDA PCB export in fped 7 years ago
README 103933acf5 fix a few whitespace issues in previous commit 7 years ago
TODO b2b3a46119 A bit of cleanup. 14 years ago
bitset.c c9af8cd0fe The mechanism for selecting points for measurements reaches its limits when 14 years ago
bitset.h c9af8cd0fe The mechanism for selecting points for measurements reaches its limits when 14 years ago
coord.c 7081258910 diff for gEDA PCB export in fped 7 years ago
coord.h 7081258910 diff for gEDA PCB export in fped 7 years ago
cpp.c e455b37abb Moved fped over to /trunk/eda 14 years ago
cpp.h e455b37abb Moved fped over to /trunk/eda 14 years ago
delete.c 3c39600c1c add %iprint, to track variables during instantiation 12 years ago
delete.h 9e7e804d1a - delete.c: added more destructor functions 14 years ago
dump.c ad2c07f49c dump.c (order_vecs): don't trip over vectors with deferred resolution 9 years ago
dump.h f44accdad7 fped: added option -1 package to select a single package to output with -p/-P 13 years ago
error.c c9af8cd0fe The mechanism for selecting points for measurements reaches its limits when 14 years ago
error.h c9af8cd0fe The mechanism for selecting points for measurements reaches its limits when 14 years ago
expr.c 688f2ab934 dimensions can now be specified in micrometers (um) 7 years ago
expr.h 688f2ab934 dimensions can now be specified in micrometers (um) 7 years ago
file.c 103933acf5 fix a few whitespace issues in previous commit 7 years ago
file.h 7081258910 diff for gEDA PCB export in fped 7 years ago
fpd.h 8982d09474 add experimental reload feature 11 years ago
fpd.l 688f2ab934 dimensions can now be specified in micrometers (um) 7 years ago
fpd.y bb055fa209 experimental directive "allow holes" to allow multiple holes per pad 11 years ago
fped.1 0acff965b0 new option -l (lower case L) to list package names 7 years ago
fped.c fa98e58157 fped.c (usage): fix typo "heigth" 7 years ago
fped.h 8982d09474 add experimental reload feature 11 years ago
geda.c 103933acf5 fix a few whitespace issues in previous commit 7 years ago
geda.h 7081258910 diff for gEDA PCB export in fped 7 years ago
gnuplot.c 6dfbb51af9 fped/gnuplot.c (gnuplot_arc): implemented drawing of arcs 12 years ago
gnuplot.h e5d8fd87c3 fped/: added gnuplot output for line/rect/circle with -g (experimental) 12 years ago
gui.c 7081258910 diff for gEDA PCB export in fped 7 years ago
gui.h e3deb3978f update the menu bar (specifically, View > Show ...) after changes with "/" 9 years ago
gui.html 73389fba76 sanitize show var/code handling; switch to enum for future changes 9 years ago
gui_canvas.c e3deb3978f update the menu bar (specifically, View > Show ...) after changes with "/" 9 years ago
gui_canvas.h 0b241a14fe Dragging a frame into the canvas now works. It's built on top of the frame 14 years ago
gui_frame.c 15e5811aea gui_frame.c (loop_scroll_event): reverse direction 9 years ago
gui_frame.h 5fdea0e99a gui_canvas.c (key_press_event): make / rotate through packages as well 9 years ago
gui_frame_drag.c f2d3986600 fix whitespace anomalies 12 years ago
gui_frame_drag.h 0b241a14fe Dragging a frame into the canvas now works. It's built on top of the frame 14 years ago
gui_inst.c f2d3986600 fix whitespace anomalies 12 years ago
gui_inst.h 1dda2ac2ae When creating an object in the GUI, its label wasn't initialized. Added 14 years ago
gui_meas.c b2b3a46119 A bit of cleanup. 14 years ago
gui_meas.h 9c68c0de34 - File>Save now saves to a file if a second name is given on the command line, 14 years ago
gui_over.c 14f21c0aee More work on tooltips and a build fix. 14 years ago
gui_over.h 39690c9cb2 - to simplify communication between the various modules, renamed "ctx" to 14 years ago
gui_status.c 57dbeb1aad gui_status.c (show_pad_type): share pad type to name translation 11 years ago
gui_status.h 4c3dea7111 support switching variables between assignment and key (WIP) 12 years ago
gui_style.c 49a1bbdd05 Added a new pad type: trace pads, for antennas and other trace-like elements. 13 years ago
gui_style.h 49a1bbdd05 Added a new pad type: trace pads, for antennas and other trace-like elements. 13 years ago
gui_tool.c 424b74e482 change use of curly braces with "if-else" to kernel style 12 years ago
gui_tool.h 82a12023cd I thought there was a bug in frame ordering, but it turns out that it works 14 years ago
gui_util.c f2d3986600 fix whitespace anomalies 12 years ago
gui_util.h 4bfb601a40 Wrap wide tables. 14 years ago
hole.c bb055fa209 experimental directive "allow holes" to allow multiple holes per pad 11 years ago
hole.h bb055fa209 experimental directive "allow holes" to allow multiple holes per pad 11 years ago
inst.c 8a1a310396 inst.c (find_point_vec): correct indentation 9 years ago
inst.h 86c082f5a9 track bounding box also on a per-package basis and use this to scale Postscript 11 years ago
kicad.c f2d3986600 fix whitespace anomalies 12 years ago
kicad.h f44accdad7 fped: added option -1 package to select a single package to output with -p/-P 13 years ago
layer.c 7c037ae78a layer.c (pad_type_to_layers): fix harmless typo 11 years ago
layer.h 57dbeb1aad gui_status.c (show_pad_type): share pad type to name translation 11 years ago
leak.supp 94f4534494 - measurement offsets can now use variables. We evaluate the offset during 14 years ago
leakcheck 94f4534494 - measurement offsets can now use variables. We evaluate the offset during 14 years ago
meas.c e0351bdf73 make active package track active variables (for the GUI) 12 years ago
meas.h f2d3986600 fix whitespace anomalies 12 years ago
obj.c bb055fa209 experimental directive "allow holes" to allow multiple holes per pad 11 years ago
obj.h bb055fa209 experimental directive "allow holes" to allow multiple holes per pad 11 years ago
overlap.c f2d3986600 fix whitespace anomalies 12 years ago
overlap.h e6b2658a65 Added relaxation of pad overlap checking. Not GUI-settable yet. 13 years ago
postscript.c b4d61a867e postscript.c: only show the key for pad types actually used in the package 11 years ago
postscript.h d250ed236c postscript.c: show key for pad types at bottom of fullpage drawings (-P -K) 11 years ago
tsort.c bc27b094af With a little help from m8cutils and abyss, we now have regression tests for 14 years ago
tsort.h 190bcaf982 Added a topological sort algorithm, for use when dumping. 14 years ago
unparse.c f2d3986600 fix whitespace anomalies 12 years ago
unparse.h e455b37abb Moved fped over to /trunk/eda 14 years ago
util.c f2d3986600 fix whitespace anomalies 12 years ago
util.h b2b3a46119 A bit of cleanup. 14 years ago

README

fped - Footprint editor
=======================

fped is an editor that allows the interactive creation of footprints of
electronic components. Footprint definitions are stored in a text format
that resembles a programming language.

The language is constrained such that anything that can be expressed in
the textual definition also has a straightforward equivalent operation
that can be performed through the GUI.

This README describes only the footprint definition language. A
description of the GUI can be found here:

http://downloads.qi-hardware.com/people/werner/fped/gui.html

This work is distributed under the terms of the GNU GENERAL PUBLIC
LICENSE, Version 2:

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.

For your convenience, a copy of the complete license has been included
in the file COPYING.GPLv2.


Building
--------

Prerequisites:

- bash
- flex
- bison
- fig2dev (transfig)
- ImageMagick
- Netpbm
- Gtk+ 2.x development package (libgtk2.0-dev or similar)
- Liberation Fonts (ttf-liberation or similar)

Check out the repository:

git clone git://projects.qi-hardware.com/fped.git
cd fped

Get updates:

git pull

Compile:

make

Run an example:

./fped examples/qfn.fpd


Motivation
----------

KiCad already includes a footprint ("module") editor, so why do we need
a new one ? The issue with footprint generation for KiCad is that the
built-in module editor is basically a drawing program that only captures
the result of the module author's interpretation of a footprint drawing,
but does not include the steps that led to this construction.

Furthermore, accurate measuring of dimensions in the drawing can only be
done manually in the module editor, which makes review difficult and
time-consuming.

In fped, the construction process is made explicit and each step can be
expressed in terms of the parameters that appear in the vendor's
drawing. Dimensions can be explicitly measured and the results can be
included in the graphical output generated by fped.

Directly using parameters and construction steps from the reference
drawing reduces the risk of mistakes. Visualizing the construction
process and verificative measurements helps efficient and accurate
review.

Leveraging the work already done, and growing the intellectual commons
of available footprints has motivated the addition of an export to gEDA
pcb format option. Single or multiple footprints are exported in a
gEDA PCB layout (.pcb) file. A select all command can be used, followed
by a "disperse elements" command, to allow viewing of multiple elements
in the gEDA layout editor. An element can then be selected, cut to
buffer, and exported to a footprint (.fp) file with the usual menu
commands.

gEDA PCB format footprints are exported in centimil units. Pads with
offset centre holes are not faithfully reproduced; the pad is exported
with minimum dimensions and centred on the hole. Trapezoidal and
roundrect pads are not supported in gEDA.


Footprint definition file format
--------------------------------

Footprint definitions are stored in text files. The program "fped" reads
and (soon) writes such files, visualizes their content, and provides a
graphical editor for them.

The syntax is unique and draws from elements of a variety of languages
commonly found on unix systems. One specialty is that there are no
reserved words - the language keywords appear only at the beginning of
a line and can thus be recognized as such without restricting their use
for identifiers. This reduces the risk of creating incompatibilities
with existing designs when introduction future language features.

fped uses the C preprocessor for comments, conditional compilation,
and - to a limited extent - also macros. Long lines can be split by
ending them with a backslash. If multiple items need to be placed in a
single line, e.g., in a macro, they can be separated with semicolons.

The file has the following structure:

frame definitions
...
package name
setup
objects
...


Geometry model
--------------

The geometry model consists of frames, vectors, and objects. The shape of
objects is defined by a number of points. These points are produced by
concatenating vectors.

E.g., to draw a line from (1mm, 1mm) to (2mm, 2mm), one would make a
vector from the origin to (1mm, 1mm) and one either from the origin or
from the previous vector to (2mm, 2mm), and then make a line connecting
the two points.


Setup
- - -

The setup section defines settings that affect the entire footprint.
It is optional and can contain a "unit" directive and an "allow"
directive.


Units
- - -

fped can calculate in mm and mil. Units are specified by following a
number with "mm", "um", or "mil", separated by zero or more spaces or
tabs.

Examples:

1mm
2 mil

Units can be mixed in calculations, e.g.,

set a = 1mm+20mil
set b = 10*1mm

All values used as dimensions must be either mm or mil.

The default unit can be set with one of the following directives:

unit mm
unit mil
unit auto

If the "unit" directive is omitted, fped defaults to millimeters.

When saving a footprint definition, the default unit is set to the
unit set in the GUI.


Allow
- - -

fped normally disallows overlapping pads. This restriction can be
relaxed with the "allow" directive.

allow touch

Allows pads touching but not having more than their border in common.

allow overlap

Do not check for overlaps at all.

If the "allow" directive is omitted, fped defaults to allowing
neither overlap nor touch.

There is also the following experimental directive that can be used
alone or without one of the overlap-checking directives:

allow holes

Allow multiple holes per pad.


Vectors
- - - -

Vectors can be anonymous or they can be named for future reference:

vec ( , )
: vec ( , )

The base can be one of the following items:

- @ is the origin of the frame containing the vector
- . is the end of the previous vector in this frame
- is the name of a previous vector in the same frame

The following example would draw the line described in the previous
section:

a: vec @(1mm, 1mm)
b: vec .(1mm, 1mm)
line a b


Silk screen objects
- - - - - - - - - -

The output of fped is a footprint definition that contains pads and silk
screen drawings (we may add more layers in the future). These items are
called "objects". Their geometry is defined through points obtained with
vectors.

A line connects two points:

line []

The points can be specified with @, ., and an identifier, just like
a vector base. The option width specifies the thickness of the silk
screen line. If omitted, a hard-coded default of 15 mil is used.

A rectangle has sides parallel to the x and y axis and is defined
by two diagonally opposite corners:

rect []

A circle is defined by its center and a point on the circle:

circ []

This example draws a unit circle:

vec @(1mm, 0mm)
circ @ .

An arc is like a circle, but the part of the circle drawn is determined
by two points. The first point determines the radius and the starting
angle. The second point only determines the end angle but its distance
from the center is ignored.

arc []

The arc is drawn in a counter-clockwise direction. The following example
draws an arc of the unit circle in the x > 0, y > 0 quadrant:

from: vec @(1mm, 0mm)
to: vec @(0mm, 1mm)
arc @ from to


Pads
- -

Pads are similar to rectangles, but they also have a name.

pad "" []

Variables can be expanded in a pad's name by prefixing their name with
a dollar sign. The ${name} syntax is also available.

Example:

vec @(1mm, 1mm)
pad "1" @ .

Pads normally affect the surface copper layer, the solder mask layer,
and the solder paste layer. This can be modified with the optional
type argument:

Type Layers
--------- -------------------------------------
(default) copper, solder mask, and solder paste
bare copper and solder mask
trace copper without solder mask opening
paste solder paste
mask solder mask

Typical uses:
- "bare": connectors printed directly on the PCB
- "trace": connections or antennas
- "paste": sparse solder paste, e.g., for QFN center pads
- "mask": non-standard mask openings, e.g., for solder mask defined
pads


Rounded pads
- - - - - -

Rounded pads are like rectangular pads except that they end with a
semi-circle at each of the smaller sides of the enclosing rectangle.
If enclosed in a square, rounded pads form a circle.

rpad "" []


Holes
- - -

Holes can be used for through-hole pins or for mechanical support.
In the former case, the hole must be placed inside a pad. Only one
hole per pad is allowed. Mechanical holes must be outside any pads.

Through-hole pads are always present on both sides of the board, i.e.,
when fped generates a KiCad module, the surface layers of a pad
containing a hole are propagated to the opposite side of the board.

Holes have the same shape as a rounded pad and their geometry is
defined in the same way:

hole


Measurements
- - - - - -

*** This is obsolete - see the section on new-style mesurements at the end. ***

Measurements show the distance between two points:

meas

The offset is the distance from the imaginary line connecting points A
and B the measurement line is draw:

- if the offset is 0mm, the line will connect A and B
- if the offset is positive, the line would be on the left-hand side when
traveling from A to B
- if the offset is negative , the line would be on the right-hand side when
traveling from A to B

Example:

a: vec @(-1mm, 1mm)
b: vec @(1mm, 1mm)
meas a b 0.2 mm


Package name
- - - - - -

The package name is a non-empty string of printable ASCII characters,
including spaces. If the "package" directive is omitted, fped defaults
to using the name "_".

package ""

Examples:

package "48-SSOP"
package "0603"

Like in pad names, variables are expanded in package names. This allows
the generation of multiple packages from a single definition.


Frames
- - -

Frames are used to group things and to reuse them multiple times. Frames
must be defined before they can be used:

frame {
... items ...
}

Once defined, a frame is placed at a given location with

frame

The frame definitions must precede all other items in a footprint
description. Frames cannot be defined inside other frames, but frames
can invoke each other recursively.

For example, this puts two unity squares, one centered at (0 mm, 0 mm),
the other at (2 mm, 0 mm):

frame unit_square {
a: vec @(-0.5mm, -0.5mm)
b: vec .(1mm, 1mm)
rect a b
}

frame unit_square @
vec @(2mm, 0mm)
frame unit_square .


Names and variables
-------------------

fped uses several name spaces:

- frame names occupy one global name space

- vector names occupy name spaces delimited by the frame they're
contained in. A vector name is only visible inside the frame in which
it is defined.

- variable names occupy name spaces delimited by the frame they're
contained in. A variable lookup starts in the frame in which the
corresponding expression appears and propagates to outer frames
until the variable is found.

- pads occupy one global name space (this is currently not enforced)

Note that names cannot be redefined. E.g., this does not work:

set a = 1
set a = a+1

The names spaces of frames, vectors, variables, and pads are separate
from each other.


Simple variables
- - - - - - - -

A variable with a single value is defined with the following
assignment syntax:

set =

Example:

set a = b+2


Loops
- - -

A loop is a variable with a range of values:

loop = ,

The variable assumes all the values i for <= i <= , in
increments of one. E.g.,

loop n = 1, 3

and

loop n = 1, 3.5

both assign the values 1, 2, and 3 to the variable "n". The
following loop would not execute at all:

loop n = 1, 0

This can be used to implement conditional execution. For example,
the items in the following frame would be instantiated if the
variable "enable" is set to 1 but not it is set to 0:

frame ... {
loop dummy = 1, enable
...
}

When a loop is executed, the objects contained in the body of the
enclosing frame are generated for each value of the variable. If
a frame contains multiple loops, all possible combinations of the
values are generated.

The following example draws three concentric circles around the
origin, with radii 1, 2, and 3:

loop x = 1, 3
vec @(x*1mm, 0mm)
circ @ .


Tables
- - -

Tables combine values for multiple variables. Like loops, they are
used to iteratively generate objects. A table begins with a row of
variable names, followed by one or more rows with values. Rows are
enclosed in curly braces and their elements are separated by commas.

table
{ , ... }
{ , ... }
...

Like loops, tables are iterated to generate objects. The following
example is equivalent to the one in the previous section:

table
{ x }
{ 1mm }
{ 2mm }
{ 3mm }
vec @(x, 0mm)
circ @ .

Note that we can set the unit of the values directly in this case.

Iteration is performed over rows. All variables of the table are set
to the value in the respective row at the same time. For example, in

table
{ x, y }
{ 1, 2 }
{ 3, 4 }

(x, y) assume the values (1, 2) and (3, 4).

Tables can also be used to provide information that depends on
other variables. The value of such a variable acts as a key, and a
row is only selected if all the keys in that row match the
respective variables. To mark a variable as being used as key, its
name it prefixed with a question mark.

Example:

loop n = 1, 2, 3
table
{ ?n, name }
{ 1, "one" }
{ 2, "two" }
{ 3, "three" }


Expressions
-----------

Expressions can contain numeric constants (in non-exponential notation),
variable names, the arithmetic operations +, -, *, /, unary -, and the
functions sin(), cos(), sqrt(), and floor().

Parentheses can be used to change precedence.

The argument of sin and cos is a dimensionless number that specifies the
angle in degrees. E.g., sin(90) yields 1.

The argument of sqrt() can be dimensionless or have a dimension with an
exponent that's a multiple of two. E.g., sqrt(2) and sqrt(2mm*3mm) are
valid expressions, sqrt(2mm) isn't.

The function floor() returns the next integer that is below or equal to
the argument. If the argument has a dimension, that dimension is
preserved. E.g., floor(-1.2) returns -2, floor(4.7mm) returns 4mm.


GUI
---

Part of the GUI is described in
http://downloads.qi-hardware.com/people/werner/fped/gui.html


Keyboard shortcuts
- - - - - - - - -

Space reset user coordinates
+, = zoom in (like mouse wheel forward)
- zoom out (like mouse wheel backward)
. cursor position to screen center (like middle click)
* zoom and center to extents
# zoom and center to currently active frame instance
U undelete the previously deleted object
/ Switch between variables, code, and packages display.


Canvas
- - -

To create a new object, click on the corresponding tool icon, move the
mouse to the base point of the new object, then drag to the object's
second point.

Frame references are created as follows:

- select the frame you want to add
- click on the frame icon. A black dot should appear on the icon.
- select the frame on which you want to add the new reference.
The black dot should change to a green dot. If the current frame
is a child of the selected frame, the dot remains black.
- click on the desired base location

To change a point of an object, select the object, then drag the point
to its new location. To edit the object's parameters, select it and
make the changes in the input area at the bottom.

To delete an object, select the delete tool and click on the object.
Deleted objects can be undeleted by pressing "u". If any other changes
have been made since deletion, fped may misbehave. If deleting a vector,
all items that reference it are deleted as well.


Experimental: new-style measurements
------------------------------------

New-style measurements can measure the distance between various pairs
of points, not only between points in the same instance and the same
frame. They operate on the set of points produced during instantiation.

New-style measurements are placed in the root frame after all other
items.

Known issues:
- they currently can't be edited through the GUI
- tie-breaking heuristics don't always do what one expects

Syntax:

[] []

Types:
- meas: measure diagonally
- measx: measure along the X axis
- measy: measure along the y axis

Note that the type also affects the selection of the points. E.g.,
measx will select maximum x values.

Operators:
- A -> B: smallest value of A and smallest B greater than A
- A <- B: like A -> B, but normal (for offset and text) is inverted
- A >> B: smallest value of A and greatest value of B
- A << B: like A -> B, but normal (for offset and text) is inverted

Operands are qualified vector names. Vectors in the root frame are
referenced by their name. Vectors in other frames are prefixed with
the name of the frame followed by a dot.

Example:

measx pad.sw -> pad.se 1mm

The optional label is printed directly before the distance. Example:

a: vec @(0mm, 0mm)
b: vec @(1mm, 0mm)
measx "width = " a >> b 0mm

would print "width = 1mm"


Additional qualifiers
- - - - - - - - - - -

When using frames as reusable building blocks, similar to functions or
macros in many programming languages, one may need finer control over
the points that are selected for measurements.

For example, let us consider a frame "square" that draws a square
centered at the frame's origin and with a side length given by the
variable "size". This variable be set in the frame referencing
"square".

frame square {
a: vec @(-size/2, -size/2)
b: vec @(size/2, size/2)
rect a b
}

frame small {
set size = 2mm
frame square @
}

frame big {
set size = 5mm
frame square @
}

frame small @
vec @(5mm, 0mm)
frame big .

If we want to measure the size of each square, we could use

measx square.a -> square.b

Unfortunately, this only measures the small square. To reach the
big frame, we need to tell fped to use only those points in "square"
that have been placed when "square" was invoked from the big frame.

This is accomplished by prefixing the points in question with the
name(s) of the frames that need to be visited. The frame names are
separated by slashes (/).

measx big/square.a -> square.b

For clarity, it's better to qualify both points, e.g.,

measx big/square.a -> big/square.b

If multiple frame names are given, they must be in the order in
which they are invoked.


Experimental: debugging directives
----------------------------------

For debugging and regression tests, fped supports the following commands,
most of which mimick the effect of GUI operations:

%del
%move []
%frame
%print
%iprint
%meas
%dump
%exit
%tsort { - | + | [] ... }

%del removes the specified item. This can be a vector, an object, or
a frame. If the vector or object is in a different frame than the
current, its name is qualified with the frame name, e.g., "foo.obj".

For this purpose, also objects can be labeled. Object labels behave like
vector labels and share the same name space. They are not normally
accessible in the GUI. (You can see them in the code view.)

%move take as its first argument the name of the vector or object to
manipulate. %move sets an anchor point to the vector named as its last
argument. The anchor point is identified by index as follows:

anchor index vec/frame line/rect/pad arc measurement
-------------- --------- ------------- ------------ -----------
0 (or omitted) base first point center low point
1 - second point end of arc high point
2 - - start of arc -

%frame creates a frame reference. Unlike "frame", the destination frame
can be different from the current frame. E.g., "%frame foo bar.a" would
add a reference to frame "foo" in frame "bar", rooted at vector "a". The
parent frame's origin can be references as "@".

%dump writes the footprint definition in the fped language to standard
output. %exit immediately exits fped, without invoking the GUI.

%print and %iprint evaluate the expression and print the result to
standard output. The difference between them is that %print runs only
once and without explicit instantiation, while %iprint is treated as
a regular object and is executed as many times as instantiation
demands.

For example, after loop x = 1, 3 we would obtain just 1 with %print
while %iprint would display, 1, 2, and 3.

%meas performs an instantiation and prints the value of the labeled
measurement.

%tsort is used to test-drive the topological sort algorithm. The items
in the curly braces are declarations of nodes with (-) or without
(+) decay or edges in the partial order. The optional number is
the edge's priority. See tsort.c for details, test/tsort for examples.