Compare commits

...

333 Commits

Author SHA1 Message Date
R. Timothy Edwards 0cbed6078a 2nd part of last commit's work: Implement a simple math solving
parser that allows simple expressions to be entered for dimensions,
such as "2um + 2um" or even mixtures of units like "3um + 200i".
This feature is currently experimental.
2026-01-24 21:02:00 -05:00
R. Timothy Edwards 9760ef6d1d Made some changes to the "snap" HTML document to reflect the way
that "units" now affects its behavior.
2026-01-24 16:55:14 -05:00
R. Timothy Edwards bd13febb72 Added HTML documentation for the new "units" command. 2026-01-24 16:50:16 -05:00
R. Timothy Edwards 81436b75ed Reworked the way that magic displays measurement values (both linear
and area) so that they are consistent across commands.  The default
behavior remains the same, for backwards compatibility.  However, a
new "units" command has been added, so that "units microns" results
in measurements always being displayed in microns, with choice of
that or "internal", "lambda", or "grid".  The units themselves may
be printed (for interactive use) or not (for scripted use).  The
use of "units" is independent of "snap", after overriding the
default behavior, so that units parsed on the command line are
interpreted according to "units", not to "snap".
2026-01-24 16:19:12 -05:00
R. Timothy Edwards 8822f8dce2 Added additional code to make the last pull request merge work,
which is to not force a setting for the command entry window
when creating a new window if the option variable already exists.
2026-01-22 11:55:36 -05:00
R. Timothy Edwards f03003b79f Just added a comment to the command entry enablement in the
wrapper.tcl script.
2026-01-22 11:42:45 -05:00
Daniel Hwang 802c31d16a wrapper.tcl: allow cmdentry to be enabled (by default) 2026-01-22 11:31:33 -05:00
R. Timothy Edwards 308224109f Multiple fixes and updates:
(1) Fixed an error that was introduced in version 8.3.590 with
    a patch that should have been applied only for the case of
    BJT devices, and not for MOSFETs.  The patch will cause
    devices generated by "device mosfet" or "device asymmetric"
    to be read incorrectly from a .ext file during "ext2spice".
(2) Fixed an error in the tech file reading, where using CDL
    parameters on a capacitor device would cause the tech file
    loader to print an error message.  The parsing was correct
    and only the message should not have been printed.
(3) Added a new feature with the new command option "extract
    do unique".  This replaces the "extract unique" command by
    running the same code within the extraction, but has the
    additional effect of reverting the label changes afterward.
    This prevents the user from inadvertently writing the
    altered labels back to the database file.
2026-01-22 11:20:20 -05:00
R. Timothy Edwards 4d9c7fd7d7 Corrected an inadvertent error in ResMakeRes.c introduced in a
recent commit, and fixed a more long-standing error in ext2spice.c
where a nodeClient structure was initialized to the wrong type.
2026-01-21 14:26:15 -05:00
R. Timothy Edwards a55ec49434 Corrected a callback function call in the router code which was
made outside of a search routine and so needed to have a "dinfo"
argument added.
2026-01-20 15:56:50 -05:00
R. Timothy Edwards c0dbb2067b Corrected an error in "extresist" that can cause a segfault which
is unrelated to recent code changes, and also corrected a bunch
of code to (somewhat) more properly handle non-Manhattan geometry.
2026-01-20 12:59:36 -05:00
R. Timothy Edwards b59708e27a Updating the version number after merging in work done in a
separate branch.  This completes the work preventing magic from
altering tile record contents during a basic search, but also
corrects W and L calculations for non-Manhattan geometry, and
a number of other corrections detailed in the branch's commit
messages.
2026-01-19 17:41:22 -05:00
R. Timothy Edwards c0c5e1b5bf Last set of changes to get non-Manhattan area and perimeter
device extraction working, and also resolved an unrelated error
in "getnode" and another unrelated error reading "resist" values
from the tech file "extract" section.
2026-01-19 17:18:10 -05:00
R. Timothy Edwards 3de9ed9cbf More updates. . . Got it to the point were gpio_ovtv2 is LVS
clean, which has never happened before.
2026-01-17 20:49:52 -05:00
R. Timothy Edwards 846c8e0f65 Additional changes; fixed some of the most problematic issues
involving searches on split tile areas, including one very
important check for interaction between split tiles during
hierarchical extraction.  There is still something wrong in
the hierarchical extraction, but it could be the last remaining
issue.
2026-01-15 21:35:46 -05:00
R. Timothy Edwards 8bd01f5597 Additional work to incorporate handling of split tiles throughout
the extraction, especially for routines like ExtFindNeighbors where
it was previously not handled at all.  A new method was introduced
in which split tiles with neither side TT_SPACE will get an extra
allocated structure that contains pointers to two regions representing
the nodes on the tile's left and right sides, independently.  The fix
(as yet not fully tested) should resolve problems with extracting the
sky130 I/O cells, which contain a FET with 45 degree angles on the
gate, where a split tile is divided between the gate and the source or
drain, and therefore represents two different nodes.  Also, there were
extraction errors related to incorrect handling of split tiles having
only one node, where a split tile became connected to the wrong node.
2026-01-09 12:05:03 -05:00
R. Timothy Edwards 1cb58e973a Committing changes to date, which includes a number of fixes,
especially around the extraction code.  Extraction is now
more or less working, although the original known issues
around areas where split tiles contain two regions has not
yet been addressed.
2026-01-09 12:05:03 -05:00
R. Timothy Edwards 516c9d7635 First cut of pulling the TT_SIDE bit out of the tile database
and forcing it to be passed as an argument to all the callback
functions for the search routines that require it.  Magic now
compiles and runs with the new code, but there are a number of
known issues that need to be fixed up.  Committing now so that
I can rebase on the last update to the master branch.
2026-01-09 12:05:03 -05:00
R. Timothy Edwards d24d52e403 Corrected an error in EFbuild.c in routine efBuildDevice(), which
had one error and one missing method.  The error was an incorrect
argument count for regular (not subcircuit) FETs and BJTs.  The
missing method was to handle parameters w0, w1, w2, etc., like
l0, l1, l2, . . .   Those had been defined for output in ExtBasic.c
but were not being handled on input from the .ext file.  This fix
corresponds more or less to PR #480 on github, although that PR
incorrectly addressed the argument numbering problem, so I have
redone the code changes by hand.
2026-01-09 11:51:11 -05:00
R. Timothy Edwards a93d248a5a Removed some diagnostic print lines that had been used for
debugging the problem that was corrected in the December 29
commit, and which had inadvertently been left in the code.
2026-01-05 16:56:05 -05:00
R. Timothy Edwards 4ccd5a78d1 Corrected a couple of lines in the paint code that had been
improperly messed with during a commit back in August.  At the
time I was unsure of what to do with those lines, but now I'm
quite sure they were correct to have been commented out.  I
have now removed them so that they should not cause trouble in
the future.  Quick explanation:  After a non-Manhattan tile
4-way split, merging should be done to the left conditionally
on the merge flags (the latter part of that being the August
1 fix), but merging should never be done to the right because
the right side is still fractured and has yet to be visited.
The merging will eventually get handled.  Whether the merge
flag has been set or not does not matter.
2026-01-02 19:54:08 -05:00
R. Timothy Edwards f998f8ee6f Corrected an error that has been known for a while but which had
not previously been tracked down.  Behavior was that GDS additions
to correct hierarchical interactions would miss areas, especially
on large chip designs.  This was found to be caused by a nested
use of DBSrCellPlaneArea();  the inner use was changing the outer
use's search area and causing it to exit early.  Corrected by
removing the nested use of the subroutines.  Also, created a
proper client data structure to pass information to and from the
subroutine, eliminating the ugly global variables that had been
used for that purpose.
2025-12-30 12:15:15 -05:00
R. Timothy Edwards 662e21a2d1 Corrected an error that had been introduced when creating the
parameter types "l1", "l2", etc., for terminal lengths.  There
was a string comparison against an unterminated character array
which was causing intermittant errors.  This problem was masking
the incorrect handling of "l1", "l2", etc., parameters.  The
parameter types had been introduced to cover a specific type of
drain-unsalicided FET in GF180MCU, which is used as an ESD
device in the foundry I/O cells, so the impact had been
relatively limited, although typically showed up as unexpected
property errors on the ESD devices when running LVS on a chip
top level.  Both discovered errors have been fixed.
2025-12-29 10:52:08 -05:00
R. Timothy Edwards 949ec7672c Reworked the code from the previous commit in a completely different
way.  The code as previously written was undermining other code
written to avoid long run-times on ext2spice, and didn't solve at
least one issue with unnecessary resistor shorts being added to the
netlist output.  The current solution fixes one underlying problem
where a wrongly-placed parenthesis caused the "preferred net name"
routine EFHNBest() not to be run, which prevented original node
names from being preferred over their suffixed versions created by
"extract unique".  However, I also added code to EFbuild.c to
merge unique nodes when the nodes are not really unique.  The
problem is caused by "extract unique" operating only on one level
of hierarchy and being unable to see where nets may connect through
subcircuits.  That can be determined from the "merge" statements
in the .ext file, and now the EFbuild routines will merge these
"false unique" names back into the original net.
2025-12-24 16:00:08 -05:00
R. Timothy Edwards bd417aa54b Updating the version number to go along with the merge of pull
request #478 from Mitch Bailey.  Also edited the code from the
PR for programming style.
2025-12-24 11:31:43 -05:00
Mitch Bailey 73e08e0c88 Prefer original ports over duplicate ports in extracted spice netlist.
Prioritize lowest port number when merging nodes.

Signed-off-by: Mitch Bailey <d.mitch.bailey@gmail.com>
2025-12-24 11:19:16 -05:00
R. Timothy Edwards 893a36cae7 Updated the version to go along with the merge of pull requests
475, 476, and 477 (first ones for mac OS and arch Linux support
on github;  the last to modify recent code changes to work with
the last code merge for eliminating the one-off freeMagic().
2025-12-22 09:57:56 -05:00
Darryl L. Miles 3b4d66e7d7 freeMagic1() additions
These additional uses of freeMagic() also require defer-by-one using stack
storage (not global storage idiom, recently introduced).
Not sure if they were missed original or new/modified code in the past
12 months.  Some areas/line-of-code are not usually compiled, maybe that
is why they were originally missed.
2025-12-22 09:57:42 -05:00
Darryl L. Miles 5e8a3f038a CalmaWrite: fix: introduced memory leak, missed free
Appears the 'listtop' is a sentinal/entryexit value to a circular list
My recent patch does not copy original behaviour in freeing this list
entry (as well as the reset of the list).
2025-12-22 09:57:42 -05:00
Darryl L. Miles 9850c5586e GHA: main-aarch64.yml: insert apt-get update 2025-12-22 09:57:29 -05:00
Darryl L. Miles 27df5f9c5f GHA: Migrate macos-13 => macos-15-intel 2025-12-22 09:57:04 -05:00
Darryl L. Miles e9202c1d29 malloc: remove #pragma weak as MacOS does not like
Originally the use of a weak symbol was to provide a fallback for
non-inline supporting compilers.  However all compilers (we care about)
support inline keyword (which was not known at the original time of the
work).  Furthermore GCC have already worked through the solution and make
it easy to implement.

The use of __GNUC_STDC_INLINE__ pattern in this way manages the fallback
and emits a hard symbol this can be tested with:

CFLAGS="-g" ./configure; make; nm */lib*.o | grep freeMagic1

CFLAGS="-O3" ./configure; make; nm */lib*.o | grep freeMagic1

A hard 'T' symbol is emitted (to provide fallback) with all builds, but
in the -O3 all usage is inlined.  So an individual file can decide to
inline or not at the occasion (compile time options) allows.
2025-12-19 09:31:58 -05:00
Darryl L. Miles ea1a89b19c EFbuild.c: efConnectionFreeLinkedList() remove delay-by-one assumption
freeMagic1 series 2nd order find
2025-12-19 09:31:58 -05:00
Darryl L. Miles 9489b23985 freeMagic1() idiom insertion at all sites reported by static code analysis 2025-12-19 09:31:58 -05:00
Darryl L. Miles c74215ad55 scripts/defs.mak.in: FEATURE_FLAGS -DSUPPORT_DIRECT_MALLOC -DSUPPORT_REMOVE_MALLOC_LEGACY
./configure
 # If you are brave, enable with your favourite editor after ./configure
 sed -e 's/^#FEATURE_FLAGS /FEATURE_FLAGS /' -i defs.mak
 make
 make install
2025-12-19 09:31:58 -05:00
Darryl L. Miles 4201f56048 callocMagic has same API argument convention as calloc() 2025-12-19 09:31:58 -05:00
Darryl L. Miles 26372f5d50 gtTkCommon.c: SUPPORT_DIRECT_MALLOC around function pointer use of legacy malloc
Just in case I also modify the allocation to ensure it was also performed
via exactly the same method.
2025-12-19 09:31:58 -05:00
Darryl L. Miles ef419258ab SUPPORT_DIRECT_MALLOC and SUPPORT_REMOVE_MALLOC_LEGACY
This supports three build modes:

No additional -D options, default legacy mode

-DSUPPORT_DIRECT_MALLOC, magic will use direct calls to libc malloc/free
 and will leave in place the symbols now renamed as mallocMagicLegacy()
 freeMagicLegacy() and callocMagicLegacy().

-DSUPPORT_DIRECT_MALLOC -DSUPPORT_REMOVE_MALLOC_LEGACY as above but will
 remove the three legacy functions from the binary to provide assurance
 they can not be used.

The system malloc is thread-safe the legacy magic malloc has a global
deferred free pointer and the mmap() allocate has a free-list that is
not thread-safe making use of free not thread-safe.
This could of course be improved with the use of
atomic_compare_and_exchange operations but for what gain ?

Then there is the additional function call overhead (of the indirection)
and a few tests/branches inserted into a commonly used code paths around
memory allocation, it hides the call site of the malloc/free usage from
the compiler which maybe have special optimization cases.

The existing malloc/free makes static code analysis around memory
allocation more problematic, also use of runtime analysers will operate
better with a fail-fast to bad memory usage.
2025-12-19 09:31:58 -05:00
R. Timothy Edwards 97134848ab A few minor changes to message reporting, plus some additional
support for compressed formats, specifically when given on the
command line (which is handled in a Tcl script, not in the C
code).
2025-12-19 09:30:35 -05:00
R. Timothy Edwards 00c692b140 Added better support for compressed .mag files. While magic doesn't
generate compressed .mag files itself, it is often very useful to
compress a massive layout file to save disk space or to hit a github
size target.  The code change looks for files with either ".mag" (default)
or ".mag.gz" extensions.  No check is made to see if both files might
exist at the same time and have incompatible content;  it is up to the
end user to manage the file compression.
2025-12-11 09:55:28 -05:00
R. Timothy Edwards 203ece1a16 Fixed the "interacting" GDS output operator (which includes
"noninteracting", "overlapping", and "nonoverlapping") which
were incorrectly ignoring tiles outside the search area.
Otherwise they will miss areas that pass outside of the the
search area and return back inside somewhere else.
2025-12-01 15:16:14 -05:00
R. Timothy Edwards 22a230edc9 Found a mistake in the original edit for time stamps from two
commits back, and fixed it.  Also found that the version was
changed between today's first two commits, which it should not
have been, so dialed it back.
2025-11-29 15:49:17 -05:00
R. Timothy Edwards 7f1217596e Missed one additional place in the last commit where timestamps
need to be predecated on the read/write status of cells.
2025-11-29 15:01:21 -05:00
R. Timothy Edwards ff718c3ecf Got rid of one problem with timestamps, which was the requirement
to force an update on a child cell to match the timestamp of the
parent.  This is no longer done on read-only cells, although it
probably ought to be applied to all cells.  A timestamp should
change when a cell has been modified, but a parent cell should never
force a child cell to update its timestamp if the child cell has
not been modified.  The main problem is that "drc check" runs checks
on all child cells, and they then are marked as modified without
consideration of whether the child's DRC status changed.  A better
solution would be to avoid unnecessary updates by detecting a
change in DRC results, but for now, just disabling updates on
read-only cells (which can't be updated anyway) should suffice.
2025-11-29 13:24:23 -05:00
R. Timothy Edwards 98aa2f760a Corrected an error from a recent commit: An attempt to add array
checks when checking for exactly overlapping instances of the same
cell def was faulty and resulted in magic no longer detecting when
unarrayed instances exactly overlap.  Now both conditions (arrayed
and not arrayed) should be handled correctly.
2025-11-25 12:57:46 -05:00
R. Timothy Edwards 441d933148 Updated version to go along with the merge of pull request #473
from Sylvain Munaut.
2025-11-23 17:06:56 -05:00
Sylvain Munaut 9d3fb61cf3 defRead: Accept usename longer than 511 char
The previous code always read in a defined size buffer and any
name longer gets cut which causes issue during extraction because
any collision on the truncated name causes components to get "lost".

So here instead we keep a local stack buffer of 512 byte and use it
if possible, but for longer string we allocate some space on the heap
temporarily.

Some later error processing had to be refactored a bit to make sure
we can always clean-up after ourselves once we're done with the
buffer.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
2025-11-23 20:14:21 +01:00
R. Timothy Edwards a1fb779314 Added a LEF section to nmos.tech, provided by Dave in fossi-chat.org. 2025-11-19 17:49:43 -05:00
R. Timothy Edwards abd3975997 Corrected the (very old) "nmos.tech" file, which had GDS layer
assignments for output but not for input.  Also, one layer was
given two different GDS numbers for GDS output, which was
incorrect.
2025-11-19 17:42:40 -05:00
R. Timothy Edwards 227f264838 Fixed the error that causes problems with the tile allocation.
The error was in selStretchEraseFunc2() which was calling
DBErase().  But DBErase() can call DBSrPaintArea() and thereby
start another search of the same plane while the plane is
already in a search.  This is absolutely invalid.  However, it
is simple just to use selStretchEraseFunc2() to collect a mask
of the types that need to be erased and pass that back to the
caller, and apply DBErase() to each type in the mask, outside
of the DBSrPaintArea() search.  With this fix, the tile
allocation is no longer causing problems, and the code to add
tiles deallocated by TiJoinX and TiJoinY to the free tile list
has been uncommented again.
2025-11-09 12:52:03 -05:00
R. Timothy Edwards c87e5baff4 Rolling back part of the last commit; the correction to the tile
allocation fixes the issue with memory being grabbed constantly
and never released, but re-surfaces an error with tiles being
used after being freed.  This is assumed to be a long-standing
bug that has not been found yet.  Meanwhile, the error that uses
up excess memory is better than the error that causes layouts to
get completely screwed up.
2025-11-08 17:24:09 -05:00
R. Timothy Edwards 957d7edd64 A number of things in one commit:
1) Added a "*showmem" "wizard" command to get a dump of all memory
   being used by tiles in the database.
2) Made a slight correction to the way magic detects exact overlap
   of instances of the same cell.  This probably does not make any
   actual difference in practice.
3) Corrected an uninitialized variable in dbReComputeBboxFunc().
4) Changes DBSrCellPlaneArea() to use a static BPEnum variable, so
   that it does not waste time allocating and freeing memory for
   the same thing over and over again.
5) Corrected a memory leak in the tech file "extract" section that
   loses memory every time the extraction style is changed.
6) Corrected the tile join routines to fix a bad memory leak in the
   tile allocation and recovery---a fix which was mentioned in issue
   #414 but which had not yet been implemented.  This has now been
   tested and confirmed to work.
2025-11-07 11:00:22 -05:00
R. Timothy Edwards 969137d1e2 Corrected an unfortunate error from the previous commit due to
missing copying one line with a conditional.  The error results
in "bloat-all" DRC checks reporting false positive errors.  This
commit fixes that error.
2025-11-03 15:06:54 -05:00
R. Timothy Edwards f3adea8c65 Made a few corrections to recent code additions. Also added
more points to accept interrupts during DRC checks, and
modified the tech file parser to allow the full syntax for
magic layers that is allowed elsewhere (e.g., "(*ndiff,poly)/a")
(this applies to magic layers, not GDS layers).  Fixed a
clipping error in the bloat-all function which was causing
non-manhattan geometry to produce bad results, which would
cause false-positive DRC errors when used in a CIF-DRC rule.
2025-10-31 17:37:02 -04:00
R. Timothy Edwards 246c0ea7a4 Extended the "maxwidth" DRC rule to take an optional set of layers
that exclude the maxwidth rule from taking effect.  This is
especially useful for implementing a maxwidth rule on top metal
that does not apply to pads, using the passivation cut layer to
prevent the maxwidth rule from being applied.
2025-10-30 16:39:54 -04:00
R. Timothy Edwards 47778971ee And one more fix to the method, for which I added a variation of
DBNMSrPaintPlane() where if "tile" is non-NULL then "plane" can be
NULL;  the hint tile does not get set but the routine can be called
without knowing the plane other than that the tile is in it somewhere.
2025-10-30 13:18:12 -04:00
R. Timothy Edwards cccd79ab0d One correction to the last commit---The additional check is not
limited to the DRC_REVERSE case but must be done in both the
forward and reverse cases.
2025-10-30 12:37:00 -04:00
R. Timothy Edwards 51b9846120 Made a correction to the DRC error checking on a non-Manhattan
edge.  This was catching geometry unrelated to the error when doing
a spacing check between geometry on different planes.  In the
reverse-edge case, magic needed to run an additional search over
the area on the other side of the original edge that triggered
the rule to effectively clip that corner of the triangle from the
search area.
2025-10-30 12:07:29 -04:00
R. Timothy Edwards 1afd48e840 Corrected an error in which an invalid client name passed to the
"macro" command will crash magic.  This will happen if, for
example, magic is compiled without OpenGL support, in which case
the "wind3d" client does not exist, and parsing the default
macros from the system .magicrc file will cause an immediate
crash.
2025-10-29 09:32:03 -04:00
R. Timothy Edwards 99a5a28a3e Added a drc check to the gencell change procedure, as it appears
that otherwise DRC is not re-checked after a gencell update.  It
is not clear to me why checks are not done otherwise.
2025-10-28 15:10:03 -04:00
R. Timothy Edwards 0ac4d3a465 Found a way to work around the problem of having subcell DRC
errors show up as "See error definition in subcell", which has
been the case since I modified the code to prevent showing DRC
errors in subcells that have been resolved by the hierarchy
above them.  DRC errors are now intelligently searched
downward in the heirarchy when enumerated for "drc why".
Also changed the DRC check tile definition to offset such that
there is a tile centered on the origin, instead of the origin
being between four tiles.  Since most layouts are subcells and
most subcells are small relative to the DRC check tile area,
and most subcells are placed near the origin, then most subcells
will appear in only one tile, which speeds up the DRC process
somewhat.
2025-10-23 17:11:44 -04:00
R. Timothy Edwards 42aa06f8f5 Corrected what seems to be a long-standing error in which
DRCCheckThis() is called in order of top to bottom of the hierarchy
when called from drcCheckFunc() although it was changed to order
DRCPendingRoot from bottom to top.  drcCheckFunc() then does it
backwards.  Fixing this appears to have resolved some weird errors
with DRC errors not showing up when doing "drc check" (initially)
and DRC errors disappearing when making changes to a generated
cell.  Appears to be okay now.
2025-10-22 17:27:00 -04:00
R. Timothy Edwards 4d2912a406 Corrected the return value of spcWriteValue() (recently added)
from "bool" to "void" (does not return a value).
2025-10-21 09:15:05 -04:00
R. Timothy Edwards b668b02a1f Corrected a problem in which "cellname delete" never cleared the
cell name from the cell name hash table.  So when "cellname rename"
was changed recently to prevent changing the name of a cell that
already exists, the suggested recipe for R-C extraction no longer
works:  "load x; flatten y; load y; cellname delete x; cellname
rename y x".  Solved by adding a HashRemove() function to the
cell deletion routine.  Thanks to Egor Lukyachenko for reporting
the issue (Github issue tracker #467).
2025-10-20 11:03:03 -04:00
R. Timothy Edwards 6b8f5d1d67 Modified the toolkit behavior so that a default callback to update
the dialog (and run limit checks) is installed by default on
checkboxes and selection menus, as it is already done for entry
boxes.  Otherwise it is possible to make a selection (like changing
a device type) that invalidates the existing values, but if Apply
is hit immediately afterward, then no checks will be run and the
values may be used as-is even if invalid.  This does not prohibit
the use of "add_dependency" to change the callback behavior.
2025-10-16 17:08:15 -04:00
R. Timothy Edwards c977e4cf76 Corrected an error introduced yesterday by a hasty fix, which
ended up breaking the "extresist" function by failing to parse
the comment line of a .sim file.  This is now fixed.
2025-10-15 10:00:02 -04:00
R. Timothy Edwards 9327e319da Corrected ext2sim to handle the new "dsubcircuit" device type,
added in a recent commit.  The extension was handled by
"ext2spice" but "ext2sim" was missed.  Without it, "extresist"
will fail for any circuit containing a device defined in the
tech file extract section with "dsubcircuit".
2025-10-15 08:31:58 -04:00
R. Timothy Edwards 0e84616af8 Corrected an error that allows a cell to be renamed with the name
of an existing cell, which does not appear to be a fatal problem,
but must be causing a memory leak.  Also:  Corrected an error in
extresist when reading .sim files, in code that is slated to be
overhauled, so this is just a patch to avoid a crash condition.
2025-10-14 10:36:07 -04:00
R. Timothy Edwards c42db8e71b Modified the key input redirection so that it captures and
handles Control-u in the same way that tkcon does, so that when
typing via redirection into the console, Control-u will delete
the entire command back to the prompt. (See github issue #456.)
2025-10-10 10:39:40 -04:00
R. Timothy Edwards 27c423c2ed Substantially revised the "macro" command callback functions and
the "tool" implementation.  Previously, the "tool" implementation
would overwrite the button bindings for the mouse.  The problem
with that is that if the user customizes one or more of the
bindings, such as using the mouse wheel for zooming instead of
panning, then the custom macro gets obliterated when the tool
changes.  The reimplementation creates multiple macro sets which
are unique to each tool.  The "enable_tools" function sets up
the initial unique default bindings for each tool.  The user
can then customize the bindings for any tool, and the
implementation no longer requires the constant changing of key
bindings.  Note that the new implementation is slightly less
efficient because the macro tables are found by string hash
based on the name of the tool or client type, not the integer
client ID.  The reduction in efficiency is balanced by the
increased flexibility of the macros.
2025-10-09 15:43:54 -04:00
Darryl L. Miles 53e7dfe04c ext2spice.c: ifdef for !MAGIC_WRAPPER build 2025-10-08 20:56:41 -04:00
R. Timothy Edwards 9ca81f8ea6 Modified the "tag" command to add an optional subcommand "add" or
"replace" as the 2nd argument.  This allows a simpler 'tag add
<command> <value>' than the existing awkward 'tag <command>
"[tag <command>]; <value>'.  Using "add" also helps avoid
mistakes like one that was in the code for a long time which
overwrites one of the helper window callbacks.  With this done,
added some additional callbacks to the "library manager" to
update when a new file is created by "select save" or "writeall".
Also added "Refresh" buttons to these windows, just in case.
Implemented a zoom function on the mouse scroll wheel when the
Control key is pressed.  This is a stop-gap for a problem with
overriding button bindings that re-establish themselves when the
tool (box, wiring, etc.) changes.  That needs to have a more
comprehensive solution (such as tool-specific bindings).
2025-10-08 17:11:27 -04:00
R. Timothy Edwards d822353e85 One additional fix, since the previous fix needed to be made in
both ext2spice.c AND ext2hier.c.
2025-10-08 10:08:29 -04:00
R. Timothy Edwards 4951f013d5 Corrected the output of the new "dsubcircuit" device which was
generating output for one of the device nodes twice in the
netlist.
2025-10-08 10:04:38 -04:00
R. Timothy Edwards d3a0228958 Added a new device type "dsubcircuit" which basically behaves like
"csubcircuit" but swaps the first two pins (with the device
identifier layer becoming the 2nd pin and the other terminal the
first), which is needed for n-type diodes modeled as subcircuits
where the subcircuit pin order matches the order of pins for a
SPICE n-type diode component.  Previously "msubcircuit" was used
for this purpose, but will calculate the wrong L and W.  While
use of L and W for diodes is rare, this device type also works for
reversed capacitors (where the bottom or non-identifying layer
terminal is in the first pin position of the subcircuit).
2025-10-07 16:45:22 -04:00
R. Timothy Edwards 656d27b17a Added a new "devresist" type "terminal" to account for resistor
terminal resistance, for cases where the resistor value is
estimated and output along with (or instead of) the physical
length and width or area and perimeter.  Corrected the "area"
and "perimeter" type handling so that they combine in parallel,
not in series (note that "perimeter" resistance is just an area
resistance with the depth of the material factored in).
2025-10-07 12:12:33 -04:00
R. Timothy Edwards 3631892cfa One more minor change to the behavior just implemented: A value
for a resistor or capacitor is optional but is valid SPICE and not
just limited to CDL format, so it is now allowed to add "r=" at
the end of a resistor or capacitor component (not subcircuit) to
generate the optional component value.
2025-10-06 20:37:30 -04:00
R. Timothy Edwards 8c323803b7 Additional modification to write out a resistor or capacitor value
as-is, without a parameter name and before any device model name or
substrate pin, according to CDL syntax, if the parameter has been
specified without a parameter name (e.g., "r=" instead of "r=r").
Corrected an error in the extract code which put the substrate node
name in front of parameters instead of after.  This was previously
unexercised because only in CDL format does a resistor or capacitor
model have parameters listed by name.
2025-10-06 17:42:34 -04:00
R. Timothy Edwards acdfb256a1 Made a change to CDL format output to place the substrate parameter
in front of the device name, which is a very inconsistent way to
make the syntax, but whatever.
2025-10-06 16:40:19 -04:00
R. Timothy Edwards 5e74ecf9fa Added code to avoid a segfault if a resistor or capacitor is
specified without a list of substrate connection types, but
the "s=" parameter is used, resulting in an attempt to access a
substrate node that does not exist.
2025-10-06 14:14:05 -04:00
R. Timothy Edwards d6d8620a7c Added new statements "connect" and "disconnect" to the extract
section of the tech file, which can be used to alter the layer
connectivity tables from the default.  This can be used, for
example, to disconnect substrate and well from taps, to
generate a netlist that checks for soft-connect errors.
2025-10-06 11:50:38 -04:00
R. Timothy Edwards a2390167e6 Updated the version to go along with the merge of pull request #455
from Darryl Miles.
2025-10-04 20:50:51 -04:00
Darryl L. Miles 3cfc24f4b9 AppImage: AppRun use #!/usr/bin/env bash
There are Linux systems without bash installed at /bin/sh or it is
in a non-standard location.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 7e12bec49d txInput.c: comment #endif markers 2025-10-04 20:50:31 -04:00
Darryl L. Miles 5f1f92f30d GHA: update canary-matrix.yml
Removes ubuntu-20.04 config (no longer available on GitHub CI)
added clang-19 and gcc-13
removed no_gc_gu, as all 'gl' (GL) options require 'gu' (GLU)
added build for --enable-readline-bundled
added X11+Cairo
2025-10-04 20:50:31 -04:00
Darryl L. Miles 15faa19346 configure: autoconf regen (2.69) --enable-readline-bundled GR_SRCS 2025-10-04 20:50:31 -04:00
Darryl L. Miles af7b6bf119 graphics: minor change to Makefile and configure
This splits and groups DEPSRCS better so errors are not seen trying to
include files that are not present with no intention to build that
source file.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 8b0616eaf5 readline: add configure --enable-readline-bundled option
Cleanup autoconf handling, should always work as expected.
Use of --enable-readline-bundled when readline is needed will use
copy in subdir.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 2b62123459 SimRsim.c: removal of pre-POSIX.1-2001 select() interface ifdefs
POSIX.1-2001 introduced fd_set for use with select() and all current
systems support POSIX.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 2259ef626d SimRsim.c: EMSCRIPTEN fix for select/fd_set
The compiler has started to error on casting int* to fd_set*
Since WASM build has presense of fd_set then the ifdef have been
switched away from the legacy (pre 2000) method.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 3c9987f460 CmdFI.c: CmdGoto() correct printf output
non-tktcl build check
2025-10-04 20:50:31 -04:00
Darryl L. Miles f4212d8e0e graphics: cleanup various warnings 2025-10-04 20:50:31 -04:00
Darryl L. Miles a16c667290 txInput.c: USE_READLINE constify rl_completion_function
There is a use case of fully .rodata data table of strings but also
a dynamic version built at runtime.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 6e2babd141 txInput.c: constify localvars
non-tktcl build check
2025-10-04 20:50:31 -04:00
Darryl L. Miles b80279c6db grOGL1.c: HashLookOnly() using X11 Window type a key on LLP64 needs cast 2025-10-04 20:50:31 -04:00
Darryl L. Miles 722209b1ae parser.c: ParsSplit() constify (const char **remainder) 2025-10-04 20:50:31 -04:00
Darryl L. Miles 692c0f2339 grX11su3.c: warning for ClientData compare
MAGIC_WRAPPER build option
2025-10-04 20:50:31 -04:00
Darryl L. Miles dbdec3aa17 readline/Makefile: lib target (for no-tktcl build option) 2025-10-04 20:50:31 -04:00
Darryl L. Miles f7d2debb98 txOutput.c: $PAGER handling constify 2025-10-04 20:50:31 -04:00
Darryl L. Miles 0f047b89ce txMain.c: readline needs function shim for prototype difference TxGetChar
USE_READLINE build option
2025-10-04 20:50:31 -04:00
Darryl L. Miles 3b57ae1179 txMain.c: MAGIC_WRAPPER constify fix 2025-10-04 20:50:31 -04:00
Darryl L. Miles dc45242d46 database: DBTypeLongNameTbl() constify data (const char*) 2025-10-04 20:50:31 -04:00
Darryl L. Miles 6d8c3eee1a database: DBTechAddPlane() constify API (const char*) 2025-10-04 20:50:31 -04:00
Darryl L. Miles c8fe30398b database: DBTechInitPlane() consumer (DBPlaneLongNameTbl constify) 2025-10-04 20:50:31 -04:00
Darryl L. Miles 5093182f4a database: DBPlaneShortName() return const char * 2025-10-04 20:50:31 -04:00
Darryl L. Miles 4864a80179 database: DBTypeShortName() return const char * 2025-10-04 20:50:31 -04:00
Darryl L. Miles 70054ccde2 EFread.c: ANSI prototype efReadDef() 2025-10-04 20:50:31 -04:00
Darryl L. Miles c007d8077c EFbuild.c: ANSI prototype efBuildDevNode() 2025-10-04 20:50:31 -04:00
Darryl L. Miles da216195b3 SimSelect.c: fix theoretical potential to write to .rodata string
We make a copy of readonly string on function entry and use that instead.
strrchr() is a bit of an annoying API, takes const char* but returns char*
but it is the same string.  One for static analysis or C++.

SimSelectArea() argument unused.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 5fe586100b extflat: ANSI prototype efBuildDevice() and constify (const Rect*) 2025-10-04 20:50:31 -04:00
Darryl L. Miles c7ef7d743a CmdRS.c: SimGetNodeCommand() returns (const char *) now 2025-10-04 20:50:31 -04:00
Darryl L. Miles df7b9079bd CmdFindLabel: fix off-by-one error with: findlabel -glob name
Thanks @d-m-bailey Mitch Bailey for reporting
2025-10-04 20:50:31 -04:00
Darryl L. Miles cfd1d567bd commands: Various fixes for TxPrintf() with !MAGIC_WRAPPER
!MAGIC_WRAPPER build for WASM exposes
2025-10-04 20:50:31 -04:00
Darryl L. Miles b1424bfaf3 plow: add ANSI prototypes plowMergeBottom() plowMergeTop()
This exposes the incorrect call sites, that are also fixed here.
2025-10-04 20:50:31 -04:00
Darryl L. Miles aef23fd5f3 plotRutils.c: use #include <math.h> 2025-10-04 20:50:31 -04:00
Darryl L. Miles 1dfe1ed645 SimSelect.c: constify (const char*) TLE.tl_nodeName TLE.tl_simLabel 2025-10-04 20:50:31 -04:00
Darryl L. Miles 9c5cf1a567 magic.h: DLONG_PREFIX add other Linux 64bit ifdefs 2025-10-04 20:50:31 -04:00
Darryl L. Miles 55931e8811 GHA: .github/workflows/main-aarch64.yml 2025-10-04 20:50:31 -04:00
R. Timothy Edwards bb131f14d0 One additional modification to output the message about duplicate
cells as a "note" if "gds noduplicates" has been set, and a
"warning" otherwise.  This makes error handling of magic's
output a bit easier.
2025-10-01 15:38:41 -04:00
R. Timothy Edwards 78f7d22796 A number of changes:
1) Corrected spurious error messages about cells already existing
   in GDS when using "flatten" or "flatglob".
2) Fixed handling of resistance as a subcircuit parameter
3) Added area and perimeter resistance for a device;  this is done
   through the "devresist" statement in the tech file, which is an
   extension of the original "fetresist" statement.  Where "fetresist"
   only supported type "linear", "devresist" supports types "area"
   and "perimeter".
4) Support for CDL syntax, including generating subcircuit-like
   parameters for components starting with SPICE-standard prefixes
   like M, R, C, etc., adding "/" between pins and subcircuit name,
   and saving the file as ".cdl" instead of ".spice".
5) Estimated L and W for devices whose geometry is complex and do not
   reduce to a simple rectangle.  L and W are estimated as the square
   root of the area.
6) Changed the method of extracting L and W for diodes to use the same
   method as capacitors.  Note that diodes are not usually specified
   by L and W, but if they are, this will produce the right result.
7) Corrected the reported filename and line number when printing error
   messages related to errors inside a technology file, when the
   technology file uses "include" to combine multiple files.
2025-10-01 15:17:49 -04:00
R. Timothy Edwards b1c7b52ed2 Modified "gds flatglob" to have the value "*_CDNS_*" by default,
since this is a common artifact of foundry cells and almost
always incompatible with magic.  Modified the "port" command to
allow "port make <index>" on a label where other labels of the
same text already have the same index.  Removed deprecated
documentation and added some missing documentation, such as an
explanation of the "ext2spice subcircuit auto" option.
2025-09-26 09:18:43 -04:00
R. Timothy Edwards 5de118b762 Corrected the greatest common factor routine that is run when
doing "save", which was missing checks on properties representing
coordinates (e.g., FIXED_BBOX) resulting in those values
potentially getting truncated by scaling the output to an
incompatible common factor.  Thanks to Sylvain Munaut for finding
the issue!
2025-09-17 12:20:13 -04:00
R. Timothy Edwards 00e3bbd12a Corrected the tech loader, which was failing to set the file
prefix when doing a reentrant load, causing include files to not
be found.  Fixed a divide-by-zero issue that occurs when some
tech file sections are not loaded to the abovementioned error.
2025-09-11 10:51:14 -04:00
R. Timothy Edwards 0022c502c8 Correction to dbReComputeBboxFunc() to fix a potential issue with
an uninitialized bounding box value.
2025-09-10 16:54:25 -04:00
R. Timothy Edwards 741216d6f3 Added a new command "archive" that works roughly like the "crash"
command, but with some critical differences, since the "crash"
command is designed for crash backups.  "crash" will save in a
temp file and removes the file after a successful recovery.
"archive" can be used at any time to make a complete snapshot of
a layout in a single file, or to read back that snapshot.
There is a "writeall" option that will make a snapshot including
layout of all read-only (PDK) cells.
2025-09-10 12:40:40 -04:00
R. Timothy Edwards 6195c20d3d Fixed an egregious error introduced by the "save <file>.tcl"
command handling in the previous commit, that can cause a crash
whenever "writeall" is called while a cell's filename is still
NULL.  Thanks to Daniel Estevez for reporting the error.
2025-09-08 09:22:14 -04:00
R. Timothy Edwards 59a1953f3c Modified the GDS read routine to give location information when
a self-intersecting or reversing path is seen in the input.
Added a new feature in which "save <cell>.tcl" will create a
file of magic commands that will re-create the cell when sourced
as a command file.
2025-09-05 17:51:46 -04:00
R. Timothy Edwards b1095b323c Added a command option for "select move" without specifying the
X and Y values, in which case the selection is moved to the
current pointer position.  This allows a different implementation
of the "copy" command as "select move; select keep", which avoids
the problem that "copy" has of modifying the selection with layer
interactions with the existing layout.
2025-08-27 09:57:22 -04:00
R. Timothy Edwards e9f2628f41 Reworked the "def read" command such that it creates a new CellDef
for the DEF file contents, and loads the cell into the layout
window when done.  That makes it consistent with other similar
functions such as "gds read".  Existing scripts which create (by
loading) a new cell before reading the DEF should not be affected
by the change.
2025-08-26 14:48:27 -04:00
R. Timothy Edwards e04307c085 Corrected an issue in computing the extended (includes area of
label text) vs. non-extended bounding box of a cell when doing
"getcell" (and probably a number of other commands/functions, as
well).  A function was always computing the extended bounding box
and then setting both the normal and extended bounding boxes of
the cell to this value, resulting in incorrect cell selections.
2025-08-26 11:00:20 -04:00
R. Timothy Edwards d2acdac901 Corrected an error accidentally introduced a few commits ago in
(commit 4084a6a246) in which a
misplaced close-brace altered the way that "getcell" handles
some orientation cases.  Thanks to Sylvain Munaut for discovering
the error.
2025-08-21 10:44:24 -04:00
R. Timothy Edwards 8d762b4f59 Corrected an error that accidentally misses an input line from a
LEF macro if the FOREIGN statement ends without the optional
coordinates.
2025-08-20 15:01:57 -04:00
R. Timothy Edwards 0301bdec9e Made a simple change to "extresist" to set the REDUNDANT flag on
nodes which are created due to having multiple ports with different
names on the same wire (electrically connected pins).  This prevents
"extresist" from double-counting the wire.
2025-08-19 10:00:05 -04:00
R. Timothy Edwards 4084a6a246 Modified the syntax of the "getcell" command to make the
arguments unambiguous, and to allow coordinates to be given in
any units.  To do this, the (seldom if ever used) passing of a
label as a reference point was changed to require the "label"
keyword before the label name, avoiding the code having to
disambiguate arguments from label text.  This now makes it
possible to specify the coordinates in microns, lambda, etc.,
units.
2025-08-15 10:24:31 -04:00
R. Timothy Edwards 117ca41b8a Corrected an error in the substrate generation for extraction, where
non-manhattan geometry was not being transformed into the parent
orientation.  This went unnoticed for some time due to testing on
PDKs where substrate and well were not allowed to have non-orthogonal
edges.
2025-08-14 08:51:36 -04:00
R. Timothy Edwards 0fb19e568c Extended the "spacing" and "edge"/"edge4way" rules to take an
option "manhattan_dist" that causes corner checks to assume a
manhattan distance measure.  This is useful for checking
distances involving generated edges that are created by a CIF
"grow" operator.  For "spacing", "manhattan_dist" is equivalent
to "touching_illegal", as a use-case for forcing manhattan
distance measurements in corners has not been found for other
"spacing" options.
2025-08-13 11:34:29 -04:00
R. Timothy Edwards 5791ae3701 Made a small change to the "cifmaxwidth" rule check implementation
to ignore non-Manhattan (split) tiles.  This avoids creating false-
positive DRC results on split tiles which are larger in X and Y
than the max-width distance.  False negatives are possible but
correctly implementing a "maxwidth" rule for non-orthogonal areas
requires a completely different algorithm.
2025-08-11 12:10:09 -04:00
R. Timothy Edwards b4912fd550 Updated the version to go along with the merge of pull request
version 8.3.521 that, due to an argument size mismatch, causes
device parameters in netlist output to be printed as zero.
Also added a small extension to the list of extraction types
to include "device veriloga", which has the same syntax as
"device subcircuit" but generates a component type "N"
(Verilog-A component) in the netlist output.
2025-08-07 11:54:49 -04:00
Darryl L. Miles 56598ca0f4 ext2spice.c: bugfix esOutputResistor() uses name without initialization
Constification of APIs has shown up this bug.
spcdevOutNode() uses 'name' as a read-only string, used for
EFHNConcatLook() as 'errorStr' which is used to prefix error log
messages.

EFHNConcatLook() will already defer resolving hierName for the message.

So the only useful thing to indicate to the user is the procedure that
was trying to do the lookup.
2025-08-06 22:58:30 +01:00
Darryl L. Miles c6fe62f64a ext2spice.c: cleanup unused localvars -Wunused-variable -Wunused-but-set-variable 2025-08-06 22:58:30 +01:00
Darryl L. Miles ad5383c307 ext2spice.c: cleanup -Wunused-local-typedefs yesnoType 2025-08-06 22:58:30 +01:00
Darryl L. Miles ab24761d88 ext2hier.c: cleanup unused localvars -Wunused-variable -Wunused-but-set-variable 2025-08-06 22:58:30 +01:00
Darryl L. Miles 66f281c5e1 extflat/EFhier.c: workaround K&R cb_extflat_hiervisitresists_t 2025-08-06 22:58:30 +01:00
Darryl L. Miles 5bdff336e9 EFhier.c: constify local vars efHierVisitSingleResist() 2025-08-06 22:58:30 +01:00
Darryl L. Miles d4e4930de3 EFhier.c: convert to ANSI efHierVisitSingleResist() 2025-08-06 22:58:30 +01:00
Darryl L. Miles e6f04ebb46 EFhier.c: convert to ANSI efHierVisitResists() 2025-08-06 22:58:30 +01:00
Darryl L. Miles 8c61014677 extflat/EFvisit.c: workaround K&R cb_extflat_visitresists_t 2025-08-06 22:58:30 +01:00
Darryl L. Miles 7a122c8619 extflat: implement cb_extflat_hiersrarray_t for efHierSrArray() efVisitSingleResist() 2025-08-06 22:58:30 +01:00
Darryl L. Miles 420a24ef33 extflat: integrate cb_extflat_hiervisitresists_t for EFHierVisitResists()
Additionally the HierName's hierName1 and hierName2 arguments have been
made 'const' to help convey the receiver can not modify the referenced
data passed.
2025-08-06 22:58:30 +01:00
Darryl L. Miles 0141a99af5 extflat: integrate cb_extflat_visitresists_t for EFVisitResists()
Additionally the HierName's hierName1 and hierName2 arguments have been
made 'const' to help convey the receiver can not modify the referenced
data passed.
2025-08-06 22:58:30 +01:00
Darryl L. Miles 0bb29ae5f8 extflat/EFhier.c: workaround K&R ca_hiervisitdevs_proc 2025-08-06 22:58:30 +01:00
Darryl L. Miles d59a87bafa extflat/EFvisit.c: workaround K&R cb_extflat_visitdevs_t 2025-08-06 22:58:30 +01:00
Darryl L. Miles 6bbcd65c5f extflat: integrate cb_extflat_hiervisitdevs_t for EFHierVisitDevs() 2025-08-06 22:58:30 +01:00
Darryl L. Miles e1be3fe7d2 extflat: integrate cb_extflat_visitdevs_t for EFVisitDevs() 2025-08-06 22:58:30 +01:00
Darryl L. Miles 6876c007f5 extflat.h: include EFint.h (need to provide types ready for ANSI prototypes) 2025-08-06 22:58:30 +01:00
Darryl L. Miles 301a5329db extflat: nodeSpiceHierName() constify API 2025-08-06 22:58:30 +01:00
Darryl L. Miles 6df8257505 extflat: nodeSpiceName() constify API 2025-08-06 22:58:30 +01:00
Darryl L. Miles e3bd60eba6 extflat: DevParam.(const char*)param_name consumer, nodeSpiceName() 2025-08-06 22:58:30 +01:00
Darryl L. Miles d78d7eddfd extflat: nodeSpiceName() consumer 2025-08-06 22:58:30 +01:00
Darryl L. Miles aa0b033053 extflat: spcdevOutNode() constify API 2025-08-06 22:58:30 +01:00
Darryl L. Miles 22b96d5112 EFantenna.c: antennacheckVisit cb_extflat_visitdevs_t 2025-08-06 22:58:30 +01:00
Darryl L. Miles a00a5eb1b2 EFantenna.c: convert to ANSI antennacheckVisit() 2025-08-06 22:58:30 +01:00
Darryl L. Miles fddb458339 extflat: forward declaration arguments added 2025-08-06 22:58:30 +01:00
Darryl L. Miles 05876c63d2 EFtypes.h: new header file to provide types for extraction subsystem
This is needed to allow K&R to be removed and struct prototypes to
exist that have fully declared (argument) types.

It maybe necessary (in the future) to have public types and module
internal type in separate header files, but it is unclear if such a
clear split exists.

Copyright plate taken from extflat.h
2025-08-06 22:58:30 +01:00
Darryl L. Miles f031d16f50 database.h: refactor struct ArrayInfo defn into it arrayinfo.h
EFint.t has an ugly ifndef _DATABASE_H that is very include order
dependent (brittle to failure) so this moves the (struct ArrayInfo) type
definition into its own file, which has standard ifndef once file guards.
So include file order no longer matters.

Copyright plate taken from database.h.in
2025-08-06 22:58:30 +01:00
Darryl L. Miles 66d6931120 EFint.h: remove nonexistent function decl EFRootDef() 2025-08-06 22:58:30 +01:00
Darryl L. Miles a31018f721 ext2spice: use strict callback prototypes 2025-08-06 22:58:30 +01:00
Darryl L. Miles ddc0adcb41 extcheck: use strict callback prototypes 2025-08-06 22:58:30 +01:00
Darryl L. Miles 22ffeee2a4 extcheck: forward declaration arguments added 2025-08-06 22:58:30 +01:00
Darryl L. Miles d7fa508067 extcheck: use 'const' with 'rcsid' 2025-08-06 22:58:30 +01:00
Darryl L. Miles 05c242a28f K&R extcheck/*.c: bulk function implementation conversion 2025-08-06 22:58:30 +01:00
Darryl L. Miles b8170ea851 appimage: README.md update (add example on how to run inside docker)
While AppImage attempts to be a more portable way of running
applications across linux installations, sometime is maybe necessary
to run inside docker.

So examples are provided, which also provides testing regime to
validate how the AppImage can be quickly tested.
2025-08-06 10:44:33 -04:00
Darryl L. Miles a9a9efca57 appimage: AppRun minor change for more seamless docker use
Removes NOFILE warning (by default) when running under TCL8 but
still allows user to override with "export MAGIC_ULIMIT_NOFILE="
before running docker with extra argument '-e MAGIC_ULIMIT_NOFILE'.
2025-08-06 10:44:33 -04:00
Darryl L. Miles 2e4a9fd2d2 GHA: appimage: bring back tag --list -n message in release info
For example the message string here.

$ git tag --list -n 8.3.536
8.3.536         "Tagging version 8.3.536"

This could contain additional information relating to the authenticity
and signing info should that feature be used.  Which is useful to see
with the release info.

Also git_previous_tag resolution is allowed to fail to an empty string.
2025-08-06 10:44:33 -04:00
Darryl L. Miles 48dccc68c6 tile.c: fix TiFree() non-inline symbol should always be emitted
This is considered external public API for the tiles module, so
while internal magic code might inline all call sites internally
for performance the DSO (tclmagic.so) should always provide the
API symbol even if it does not use it.

This affects EL7 (gcc 4.8.5) and older:
 #define __GNUC_GNU_INLINE__ 1

This does not affect newer GCC from EL8 (gcc 8.5.0) and later has:
 #define __GNUC_STDC_INLINE__ 1

This can be seen as:

./Magic-8.3.536-x86_64-EL7.AppImage
/tmp/.mount_Magic-FDdbKA/bin/wish: symbol lookup error: /tmp/.mount_Magic-FDdbKA/lib/magic/tcl/tclmagic.so: undefined symbol: TiFree

This fixes the oversight introduced around commit f8ef715608
2025-08-06 10:44:33 -04:00
Darryl L. Miles b577619395 ext2spice: parallelDevs constify API (const devMerge*) 2025-08-06 10:42:55 -04:00
Darryl L. Miles 7ab4911514 Revert "Added a type cast in ext2spice/ext2hier.c to avoid having the"
This reverts commit a3d02d92cc.
2025-08-06 10:42:55 -04:00
R. Timothy Edwards 3472474617 Re-implemented parts of the DRC angle check to make it consider
that all layer types passed to a single "angles" statement in the
tech file are mutually non-interacting.  That is, "angles allm1 45"
will check angles on edges between metal1 and space, but not edges
between metal1 and via (which makes sense, given that a via is an
area into which to place contact cuts, and its edge is not a
physical boundary).
2025-08-06 09:22:12 -04:00
R. Timothy Edwards a3d02d92cc Added a type cast in ext2spice/ext2hier.c to avoid having the
compiler complain about a "const" variable passed to a routine
not declaring "const".
2025-08-04 16:38:41 -04:00
Darryl L. Miles 1653b982af CodeQL FileMayNotBeClosed.ql flock.c may also leak 'fd' in error paths
This is due to the transfer of ownership of the 'fd' into libz/gzip
but the error handling wasn't always being checked.
2025-08-04 16:31:07 -04:00
Darryl L. Miles 0dac3fd19c path.c: CodeQL File{MayNot,Never}BeClosed.ql file-handle resource leaks
Guided by CodeQL static code analyser.

FileMayNotBeClosed.ql
FileMayNeverBeClosed.ql

Multiple paths exist that seems to be equivalent, some of those
paths handled the error path, some of them didn't.

CodeQL will still report a concern (instead of multiple concerns)
so this has been commented to clarify when the libz handle setup
is successful, the ownership of the 'fd' changed.
2025-08-04 16:31:07 -04:00
R. Timothy Edwards 63ad80b8bc Added the keyword "COVER" to the list of keywords expected for a
PIN entry in a DEF file when read by "def read".  Previously,
"PLACED" and "FIXED" were handled, but "COVER" was missed.  Magic
treats all three the same way.
2025-08-04 16:13:36 -04:00
R. Timothy Edwards 2630ebcde1 Reverted a change made to "select area" earlier in the year, which
changed the behavior from selecting subcells if they are unexpanded
to selecting subcells regardless of the expansion state.  The
change was short-sighted and the implementation hard to use.  There
is a need, I think, for a selection method that effectively
unexpands instances, selects everything, and re-expands afterward.
But it's not clear if it is better to select all touching instances
or instances inside the box area;  maybe only interacting
instances (instances with non-space content inside the box).
Regardless, it needs more thought, and meanwhile, the original
behavior works better.
2025-08-04 14:39:10 -04:00
Darryl L. Miles 4e08d178dc appimage: allow git tags with annotation to match expected SHA for ChangeLog
The situation is due to the difference for tags with message / annotation:

$ git tag -l -n1 8.3.534
8.3.534         "Tagging version 8.3.534"

$ git show-ref -s -d refs/tags/8.3.534
4426cc859e
1ec8b6ee1a refs/tags/8.3.534^{}

$ git rev-list -n1 refs/tags/8.3.534
1ec8b6ee1a

Use of rev-lsit will always get the commit ID we expect to see for
the workflow, so we allow either of the SHA above to match at the
point of failure.
2025-08-01 10:58:04 -04:00
Darryl L. Miles 3e5502b936 readline/Makefile: clean fix to unwanted error message 2025-08-01 10:55:50 -04:00
R. Timothy Edwards 8ed7394431 Corrected some basic paint code related to drawing over top non-
Manhattan tiles.  After splitting a non-Manhattan tile crossing
a search area to paint, the routine was automatically merging
tiles to the right.  This is incorrect for tiles inside the search
area, as it can cause the search algorithm to miss unvisited tiles
whose origins are to the left of the split tile, resulting in part
of the area not getting painted.
2025-08-01 10:47:01 -04:00
Darryl L. Miles 1ec8b6ee1a appimage: GHA more debugging for fetch --tags issue 2025-07-29 14:41:49 -04:00
R. Timothy Edwards f52d90346e Updated the version to go along with the merge of pull request #428
from Darryl Miles, which overhauled the Makefile and cleaned up a
lot of long-standing minor issues.
2025-07-29 10:56:54 -04:00
Darryl L. Miles b16bcb35bf Makefile: make -j ordering fix 2025-07-29 10:50:32 -04:00
Darryl L. Miles a77c4906f8 Makefile: fix 'force' target to ensure serialization 2025-07-29 10:50:32 -04:00
Darryl L. Miles 8eb2ec9ead Makefile: allow 'modules' and 'libs' to build in parallel
Removes the shell serialisation `for .. in ..` expression

This provides another significant speed up, after */Depend was made
parallel.  x3+ speedup over -j1.
2025-07-29 10:50:32 -04:00
Darryl L. Miles a81184e205 Makefile: cleanup targets: standard tcl
No need for submake.
2025-07-29 10:50:32 -04:00
Darryl L. Miles bcd17d4f85 Makefile: removed errnous echo message for make.log 2025-07-29 10:50:32 -04:00
Darryl L. Miles f513a0ca3b Makefile: check make depend is parallel 2025-07-29 10:50:32 -04:00
Darryl L. Miles 4aee95e092 autoconf: utilize HAVE_SYS_IOCTL_COMPAT_H HAVE_TERMIO_H 2025-07-29 10:50:32 -04:00
Darryl L. Miles 92b4d6a1f7 configure: autoconf regen (2.69) AC_CHECK_HEADERS sys/ioctl_compat.h sgtty.h 2025-07-29 10:50:32 -04:00
Darryl L. Miles 730d327702 configure.in: AC_CHECK_HEADERS sys/ioctl_compat.h sgtty.h 2025-07-29 10:50:32 -04:00
Darryl L. Miles be6483bf4b GHA: main-macos.yml brew install gnu-sed 2025-07-29 10:50:32 -04:00
Darryl L. Miles 8485820526 GHA: main.yml: emit defs.mak into CI logging 2025-07-29 10:50:32 -04:00
Darryl L. Miles 54bbedfdbb INSTALL_MacOS.md: Update to install gnu-sed
The platform /usr/bin/sed does this:

/usr/bin/sed -e "/#/D" -e "/ \//s/ \/.*\.h//" -e "/  \\\/D" -i Depend$PPID.tmp
sed: -I or -i may not be used with stdin

But a filename was specified, so the error should be file does not exist
2025-07-29 10:50:32 -04:00
Darryl L. Miles b1e2913435 Makefile: sed => ${SED}
This will find GNU make in preference if available on the platform.
2025-07-29 10:50:32 -04:00
Darryl L. Miles f179d1240e Makefile: rm => ${RM} 2025-07-29 10:50:32 -04:00
Darryl L. Miles 6f304318ec Makefile: ln => ${LN} 2025-07-29 10:50:32 -04:00
Darryl L. Miles 6b0bc5bbdc SunOS: FOPEN rename to magicFOPEN due to sys/file.h definition
Example build issue using SunOS Solaris solaris 5.11 11.4.42.111.0 i86pc i386
with gcc version 5.5.0 (GCC).

It turns out the definition is not used by the magic codebase.  So only the
macro name is changed by this commit.

This platform also has a definition for FREAD but the MacOS patch can be used
to rename that.

 In file included from DBio.c:51:0:
 ../utils/magic.h:141:0: warning: "FOPEN" redefined
      #define FOPEN    gzopen
  ^
 In file included from DBio.c:30:0:
 /usr/include/sys/file.h:74:0: note: this is the location of the previous definition
  #define FOPEN  0xffffffff
  ^

 In file included from DBio.c:51:0:
 ../utils/magic.h:144:0: warning: "FREAD" redefined
      #define FREAD(a,b,c,d)    gzread(d,a,b*c)
  ^
 In file included from DBio.c:30:0:
 /usr/include/sys/file.h:75:0: note: this is the location of the previous definition
  #define FREAD  0x01 /* <sys/aiocb.h> LIO_READ must be identical */
  ^
2025-07-29 10:50:32 -04:00
Darryl L. Miles 778201fbc2 DBio.c: HAVE_STRUCT_DIRENT_D_TYPE direct->d_type 2025-07-29 10:50:32 -04:00
Darryl L. Miles c3054f265b configure: autoconf regen (2.69) LIBS 2025-07-29 10:50:32 -04:00
Darryl L. Miles a8f5291bd7 defs.mak.in: restore autoconf LIBS functionality
This is a standard autoconf variable, it was probably disabled due to
how the graphics/Makefile works and the more complex detection taking
place there.

Needed to use it to add -lpthread to some platforms (freebsd/openbsd)
to make it build out the box.
2025-07-29 10:50:32 -04:00
Darryl L. Miles aaa477e44a configure: autoconf regen (2.69) AC_STRUCT_DIRENT_D_TYPE 2025-07-29 10:50:32 -04:00
Darryl L. Miles f45aeb6cee configure.in: AC_STRUCT_DIRENT_D_TYPE 2025-07-29 10:50:32 -04:00
Darryl L. Miles 9f0f5f5b4e configure: autoconf regen (2.69) AC_PATH_PROG(PERL,) AC_SUBST(PERL) 2025-07-29 10:50:32 -04:00
Darryl L. Miles ec7d0fc79a configure.in: AC_PROG_PERL 2025-07-29 10:50:32 -04:00
Darryl L. Miles d2449dc971 configure: autoconf regen (2.69) AC_PROG_SED 2025-07-29 10:50:32 -04:00
Darryl L. Miles e51189911b configure.in: AC_PROG_SED (looking for GNU sed) 2025-07-29 10:50:32 -04:00
Darryl L. Miles 3ca0b616c0 Makefile: toplevel 'make techs' target to process scmos during build
Previously it would only build the 'scmos' subdir when the
'make install' target is running, which is done sudo.  This
would result in a number of files in scmos/cif_template/objs
to be owned by 'root'.

Renamed TECH to TECHS which is inline with the other caregories
MODULES and LIBS.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 412d0570e2 configure: autoconf regen (2.69) ALLOCA NDEBUG DEBUG
also --enable-assertions --enable-debug
also termio.h termios.h sys/ioctl.h
2025-07-29 10:50:32 -04:00
Darryl L. Miles 9f1398dfcb utils/magsgtty.h: detect termio/ioctl headers
Linux is not based on BSD and this file appears to exist to manage
historic BSD conventions concerning termios.
2025-07-29 10:50:32 -04:00
Darryl L. Miles c5ebd7d3c0 makedbh.in _DATABASE_H => _MAGIC__DATABASE__DATABASE_H 2025-07-29 10:50:32 -04:00
Darryl L. Miles 2db18509c5 header file #endif guard middle program once style consistency 2025-07-29 10:50:32 -04:00
Darryl L. Miles d55a2b74ac header file #ifndef guard namespace consistency (global change)
This add an effective namespace prefix to the guard ifndef
2025-07-29 10:50:32 -04:00
Darryl L. Miles 5e17855f31 header file #ifndef guard presence consistency 2025-07-29 10:50:32 -04:00
Darryl L. Miles 3294524111 header file #endif guard trailer comment consistency
oa/magicInit.h
utils/malloc.h
2025-07-29 10:50:32 -04:00
Darryl L. Miles de1b76cb11 niceabort.c: include <time.h> remove preC89 declarations 2025-07-29 10:50:32 -04:00
Darryl L. Miles b6e70f9632 utils/magic_alloca.h: with autoconf AC_FUNC_ALLOCA
Unclear what the correct Copyright header should be on this one,
given most of the lines in the file are from the autoconf
documentation.
2025-07-29 10:50:32 -04:00
Darryl L. Miles f88c7a86cb utils/magic_zlib.h: limit #include <zlib.h> to files that need it
Remove limited use HAVE_ZLIB wrapper API into separate header as
utils.h is used in many places and most source files don't need
to drag in the header file from this external dependency.

Copyright date(s) taken from original source file / git blame.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 4a1da7fe7c utils/magic_assert.h: separate assert.h and ASSERT
This is a low level thing that other lowlevel API (platform shims for
strlen_s() and ctime_r() want to make use of, without any application
global pollution).

Copyright date(s) taken from git blame information for moved lines.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 4d2def46f4 configure.in: whitespace cleanup align --help columns 2025-07-29 10:50:32 -04:00
Darryl L. Miles 49caa3267b configure: --enable-debug make this a user accessible config
This should help with automated CI testing as well, where a suite
can be run and debug enabled and checked, just via a specific
CI setup.
2025-07-29 10:50:32 -04:00
Darryl L. Miles dd49ca21d2 configure: --enable-assertions make this a user accessible config
This should help with automated CI testing as well, where a suite
can be run and assertions enabled and checked, just via a specific
CI setup.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 2a78de8cb9 magic/Makefile: MAGIC_BUILDDATE and inherit values when possible
Went the whole way and make it inherit from toplevel Makefile.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 4e7396162d scripts/configure: autoconf regen (2.69) MAKE_xxxxx generation 2025-07-29 10:50:32 -04:00
Darryl L. Miles d13fa6872e MAKE_xxxxx: to skip building OBJs part of configure 2025-07-29 10:50:32 -04:00
Darryl L. Miles bd541d3e6f rules.mak: fix module Depend and build rules
The ../database/database.h dependency is already described (only when
necessary) inside the Depend file for the specific complication unit.
Not all objects are affected by database.h changes, so it doesn't need
to be forced as a dependency for all OBJS.

Depend itself was never rebuilt when a source file changed.  This now
happens, however technically the superior MAKE process needs to restart
so it includes the new updated copy of Depend file we just updated.
However in practice when developing, modifying #include directives does
not happen often and doing 'make; make' will fix the issue performing
an incremental build both times.  So a minor caveat.

Previously when a single source file was changed the entire module was
recompiled, but we have a Depends file to manage the incremental build
problem and we are not really using it (if we always recompile the entire
module due to any one file change, there would be no need for Depends).

Now when developing, a single *.c file change results in the Depends
being rebuilt, then the single file compiled, then the module relinked.
This is exactly the kind of incremental build speedup having a Depends
file is designed to achieve.

Additionally the use of a direct pipeline to create the file does not
manage error scenarios.  MAKE itself is driven by file existance and
their timestamps for targets, so even if 'make depend' failed, it
would still create an output file that MAKE can not distunguish
between a well formed (possibly empty) Depend file and an incorrectly
created partial.  So building in a *.tmp file first and only if all the
commands are successful then rename to target filename.  This has the
effect of making 'make depend' able to fail now.
2025-07-29 10:50:32 -04:00
Darryl L. Miles d1ff3671cd rules.mak: include ${DEPEND_FILE} only if the file exists
This is a modified fix to the "make clean; make clean" issue.
'clean' is not the only target affected.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 3aebbbd038 Makefile: various consistency matters
Using defined variables ${RM} for common tools
error handling
ensuring default target (is not install)
2025-07-29 10:50:32 -04:00
Darryl L. Miles 8b7e0aaec6 Makefile: whitespace only change 2025-07-29 10:50:32 -04:00
Darryl L. Miles 2947e7ea3d Makefile: database.h removal by toplevel Makefile 2025-07-29 10:50:32 -04:00
Darryl L. Miles f0ade2fc55 Makefile: lookup VERSION local variable once
This was more a clarity matter as relocatable autoconf makes all
references to the path look longer and more unweildly making it
a variable makes shorter and easier to read work through.

Especially when related to risks with RM arguments using the output
of a shell call in the argument list.  What could go wrong ?
2025-07-29 10:50:31 -04:00
Darryl L. Miles 394a01e0d4 Makefile: make depend (will now parallelize via -j)
This target consumes ~50% of the total build time due to the
serialization of the shell for loop method.

Also the removal of the */Depend is deferred to the subdir
Makefile's responsibility.
2025-07-29 10:50:31 -04:00
Darryl L. Miles a18acc4772 Makefile: exit 1 && libs: Makefile deps 2025-07-29 10:50:31 -04:00
Darryl L. Miles acefe4811f readline/Makefile: move up before with no scheme
rename symlink(s) use phony targets, delegate the symlink creation
management command sequence to a single point in the project inside
the readline/Makefile
2025-07-29 10:50:31 -04:00
Darryl L. Miles 80c043db79 configure: wrapper CFLAGS inherit if already set
It is usual for the user to have control of CFLAGS like:
  CFLAGS="-O2" ./configure
2025-07-29 10:50:31 -04:00
Darryl L. Miles ebf2db91b1 defs.mak.in: DFLAGS_MAGICVERSION
This seems needed in multiple places so made a variable on its own.
2025-07-29 10:50:31 -04:00
Darryl L. Miles 4b094e4632 defs.mak.in: OBJS split into C_OBJS CXX_OBJS
This split has the effect (with modified .o.c Makefile rule of
correctly using the $CC for .c files and not try to build .cpp
with C compiler, which fails in oa/** for example.
2025-07-29 10:50:31 -04:00
Darryl L. Miles 73a6ac1650 defs.mak.in: Remove -I. from default compiler options
This can only cause trouble being a global default setting.

All project include files are qualified with a path prefix to help
disambiguate duplication of header file names to effectively provide
a namespace.

When removing it nothing seemed break.  Maybe more configurations
should be tested.  They were all ok.
2025-07-29 10:50:31 -04:00
Darryl L. Miles 271aef82bd defs.mak.in: replace backtick with $(shell ...)
Previously the variable resolution was passed to compiler command line
when ideally this only needs to be resolved once per build and the
entrie build uses the same value.

Compiler command line is computed at least once per file (plus Depends
pass), so this is forking at least 5 extra times during the build.

This improves things somewhat so resolution is performed less.

This may have the effect of making the build appear faster when
ccache is working.  As the command line options maybe seen as a
constant.
2025-07-29 10:50:31 -04:00
Darryl L. Miles 0dccf5826d defs.mak.in: ARFLAGS = cr (removed 'v') 2025-07-29 10:50:31 -04:00
Darryl L. Miles f15e7675cd defs.mak.in: Add RMDIR MKDIR MV LN SED common tools 2025-07-29 10:50:31 -04:00
Darryl L. Miles 62149adc16 DBTechname.c: fix !MAGIC_WRAPPER incorrect use of TxPrintf() warning 2025-07-28 21:28:24 -04:00
Darryl L. Miles df1a27fc01 ext2sim.c: fix syntax error, missing argument name
Caused by recent commit a7dd64b24
2025-07-28 21:28:24 -04:00
Darryl L. Miles dd5fa02556 fix: add missing #include <unistd.h>
Fallout from removing it from tiles.h
2025-07-28 21:28:24 -04:00
Darryl L. Miles b042383664 appimage: GHA action/checkout fetch-tags=true workaround
Still battling again GHA checkout with tags.
2025-07-28 21:28:24 -04:00
R. Timothy Edwards 1cc4d83425 Corrected an issue with "bloat-all ... [dist]" in which an attempt
not to re-process processed tiles made an incorrect assumption,
causing tiles not to be re-processed when the clip area changed,
such that areas would be missed.  It is not clear that in its
corrected version, "bloat-all ... [dist]" is any more efficient
than the original implementation of an incremental series of bloat
+ AND.  At least the syntax in the tech file is much simplified.
2025-07-28 11:53:44 -04:00
Darryl L. Miles 68e1c76f88 appimage: GHA fetch-tags=true
The ChangeLog history summary is showing more information than wanted.
2025-07-27 21:06:19 -04:00
Darryl L. Miles 4b9d3f3003 appimage: remove libfuse2 desktop-file-utils
as not required with current AppImage builder.
2025-07-27 21:06:19 -04:00
Darryl L. Miles 5b81fbe7fe appimage: whitespace only cleanup 2025-07-27 21:06:19 -04:00
Darryl L. Miles e701b6d594 appimage: use git show for hash of current checkout state
This switches the 'remotes/origin/HEAD' and uses the current HEAD of the
current checked out git repo.

Revised the sed rule that is transforming (to be more specific on the
 matching regex /-\d+-g/ than just the first /-/):

8.3.530-7-gb64321d4 => 8.3.530+7-gb64321d4 (replace first '-' with '+'
 to indicate it is tag plus this many commits)
8.3.530 => 8.3.530 (no change)
2025-07-27 21:06:19 -04:00
Darryl L. Miles 62a99f6167 appimage: The AppImageTool changes their releases distribution point
This switches to the 'continuous' tag release, that will auto update.

This broke the very old AppImage7 tool since that release not return
HTTP/404.  But I updated all to use their current recommendation.
2025-07-27 21:06:19 -04:00
R. Timothy Edwards 9fe7bf4ab7 Fixed an issue with a non-boolean variable in DBtiles.c being
cast as "bool", causing issues with the proper/strict use of
the "bool" type.  Changed the version back so that it will
update the github mirror tonight, since the current version
appears to be working.
2025-07-27 21:02:40 -04:00
R. Timothy Edwards 43bc006338 Reducing VERSION back to the previous value so that a mirror copy of the
bad code won't be made to github in case the issue with stdbool isn't
resolved by tonight.
2025-07-27 16:52:57 -04:00
R. Timothy Edwards 669604ace3 Updated the version number to go along with merges of pull requests
from Darryl Miles and Torleif Skoar.
2025-07-27 12:54:25 -04:00
Torleif Skår f76826eff8 cif_templates: Fix Makefile race condition with objs directory creation
Fixes racy-ness seen intermittently when building,
where the objs folder doesn't exist when
targets try to write to it.
2025-07-27 12:53:02 -04:00
Darryl L. Miles 189c9f2452 ext2spice: forward declaration arguments or removal
Remove unnecessary forward declaration:
 extHierSDAttr() as ext2spice.h has prototype
2025-07-27 12:52:12 -04:00
Darryl L. Miles 659ec36d2d ext2spice: Makefile use EXT2SPICE_MAIN for deprecated standalone 2025-07-27 12:52:12 -04:00
Darryl L. Miles df6bc6bc51 ext2spice: use 'const' with 'rcsid' 2025-07-27 12:52:12 -04:00
Darryl L. Miles 828cec7bca K&R ext2spice/*.c: bulk function implementation conversion
int spcnAP() follows K&R param ordering
int spcnAPHier() follows K&R param ordering

TODO mergeAttr() sharing references (does this setup a future potential
use-after-free concern?)
2025-07-27 12:52:12 -04:00
Darryl L. Miles f77c4cbaa1 ext2spice.h: move function prototype after arg type decls 2025-07-27 12:52:12 -04:00
Darryl L. Miles 2d889b3e9d ext2spice.h: one line per declaration 2025-07-27 12:52:12 -04:00
Darryl L. Miles 1cab3852f1 K&R ext2spice.h: conversion to ANSI 2025-07-27 12:52:12 -04:00
Darryl L. Miles e258b21251 K&R ext2spice: remove non-existent function prototypes
extern int _ext2spice_start();
 extern EFNode *spcdevHierSubstrate();
2025-07-27 12:52:12 -04:00
Darryl L. Miles d5341659fb ext2sim: cleanup unused localvars -Wunused-variable -Wunused-but-set-variable 2025-07-27 12:49:54 -04:00
Darryl L. Miles 7028fbe546 ext2sim: whitespace only changes 2025-07-27 12:49:54 -04:00
Darryl L. Miles 0badf814c5 extraction: constify struct devMerge.next, devMergeList
Feel free to undo variables as necessary in the future as requirements change.
2025-07-27 12:49:54 -04:00
Darryl L. Miles 49115d7d06 ext2sim: gratuitous constification of localvars, struct members, prototypes
Feel free to undo variables as necessary in the future as requirements change.
2025-07-27 12:49:54 -04:00
Darryl L. Miles 7c3df3ce22 ext2sim.c: (ClientData) cast use PTR2CD() 2025-07-27 12:49:54 -04:00
Darryl L. Miles 6a0dc54af8 ext2sim.c: constify whatever the compiler let me 2025-07-27 12:49:54 -04:00
Darryl L. Miles 82a57f8714 ext2sim.c: constify string globals 2025-07-27 12:49:54 -04:00
Darryl L. Miles dc2de91668 finds.c: constify file 2025-07-27 12:49:54 -04:00
Darryl L. Miles 260e08f160 sim2simp.c: constify file 2025-07-27 12:49:54 -04:00
Darryl L. Miles 20d72e9eb2 ext2sim: constify APIs and local vars 2025-07-27 12:49:54 -04:00
Darryl L. Miles a7dd64b242 ext2sim: use strict callback prototypes 2025-07-27 12:49:54 -04:00
Darryl L. Miles 1f9ce81154 ext2sim: Makefile target for: finds sim2simp
Not a serious attempt to make these work but they appear to compile
so this helps CI to cover as much code as possible.

ext2sim_main standalone does not link (probably due to unclean cross
module dependencies that now exist due to libutil.a being a heap where
anything with no modular home ends up)
2025-07-27 12:49:54 -04:00
Darryl L. Miles 975411f40b ext2sim.c: forward declaration prototypes 2025-07-27 12:49:54 -04:00
Darryl L. Miles 4b855fef13 ext2sim: use 'const' with 'rcsid' 2025-07-27 12:49:54 -04:00
Darryl L. Miles 2f2fd85af0 ext2sim: fixup prototypes for TxError() MainExit()
Correct return and argument types.
Use of <stdarg.h> with modern compiler.
2025-07-27 12:49:54 -04:00
Darryl L. Miles bb6e55efb1 ext2sim: Ensure main() have return type and arguments 2025-07-27 12:49:54 -04:00
Darryl L. Miles 22e8ab847c K&R ext2sim/*.c: bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2025-07-27 12:49:54 -04:00
Darryl L. Miles cef9e0bede ext2sim: Remove non-existent function fwd-decl
int _ext2sim_start();
2025-07-27 12:49:54 -04:00
Darryl L. Miles 27a91ee5a3 net2ir: use 'const' with 'rcsid' 2025-07-27 12:47:15 -04:00
Darryl L. Miles b6ec131355 K&R net2ir/** 2025-07-27 12:47:15 -04:00
Darryl L. Miles 105f8a728d K&R magic/** 2025-07-27 12:46:38 -04:00
Darryl L. Miles 0b29b1cc12 fix GrTextSizePtr API interface return type consistency
commit 86b5d591d from 20241004 by me, modified return type of
GrTextSize API in the graphics from 'void' to 'int' to convey
and error scenario to indicate when 'r' was not filled in for
the caller, but this is a multi graphics driver API interface
so requires all downstream graphics engines to also support
the return type change.

This API can error and indicates when 'Rect *r' was
successfully updated.
2025-07-27 12:45:51 -04:00
Darryl L. Miles 2173d03b14 netlist.c: whitespace only cleanup 2025-07-27 12:44:42 -04:00
Darryl L. Miles d7935930ad F42: fix for etext symbol glibc 2.29+
The man page end(3) changed as well over time to support the new definition.

This was revised from 2.41+ to 2.29+ as it seems top relate to a mix of
Kernel / Glibc / Compiler and the new defintion probably works on any
older system.
2025-07-27 12:44:42 -04:00
Darryl L. Miles 3fd0798312 CalmaRdpt.c: -Wall -O3 savedef used uninitialized
GCC11 -Wall -Wpedantic -O3
2025-07-27 12:43:59 -04:00
Darryl L. Miles 5d8cfdc760 CalmaRdpt.c: -Wall -O3 snprintf("polygon%5d")
Finds this a problem still.

GCC11 -Wall -Wpedantic -O3
2025-07-27 12:43:59 -04:00
Darryl L. Miles 046401cbd8 Use HAVE_SYS_TIME_H and TIME_WITH_SYS_TIME from autoconf where possible 2025-07-27 12:43:04 -04:00
Darryl L. Miles 957904a389 configure: autoconf regen (2.69) AC_HEADER_TIME 2025-07-27 12:43:04 -04:00
Darryl L. Miles c695980145 configure.in: Add AC_HEADER_TIME 2025-07-27 12:43:04 -04:00
Darryl L. Miles df0623a435 include <unistd.h> where necessary in files using API calls
When global <sys/mman.h> was removed from tile.h it also removed
<unistd.h> nearby.  This exposes the lack of <unistd.h> being
included where needed using APIs like close()/read()/unlink()/isatty()
the WASM build seems to show this as the header file set is structured
differently.
2025-07-27 12:42:05 -04:00
Darryl L. Miles 4023ed9da0 tiles: Remove TiJoinFree() now that TiJoin[XY]1() exists and all use-cases utilize 2025-07-27 12:42:05 -04:00
Darryl L. Miles fd50bc1f4d TiJoin[XY]1 API introduction at all call sites 2025-07-27 12:42:05 -04:00
Darryl L. Miles 489f4fe057 tile.h: move #include <sys/mman.h> into tile.c
tile.h is included by a large part of the project, but the definitions
in sys/mman.h are only needed by the implementation code inside tile.c
so this reduces project wide include dependencies.
2025-07-27 12:42:05 -04:00
Darryl L. Miles f8ef715608 tiles: Make TiFree() easier to inline for compiler
Removal of unnecessary function call indirection into TileStoreFree()
since TiFree() is has multiple implementation already and we can
customize TiFree() directly as required.

Move the function definitions into the tile.h to they are visible to
compiler during code generation to consider inline potential.

This has made global 'Tile *TileStoreFreeList' more visible.
2025-07-27 12:42:05 -04:00
Darryl L. Miles db8e790aea TiJoin[XY]1() API introduction 2025-07-27 12:42:05 -04:00
Darryl L. Miles a6fd0ed320 DBtiles.c: DBFreePaintPlane() remove the TiFree() deferred assumption
The comment indicates the expectation that TiFree() is deferred-by-one,
which would be true if freeMalloc() was used but since the custom mmap()
allocator technically this is not true.

The TiFree() allocator is single-threaded and separate from libc so the
assumption is still kind of true but for different reasons
(single-threaded).

But since it doesn't really cost anything (other than a few lines of
code a human needs to read) the compiler would be expected to perform a
load (which it was going to do anyway) into a caller-saves register over
the function call.
Most of the other function state is invalidated anyway due to the heavy
linked-list navigation and low number of local variables, I would not
think there is much register allocation pressure.

TODO this code can be tested by confirming zero allocations are active
and by invalidating (poison) all fields inside TiFree().
2025-07-27 12:42:05 -04:00
Darryl L. Miles 15e5b36f52 tile.h: TiFreeIf/TiFree1() API 2025-07-27 12:42:05 -04:00
Darryl L. Miles 1eb2231bbf configure: autoconf regen (2.69) AC_C_INLINE AC_C_RESTRICT 2025-07-27 12:42:05 -04:00
Darryl L. Miles 52d3feac73 configure.in: AC_C_INLINE AC_C_RESTRICT 2025-07-27 12:42:05 -04:00
R. Timothy Edwards d4f487266f Updating the version number to go along with the merge of a bunch
of pull requests (about half of those pending) from Darryl Miles.
2025-07-26 20:54:46 -04:00
Darryl L. Miles c534eb318d magic/main.c: add missing ifdef SCHEME_INTERPRETER 2025-07-26 17:48:31 -04:00
Darryl L. Miles cc57510019 textio/txCommands.c: add missing ifdef SCHEME_INTERPRETER 2025-07-26 17:48:31 -04:00
Darryl L. Miles bcc9852cba configuration: #ifdef LEF_MODULE
Enclosed symbols only seem available with when this ifdef.
2025-07-26 17:48:31 -04:00
Darryl L. Miles bfefc7196e configuration: #ifdef CIF_MODULE
Enclosed symbols only seem available with when this ifdef.
2025-07-26 17:48:31 -04:00
Darryl L. Miles 22c074537d configuration: #ifdef ROUTE_MODULE
Enclosed symbols only seem available with when this ifdef.
2025-07-26 17:48:31 -04:00
Darryl L. Miles 534a56376a DBcellsrch.c: #ifdef ROUTE_MODULE around hook to update MZAttachHintPlanes()
When building without this module MZInit() does not get called and
MZAttachHintPlanes() does not guard against that situation.

To allow unused code to be pruned from final binary, better to remove
the cross module hook breaking the dependency.
2025-07-26 17:48:31 -04:00
Darryl L. Miles 142b7e5a78 tclmagic.c: memleak Tcl ref counting over Eval memory leak
API docs indicate the original usage seems ok.
Calling Tcl_GetIndexFromObj() is allowed with a refcount == 0.
But in actual usage it leaks the Tcl_NewStringObj() memory across the
Tcl_EvalObjv() call like the object accounting system doesn't work on
that anymore (because the use of Tcl_EvalObjv() disrupted things).

Looking at the code nearby it increments refs (for all recently created
objs) and decrements around Tcl_EvalEx() for the actual data the 'eval'
needs pinned and is working on.

If we just repeat this same pattern but with 'objv0' the memory leak is
gone.  The decrement must wake it up / make it remember what to do.
So this required covering all the exit paths to decrement as well.
2025-07-26 17:46:59 -04:00
Darryl L. Miles 7029971c33 configure: autoconf regen (2.69) AC_HEADER_STDBOOL 2025-07-26 17:44:45 -04:00
Darryl L. Miles bfbdf45b88 C23: use AC_HEADER_STDBOOL #include <stdbool.h> 2025-07-26 17:44:45 -04:00
Darryl L. Miles 35d455fd72 C23: CmdSubrs.c fixup deprecated isascii() 2025-07-26 17:44:45 -04:00
Darryl L. Miles 9e181f0d2e rtrTravers.c: missing const
This is to remove the constness warning.
2025-07-26 17:38:19 -04:00
Darryl L. Miles a53f71d5c6 GHA: appimage10: Add support for EL10 2025-07-26 17:29:19 -04:00
Darryl L. Miles b7dd2f0e9c GHA: appimage9: Add support for EL9 2025-07-26 17:29:19 -04:00
Darryl L. Miles c5e0165e5e GHA: appimage8: Add support for EL8 2025-07-26 17:29:19 -04:00
Darryl L. Miles b9296074b2 GHA: appimage7: fixup relocated files 2025-07-26 17:29:19 -04:00
Darryl L. Miles 96b89a53b7 GHA: appimage7: appimage/* => appimage/7/* (relocate EL7) 2025-07-26 17:29:19 -04:00
Darryl L. Miles 6c952f98eb GHA: appimage7: Maintenance update
Upgrade Tcl to 8.6.16
Use versioning to include tag, indication of timestamp and git hash.
Rename to include '7' in the labeling (as it is EL7 based)
Improve log output to keep information about versions used.
Update README.md a little.
2025-07-26 17:29:19 -04:00
Darryl L. Miles ea5f1ed3f1 tiles/tile.h: Remove unused inlines breaking older GCC
This was breaking on older GCCs (such as GCC 4.8.x used for
AppImage with CentOS7).
2025-07-26 17:29:19 -04:00
Darryl L. Miles 66e72c748a CIFParsePath() prototype change to simply return of created data
Previously this was returning two values, a 'bool' and a data
structure that is created.  Now it simply returns the data
structure which makes it easier to reason about who takes
ownership of the memory and when, also that no address-of can
be supplied that has any side-effect that interacts with how
the method works / the returned result.

-extern bool CIFParsePath(CIFPath **pathheadpp, int iscale);
+extern CIFPath *CIFParsePath(int iscale);

Previous related comments:

Easier to reason about, there can be no interaction from *pathheadpp
and the various functions called, which maybe the first concern to
the next reader as visibility of new data is limited to that of a
local variable of the function.
2025-06-26 16:09:43 +01:00
R. Timothy Edwards eb81da6c56 Updated the version to go along with pull request #406 from Darryl
Miles (updates for github actions).
2025-06-19 09:55:57 -04:00
Darryl L. Miles ab73c716a4 GHA: main.yml (move to ubuntu-22.04) 2025-06-17 16:35:34 +01:00
Darryl L. Miles f947543fe3 GHA: canary-matrix.yml: remove sunseted ubuntu-20.04 runner 2025-06-17 16:35:27 +01:00
Darryl L. Miles 9551167e10 GHA: canary-matrix.yml: use set -o pipefail 2025-06-17 16:35:24 +01:00
Darryl L. Miles 5e32174dbb GHA: appimage.yml (move to ubuntu-latest) 2025-06-17 16:17:29 +01:00
396 changed files with 15427 additions and 7037 deletions

View File

@ -1,28 +0,0 @@
on:
push:
tags:
- "*"
name: CI-appimage
jobs:
build_appimage:
name: Build AppImage
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get the version
id: get_version
run: |
export VERSION_NUM=$(ruby -e "print '$GITHUB_REF'.split('/')[2]")
echo ::set-output name=value::${VERSION_NUM}
- name: Build project
run: |
cd appimage
make
cp Magic-x86_64.AppImage /tmp/Magic-${{ steps.get_version.outputs.value }}-x86_64.AppImage
- name: Upload Release Asset
uses: softprops/action-gh-release@v1
with:
files: /tmp/Magic-${{ steps.get_version.outputs.value }}-x86_64.AppImage

170
.github/workflows/appimage10.yml vendored Normal file
View File

@ -0,0 +1,170 @@
on:
push:
tags:
- "*"
workflow_dispatch:
name: CI-appimage10
env:
APPIMAGETOOL_DOWNLOAD_URL: https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
jobs:
build_appimage10:
name: Build AppImage EL10
runs-on: ubuntu-latest
permissions:
contents: write # action-gh-release
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 149 # enough to cover between tags
#fetch-tags: true # this should work see actions/checkout~issue#1471
- name: Get the version
id: get_version
run: |
git show -s
version=$(cat VERSION) # 8.9.999
version_tstamp=$(git show -s "--format=%cs" | tr -d '-') # YYYYMMDD
version_hash=$(git show -s "--format=%h") # abcdefg
version_num=$(ruby -e "print '$GITHUB_REF'.split('/')[2]") # legacy version method: master
echo "version=${version}"
echo "version_tstamp=${version_tstamp}"
echo "version_hash=${version_hash}"
echo "version_num=${version_num}"
VERSION_NUM="${version}~${version_tstamp}~${version_hash}"
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
echo "MAGIC_APPIMAGE_OUTPUT_FILENAME=Magic-${VERSION_NUM}-x86_64-EL10.AppImage" >> $GITHUB_ENV
# Is this GHA being run due to a push-on-tag ? if so we make a GitHub release, otherwise we just publish artifact
github_tag=$(echo -n "$GITHUB_REF" | sed -e 's#refs/tags/##') # 8.9.999
echo "github_tag=$github_tag"
if echo -n "$GITHUB_REF" | egrep -q "^refs/tags/" # check prefix
then
if [ -n "$github_tag" ]
then
echo "MY_GITHUB_TAG=${github_tag}" >> $GITHUB_ENV
fi
fi
- name: Build project
run: |
cd appimage/10
make
ln -v Magic-x86_64.AppImage "${MAGIC_APPIMAGE_OUTPUT_FILENAME}"
ls -l *.AppImage
sha256sum *.AppImage
pwd
- name: Create RELEASE-NOTES.txt
run: |
cd appimage/10
# Find the last tag (that does not match the current GITHUB_REF)
echo GITHUB_REF=$GITHUB_REF
echo GITHUB_SHA=$GITHUB_SHA
# GitHub CI is a shallow checkout by default (just the files needed to build)
# but we also want history back to next tag, see fetch-tags/fetch-depth actions/checkout~issue#1471
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# remove only if ref of tag (to avoid conflict during fetch)
git update-ref -d $GITHUB_REF
echo git_update_ref_exitstatus=$?
fi
set +e
git fetch --tags --prune --no-recurse-submodules --depth=149 origin +$GITHUB_SHA # fetch-tags: true # is broken
echo git_fetch_exitstatus=$?
git_show_ref=$(git show-ref --hash $GITHUB_REF) # get tagcommit hash
git_show_ref_exitstatus=$?
echo git_show_ref_exitstatus=$git_show_ref_exitstatus
echo git_show_ref=$git_show_ref
git_rev_list=$(git rev-list -n1 $GITHUB_REF) # get commit hash
git_rev_list_exitstatus=$?
echo git_rev_list_exitstatus=$git_rev_list_exitstatus
echo git_rev_list=$git_rev_list
set -e
test "$git_show_ref" = "$GITHUB_SHA" || test "$git_rev_list" = "$GITHUB_SHA" # check we got the ref back (or fail CI)
git_describe=$(git describe --tags $GITHUB_SHA | sed -e 's#\-\([0-9]\+\-g\)#\+\1#') # /-\d+-g/
echo git_describe=$git_describe
# RELEASE-NOTES-EL10.txt
echo "### ${MAGIC_APPIMAGE_OUTPUT_FILENAME} commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-EL10.txt
echo "" >> RELEASE-NOTES-EL10.txt
echo "This release is based on EL10 (AlmaLinux10), the AppImage format is designed to run on a wide range of Linux distributions." >> RELEASE-NOTES-EL10.txt
echo "" >> RELEASE-NOTES-EL10.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/10/README.md" >> RELEASE-NOTES-EL10.txt
echo "" >> RELEASE-NOTES-EL10.txt
length_info=$(stat "--format=%s bytes" "${MAGIC_APPIMAGE_OUTPUT_FILENAME}")
sha256_info=$(sha256sum "${MAGIC_APPIMAGE_OUTPUT_FILENAME}" | cut -d ' ' -f1)
echo "| | |" >> RELEASE-NOTES-EL10.txt
echo "| :-------- | :------ |" >> RELEASE-NOTES-EL10.txt
echo "| File Name | ${MAGIC_APPIMAGE_OUTPUT_FILENAME} |" | sed -e 's#~#\\~#g' >> RELEASE-NOTES-EL10.txt
echo "| File Length | ${length_info} |" >> RELEASE-NOTES-EL10.txt
echo "| File SHA256 | ${sha256_info} |" >> RELEASE-NOTES-EL10.txt
echo "" >> RELEASE-NOTES-EL10.txt
# RELEASE-NOTES-CL.txt
set +e # allow this to fail to empty string
git_previous_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1))
echo git_previous_tag=$git_previous_tag
set -e
if [ -n "${git_previous_tag}" ]
then
echo "### Change Log (since previous tag):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline --no-color --no-decorate "refs/tags/${git_previous_tag}..${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
else
echo "### Change Log (last commit only):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline -n1 --no-color --no-decorate "${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
fi
echo "" >> RELEASE-NOTES-CL.txt
#echo "### Build Info:" > RELEASE-NOTES-BI.txt
# FIXME extract package version info and DSO symvers into RELEASE-NOTES.txt
#echo "" >> RELEASE-NOTES-BI.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-EL10.txt
cat RELEASE-NOTES-EL10.txt
# RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/7/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/8/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/9/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/10/README.md" >> RELEASE-NOTES-DOCS.txt
# RELEASE-NOTES-GH.txt (this is shared for all AppImage for one tag)
echo "### commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-GH.txt
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# show tag annotation with tags like before
git tag --cleanup=strip "--format=%(contents)" -n "${GITHUB_REF:10}" | sed -e 's#\([~|]\)#\\\1#g' >> RELEASE-NOTES-GH.txt
fi
echo "" >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-DOCS.txt >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-GH.txt
# Show in action/artifact output
echo "## RELEASE NOTES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat RELEASE-NOTES-EL10.txt >> $GITHUB_STEP_SUMMARY
- name: Upload Release Asset
if: ${{ env.MY_GITHUB_TAG != '' }} # if: ${{ github.ref_type == 'tag' }}
uses: softprops/action-gh-release@v2
with:
body_path: ${{ github.workspace }}/appimage/10/RELEASE-NOTES-GH.txt
files: |
${{ github.workspace }}/appimage/10/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
${{ github.workspace }}/appimage/10/RELEASE-NOTES-EL10.txt
- name: Upload Artifact
#if: ${{ env.MY_GITHUB_TAG == '' }} # commented out to always upload
uses: actions/upload-artifact@v4
with:
name: ${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
path: |
${{ github.workspace }}/appimage/10/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}

170
.github/workflows/appimage7.yml vendored Normal file
View File

@ -0,0 +1,170 @@
on:
push:
tags:
- "*"
workflow_dispatch:
name: CI-appimage7
env:
APPIMAGETOOL_DOWNLOAD_URL: https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
jobs:
build_appimage7:
name: Build AppImage EL7
runs-on: ubuntu-latest
permissions:
contents: write # action-gh-release
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 149 # enough to cover between tags
#fetch-tags: true # this should work see actions/checkout~issue#1471
- name: Get the version
id: get_version
run: |
git show -s
version=$(cat VERSION) # 8.9.999
version_tstamp=$(git show -s "--format=%cs" | tr -d '-') # YYYYMMDD
version_hash=$(git show -s "--format=%h") # abcdefg
version_num=$(ruby -e "print '$GITHUB_REF'.split('/')[2]") # legacy version method: master
echo "version=${version}"
echo "version_tstamp=${version_tstamp}"
echo "version_hash=${version_hash}"
echo "version_num=${version_num}"
VERSION_NUM="${version}~${version_tstamp}~${version_hash}"
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
echo "MAGIC_APPIMAGE_OUTPUT_FILENAME=Magic-${VERSION_NUM}-x86_64-EL7.AppImage" >> $GITHUB_ENV
# Is this GHA being run due to a push-on-tag ? if so we make a GitHub release, otherwise we just publish artifact
github_tag=$(echo -n "$GITHUB_REF" | sed -e 's#refs/tags/##') # 8.9.999
echo "github_tag=$github_tag"
if echo -n "$GITHUB_REF" | egrep -q "^refs/tags/" # check prefix
then
if [ -n "$github_tag" ]
then
echo "MY_GITHUB_TAG=${github_tag}" >> $GITHUB_ENV
fi
fi
- name: Build project
run: |
cd appimage/7
make
ln -v Magic-x86_64.AppImage "${MAGIC_APPIMAGE_OUTPUT_FILENAME}"
ls -l *.AppImage
sha256sum *.AppImage
pwd
- name: Create RELEASE-NOTES.txt
run: |
cd appimage/7
# Find the last tag (that does not match the current GITHUB_REF)
echo GITHUB_REF=$GITHUB_REF
echo GITHUB_SHA=$GITHUB_SHA
# GitHub CI is a shallow checkout by default (just the files needed to build)
# but we also want history back to next tag, see fetch-tags/fetch-depth actions/checkout~issue#1471
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# remove only if ref of tag (to avoid conflict during fetch)
git update-ref -d $GITHUB_REF
echo git_update_ref_exitstatus=$?
fi
set +e
git fetch --tags --prune --no-recurse-submodules --depth=149 origin +$GITHUB_SHA # fetch-tags: true # is broken
echo git_fetch_exitstatus=$?
git_show_ref=$(git show-ref --hash $GITHUB_REF) # get tagcommit hash
git_show_ref_exitstatus=$?
echo git_show_ref_exitstatus=$git_show_ref_exitstatus
echo git_show_ref=$git_show_ref
git_rev_list=$(git rev-list -n1 $GITHUB_REF) # get commit hash
git_rev_list_exitstatus=$?
echo git_rev_list_exitstatus=$git_rev_list_exitstatus
echo git_rev_list=$git_rev_list
set -e
test "$git_show_ref" = "$GITHUB_SHA" || test "$git_rev_list" = "$GITHUB_SHA" # check we got the ref back (or fail CI)
git_describe=$(git describe --tags $GITHUB_SHA | sed -e 's#\-\([0-9]\+\-g\)#\+\1#') # /-\d+-g/
echo git_describe=$git_describe
# RELEASE-NOTES-EL7.txt
echo "### ${MAGIC_APPIMAGE_OUTPUT_FILENAME} commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-EL7.txt
echo "" >> RELEASE-NOTES-EL7.txt
echo "This release is based on EL7 (CentOS7), the AppImage format is designed to run on a wide range of Linux distributions." >> RELEASE-NOTES-EL7.txt
echo "" >> RELEASE-NOTES-EL7.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/7/README.md" >> RELEASE-NOTES-EL7.txt
echo "" >> RELEASE-NOTES-EL7.txt
length_info=$(stat "--format=%s bytes" "${MAGIC_APPIMAGE_OUTPUT_FILENAME}")
sha256_info=$(sha256sum "${MAGIC_APPIMAGE_OUTPUT_FILENAME}" | cut -d ' ' -f1)
echo "| | |" >> RELEASE-NOTES-EL7.txt
echo "| :-------- | :------ |" >> RELEASE-NOTES-EL7.txt
echo "| File Name | ${MAGIC_APPIMAGE_OUTPUT_FILENAME} |" | sed -e 's#~#\\~#g' >> RELEASE-NOTES-EL7.txt
echo "| File Length | ${length_info} |" >> RELEASE-NOTES-EL7.txt
echo "| File SHA256 | ${sha256_info} |" >> RELEASE-NOTES-EL7.txt
echo "" >> RELEASE-NOTES-EL7.txt
# RELEASE-NOTES-CL.txt
set +e # allow this to fail to empty string
git_previous_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1))
echo git_previous_tag=$git_previous_tag
set -e
if [ -n "${git_previous_tag}" ]
then
echo "### Change Log (since previous tag):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline --no-color --no-decorate "refs/tags/${git_previous_tag}..${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
else
echo "### Change Log (last commit only):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline -n1 --no-color --no-decorate "${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
fi
echo "" >> RELEASE-NOTES-CL.txt
#echo "### Build Info:" > RELEASE-NOTES-BI.txt
# FIXME extract package version info and DSO symvers into RELEASE-NOTES.txt
#echo "" >> RELEASE-NOTES-BI.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-EL7.txt
cat RELEASE-NOTES-EL7.txt
# RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/7/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/8/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/9/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/10/README.md" >> RELEASE-NOTES-DOCS.txt
# RELEASE-NOTES-GH.txt (this is shared for all AppImage for one tag)
echo "### commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-GH.txt
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# show tag annotation with tags like before
git tag --cleanup=strip "--format=%(contents)" -n "${GITHUB_REF:10}" | sed -e 's#\([~|]\)#\\\1#g' >> RELEASE-NOTES-GH.txt
fi
echo "" >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-DOCS.txt >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-GH.txt
# Show in action/artifact output
echo "## RELEASE NOTES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat RELEASE-NOTES-EL7.txt >> $GITHUB_STEP_SUMMARY
- name: Upload Release Asset
if: ${{ env.MY_GITHUB_TAG != '' }} # if: ${{ github.ref_type == 'tag' }}
uses: softprops/action-gh-release@v2
with:
body_path: ${{ github.workspace }}/appimage/7/RELEASE-NOTES-GH.txt
files: |
${{ github.workspace }}/appimage/7/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
${{ github.workspace }}/appimage/7/RELEASE-NOTES-EL7.txt
- name: Upload Artifact
#if: ${{ env.MY_GITHUB_TAG == '' }} # commented out to always upload
uses: actions/upload-artifact@v4
with:
name: ${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
path: |
${{ github.workspace }}/appimage/7/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}

170
.github/workflows/appimage8.yml vendored Normal file
View File

@ -0,0 +1,170 @@
on:
push:
tags:
- "*"
workflow_dispatch:
name: CI-appimage8
env:
APPIMAGETOOL_DOWNLOAD_URL: https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
jobs:
build_appimage8:
name: Build AppImage EL8
runs-on: ubuntu-latest
permissions:
contents: write # action-gh-release
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 149 # enough to cover between tags
#fetch-tags: true # this should work see actions/checkout~issue#1471
- name: Get the version
id: get_version
run: |
git show -s
version=$(cat VERSION) # 8.9.999
version_tstamp=$(git show -s "--format=%cs" | tr -d '-') # YYYYMMDD
version_hash=$(git show -s "--format=%h") # abcdefg
version_num=$(ruby -e "print '$GITHUB_REF'.split('/')[2]") # legacy version method: master
echo "version=${version}"
echo "version_tstamp=${version_tstamp}"
echo "version_hash=${version_hash}"
echo "version_num=${version_num}"
VERSION_NUM="${version}~${version_tstamp}~${version_hash}"
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
echo "MAGIC_APPIMAGE_OUTPUT_FILENAME=Magic-${VERSION_NUM}-x86_64-EL8.AppImage" >> $GITHUB_ENV
# Is this GHA being run due to a push-on-tag ? if so we make a GitHub release, otherwise we just publish artifact
github_tag=$(echo -n "$GITHUB_REF" | sed -e 's#refs/tags/##') # 8.9.999
echo "github_tag=$github_tag"
if echo -n "$GITHUB_REF" | egrep -q "^refs/tags/" # check prefix
then
if [ -n "$github_tag" ]
then
echo "MY_GITHUB_TAG=${github_tag}" >> $GITHUB_ENV
fi
fi
- name: Build project
run: |
cd appimage/8
make
ln -v Magic-x86_64.AppImage "${MAGIC_APPIMAGE_OUTPUT_FILENAME}"
ls -l *.AppImage
sha256sum *.AppImage
pwd
- name: Create RELEASE-NOTES.txt
run: |
cd appimage/8
# Find the last tag (that does not match the current GITHUB_REF)
echo GITHUB_REF=$GITHUB_REF
echo GITHUB_SHA=$GITHUB_SHA
# GitHub CI is a shallow checkout by default (just the files needed to build)
# but we also want history back to next tag, see fetch-tags/fetch-depth actions/checkout~issue#1471
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# remove only if ref of tag (to avoid conflict during fetch)
git update-ref -d $GITHUB_REF
echo git_update_ref_exitstatus=$?
fi
set +e
git fetch --tags --prune --no-recurse-submodules --depth=149 origin +$GITHUB_SHA # fetch-tags: true # is broken
echo git_fetch_exitstatus=$?
git_show_ref=$(git show-ref --hash $GITHUB_REF) # get tagcommit hash
git_show_ref_exitstatus=$?
echo git_show_ref_exitstatus=$git_show_ref_exitstatus
echo git_show_ref=$git_show_ref
git_rev_list=$(git rev-list -n1 $GITHUB_REF) # get commit hash
git_rev_list_exitstatus=$?
echo git_rev_list_exitstatus=$git_rev_list_exitstatus
echo git_rev_list=$git_rev_list
set -e
test "$git_show_ref" = "$GITHUB_SHA" || test "$git_rev_list" = "$GITHUB_SHA" # check we got the ref back (or fail CI)
git_describe=$(git describe --tags $GITHUB_SHA | sed -e 's#\-\([0-9]\+\-g\)#\+\1#') # /-\d+-g/
echo git_describe=$git_describe
# RELEASE-NOTES-EL8.txt
echo "### ${MAGIC_APPIMAGE_OUTPUT_FILENAME} commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-EL8.txt
echo "" >> RELEASE-NOTES-EL8.txt
echo "This release is based on EL8 (AlmaLinux8), the AppImage format is designed to run on a wide range of Linux distributions." >> RELEASE-NOTES-EL8.txt
echo "" >> RELEASE-NOTES-EL8.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/8/README.md" >> RELEASE-NOTES-EL8.txt
echo "" >> RELEASE-NOTES-EL8.txt
length_info=$(stat "--format=%s bytes" "${MAGIC_APPIMAGE_OUTPUT_FILENAME}")
sha256_info=$(sha256sum "${MAGIC_APPIMAGE_OUTPUT_FILENAME}" | cut -d ' ' -f1)
echo "| | |" >> RELEASE-NOTES-EL8.txt
echo "| :-------- | :------ |" >> RELEASE-NOTES-EL8.txt
echo "| File Name | ${MAGIC_APPIMAGE_OUTPUT_FILENAME} |" | sed -e 's#~#\\~#g' >> RELEASE-NOTES-EL8.txt
echo "| File Length | ${length_info} |" >> RELEASE-NOTES-EL8.txt
echo "| File SHA256 | ${sha256_info} |" >> RELEASE-NOTES-EL8.txt
echo "" >> RELEASE-NOTES-EL8.txt
# RELEASE-NOTES-CL.txt
set +e # allow this to fail to empty string
git_previous_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1))
echo git_previous_tag=$git_previous_tag
set -e
if [ -n "${git_previous_tag}" ]
then
echo "### Change Log (since previous tag):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline --no-color --no-decorate "refs/tags/${git_previous_tag}..${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
else
echo "### Change Log (last commit only):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline -n1 --no-color --no-decorate "${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
fi
echo "" >> RELEASE-NOTES-CL.txt
#echo "### Build Info:" > RELEASE-NOTES-BI.txt
# FIXME extract package version info and DSO symvers into RELEASE-NOTES.txt
#echo "" >> RELEASE-NOTES-BI.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-EL8.txt
cat RELEASE-NOTES-EL8.txt
# RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/7/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/8/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/9/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/10/README.md" >> RELEASE-NOTES-DOCS.txt
# RELEASE-NOTES-GH.txt (this is shared for all AppImage for one tag)
echo "### commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-GH.txt
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# show tag annotation with tags like before
git tag --cleanup=strip "--format=%(contents)" -n "${GITHUB_REF:10}" | sed -e 's#\([~|]\)#\\\1#g' >> RELEASE-NOTES-GH.txt
fi
echo "" >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-DOCS.txt >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-GH.txt
# Show in action/artifact output
echo "## RELEASE NOTES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat RELEASE-NOTES-EL8.txt >> $GITHUB_STEP_SUMMARY
- name: Upload Release Asset
if: ${{ env.MY_GITHUB_TAG != '' }} # if: ${{ github.ref_type == 'tag' }}
uses: softprops/action-gh-release@v2
with:
body_path: ${{ github.workspace }}/appimage/8/RELEASE-NOTES-GH.txt
files: |
${{ github.workspace }}/appimage/8/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
${{ github.workspace }}/appimage/8/RELEASE-NOTES-EL8.txt
- name: Upload Artifact
#if: ${{ env.MY_GITHUB_TAG == '' }} # commented out to always upload
uses: actions/upload-artifact@v4
with:
name: ${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
path: |
${{ github.workspace }}/appimage/8/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}

170
.github/workflows/appimage9.yml vendored Normal file
View File

@ -0,0 +1,170 @@
on:
push:
tags:
- "*"
workflow_dispatch:
name: CI-appimage9
env:
APPIMAGETOOL_DOWNLOAD_URL: https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
jobs:
build_appimage9:
name: Build AppImage EL9
runs-on: ubuntu-latest
permissions:
contents: write # action-gh-release
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 149 # enough to cover between tags
#fetch-tags: true # this should work see actions/checkout~issue#1471
- name: Get the version
id: get_version
run: |
git show -s
version=$(cat VERSION) # 8.9.999
version_tstamp=$(git show -s "--format=%cs" | tr -d '-') # YYYYMMDD
version_hash=$(git show -s "--format=%h") # abcdefg
version_num=$(ruby -e "print '$GITHUB_REF'.split('/')[2]") # legacy version method: master
echo "version=${version}"
echo "version_tstamp=${version_tstamp}"
echo "version_hash=${version_hash}"
echo "version_num=${version_num}"
VERSION_NUM="${version}~${version_tstamp}~${version_hash}"
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
echo "MAGIC_APPIMAGE_OUTPUT_FILENAME=Magic-${VERSION_NUM}-x86_64-EL9.AppImage" >> $GITHUB_ENV
# Is this GHA being run due to a push-on-tag ? if so we make a GitHub release, otherwise we just publish artifact
github_tag=$(echo -n "$GITHUB_REF" | sed -e 's#refs/tags/##') # 8.9.999
echo "github_tag=$github_tag"
if echo -n "$GITHUB_REF" | egrep -q "^refs/tags/" # check prefix
then
if [ -n "$github_tag" ]
then
echo "MY_GITHUB_TAG=${github_tag}" >> $GITHUB_ENV
fi
fi
- name: Build project
run: |
cd appimage/9
make
ln -v Magic-x86_64.AppImage "${MAGIC_APPIMAGE_OUTPUT_FILENAME}"
ls -l *.AppImage
sha256sum *.AppImage
pwd
- name: Create RELEASE-NOTES.txt
run: |
cd appimage/9
# Find the last tag (that does not match the current GITHUB_REF)
echo GITHUB_REF=$GITHUB_REF
echo GITHUB_SHA=$GITHUB_SHA
# GitHub CI is a shallow checkout by default (just the files needed to build)
# but we also want history back to next tag, see fetch-tags/fetch-depth actions/checkout~issue#1471
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# remove only if ref of tag (to avoid conflict during fetch)
git update-ref -d $GITHUB_REF
echo git_update_ref_exitstatus=$?
fi
set +e
git fetch --tags --prune --no-recurse-submodules --depth=149 origin +$GITHUB_SHA # fetch-tags: true # is broken
echo git_fetch_exitstatus=$?
git_show_ref=$(git show-ref --hash $GITHUB_REF) # get tagcommit hash
git_show_ref_exitstatus=$?
echo git_show_ref_exitstatus=$git_show_ref_exitstatus
echo git_show_ref=$git_show_ref
git_rev_list=$(git rev-list -n1 $GITHUB_REF) # get commit hash
git_rev_list_exitstatus=$?
echo git_rev_list_exitstatus=$git_rev_list_exitstatus
echo git_rev_list=$git_rev_list
set -e
test "$git_show_ref" = "$GITHUB_SHA" || test "$git_rev_list" = "$GITHUB_SHA" # check we got the ref back (or fail CI)
git_describe=$(git describe --tags $GITHUB_SHA | sed -e 's#\-\([0-9]\+\-g\)#\+\1#') # /-\d+-g/
echo git_describe=$git_describe
# RELEASE-NOTES-EL9.txt
echo "### ${MAGIC_APPIMAGE_OUTPUT_FILENAME} commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-EL9.txt
echo "" >> RELEASE-NOTES-EL9.txt
echo "This release is based on EL9 (AlmaLinux9), the AppImage format is designed to run on a wide range of Linux distributions." >> RELEASE-NOTES-EL9.txt
echo "" >> RELEASE-NOTES-EL9.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/9/README.md" >> RELEASE-NOTES-EL9.txt
echo "" >> RELEASE-NOTES-EL9.txt
length_info=$(stat "--format=%s bytes" "${MAGIC_APPIMAGE_OUTPUT_FILENAME}")
sha256_info=$(sha256sum "${MAGIC_APPIMAGE_OUTPUT_FILENAME}" | cut -d ' ' -f1)
echo "| | |" >> RELEASE-NOTES-EL9.txt
echo "| :-------- | :------ |" >> RELEASE-NOTES-EL9.txt
echo "| File Name | ${MAGIC_APPIMAGE_OUTPUT_FILENAME} |" | sed -e 's#~#\\~#g' >> RELEASE-NOTES-EL9.txt
echo "| File Length | ${length_info} |" >> RELEASE-NOTES-EL9.txt
echo "| File SHA256 | ${sha256_info} |" >> RELEASE-NOTES-EL9.txt
echo "" >> RELEASE-NOTES-EL9.txt
# RELEASE-NOTES-CL.txt
set +e # allow this to fail to empty string
git_previous_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1))
echo git_previous_tag=$git_previous_tag
set -e
if [ -n "${git_previous_tag}" ]
then
echo "### Change Log (since previous tag):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline --no-color --no-decorate "refs/tags/${git_previous_tag}..${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
else
echo "### Change Log (last commit only):" > RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
git log --oneline -n1 --no-color --no-decorate "${GITHUB_REF}" >> RELEASE-NOTES-CL.txt
echo "\`\`\`" >> RELEASE-NOTES-CL.txt
fi
echo "" >> RELEASE-NOTES-CL.txt
#echo "### Build Info:" > RELEASE-NOTES-BI.txt
# FIXME extract package version info and DSO symvers into RELEASE-NOTES.txt
#echo "" >> RELEASE-NOTES-BI.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-EL9.txt
cat RELEASE-NOTES-EL9.txt
# RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/7/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/8/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/9/README.md" >> RELEASE-NOTES-DOCS.txt
echo "See documentation at https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_SHA:0:8}/appimage/10/README.md" >> RELEASE-NOTES-DOCS.txt
# RELEASE-NOTES-GH.txt (this is shared for all AppImage for one tag)
echo "### commit ${git_describe}" | sed -e 's#~#\\~#g' > RELEASE-NOTES-GH.txt
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]
then
# show tag annotation with tags like before
git tag --cleanup=strip "--format=%(contents)" -n "${GITHUB_REF:10}" | sed -e 's#\([~|]\)#\\\1#g' >> RELEASE-NOTES-GH.txt
fi
echo "" >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-DOCS.txt >> RELEASE-NOTES-GH.txt
cat RELEASE-NOTES-CL.txt >> RELEASE-NOTES-GH.txt
# Show in action/artifact output
echo "## RELEASE NOTES" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
cat RELEASE-NOTES-EL9.txt >> $GITHUB_STEP_SUMMARY
- name: Upload Release Asset
if: ${{ env.MY_GITHUB_TAG != '' }} # if: ${{ github.ref_type == 'tag' }}
uses: softprops/action-gh-release@v2
with:
body_path: ${{ github.workspace }}/appimage/9/RELEASE-NOTES-GH.txt
files: |
${{ github.workspace }}/appimage/9/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
${{ github.workspace }}/appimage/9/RELEASE-NOTES-EL9.txt
- name: Upload Artifact
#if: ${{ env.MY_GITHUB_TAG == '' }} # commented out to always upload
uses: actions/upload-artifact@v4
with:
name: ${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}
path: |
${{ github.workspace }}/appimage/9/${{env.MAGIC_APPIMAGE_OUTPUT_FILENAME}}

View File

@ -12,37 +12,35 @@ jobs:
strategy:
max-parallel: 3
matrix:
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-20.04]
os: [ubuntu-24.04, ubuntu-22.04]
# Configure Options
pkgs: [all, none, no_tk_tcl_rl, no_rl, no_zlib, no_gc_gl_gu, no_gc_gu]
# X11 OGL CAIRO
pkgs: [all, none, no_tk_tcl_rl, no_tk_tcl_brl, no_zlib, no_gc_gl_gu, no_gc, no_gl_gu]
# Toolchain
# ubuntu-20.04 [gcc-9] gcc-10
# ubuntu-22.04 [gcc-11] gcc-12
# ubuntu-24.04 [gcc-13] gcc-14
tc: [default, gcc-10, gcc-12, gcc-14, clang-17, clang-18]
# ubuntu-20.04 [gcc-9, clang-10]
# ubuntu-22.04 [gcc-11, clang-14]
# ubuntu-24.04 [gcc-13, clang-18]
tc: [default, gcc-10, gcc-11, gcc-12, gcc-13, gcc-14, clang-14, clang-15, clang-17, clang-18, clang-19]
exclude:
- os: ubuntu-20.04
tc: gcc-12
- os: ubuntu-20.04
tc: gcc-14
- os: ubuntu-20.04
tc: clang-17
- os: ubuntu-20.04
tc: clang-18
- os: ubuntu-22.04
tc: gcc-10
tc: gcc-13
- os: ubuntu-22.04
tc: gcc-14
- os: ubuntu-22.04
tc: clang-17
- os: ubuntu-22.04
- os: ubuntu-22.04 # some sources show this as present but not found
tc: clang-18
- os: ubuntu-22.04
tc: clang-19
- os: ubuntu-24.04
tc: gcc-10
- os: ubuntu-24.04
tc: gcc-12
tc: gcc-11
- os: ubuntu-24.04
tc: clang-14
- os: ubuntu-24.04
tc: clang-15
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
@ -69,16 +67,19 @@ jobs:
# z no.*_zl zlib1g-dev
# n no.*_nc libncurses-dev
# r no.*_rl libreadline-dev
# R no.*_brl --enable-readline-bundled
# c no.*_tcl tcl-dev
# k no.*_tk tk-dev
# C no.*_gc libcairo-dev
# L no.*_gl libgl-dev
# U no.*_gu libglu1-mesa-dev
# U no.*_gu libglu1-mesa-dev # GLU requires GL
# X no.*_gx libx11-dev
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#z##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_nc"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#n##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_brl"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#r#R#'); fi # replace
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#r##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
@ -111,6 +112,8 @@ jobs:
_configure_args=()
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_zl"; then
_configure_args+=(--disable-compression); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_brl"; then
_configure_args+=(--enable-readline-bundled); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_rl"; then
_configure_args+=(--disable-readline); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tcl"; then
@ -203,6 +206,7 @@ jobs:
export CPP="clang-cpp-${BUILD_CLANG_VERSION}"
fi
set -o pipefail # due to pipe inside CI
./configure $CONFIGURE_ARGS 2>&1 | tee CONFIGURE.LOG
egrep "^(CPP|CXX|CC)\s" defs.mak

49
.github/workflows/main-aarch64.yml vendored Normal file
View File

@ -0,0 +1,49 @@
# This is a basic workflow to help you get started with Actions
name: CI-aarch64
# Controls when the workflow will run
on:
push:
pull_request:
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
simple_build_linux_arm:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- name: Get Dependencies
run: |
sudo apt-get update
sudo apt-get install -y tcl-dev tk-dev libcairo-dev
- name: Build
run: |
./configure
make database/database.h
make -j$(nproc)
simple_build_wasm_arm:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- name: Get Dependencies
run: |
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
- name: Build
run: |
source ./emsdk/emsdk_env.sh
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="
emmake make
- name: archive wasm bundle
uses: actions/upload-artifact@v4
with:
name: magic-wasm-bundle-arm
path: |
${{ github.workspace }}/magic/magic.wasm

View File

@ -10,8 +10,8 @@ on:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
simple_build_macos13:
runs-on: macos-13
simple_build_macos15:
runs-on: macos-15-intel # only and last supported intel MacOS
timeout-minutes: 45 # x86_64 seems non-SSD based (slower)
steps:
- name: Checkout
@ -22,8 +22,8 @@ jobs:
run: |
brew install --cask xquartz
PACKAGE_LIST="xquartz"
brew install cairo tcl-tk@8 tcsh
_package_list="cairo tcl-tk@8 tcsh"
brew install cairo tcl-tk@8 tcsh gnu-sed
_package_list="cairo tcl-tk@8 tcsh gnu-sed"
# These seem needed maybe they are being provided from somewhere else GHA runner
# or brew transitive depend either way doesn't hurt to confirm they are installed.
_package_list="$_package_list libglu freeglut"
@ -54,6 +54,7 @@ jobs:
brew info tcl-tk > $TMPFILE && head -n1 $TMPFILE
brew info tcl-tk@8 > $TMPFILE && head -n1 $TMPFILE
brew info tcsh > $TMPFILE && head -n1 $TMPFILE
brew info gnu-sed > $TMPFILE && head -n1 $TMPFILE
echo ""
cc -v 2>&1
echo ""
@ -234,10 +235,10 @@ jobs:
cp *.mak dist/BUILD-INFO/
cp *.LOG dist/BUILD-INFO/
- name: Upload archive magic-macos13
- name: Upload archive magic-macos15
uses: actions/upload-artifact@v4
with:
name: magic-macos13
name: magic-macos15
path: |
${{ github.workspace }}/dist
@ -253,8 +254,8 @@ jobs:
run: |
brew install --cask xquartz
PACKAGE_LIST="xquartz"
brew install cairo tcl-tk@8 tcsh
_package_list="cairo tcl-tk@8 tcsh"
brew install cairo tcl-tk@8 tcsh gnu-sed
_package_list="cairo tcl-tk@8 tcsh gnu-sed"
# These seem needed maybe they are being provided from somewhere else GHA runner
# or brew transitive depend either way doesn't hurt to confirm they are installed.
_package_list="$_package_list libglu freeglut"
@ -285,6 +286,7 @@ jobs:
brew info tcl-tk > $TMPFILE && head -n1 $TMPFILE
brew info tcl-tk@8 > $TMPFILE && head -n1 $TMPFILE
brew info tcsh > $TMPFILE && head -n1 $TMPFILE
brew info gnu-sed > $TMPFILE && head -n1 $TMPFILE
echo ""
cc -v 2>&1
echo ""

View File

@ -24,7 +24,7 @@ jobs:
- name: Run the testing on the container and send the mail
run: docker exec test_magic /vezzal/test_magic.sh "lankasaicharan123@gmail.com,tim@opencircuitdesign.com" ${{secrets.MAILING_KEY}}
simple_build_linux:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get Dependencies
@ -36,7 +36,7 @@ jobs:
make database/database.h
make -j$(nproc)
simple_build_wasm:
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Get Dependencies
@ -49,6 +49,9 @@ jobs:
run: |
source ./emsdk/emsdk_env.sh
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="
emmake make
- name: archive wasm bundle
uses: actions/upload-artifact@v4

View File

@ -3,11 +3,10 @@
Get [Homebrew](https://brew.sh).
```sh
# TCL9 should be supported soon (Q2 2025)
brew install cairo tcl-tk@8 python3
brew install cairo tcl-tk@8 python3 gnu-sed
brew install --cask xquartz
./scripts/configure_mac
# If you have both TCL8 and TCL9 installed you may need to verify TCL8 was selected.
# If you have both TCL8 and TCL9 installed you may need to verify which was selected.
make database/database.h
make -j$(sysctl -n hw.ncpu)
make install # may need sudo depending on your setup

103
Makefile
View File

@ -4,31 +4,33 @@
MAGICDIR = .
PROGRAMS = magic
TECH = scmos
TECHS = scmos
LIBRARIES = database utils extflat
MODULES = bplane cmwind commands database dbwind debug drc extflat \
extract graphics netmenu plow resis select sim textio tiles \
utils windows wiring
# This was `cat VERSION`
VERSION := $(shell cat ${MAGICDIR}/VERSION)
MAKEFLAGS =
INSTALL_CAD_DIRS = windows doc ${TECH}
INSTALL_CAD_DIRS = windows doc ${TECHS}
-include defs.mak
all: $(ALL_TARGET)
all: $(ALL_TARGET) techs
standard:
@echo --- errors and warnings logged in file make.log
@${MAKE} mains
standard: mains
tcl:
@echo --- errors and warnings logged in file make.log
@${MAKE} tcllibrary
tcl: tcllibrary
force: clean all
force:
@${MAKE} clean
@${MAKE} all
defs.mak:
@echo No \"defs.mak\" file found. Run "configure" to make one.
@exit 1
config:
${MAGICDIR}/configure
@ -43,24 +45,56 @@ mains: database/database.h modules libs
for dir in ${PROGRAMS}; do \
(cd $$dir && ${MAKE} main) || exit 1; done
database/database.h: database/database.h.in
database/database.h: ${MAGICDIR}/database/database.h.in
@echo --- making header file database/database.h
${SCRIPTS}/makedbh database/database.h.in database/database.h
${SCRIPTS}/makedbh ${MAGICDIR}/database/database.h.in database/database.h
modules: database/database.h depend
@echo --- making modules
for dir in ${MODULES} ${PROGRAMS}; do \
(cd $$dir && ${MAKE} module) || exit 1; done
# tiles xyz => tiles/libtiles.o xyz/libxyz.o
MODULES_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.o"; done)
# tiles xyz => tiles/libtiles.a xyz/libxyz.a
LIBS_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.a"; done)
libs:
@echo --- making libraries
for dir in ${LIBRARIES}; do \
(cd $$dir && ${MAKE} lib) || exit 1; done
.PHONY: FORCE
${MODULES_SUBDIR}: FORCE
@${MAKE} -C $(dir $@) module
depend: database/database.h
.PHONY: modules
modules: database/database.h depend ${MODULES_SUBDIR}
${LIBS_SUBDIR}: FORCE
@${MAKE} -C $(dir $@) lib
# Force the tiles/utils modules to exist first for libdatabase.a
.PHONY: libs
libs: database/database.h depend tiles/libtiles.o utils/libutils.o ${LIBS_SUBDIR}
#
# extcheck - utility tool
# net2ir - utility tool
# oa - disabled (needs 'clean' target renaming)
SUBDIRS = bplane cmwind commands database dbwind debug drc extflat extract graphics \
magic netmenu plow resis select sim textio tiles utils windows wiring
BUNDLED_MODULES = readline lisp
# Unique list of all subdir that might have Depend file, we have to deduplicate otherwise
# MAKE will warning loudly. This list is somewhat empty when defs.mak does not exist
SUBDIRS_FILTERED := $(shell echo ${MODULES} ${PROGRAMS} ${SUBDIRS} | tr ' ' '\n' | sort | uniq)
SUBDIRS_DEPEND = $(addsuffix /Depend, ${SUBDIRS_FILTERED})
${SUBDIRS_DEPEND}: database/database.h
@echo --- making dependencies
for dir in ${MODULES} ${UNUSED_MODULES} ${PROGRAMS}; do \
(cd $$dir && ${MAKE} depend) || exit 1; done
${MAKE} -C $(dir $@) depend
.PHONY: depend
depend: defs.mak ${SUBDIRS_DEPEND}
.PHONY: techs
techs: depend
@echo --- making techs
for dir in ${TECHS}; do \
(cd $$dir && ${MAKE} all) || exit 1; done
install: $(INSTALL_TARGET)
@ -95,7 +129,7 @@ install-tcl-real: install-tcl-dirs
(cd $$dir && ${MAKE} install-tcl); done
clean:
for dir in ${MODULES} ${PROGRAMS} ${TECH} ${UNUSED_MODULES}; do \
for dir in ${SUBDIRS_FILTERED} ${TECHS} ${BUNDLED_MODULES}; do \
(cd $$dir && ${MAKE} clean); done
${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags
@ -105,18 +139,19 @@ distclean:
${RM} defs.mak old.defs.mak ${MAGICDIR}/scripts/defs.mak
${RM} ${MAGICDIR}/scripts/default.conf
${RM} ${MAGICDIR}/scripts/config.log ${MAGICDIR}/scripts/config.status
${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz
${RM} *.log */Depend
${RM} database/database.h
${RM} scripts/magic.spec magic-${VERSION} magic-${VERSION}.tgz
${RM} *.log
dist:
${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz
sed -e /@VERSION@/s%@VERSION@%`cat VERSION`% \
${RM} scripts/magic.spec magic-${VERSION} magic-${VERSION}.tgz
${SED} -e /@VERSION@/s%@VERSION@%${VERSION}% \
scripts/magic.spec.in > scripts/magic.spec
ln -nsf . magic-`cat VERSION`
tar zchvf magic-`cat VERSION`.tgz --exclude CVS \
--exclude magic-`cat VERSION`/magic-`cat VERSION` \
--exclude magic-`cat VERSION`/magic-`cat VERSION`.tgz \
magic-`cat VERSION`
${LN} -nsf . magic-${VERSION}
tar zchvf magic-${VERSION}.tgz --exclude CVS \
--exclude magic-${VERSION}/magic-${VERSION} \
--exclude magic-${VERSION}/magic-${VERSION}.tgz \
magic-${VERSION}
clean-mains:
for dir in ${PROGRAMS}; do \
@ -133,6 +168,6 @@ TAGS:
setup-git:
git config --local include.path ../.gitconfig
git stash save
rm .git/index
${RM} .git/index
git checkout HEAD -- "$$(git rev-parse --show-toplevel)"
git stash pop

View File

@ -1 +1 @@
8.3.529
8.3.595

59
appimage/10/Dockerfile Normal file
View File

@ -0,0 +1,59 @@
FROM almalinux:10
USER root
# Build Dependencies (and dump version to logging)
RUN dnf install -y python3 zlib-devel ncurses-devel readline-devel cairo-devel freeglut-devel \
mesa-libGLU-devel mesa-libGL-devel libX11-devel libstdc++-devel gcc gcc-c++ make git tcsh \
zip \
&& echo "### rpm -qa:" \
&& rpm -qa | sort \
&& echo ""
#RUN dnf group install -y "Development Tools"
# Tcl/Tk
WORKDIR /tcl
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl9.0.1-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix \
&& make \
&& make install install-libraries install-msgs install-tzdata
WORKDIR /tk
RUN curl -L https://prdownloads.sourceforge.net/tcl/tk9.0.1-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix --with-tcl=/prefix/lib \
&& make \
&& make install install-libraries
WORKDIR /prefix/bin
RUN cp ./wish9.0 ./wish
RUN cp ./tclsh9.0 ./tclsh
# Magic
WORKDIR /magic
COPY . .
RUN ./configure \
--prefix=/prefix \
--with-tcl=/prefix/lib \
--with-tk=/prefix/lib \
&& make clean \
&& make database/database.h \
&& make -j$(nproc) \
&& make install
# Produce summary of what was created and confirm their DSOs
RUN echo "### filesystem:" \
find /prefix -printf "%y/%M/%m %i/%n %l %u/%U %g/%G %s/%b %T+/%T@\t%p\n"; \
ls -lR /prefix; \
find /prefix -type f -perm /111 -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
for name in libgcc_s libstdc++ libpng liblzma libxml2 libz libcairo libGL libGLU; do \
find /lib64 /usr/lib64 -maxdepth 2 -name "*.so" -name "${name}*" -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
done; \
echo "###"
WORKDIR /
RUN tar -czf /prefix.tar.gz -C ./prefix .
CMD ["/bin/bash"]

46
appimage/10/Makefile Normal file
View File

@ -0,0 +1,46 @@
MAGIC_SRC_ROOT = ../..
RESOURCES := $(shell find ../rsc/ -type f)
ARCH := $(shell uname -m)
APPIMAGE = Magic-$(ARCH).AppImage
VERSION_MAGIC := $(shell cat $(MAGIC_SRC_ROOT)/VERSION)
VERSION_TSTAMP := $(shell git show -s "--format=%cs" | tr -d '-')
VERSION_HASH := $(shell git show -s "--format=%h")
VERSION_NUM ?= $(VERSION_MAGIC)~$(VERSION_TSTAMP)~$(VERSION_HASH)
VERSION := $(VERSION_NUM)
# Allow CI to override
APPIMAGETOOL_DOWNLOAD_URL ?= https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
all: $(APPIMAGE)
.PHONY: prefix/bin/magic
prefix/bin/magic: Dockerfile Makefile
@echo "APPIMAGE=$(APPIMAGE)"
@echo "VERSION=$(VERSION)"
@echo "ARCH=$(ARCH)"
@echo "RESOURCES=$(RESOURCES)"
rm -rf prefix
docker build -t magic_build -f ./Dockerfile $(MAGIC_SRC_ROOT)
id=$$(docker create magic_build) ; \
docker cp $$id:/prefix ./prefix ; \
docker rm -v $$id
mkdir -p prefix/lib/tcl9.0.1
cp -r prefix/lib/tcl9.0 prefix/lib/tcl9.0.1/library
appimagetool:
curl -L "$(APPIMAGETOOL_DOWNLOAD_URL)" > ./appimagetool
chmod +x ./appimagetool
$(APPIMAGE): prefix/bin/magic appimagetool $(RESOURCES)
cp $(RESOURCES) ./prefix/
./appimagetool prefix
PREFIX ?= /usr/local
install:
install $(APPIMAGE) $(PREFIX)/bin/magic
.PHONY: clean
clean:
rm -f *.AppImage
rm -f prefix.tar.gz
rm -rf prefix

127
appimage/10/README.md Normal file
View File

@ -0,0 +1,127 @@
This is an AppImage that runs on all GNU/Linux platforms with:
* FUSE
* This excludes non-privileged Docker containers unfortunately, unless pre-extracted.
* GLIBC 2.38+
* Cairo 1.18+
* May require runtime CPU matching Linux ABI x86-64-v3 and newer (CPUs with SSE4.2/AVX2/BMI2/FMA via `lscpu`).
This AppImage build is based on EL10 (via AlmaLinux 10).
AlmaLinux 10 was first released on 27 May 2025.
# Version Info
See the AppImage main binary file naming, release tag information and AppInfo metadata
for the exact magic version inside the archive. When starting AppImage by default the
Tcl console banner can also provide version information, also using the `version` Tcl
command.
# Build Info
* Based on AlmaLinux 10 (EL10)
* Tcl/Tk 9.0.1
* and Magic 8.x
* all default modules enabled (including all Display drivers cairo/X11/OpenGL)
# FAQ: How to use
Download the *.AppImage file relevant to your platform and run:
```
chmod +x Magic-x86_64.AppImage
./Magic-x86_64.AppImage
```
Example startup with command line options:
```
./Magic-x86_64.AppImage -d XR -T scmos
```
# FAQ: How to use (inside docker / podman)
```
chmod +x Magic-x86_64.AppImage
### Podman or Docker, use :Z when rootless with selinux enabled
podman run --rm --device /dev/fuse --privileged \
-v "$(pwd):/tmp/work:Z" -v "/tmp/.X11-unix/X0:/tmp/.X11-unix/X0:Z" \
-e DISPLAY -ti almalinux:10
### Inside Docker:
dnf update -y
dnf install -y fuse libX11 cairo libGL libGLU
cd /tmp/work
./Magic-x86_64.AppImage -d XR -T scmos
```
# Building Requirements
* A reasonably recent GNU/Linux host
* GNU make
* Docker 20+
* Git
* curl
The final build is then packaged into an AppImage using AppImageTool on the host machine.
# Build Instructions
`make`
# Installation Instructions
`make install`
# FAQ: Is my CPU supported ?
This is built with the standard x86_64 Linux ABI version for AlmaLinux 10.
Use the command `/lib64/ld-linux-x86-64.so.2 --help` to see which CPUs your
Linux distribtion supports (and your CPU) look for the word "supported".
# FAQ: The DSO versioning link dependencies?
The information here provides an outline of what versions to expect from EL10
of the major dependencies, to assist you in a compatibility check with your
Linux distribution of choice.
The actual versions in our public releases can differ slightly inline with
the EL10 support compatibility and ABI versioning policies for the support
lifecycle of the distribution.
The most important items are the Direct Dependencies and the availabilty
of a suitable graphics DSO as per your '-d' choice.
Direct Runtime Dependencies (from /prefix/**):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.38 | glibc-2.39-37 |
| libz.so.1 | ZLIB_1.2.2 | zlib-ng-2.2.3-1 |
| | | zlib-ng-compat-2.2.3-1 |
Optional/Modular Runtime Dependencies (depending on graphics mode):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libcairo.so.2 | | |
| libcairo.so.2.11802.0 | | cairo-1.18.2-2 |
| libGL.so.1 | | libglvnd-glx-1:1.7.0-7 |
| | | mesa-libGL-24.2.8-2 |
| libGLU.so.1 | | mesa-libGLU-9.0.3-7 |
Transitive/Third-Party Runtime Dependencies (for information only):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libstdc++.so.6 | CXXABI_1.3.9 | gcc-c++-14.2.1-7 |
| libstdc++.so.6 | GLIBCXX_3.4 | gcc-c++-14.2.1-7 |
| libgcc_s.so.1 | GCC_4.2.0 | libgcc_s-14-20250110 |
| libxml2.so.2 | LIBXML2_2.6.0 | libxml2-2.12.5-5 |
| libpng16.so.16 | PNG16_0 | libpng-2:1.6.40-8 |
| liblzma.so.5 | XZ_5.0 | xz-devel-1:5.6.2-4 |
| libz.so.1 | ZLIB_1.2.9 | zlib-ng-2.2.3-1 |
| | | zlib-ng-compat-2.2.3-1 |

View File

@ -13,21 +13,24 @@ RUN ls -l /etc/yum.repos.d/ \
&& yum -y update \
&& rm -f /tmp/CentOS-Base.repo.old
# Build Dependencies
RUN yum install -y cairo-devel freeglut-devel gcc make tcsh
# Build Dependencies (and dump version to logging)
RUN yum install -y cairo-devel freeglut-devel gcc make tcsh \
&& echo "### rpm -qa:" \
&& rpm -qa | sort \
&& echo ""
# Tcl/Tk
# Tcl/Tk
WORKDIR /tcl
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl8.6.12-src.tar.gz | tar --strip-components=1 -xzC . \
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl8.6.16-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix \
&& make \
&& make install
WORKDIR /tk
RUN curl -L https://prdownloads.sourceforge.net/tcl/tk8.6.12-src.tar.gz | tar --strip-components=1 -xzC . \
RUN curl -L https://prdownloads.sourceforge.net/tcl/tk8.6.16-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix --with-tcl=/prefix/lib\
&& ./configure --prefix=/prefix --with-tcl=/prefix/lib \
&& make \
&& make install
@ -49,7 +52,17 @@ RUN ./configure \
&& make -j$(nproc) \
&& make install
# Produce summary of what was created and confirm their DSOs
RUN echo "### filesystem:" \
find /prefix -printf "%y/%M/%m %i/%n %l %u/%U %g/%G %s/%b %T+/%T@\t%p\n"; \
ls -lR /prefix; \
find /prefix -type f -perm /111 -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
for name in libgcc_s libstdc++ libpng liblzma libxml2 libz libcairo libGL libGLU; do \
find /lib64 /usr/lib64 -maxdepth 2 -name "*.so" -name "${name}*" -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
done; \
echo "###"
WORKDIR /
RUN tar -czf /prefix.tar.gz -C ./prefix .
CMD ["/bin/bash"]
CMD ["/bin/bash"]

46
appimage/7/Makefile Normal file
View File

@ -0,0 +1,46 @@
MAGIC_SRC_ROOT = ../..
RESOURCES := $(shell find ../rsc/ -type f)
ARCH := $(shell uname -m)
APPIMAGE = Magic-$(ARCH).AppImage
VERSION_MAGIC := $(shell cat $(MAGIC_SRC_ROOT)/VERSION)
VERSION_TSTAMP := $(shell git show -s "--format=%cs" | tr -d '-')
VERSION_HASH := $(shell git show -s "--format=%h")
VERSION_NUM ?= $(VERSION_MAGIC)~$(VERSION_TSTAMP)~$(VERSION_HASH)
VERSION := $(VERSION_NUM)
# Allow CI to override
APPIMAGETOOL_DOWNLOAD_URL ?= https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
all: $(APPIMAGE)
.PHONY: prefix/bin/magic
prefix/bin/magic: Dockerfile Makefile
@echo "APPIMAGE=$(APPIMAGE)"
@echo "VERSION=$(VERSION)"
@echo "ARCH=$(ARCH)"
@echo "RESOURCES=$(RESOURCES)"
rm -rf prefix
docker build -t magic_build -f ./Dockerfile $(MAGIC_SRC_ROOT)
id=$$(docker create magic_build) ; \
docker cp $$id:/prefix ./prefix ; \
docker rm -v $$id
mkdir -p prefix/lib/tcl8.6.16
cp -r prefix/lib/tcl8.6 prefix/lib/tcl8.6.16/library
appimagetool:
curl -L "$(APPIMAGETOOL_DOWNLOAD_URL)" > ./appimagetool
chmod +x ./appimagetool
$(APPIMAGE): prefix/bin/magic appimagetool $(RESOURCES)
cp $(RESOURCES) ./prefix/
./appimagetool prefix
PREFIX ?= /usr/local
install:
install $(APPIMAGE) $(PREFIX)/bin/magic
.PHONY: clean
clean:
rm -f *.AppImage
rm -f prefix.tar.gz
rm -rf prefix

137
appimage/7/README.md Normal file
View File

@ -0,0 +1,137 @@
This is an AppImage that runs on all GNU/Linux platforms with:
* FUSE
* This excludes non-privileged Docker containers unfortunately, unless pre-extracted.
* GLIBC 2.17+
* Cairo 1.15+
* Supports all Linux x86_64 CPUs
This AppImage build is based on EL7 (via CentOS 7)
CentOS 7 was first released on 07 July 2014 and went end-of-life on 30 June 2024.
# Version Info
See the AppImage main binary file naming, release tag information and AppInfo metadata
for the exact magic version inside the archive. When starting AppImage by default the
Tcl console banner can also provide version information, also using the `version` Tcl
command.
# Build Info
* Based on CentOS 7 (EL7)
* Tcl/Tk 8.6.16
* and Magic 8.x
* all default modules enabled, but without OpenGL (includes Display drivers cairo/X11)
# FAQ: How to use
Download the *.AppImage file relevant to your platform and run:
```
chmod +x Magic-x86_64.AppImage
./Magic-x86_64.AppImage
```
Example startup with command line options:
```
./Magic-x86_64.AppImage -d XR -T scmos
```
# FAQ: How to use (inside docker / podman)
```
chmod +x Magic-x86_64.AppImage
### Podman or Docker, use :Z when rootless with selinux enabled
podman run --rm --device /dev/fuse --privileged \
-v "$(pwd):/tmp/work:Z" -v "/tmp/.X11-unix/X0:/tmp/.X11-unix/X0:Z" \
-e DISPLAY -ti centos:7
### Inside Docker:
echo "FIXUP yum from vault and update" \
&& ls -l /etc/yum.repos.d/ \
&& cp /etc/yum.repos.d/CentOS-Base.repo /tmp/CentOS-Base.repo.old \
&& sed -e 's/mirror.centos.org/vault.centos.org/g' -i /etc/yum.repos.d/*.repo \
&& sed -e 's/^#.*baseurl=http/baseurl=http/g' -i /etc/yum.repos.d/*.repo \
&& sed -e 's/^mirrorlist=http/#mirrorlist=http/g' -i /etc/yum.repos.d/*.repo \
&& diff -u /tmp/CentOS-Base.repo.old /etc/yum.repos.d/CentOS-Base.repo; \
yum clean all \
&& yum -y update \
&& rm -f /tmp/CentOS-Base.repo.old
yum install -y fuse libX11 cairo
cd /tmp/work
./Magic-x86_64.AppImage -d XR -T scmos
```
# Building Requirements
* A reasonably recent GNU/Linux host
* GNU make
* Docker 20+
* Git
* curl
The final build is then packaged into an AppImage using AppImageTool on the host machine.
# Build Instructions
`make`
# Installation Instructions
`make install`
# FAQ: Is my CPU supported ?
Supports all x86_64 CPUs. The Linux ABI in use is the original x86-64 ABI (v1).
Use the command `/lib64/ld-linux-x86-64.so.2 --help` to see which CPUs your
Linux distribtion supports (and your CPU) look for the word "supported".
# FAQ: The DSO versioning link dependencies?
The information here provides an outline of what versions to expect from EL7
of the major dependencies, to assist you in a compatibility check with your
Linux distribution of choice.
The actual versions in our public releases can differ slightly inline with
the EL7 support compatibility and ABI versioning policies for the support
lifecycle of the distribution.
The most important items are the Direct Dependencies and the availabilty
of a suitable graphics DSO as per your '-d' choice.
Direct Runtime Dependencies (from /prefix/**):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.14 | glibc-2.17-326 |
| libz.so.1 | ZLIB_1.2.2 | zlib-1.2.7-21 |
Optional/Modular Runtime Dependencies (depending on graphics mode):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libcairo.so.2 | | |
| libcairo.so.2.11512.0 | | cairo-1.15.12-4 |
| libGL.so.1 | | |
| libglvnd-glx-1:1.0.1-0 | | mesa-libGL-18.3.4-12 |
| libGLU.so.1 | | mesa-libGLU-9.0.0-4 |
Transitive/Third-Party Runtime Dependencies (for information only):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.35 | glibc-2.17-326 |
| libstdc++.so.6 | GLIBCXX_3.4 | gcc-4.8.5-44 |
| libstdc++.so.6 | CXXABI_1.3.9 | gcc-4.8.5-44 |
| libgcc_s.so.1 | | |
| libgcc_s-4.8.5-20150702.so.1 | GCC_4.2.0 | libgcc-4.8.5-44 |
| libxml2.so.2 | LIBXML2_2.6.0 | libxml2-2.9.1-6 |
| libpng15.so.15 | | |
| libpng15.so.15.13.0 | PNG16_0 | libpng-1:1.5.13-8 |
| liblzma.so.5 | XZ_5.0 | xz-libs-5.2.2-2 |
| libz.so.1 | ZLIB_1.2.9 | zlib-1.2.7-21 |

58
appimage/8/Dockerfile Normal file
View File

@ -0,0 +1,58 @@
FROM almalinux:8
USER root
# Build Dependencies (and dump version to logging)
RUN dnf install -y python311 zlib-devel ncurses-devel readline-devel cairo-devel freeglut-devel \
mesa-libGLU-devel mesa-libGL-devel libX11-devel libstdc++-devel gcc gcc-c++ make git tcsh \
&& echo "### rpm -qa:" \
&& rpm -qa | sort \
&& echo ""
#RUN dnf group install -y "Development Tools"
# Tcl/Tk
WORKDIR /tcl
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl8.6.16-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix \
&& make \
&& make install
WORKDIR /tk
RUN curl -L https://prdownloads.sourceforge.net/tcl/tk8.6.16-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix --with-tcl=/prefix/lib \
&& make \
&& make install
WORKDIR /prefix/bin
RUN cp ./wish8.6 ./wish
RUN cp ./tclsh8.6 ./tclsh
# Magic
WORKDIR /magic
COPY . .
RUN ./configure \
--prefix=/prefix \
--with-tcl=/prefix/lib \
--with-tk=/prefix/lib \
&& make clean \
&& make database/database.h \
&& make -j$(nproc) \
&& make install
# Produce summary of what was created and confirm their DSOs
RUN echo "### filesystem:" \
find /prefix -printf "%y/%M/%m %i/%n %l %u/%U %g/%G %s/%b %T+/%T@\t%p\n"; \
ls -lR /prefix; \
find /prefix -type f -perm /111 -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
for name in libgcc_s libstdc++ libpng liblzma libxml2 libz libcairo libGL libGLU; do \
find /lib64 /usr/lib64 -maxdepth 2 -name "*.so" -name "${name}*" -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
done; \
echo "###"
WORKDIR /
RUN tar -czf /prefix.tar.gz -C ./prefix .
CMD ["/bin/bash"]

46
appimage/8/Makefile Normal file
View File

@ -0,0 +1,46 @@
MAGIC_SRC_ROOT = ../..
RESOURCES := $(shell find ../rsc/ -type f)
ARCH := $(shell uname -m)
APPIMAGE = Magic-$(ARCH).AppImage
VERSION_MAGIC := $(shell cat $(MAGIC_SRC_ROOT)/VERSION)
VERSION_TSTAMP := $(shell git show -s "--format=%cs" | tr -d '-')
VERSION_HASH := $(shell git show -s "--format=%h")
VERSION_NUM ?= $(VERSION_MAGIC)~$(VERSION_TSTAMP)~$(VERSION_HASH)
VERSION := $(VERSION_NUM)
# Allow CI to override
APPIMAGETOOL_DOWNLOAD_URL ?= https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
all: $(APPIMAGE)
.PHONY: prefix/bin/magic
prefix/bin/magic: Dockerfile Makefile
@echo "APPIMAGE=$(APPIMAGE)"
@echo "VERSION=$(VERSION)"
@echo "ARCH=$(ARCH)"
@echo "RESOURCES=$(RESOURCES)"
rm -rf prefix
docker build -t magic_build -f ./Dockerfile $(MAGIC_SRC_ROOT)
id=$$(docker create magic_build) ; \
docker cp $$id:/prefix ./prefix ; \
docker rm -v $$id
mkdir -p prefix/lib/tcl8.6.16
cp -r prefix/lib/tcl8.6 prefix/lib/tcl8.6.16/library
appimagetool:
curl -L "$(APPIMAGETOOL_DOWNLOAD_URL)" > ./appimagetool
chmod +x ./appimagetool
$(APPIMAGE): prefix/bin/magic appimagetool $(RESOURCES)
cp $(RESOURCES) ./prefix/
./appimagetool prefix
PREFIX ?= /usr/local
install:
install $(APPIMAGE) $(PREFIX)/bin/magic
.PHONY: clean
clean:
rm -f *.AppImage
rm -f prefix.tar.gz
rm -rf prefix

126
appimage/8/README.md Normal file
View File

@ -0,0 +1,126 @@
This is an AppImage that runs on all GNU/Linux platforms with:
* FUSE
* This excludes non-privileged Docker containers unfortunately, unless pre-extracted.
* GLIBC 2.28+
* Cairo 1.15+
* Supports all Linux x86_64 CPUs
This AppImage build is based on EL8 (via AlmaLinux 8)
AlmaLinux 8 was first released on 20 March 2021, active support ends 31 May 2024,
security support ends 31 May 2029 (please see AlmaLinux bulletins for
up-to-date information).
# Version Info
See the AppImage main binary file naming, release tag information and AppInfo metadata
for the exact magic version inside the archive. When starting AppImage by default the
Tcl console banner can also provide version information, also using the `version` Tcl
command.
* Based on AlmaLinux 8 (EL8)
* Tcl/Tk 8.6.16
* and Magic 8.x
* all default modules enabled (including all Display drivers cairo/X11/OpenGL)
# FAQ: How to use
Download the *.AppImage file relevant to your platform and run:
```
chmod +x Magic-x86_64.AppImage
./Magic-x86_64.AppImage
```
Example startup with command line options:
```
./Magic-x86_64.AppImage -d XR -T scmos
```
# FAQ: How to use (inside docker / podman)
```
chmod +x Magic-x86_64.AppImage
### Podman or Docker, use :Z when rootless with selinux enabled
podman run --rm --device /dev/fuse --privileged \
-v "$(pwd):/tmp/work:Z" -v "/tmp/.X11-unix/X0:/tmp/.X11-unix/X0:Z" \
-e DISPLAY -ti almalinux:8
### Inside Docker:
dnf update -y
dnf install -y fuse libX11 cairo libGL libGLU
cd /tmp/work
./Magic-x86_64.AppImage -d XR -T scmos
```
# Building Requirements
* A reasonably recent GNU/Linux host
* GNU make
* Docker
* Git
* curl
The final build is then packaged into an AppImage using AppImageTool on the host machine.
# Build Instructions
`make`
# Installation Instructions
`make install`
# FAQ: Is my CPU supported ?
Supports all x86_64 CPUs. The Linux ABI in use is the original x86-64 ABI (v1).
Use the command `/lib64/ld-linux-x86-64.so.2 --help` to see which CPUs your
Linux distribtion supports (and your CPU) look for the word "supported".
# FAQ: The DSO versioning link dependencies?
The information here provides an outline of what versions to expect from EL8
of the major dependencies, to assist you with a compatibility check with your
Linux distribution of choice.
The actual versions in our public releases can differ slightly inline with
the EL8 support compatibility and ABI versioning policies for the support
lifecycle of the distribution.
The most important items are the Direct Dependencies and the availabilty
of a suitable graphics DSO as per your '-d' choice.
Direct Runtime Dependencies (from /prefix/**):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.14 | glibc-2.28-251 |
| libz.so.1 | ZLIB_1.2.2 | zlib-1.2.11-25 |
Optional/Modular Runtime Dependencies (depending on graphics mode):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libcairo.so.2 | | |
| libcairo.so.2.11512.0 | | cairo-1.15.12-6 |
| libGL.so.1 | | libglvnd-glx-1:1.3.4-2 |
| | | mesa-libGL-23.1.4-4 |
| libGLU.so.1 | | mesa-libGLU-9.0.0-15 |
Transitive/Third-Party Runtime Dependencies (for information only):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.35 | glibc-2.28-251 |
| libstdc++.so.6 | GLIBCXX_3.4 | gcc-c++-8.5.0 |
| libstdc++.so.6 | CXXABI_1.3.9 | gcc-c++-8.5.0 |
| libgcc_s.so.1 | GCC_4.2.0 | libgcc-8.5.0-26 |
| libxml2.so.2 | | libxml2-2.9.7-19 |
| libpng16.so.16 | PNG16_0 | libpng-2:1.6.34-5 |
| liblzma.so.5 | | xz-libs-5.2.4-4 |
| libz.so.1 | ZLIB_1.2.9 | zlib-1.2.11-25 |

59
appimage/9/Dockerfile Normal file
View File

@ -0,0 +1,59 @@
FROM almalinux:9
USER root
# Build Dependencies (and dump version to logging)
RUN dnf install -y python311 zlib-devel ncurses-devel readline-devel cairo-devel freeglut-devel \
mesa-libGLU-devel mesa-libGL-devel libX11-devel libstdc++-devel gcc gcc-c++ make git tcsh \
zip \
&& echo "### rpm -qa:" \
&& rpm -qa | sort \
&& echo ""
#RUN dnf group install -y "Development Tools"
# Tcl/Tk
WORKDIR /tcl
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl9.0.1-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix \
&& make \
&& make install install-libraries install-msgs install-tzdata
WORKDIR /tk
RUN curl -L https://prdownloads.sourceforge.net/tcl/tk9.0.1-src.tar.gz | tar --strip-components=1 -xzC . \
&& cd unix \
&& ./configure --prefix=/prefix --with-tcl=/prefix/lib \
&& make \
&& make install install-libraries
WORKDIR /prefix/bin
RUN cp ./wish9.0 ./wish
RUN cp ./tclsh9.0 ./tclsh
# Magic
WORKDIR /magic
COPY . .
RUN ./configure \
--prefix=/prefix \
--with-tcl=/prefix/lib \
--with-tk=/prefix/lib \
&& make clean \
&& make database/database.h \
&& make -j$(nproc) \
&& make install
# Produce summary of what was created and confirm their DSOs
RUN echo "### filesystem:" \
find /prefix -printf "%y/%M/%m %i/%n %l %u/%U %g/%G %s/%b %T+/%T@\t%p\n"; \
ls -lR /prefix; \
find /prefix -type f -perm /111 -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
for name in libgcc_s libstdc++ libpng liblzma libxml2 libz libcairo libGL libGLU; do \
find /lib64 /usr/lib64 -maxdepth 2 -name "*.so" -name "${name}*" -exec bash -c "echo \#\#\# {}; ldd -v {}" \; 2>/dev/null; \
done; \
echo "###"
WORKDIR /
RUN tar -czf /prefix.tar.gz -C ./prefix .
CMD ["/bin/bash"]

46
appimage/9/Makefile Normal file
View File

@ -0,0 +1,46 @@
MAGIC_SRC_ROOT = ../..
RESOURCES := $(shell find ../rsc/ -type f)
ARCH := $(shell uname -m)
APPIMAGE = Magic-$(ARCH).AppImage
VERSION_MAGIC := $(shell cat $(MAGIC_SRC_ROOT)/VERSION)
VERSION_TSTAMP := $(shell git show -s "--format=%cs" | tr -d '-')
VERSION_HASH := $(shell git show -s "--format=%h")
VERSION_NUM ?= $(VERSION_MAGIC)~$(VERSION_TSTAMP)~$(VERSION_HASH)
VERSION := $(VERSION_NUM)
# Allow CI to override
APPIMAGETOOL_DOWNLOAD_URL ?= https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
all: $(APPIMAGE)
.PHONY: prefix/bin/magic
prefix/bin/magic: Dockerfile Makefile
@echo "APPIMAGE=$(APPIMAGE)"
@echo "VERSION=$(VERSION)"
@echo "ARCH=$(ARCH)"
@echo "RESOURCES=$(RESOURCES)"
rm -rf prefix
docker build -t magic_build -f ./Dockerfile $(MAGIC_SRC_ROOT)
id=$$(docker create magic_build) ; \
docker cp $$id:/prefix ./prefix ; \
docker rm -v $$id
mkdir -p prefix/lib/tcl9.0.1
cp -r prefix/lib/tcl9.0 prefix/lib/tcl9.0.1/library
appimagetool:
curl -L "$(APPIMAGETOOL_DOWNLOAD_URL)" > ./appimagetool
chmod +x ./appimagetool
$(APPIMAGE): prefix/bin/magic appimagetool $(RESOURCES)
cp $(RESOURCES) ./prefix/
./appimagetool prefix
PREFIX ?= /usr/local
install:
install $(APPIMAGE) $(PREFIX)/bin/magic
.PHONY: clean
clean:
rm -f *.AppImage
rm -f prefix.tar.gz
rm -rf prefix

128
appimage/9/README.md Normal file
View File

@ -0,0 +1,128 @@
This is an AppImage that runs on all GNU/Linux platforms with:
* FUSE
* This excludes non-privileged Docker containers unfortunately, unless pre-extracted.
* GLIBC 2.34+
* Cairo 1.17+
* May require runtime CPU matching Linux ABI x86-64-v2 and newer (CPUs with SSE4.2/CX16 via `lscpu`).
This AppImage build is based on EL9 (via AlmaLinux 9)
AlmaLinux 9 was first released on 26 May 2022, full support ends 31 May 2027,
maintenance support ends 31 May 2032 (please see AlmaLinux bulletins for
up-to-date information).
# Version Info
See the AppImage main binary file naming, release tag information and AppInfo metadata
for the exact magic version inside the archive. When starting AppImage by default the
Tcl console banner can also provide version information, also using the `version` Tcl
command.
# Build Info
* Based on AlmaLinux 9 (EL9)
* Tcl/Tk 9.0.1
* and Magic 8.x
* all default modules enabled (including all Display drivers cairo/X11/OpenGL)
# FAQ: How to use
Download the *.AppImage file relevant to your platform and run:
```
chmod +x Magic-x86_64.AppImage
./Magic-x86_64.AppImage
```
Example startup with command line options:
```
./Magic-x86_64.AppImage -d XR -T scmos
```
# FAQ: How to use (inside docker / podman)
```
chmod +x Magic-x86_64.AppImage
### Podman or Docker, use :Z when rootless with selinux enabled
podman run --rm --device /dev/fuse --privileged \
-v "$(pwd):/tmp/work:Z" -v "/tmp/.X11-unix/X0:/tmp/.X11-unix/X0:Z" \
-e DISPLAY -ti almalinux:9
### Inside Docker:
dnf update -y
dnf install -y fuse libX11 cairo libGL libGLU
cd /tmp/work
./Magic-x86_64.AppImage -d XR -T scmos
```
# Building Requirements
* A reasonably recent GNU/Linux host
* GNU make
* Docker
* Git
* curl
The final build is then packaged into an AppImage using AppImageTool on the host machine.
# Build Instructions
`make`
# Installation Instructions
`make install`
# FAQ: Is my CPU supported ?
This is built with the standard x86_64 Linux ABI version for AlmaLinux 9.
Use the command `/lib64/ld-linux-x86-64.so.2 --help` to see which CPUs your
Linux distribtion supports (and your CPU) look for the word "supported".
# FAQ: The DSO versioning link dependencies?
The information here provides an outline of what versions to expect from EL9
of the major dependencies, to assist you in a compatibility check with your
Linux distribution of choice.
The actual versions in our public releases can differ slightly inline with
the EL9 support compatibility and ABI versioning policies for the support
lifecycle of the distribution.
The most important items are the Direct Dependencies and the availabilty
of a suitable graphics DSO as per your '-d' choice.
Direct Runtime Dependencies (from /prefix/**):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.34 | glibc-2.34-168 |
| libz.so.1 | ZLIB_1.2.2 | zlib-1.2.11-40 |
Optional/Modular Runtime Dependencies (depending on graphics mode):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libcairo.so.2 | | |
| libcairo.so.2.11704.0 | | cairo-1.17.4-7 |
| libGL.so.1 | | libglvnd-glx-1:1.3.4 |
| | | mesa-libGL-24.2.8-2 |
| libGLU.so.1 | | mesa-libGLU-9.0.1 |
Transitive/Third-Party Runtime Dependencies (for information only):
| DSO Filename | DSO Symbol Version | Related Packages |
| :--------------------- | :------------------ | :------------------- |
| libc.so.6 | GLIBC_2.35 | glibc-2.34-168 |
| libstdc++.so.6 | CXXABI_1.3.9 | gcc-c++-11.5.0-5 |
| libstdc++.so.6 | GLIBCXX_3.4 | gcc-c++-11.5.0-5 |
| libgcc_s.so.1 | GCC_4.2.0 | libgcc-11.5.0-2 |
| libxml2.so.2 | LIBXML2_2.6.0 | libxml2-2.9.13-9 |
| libpng16.so.16 | PNG16_0 | ibpng-2:1.6.37-12 |
| liblzma.so.5 | XZ_5.0 | xz-libs-5.2.5-8 |
| libz.so.1 | ZLIB_1.2.9 | zlib-1.2.11-40 |

View File

@ -1,33 +0,0 @@
RESOURCES = $(shell find rsc/ -type f)
ARCH = $(shell uname -m)
APPIMAGE = Magic-$(ARCH).AppImage
all: $(APPIMAGE)
.PHONY: prefix/bin/magic
prefix/bin/magic: Dockerfile Makefile
rm -rf prefix
docker build -t magic_build -f ./Dockerfile ..
id=$$(docker create magic_build) ; \
docker cp $$id:/prefix ./prefix ; \
docker rm -v $$id
mkdir -p prefix/lib/tcl8.6.12
cp -r prefix/lib/tcl8.6 prefix/lib/tcl8.6.12/library
appimagetool:
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage > ./appimagetool
chmod +x ./appimagetool
$(APPIMAGE): prefix/bin/magic appimagetool $(RESOURCES)
cp $(RESOURCES) ./prefix
./appimagetool prefix
PREFIX ?= /usr/local
install:
install $(APPIMAGE) $(PREFIX)/bin/magic
.PHONY: clean
clean:
rm -f *.AppImage
rm -f prefix.tar.gz
rm -rf prefix

View File

@ -1,24 +0,0 @@
This is an AppImage that runs on all GNU/Linux platforms with:
* FUSE
* This excludes non-privileged Docker containers unfortunately, unless pre-extracted.
* GLIBC 2.17+
* Cairo 1.8+
That's most Linux distributions released in 2016 or later.
# Build Info
A Dockerfile on CentOS 7 (needed for older glibc) image builds Tcl, Tk and Magic.
The final build is then packaged into an AppImage using AppImageTool on the host machine.
# Building Requirements
* A reasonably recent GNU/Linux host
* Docker 20+
* curl
# Build Instructions
`make`
# Installation Instructions
`make install`

View File

@ -1,7 +1,39 @@
#!/bin/sh
#!/usr/bin/env bash
export CURDIR=$(dirname $(readlink -f "${0}"))
export PATH="${CURDIR}/bin":$PATH
export LD_LIBRARY_PATH=${CURDIR}/lib:$LD_LIBRARY_PATH
export CAD_ROOT="${CURDIR}/lib"
export MAGIC_WISH="${CURDIR}/bin/wish"
exec "${CURDIR}/bin/magic" $@
function my_echo() {
if [ "$MAGIC_VERBOSE" != "0" ]
then
echo -- $@
fi
}
# Attempt to set by default a valid 'ulimit -n' based on TCL version this
# will automatically apply valid limit inside docker running processes.
if [ "X${MAGIC_ULIMIT_NOFILE:+set}" = "X" ] # not set to something
then
if $MAGIC_WISH "${CURDIR}/version_check.tcl" | grep -q "=8\." # only needed for tcl8
then
if [ $(ulimit -Sn) -gt 1024 ] # only reduce >1024 to 1024
then
MAGIC_ULIMIT_NOFILE=1024
my_echo "# ulimit -Sn reduced from $(ulimit -Sn) to $MAGIC_ULIMIT_NOFILE"
fi
fi
fi
if [ "X$MAGIC_ULIMIT_NOFILE" != "X" ] # non empty
then
# Inform user we did this and hint at how to customize
my_echo "ulimit -Sn $MAGIC_ULIMIT_NOFILE # use \$MAGIC_ULIMIT_NOFILE to customize"
ulimit -Sn $MAGIC_ULIMIT_NOFILE
fi
my_echo "# Starting Magic"
exec "${CURDIR}/bin/magic" "$@"

View File

@ -0,0 +1,4 @@
# Usage: wish version_check.tcl
puts "tcl_version=$tcl_version"
puts "tk_version=$tk_version"
exit 0

View File

@ -93,7 +93,7 @@ static BinArray *bpBinArrayNew(int dx, /* x diameter of bins */
/* allocate array */
size = sizeof(BinArray) + numBins*(sizeof(void *));
new = (BinArray *)callocMagic(size);
new = (BinArray *)callocMagic(1, size);
/* initial */
new->ba_bbox = *bbox;

View File

@ -78,6 +78,7 @@ void bpDumpRect(Rect *r)
fprintf(stderr,"%d",
r->r_ytop);
}
#ifdef CIF_MODULE
else
{
float oscale;
@ -93,6 +94,7 @@ void bpDumpRect(Rect *r)
fprintf(stderr,"%f",
oscale * (float)r->r_ytop);
}
#endif
}
/*
@ -170,6 +172,7 @@ static void bpBinArrayDump(BinArray *ba, int indent)
fprintf(stderr,"{dx %d} {dy %d} ",
dx,dy);
}
#ifdef CIF_MODULE
else
{
float oscale;
@ -182,6 +185,7 @@ static void bpBinArrayDump(BinArray *ba, int indent)
fprintf(stderr,"{dy %f} ",
(float)dy * oscale);
}
#endif
fprintf(stderr,"{dimX %d} {dimY %d} { bbox ",
dimX,
dimY);

View File

@ -25,8 +25,8 @@
//
// ************************************************************************
#ifndef _BPENUM_H
#define _BPENUM_H
#ifndef _MAGIC__BPLANE__BPENUM_H
#define _MAGIC__BPLANE__BPENUM_H
/* bpEnum.h --
*
@ -534,4 +534,4 @@ static __inline__ void *BPEnumNext(BPEnum *bpe)
}
}
#endif /* _BPENUM_H */
#endif /* _MAGIC__BPLANE__BPENUM_H */

View File

@ -27,12 +27,12 @@
#ifndef _BPOPAQUE_H
#define _BPOPAQUE_H
#ifndef _MAGIC__BPLANE__BPOPAQUE_H
#define _MAGIC__BPLANE__BPOPAQUE_H
#ifndef _IHASH_H
#ifndef _MAGIC__UTILS__IHASH_H
#include "utils/ihash.h"
#endif /* _IHASH_H */
#endif
/*
* bpOpaque.h --
@ -192,4 +192,4 @@ typedef struct bpenum
BPStack bpe_stack[10000]; /* stack for tree traversal during enum */
} BPEnum;
#endif /* _BPOPAQUE_H */
#endif /* _MAGIC__BPLANE__BPOPAQUE_H */

View File

@ -27,8 +27,8 @@
#ifndef _BPLANE_H
#define _BPLANE_H
#ifndef _MAGIC__BPLANE__BPLANE_H
#define _MAGIC__BPLANE__BPLANE_H
/*
* bplane.h --
@ -232,4 +232,4 @@ BPStat(BPlane *bp,
int *totUnbinned, /* ret tot num of e's not binned */
int *maxDepth); /* ret max bin array depth */
#endif /* _BPLANE_H */
#endif /* _MAGIC__BPLANE__BPLANE_H */

View File

@ -33,8 +33,8 @@
* This file defines constants and datastructures used internally by the
* bplane module, but not exported to the rest of the world.
*/
#ifndef _BPLANEINT_H
#define _BPLANEINT_H
#ifndef _MAGIC__BPLANE__BPLANEINT_H
#define _MAGIC__BPLANE__BPLANEINT_H
/* Tcl linked Parameters */
extern int bpMinBAPop; /* don't sub(bin) when count less than this
@ -79,4 +79,4 @@ extern Plane *bpTestSnowTile(int size, bool trace);
extern int bpRand(int min, int max);
#endif /* _BPLANEINT_H */
#endif /* _MAGIC__BPLANE__BPLANEINT_H */

View File

@ -245,7 +245,9 @@ calmaExact(void)
int pNum;
Plane *newplane;
Plane **parray;
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
/* Forward reference */
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
@ -387,6 +389,15 @@ calmaParseStructure(
he = HashFind(&calmaDefInitHash, strname);
if ((def = (CellDef *)HashGetValue(he)) != NULL)
{
if (def->cd_flags & CDPRELOADED)
{
/* Cell definition was read ahead due to option "flatten" */
/* or "flatglob". Do not complain about seeing it again. */
def->cd_flags &= ~CDPRELOADED;
calmaNextCell();
return TRUE;
}
if (def->cd_flags & CDPROCESSEDGDS)
{
/* If cell definition was marked as processed, then skip */
@ -396,6 +407,7 @@ calmaParseStructure(
if (!CalmaPostOrder && !CalmaRewound)
{
cifReadCellDef = def;
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
strname);
CalmaReadError("Ignoring duplicate definition\n");
@ -407,6 +419,7 @@ calmaParseStructure(
{
char *newname;
cifReadCellDef = def;
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
strname);
newname = (char *)mallocMagic(strlen(strname) + 20);
@ -740,6 +753,7 @@ calmaParseElement(
int
calmaEnumFunc(
Tile *tile,
TileType dinfo,
int *plane)
{
return 1;
@ -773,16 +787,18 @@ calmaElementSref(
bool madeinst = FALSE;
char *sname = NULL;
bool isArray = FALSE;
bool dolookahead = FALSE;
Transform trans, tinv;
Point refarray[3], refunscaled[3], p;
CellUse *use;
CellDef *def;
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
int gdsHasUses(CellUse *use, ClientData clientdata); /* Forward reference */
/* Added by NP */
char *useid = NULL, *arraystr = NULL;
int propAttrType;
/* Forward reference */
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
int gdsHasUses(CellUse *use, ClientData clientdata);
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -798,7 +814,38 @@ calmaElementSref(
*/
def = calmaLookCell(sname);
if (!def && (CalmaPostOrder || CalmaFlattenUses || (CalmaFlattenUsesByName != NULL)))
/*
* If the "flatten" option is set, then we always have to seek
* ahead and read the structure in order to determine if it
* meets the requirement of being flattened or not. If the
* "flatglob" option is set, then we need to read ahead and
* read the cell definition so that it can be flatten. This
* requires pattern-matching the cell def.
*/
dolookahead = (CalmaPostOrder || CalmaFlattenUses) ? TRUE : FALSE;
if ((!dolookahead) && (CalmaFlattenUsesByName != NULL))
{
char *pattern;
i = 0;
while (TRUE)
{
pattern = CalmaFlattenUsesByName[i];
if (pattern == NULL) break;
i++;
/* Check pattern against strname */
if (Match(pattern, sname))
{
dolookahead = TRUE;
break;
}
}
}
if (!def && dolookahead)
{
/* Force the GDS parser to read the cell definition in
* post-order. If cellname "sname" is not defined before
@ -832,6 +879,7 @@ calmaElementSref(
FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
cifReadCellDef = calmaLookCell(currentSname);
def = calmaLookCell(sname);
def->cd_flags |= CDPRELOADED;
cifCurReadPlanes = savePlanes;
calmaLayerHash = OrigCalmaLayerHash;
if (crsMultiplier != cifCurReadStyle->crs_multiplier)
@ -1245,27 +1293,28 @@ gdsHasUses(
int
gdsCopyPaintFunc(
Tile *tile,
TileType dinfo,
GDSCopyRec *gdsCopyRec)
{
int pNum;
TileType dinfo;
TileType newdinfo;
Rect sourceRect, targetRect;
Transform *trans = gdsCopyRec->trans;
Plane *plane = gdsCopyRec->plane;
dinfo = TiGetTypeExact(tile);
newdinfo = TiGetTypeExact(tile) | dinfo;
if (trans)
{
TiToRect(tile, &sourceRect);
GeoTransRect(trans, &sourceRect, &targetRect);
if (IsSplit(tile))
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
}
else
TiToRect(tile, &targetRect);
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
(PaintUndoInfo *)NULL);
return 0;
@ -1384,13 +1433,18 @@ calmaFindCell(
}
else
{
TxPrintf("Warning: cell %s already existed before reading GDS!\n",
name);
if (CalmaNoDuplicates)
{
TxPrintf("Note: cell %s already existed before reading GDS.\n",
name);
if (predefined) *predefined = TRUE;
TxPrintf("Using pre-existing cell definition\n");
}
else
{
TxPrintf("Warning: cell %s already existed before reading GDS!\n",
name);
}
if (was_called) *was_called = TRUE;
}
HashSetValue(h, def);

View File

@ -58,7 +58,7 @@ extern int CalmaPathCount;
extern HashTable calmaDefInitHash;
extern void calmaLayerError(char *mesg, int layer, int dt);
bool calmaReadPath(CIFPath **pathheadpp, int iscale);
CIFPath *calmaReadPath(int iscale);
/*
* ----------------------------------------------------------------------------
@ -213,7 +213,7 @@ calmaElementBoundary(void)
LinkedRect *rp;
Plane *plane;
CellUse *use;
CellDef *savedef, *newdef = NULL;
CellDef *savedef = NULL, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -237,7 +237,8 @@ calmaElementBoundary(void)
plane = cifCurReadPlanes[ciftype];
/* Read the path itself, building up a path structure */
if (!calmaReadPath(&pathheadp, (plane == NULL) ? 0 : 1))
pathheadp = calmaReadPath((plane == NULL) ? 0 : 1);
if (pathheadp == NULL)
{
if (plane != NULL)
CalmaReadError("Error while reading path for boundary/box; ignored.\n");
@ -257,7 +258,7 @@ calmaElementBoundary(void)
if ((CalmaSubcellPolygons != CALMA_POLYGON_NONE) && (calmaNonManhattan > 0))
{
/* Place the polygon in its own subcell */
char newname[16];
char newname[20];
HashEntry *he;
savedef = cifReadCellDef;
@ -359,12 +360,14 @@ calmaElementBoundary(void)
}
/* Paint the rectangles (if any) */
free_magic1_t mm1 = freeMagic1_init();
for (; rp != NULL ; rp = rp->r_next)
{
if (plane)
DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL);
freeMagic((char *) rp);
freeMagic1(&mm1, (char *) rp);
}
freeMagic1_end(&mm1);
if (cifCurReadPlanes == cifEditCellPlanes)
{
@ -512,7 +515,7 @@ calmaElementPath(void)
Plane *plane;
int first,last;
CellUse *use;
CellDef *savedef, *newdef = NULL;
CellDef *savedef = NULL, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -595,7 +598,8 @@ calmaElementPath(void)
/* Read the points in the path */
savescale = calmaReadScale1;
if (!calmaReadPath(&pathheadp, 2))
pathheadp = calmaReadPath(2);
if (pathheadp == NULL)
{
CalmaReadError("Improper path; ignored.\n");
return;
@ -1098,26 +1102,24 @@ calmaElementText(void)
* centerline, to avoid roundoff errors.
*
* Results:
* TRUE is returned if the path was parsed successfully,
* FALSE otherwise.
* non-NULL CIFPath* the caller takes ownership of
* if the path was parsed successfully, otherwise NULL.
*
* Side effects:
* Modifies the parameter pathheadpp to point to the path
* that is constructed.
* None
*
* ----------------------------------------------------------------------------
*/
bool
CIFPath *
calmaReadPath(
CIFPath **pathheadpp,
int iscale)
{
CIFPath path, *pathtailp, *newpathp;
CIFPath path, *pathheadp, *pathtailp, *newpathp;
int nbytes, rtype, npoints, savescale;
bool nonManhattan = FALSE;
*pathheadpp = (CIFPath *) NULL;
pathheadp = (CIFPath *) NULL;
pathtailp = (CIFPath *) NULL;
path.cifp_next = (CIFPath *) NULL;
@ -1126,12 +1128,12 @@ calmaReadPath(
if (nbytes < 0)
{
CalmaReadError("EOF when reading path.\n");
return (FALSE);
return (NULL);
}
if (rtype != CALMA_XY)
{
calmaUnexpected(CALMA_XY, rtype);
return (FALSE);
return (NULL);
}
/* Read this many points (pairs of four-byte integers) */
@ -1142,7 +1144,7 @@ calmaReadPath(
calmaReadPoint(&path.cifp_point, iscale);
if (savescale != calmaReadScale1)
{
CIFPath *phead = *pathheadpp;
CIFPath *phead = pathheadp;
int newscale = calmaReadScale1 / savescale;
while (phead != NULL)
{
@ -1157,8 +1159,8 @@ calmaReadPath(
}
if (FEOF(calmaInputFile))
{
CIFFreePath(*pathheadpp);
return (FALSE);
CIFFreePath(pathheadp);
return (NULL);
}
if (iscale != 0)
@ -1166,7 +1168,7 @@ calmaReadPath(
newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath)));
*newpathp = path;
if (*pathheadpp)
if (pathheadp)
{
/*
* Check that this segment is Manhattan. If not, remember the
@ -1187,11 +1189,11 @@ calmaReadPath(
}
pathtailp->cifp_next = newpathp;
}
else *pathheadpp = newpathp;
else pathheadp = newpathp;
pathtailp = newpathp;
}
}
return (*pathheadpp != NULL);
return (pathheadp);
}
/*

View File

@ -613,20 +613,23 @@ CalmaTechInit(void)
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
/* NOTE: Enable the code below when CalmaContactArrays */
/* behaves like the non-arrayed function and can be enabled */
/* by default. */
#if 0
/* NOTE: Add "$$*$$" to the default "flatglob" value */
/* when CalmaContactArrays behaves like the non-arrayed */
/* function and can be enabled by default. */
/* Initialize CalmaFlattenByName to have one entry for */
/* "$$*$$" to match the name style used by the contact */
/* array cell generation. This can be overridden by the */
/* "gds flatglob none" command option. */
/* "*_CDNS_*" to match the name style used by many foundry */
/* cells and which corresponds to pcells that often split */
/* layers between cells in ways that magic can't cope with; */
/* and whose original parameterized functions cannot be */
/* recovered by magic anyway. When necessary, this default */
/* can be overridden by the "gds flatglob none" command */
/* option. */
if (CalmaFlattenUsesByName == (char **)NULL)
{
CalmaFlattenUsesByName = (char **)mallocMagic(2 * sizeof(char *));
*CalmaFlattenUsesByName = StrDup((char **)NULL, "$$*$$");
*CalmaFlattenUsesByName = StrDup((char **)NULL, "*_CDNS_*");
*(CalmaFlattenUsesByName + 1) = NULL;
}
#endif
}

View File

@ -28,9 +28,15 @@ static const char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic
#include <ctype.h>
#include <sys/types.h>
#include <arpa/inet.h> /* for htons() */
#include <time.h> /* since C89 */
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include "utils/magic.h"
@ -38,6 +44,7 @@ static const char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/utils.h"
#include "utils/magic_zlib.h"
#include "utils/hash.h"
#include "database/database.h"
#include "database/databaseInt.h"
@ -90,10 +97,10 @@ typedef struct {
/* Forward declarations */
extern int calmaWriteInitFunc(CellDef *def);
extern int calmaWritePaintFunc(Tile *tile, calmaOutputStruct *cos);
extern int calmaMergePaintFunc(Tile *tile, calmaOutputStruct *cos);
extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
extern int calmaMergePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
extern int calmaPaintLabelFunc(Tile *tile, calmaOutputStruct *cos);
extern int calmaPaintLabelFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
extern void calmaWriteContacts(FILE *f);
extern void calmaDelContacts(void);
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
@ -1393,8 +1400,10 @@ calmaOutFunc(
{
pllist[i].pl_label = ll->ll_label;
pllist[i].pl_port = (unsigned int)ll->ll_attr;
freeMagic(ll);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, ll);
ll = ll->ll_next;
freeMagic1_end(&mm1);
i++;
}
@ -2415,19 +2424,27 @@ calmaProcessBoundary(
/* Free the LinkedBoundary list */
lbref = listtop;
while (lbref->lb_next != listtop)
{
freeMagic(lbref);
lbref = lbref->lb_next;
free_magic1_t mm1 = freeMagic1_init();
lbref = listtop;
while (lbref->lb_next != listtop)
{
freeMagic1(&mm1, lbref);
lbref = lbref->lb_next;
}
freeMagic1(&mm1, lbref);
freeMagic1_end(&mm1);
}
freeMagic(lbref);
}
/* Free the BoundaryTop list */
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
freeMagic(bounds);
{
free_magic1_t mm1 = freeMagic1_init();
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
freeMagic1(&mm1, bounds);
freeMagic1_end(&mm1);
}
}
/*
@ -2447,6 +2464,7 @@ calmaProcessBoundary(
int
calmaMergePaintFunc(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information (unused) */
calmaOutputStruct *cos) /* Information needed by algorithm */
{
FILE *f = cos->f;
@ -2477,11 +2495,10 @@ calmaMergePaintFunc(
split_type = -1;
if (IsSplit(t))
{
/* If we use SplitSide, then we need to set it when the */
/* If we use TT_SIDE, then we need to set it when the */
/* tile is pushed. Since these are one-or-zero mask layers */
/* I assume it is okay to just check which side is TT_SPACE */
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
split_type = SplitDirection(t);
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
num_points = 2;
@ -2493,8 +2510,10 @@ calmaMergePaintFunc(
lb = edge;
while (lb->lb_next != edge) lb = lb->lb_next;
lb->lb_next = edge->lb_next;
freeMagic(edge);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, edge);
edge = edge->lb_next;
freeMagic1_end(&mm1);
}
}
else
@ -2702,7 +2721,9 @@ right_search:
done_searches:
if (intedges == 0)
{
calmaWritePaintFunc(t, cos);
calmaWritePaintFunc(t,
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
cos);
/* Although calmaWritePaintFunc is called only on isolated */
/* tiles, we may have expanded it. This could use a LOT of */
@ -2713,11 +2734,13 @@ done_searches:
if (num_points != 4)
{
free_magic1_t mm1 = freeMagic1_init();
for (i = 0; i < num_points; i++)
{
freeMagic(edge);
freeMagic1(&mm1, edge);
edge = edge->lb_next;
}
freeMagic1_end(&mm1);
edge = NULL;
}
if (!StackEmpty(SegStack))
@ -2770,6 +2793,7 @@ done_searches:
int
calmaWritePaintFunc(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information */
calmaOutputStruct *cos) /* File for output and clipping area */
{
FILE *f = cos->f;
@ -2805,7 +2829,7 @@ calmaWritePaintFunc(
/* Coordinates */
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
{
case 0x0:
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
@ -3046,6 +3070,7 @@ calmaWriteLabelFunc(
int
calmaPaintLabelFunc(
Tile *tile, /* Tile contains area for label. */
TileType dinfo, /* Split tile information (unused) */
calmaOutputStruct *cos) /* File for output and clipping area */
{
FILE *f = cos->f;

View File

@ -38,10 +38,15 @@ static const char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic
#include <ctype.h>
#include <sys/types.h>
#include <arpa/inet.h> /* for htons() */
#if defined(SYSV) || defined(EMSCRIPTEN)
#include <time.h>
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
#include <sys/time.h>
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#include "utils/magic.h"
@ -49,6 +54,7 @@ static const char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/utils.h"
#include "utils/magic_zlib.h"
#include "utils/hash.h"
#include "database/database.h"
#include "database/databaseInt.h"
@ -101,10 +107,10 @@ typedef struct {
} calmaOutputStructZ;
/* Forward declarations */
extern int calmaWritePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
extern int calmaMergePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
extern int calmaWritePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
extern int calmaMergePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
extern int calmaPaintLabelFuncZ(Tile *tile, calmaOutputStructZ *cos);
extern int calmaPaintLabelFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
extern void calmaWriteContactsZ(gzFile f);
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
@ -1318,8 +1324,10 @@ calmaOutFuncZ(
{
pllist[i].pl_label = ll->ll_label;
pllist[i].pl_port = (unsigned int)ll->ll_attr;
freeMagic(ll);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, ll);
ll = ll->ll_next;
freeMagic1_end(&mm1);
i++;
}
@ -1851,19 +1859,27 @@ calmaProcessBoundaryZ(
/* Free the LinkedBoundary list */
lbref = listtop;
while (lbref->lb_next != listtop)
{
freeMagic(lbref);
lbref = lbref->lb_next;
free_magic1_t mm1 = freeMagic1_init();
lbref = listtop;
while (lbref->lb_next != listtop)
{
freeMagic1(&mm1, lbref);
lbref = lbref->lb_next;
}
freeMagic1(&mm1, lbref);
freeMagic1_end(&mm1);
}
freeMagic(lbref);
}
/* Free the BoundaryTop list */
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
freeMagic(bounds);
{
free_magic1_t mm1 = freeMagic1_init();
for (bounds = blist; bounds != NULL; bounds = bounds->bt_next)
freeMagic1(&mm1, bounds);
freeMagic1_end(&mm1);
}
}
/*
@ -1883,6 +1899,7 @@ calmaProcessBoundaryZ(
int
calmaMergePaintFuncZ(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information (unused) */
calmaOutputStructZ *cos) /* Information needed by algorithm */
{
gzFile f = cos->f;
@ -1913,11 +1930,10 @@ calmaMergePaintFuncZ(
split_type = -1;
if (IsSplit(t))
{
/* If we use SplitSide, then we need to set it when the */
/* If we use TT_SIDE, then we need to set it when the */
/* tile is pushed. Since these are one-or-zero mask layers */
/* I assume it is okay to just check which side is TT_SPACE */
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
split_type = SplitDirection(t);
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
num_points = 2;
@ -1929,8 +1945,10 @@ calmaMergePaintFuncZ(
lb = edge;
while (lb->lb_next != edge) lb = lb->lb_next;
lb->lb_next = edge->lb_next;
freeMagic(edge);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, edge);
edge = edge->lb_next;
freeMagic1_end(&mm1);
}
}
else
@ -2138,7 +2156,9 @@ right_search:
done_searches:
if (intedges == 0)
{
calmaWritePaintFuncZ(t, cos);
calmaWritePaintFuncZ(t,
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
cos);
/* Although calmaWritePaintFunc is called only on isolated */
/* tiles, we may have expanded it. This could use a LOT of */
@ -2149,11 +2169,13 @@ done_searches:
if (num_points != 4)
{
free_magic1_t mm1 = freeMagic1_init();
for (i = 0; i < num_points; i++)
{
freeMagic(edge);
freeMagic1(&mm1, edge);
edge = edge->lb_next;
}
freeMagic1_end(&mm1);
edge = NULL;
}
if (!StackEmpty(SegStack))
@ -2206,6 +2228,7 @@ done_searches:
int
calmaWritePaintFuncZ(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information */
calmaOutputStructZ *cos) /* File for output and clipping area */
{
gzFile f = cos->f;
@ -2241,7 +2264,7 @@ calmaWritePaintFuncZ(
/* Coordinates */
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
{
case 0x0:
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
@ -2482,6 +2505,7 @@ calmaWriteLabelFuncZ(
int
calmaPaintLabelFuncZ(
Tile *tile, /* Tile contains area for label. */
TileType dinfo, /* Split tile information (unused) */
calmaOutputStructZ *cos) /* File for output and clipping area */
{
gzFile f = cos->f;

View File

@ -19,8 +19,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/calma/calma.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
*/
#ifndef _CALMA_H
#define _CALMA_H
#ifndef _MAGIC__CALMA__CALMA_H
#define _MAGIC__CALMA__CALMA_H
#include "utils/magic.h"
@ -97,4 +97,4 @@ extern bool CalmaWriteZ(CellDef *rootDef, gzFile f);
extern bool CalmaGenerateArrayZ(gzFile f, TileType type, int llx, int lly, int pitch, int cols, int rows);
#endif
#endif /* _CALMA_H */
#endif /* _MAGIC__CALMA__CALMA_H */

View File

@ -19,8 +19,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/calma/calmaInt.h,v 1.2 2010/06/24 12:37:15 tim Exp $
*/
#ifndef _CALMAINT_H
#define _CALMAINT_H
#ifndef _MAGIC__CALMA__CALMAINT_H
#define _MAGIC__CALMA__CALMAINT_H
#include "utils/magic.h"
#include "database/database.h"
@ -274,4 +274,4 @@ extern Plane **cifCurReadPlanes;
extern HashTable CifCellTable;
extern Plane *cifEditCellPlanes[];
#endif /* _CALMAINT_H */
#endif /* _MAGIC__CALMA__CALMAINT_H */

File diff suppressed because it is too large Load Diff

View File

@ -433,15 +433,16 @@ cifHierCopyMaskHints(
int
cifHierCopyFunc(
Tile *tile, /* Pointer to tile to copy. */
TileType dinfo, /* Split tile information */
TreeContext *cxp) /* Describes context of search, including
* transform and client data.
*/
{
TileType type = TiGetTypeExact(tile);
TileType type = TiGetTypeExact(tile) | dinfo;
Rect sourceRect, targetRect;
int pNum;
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
int dinfo = 0;
TileType newdinfo = 0;
/* Ignore tiles in vendor GDS, unless this is specifically */
/* overridden by the "see-vendor" option. */
@ -457,8 +458,8 @@ cifHierCopyFunc(
if (IsSplit(tile))
{
dinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
type = (SplitSide(tile)) ? SplitRightType(tile) :
newdinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
SplitLeftType(tile);
}
@ -473,7 +474,7 @@ cifHierCopyFunc(
{
if (DBPaintOnPlane(type, pNum))
{
DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect,
DBNMPaintPlane(def->cd_planes[pNum], newdinfo, &targetRect,
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
}
}
@ -562,9 +563,11 @@ cifHierCellFunc(
int
cifHierErrorFunc(
Tile *tile, /* Tile that covers area it shouldn't. */
TileType dinfo, /* Split tile information */
Rect *checkArea) /* Intersection of this and tile is error. */
{
Rect area;
bool side = (dinfo & TT_SIDE) ? TRUE : FALSE;
TiToRect(tile, &area);
@ -572,8 +575,8 @@ cifHierErrorFunc(
* space bounds the checkArea.
*/
if (IsSplit(tile))
if (((area.r_xbot == checkArea->r_xbot) && !SplitSide(tile)) ||
((area.r_xtop == checkArea->r_xtop) && SplitSide(tile)))
if (((area.r_xbot == checkArea->r_xbot) && !side) ||
((area.r_xtop == checkArea->r_xtop) && side))
return 0;
GeoClip(&area, checkArea);
@ -604,6 +607,7 @@ cifHierErrorFunc(
int
cifHierCheckFunc(
Tile *tile, /* Tile containing CIF. */
TileType dinfo, /* Split tile information */
Plane *plane) /* Plane to check against and modify. */
{
Rect area;
@ -612,10 +616,10 @@ cifHierCheckFunc(
if (IsSplit(tile))
{
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile),
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile) | dinfo,
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
(PaintUndoInfo *) NULL);
}
else
@ -651,6 +655,7 @@ cifHierCheckFunc(
int
cifHierTempCheckFunc(
Tile *tile, /* Tile containing CIF. */
TileType dinfo, /* Information about split tiles */
Plane *plane) /* Plane to check against and modify. */
{
Rect area;
@ -658,7 +663,7 @@ cifHierTempCheckFunc(
TiToRect(tile, &area);
if (IsSplit(tile))
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
(PaintUndoInfo *) NULL);
else
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
@ -686,6 +691,7 @@ cifHierTempCheckFunc(
int
cifHierPaintFunc(
Tile *tile,
TileType dinfo, /* Information about split tiles */
Plane *plane) /* Plane in which to paint CIF over tile's
* area.
*/
@ -693,9 +699,9 @@ cifHierPaintFunc(
Rect area;
TiToRect(tile, &area);
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
if (IsSplit(tile))
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFPaintTable,
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFPaintTable,
(PaintUndoInfo *) NULL);
else
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
@ -1067,6 +1073,7 @@ cifHierElementFunc(
int
cifGrowSliver(
Tile *tile,
TileType dinfo, /* Split tile information, needs to be handled */
Rect *area)
{
int height, width, expand_up, expand_side;
@ -1127,22 +1134,24 @@ cifGrowSliver(
int
cifHierPaintArrayFunc(
Tile *tile)
Tile *tile,
TileType dinfo,
ClientData clientdata) /* (unused) */
{
Rect area;
int i, j, xbot, xtop;
TiToRect(tile, &area);
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
xbot = area.r_xbot;
xtop = area.r_xtop;
for (i=0; i<cifHierYCount; i++)
{
for (j=0; j<cifHierXCount; j++)
for (j = 0; j < cifHierXCount; j++)
{
DBPaintPlane(cifHierCurPlane, &area, CIFPaintTable,
(PaintUndoInfo *) NULL);
CIFTileOps += 1;
DBNMPaintPlane(cifHierCurPlane, TiGetTypeExact(tile) | dinfo,
&area, CIFPaintTable, (PaintUndoInfo *) NULL);
CIFTileOps++;
area.r_xbot += cifHierXSpacing;
area.r_xtop += cifHierXSpacing;
}

View File

@ -19,8 +19,8 @@
* rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFint.h,v 1.3 2008/12/04 17:10:29 tim Exp $"
*/
#ifndef _CIFINT_H
#define _CIFINT_H
#ifndef _MAGIC__CIF__CIFINT_H
#define _MAGIC__CIF__CIFINT_H
#include "database/database.h"
@ -335,7 +335,7 @@ extern void CIFClearPlanes(Plane **planes);
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
bool hier, ClientData clientdata);
extern void CIFInitCells(void);
extern int cifHierCopyFunc(Tile *tile, TreeContext *cxp);
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
extern void CIFLoadStyle(char *stylename);
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
@ -346,7 +346,7 @@ extern bool CIFWriteFlat(CellDef *rootDef, FILE *f);
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
extern void CIFInputRescale(int n, int d);
extern int CIFScaleCoord(int cifCoord, int snap_type);
extern int cifGrowSliver(Tile *tile, Rect *area);
extern int cifGrowSliver(Tile *tile, TileType dinfo, Rect *area);
extern int cifHierElementFunc(CellUse *use, Transform *transform, int x, int y, Rect *checkArea);
extern int cifSquareFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
extern int cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
@ -367,6 +367,9 @@ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
* def.
*/
extern Plane *CIFTotalPlanes[]; /* Exported for diagnostics */
extern Plane *CIFComponentPlanes[]; /* Exported for diagnostics */
/* Valid values of CIFWarningLevel (see cif.h) */
typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN,
@ -396,4 +399,4 @@ extern void CIFError(Rect *area, char *message);
#define CIF_SOLIDTYPE 1
extern TileTypeBitMask CIFSolidBits;
#endif /* _CIFINT_H */
#endif /* _MAGIC__CIF__CIFINT_H */

View File

@ -505,6 +505,7 @@ CIFParseStart(void)
int cifCheckPaintFunc(
Tile *tile,
TileType dinfo,
ClientData clientData)
{
return 1;
@ -515,27 +516,28 @@ int cifCheckPaintFunc(
int
cifCopyPaintFunc(
Tile *tile,
TileType dinfo,
CIFCopyRec *cifCopyRec)
{
int pNum;
TileType dinfo;
TileType newdinfo;
Rect sourceRect, targetRect;
Transform *trans = cifCopyRec->trans;
Plane *plane = cifCopyRec->plane;
dinfo = TiGetTypeExact(tile);
newdinfo = TiGetTypeExact(tile) | dinfo;
if (trans)
{
TiToRect(tile, &sourceRect);
GeoTransRect(trans, &sourceRect, &targetRect);
if (IsSplit(tile))
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
}
else
TiToRect(tile, &targetRect);
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
(PaintUndoInfo *)NULL);
return 0;
@ -561,6 +563,7 @@ cifCopyPaintFunc(
int
cifMaskHintFunc(
Tile *tile,
TileType dinfo, /* Unused, do not support non-manhattan hints */
LinkedRect **lrecp)
{
Rect r;
@ -597,8 +600,9 @@ int
CIFPaintCurrent(
int filetype)
{
extern int cifMakeBoundaryFunc(Tile *tile, ClientData clientdata); /* Forward declaration. */
extern int cifPaintCurrentFunc(Tile *tile, TileType type); /* Forward declaration. */
/* Forward declarations. */
extern int cifMakeBoundaryFunc(Tile *tile, TileType dinfo, ClientData clientdata);
extern int cifPaintCurrentFunc(Tile *tile, TileType dinfo, TileType type);
Plane *plane, *swapplane;
int i;
@ -851,9 +855,11 @@ CIFPaintCurrent(
freeMagic(propstr);
}
propstr = newstr;
freeMagic(lrec);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
}
freeMagic1_end(&mm1);
}
/* NOTE: propstr is transferred to the CellDef and should
* not be free'd here.
*/
@ -889,6 +895,7 @@ CIFPaintCurrent(
int
cifMakeBoundaryFunc(
Tile *tile, /* Tile of CIF information. */
TileType dinfo, /* Split tile information (unused) */
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
{
/* It is assumed that there is one rectangle for the boundary. */
@ -968,6 +975,7 @@ cifMakeBoundaryFunc(
int
cifPaintCurrentFunc(
Tile *tile, /* Tile of CIF information. */
TileType dinfo, /* Split tile information */
TileType type) /* Magic type to be painted. */
{
Rect area;
@ -1017,7 +1025,7 @@ cifPaintCurrentFunc(
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (DBPaintOnPlane(type, pNum))
{
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
}

View File

@ -338,18 +338,20 @@ CIFPaintWirePath(
pathp = pathheadp->cifp_next;
if (pathp != NULL)
{
free_magic1_t mm1 = freeMagic1_init();
while (pathp->cifp_next != NULL)
{
if (pathp->cifp_next->cifp_x == pathp->cifp_x &&
pathp->cifp_next->cifp_y == pathp->cifp_y)
{
previousp->cifp_next = pathp->cifp_next;
freeMagic(pathp);
freeMagic1(&mm1, pathp);
}
else
previousp = pathp;
pathp = pathp->cifp_next;
}
freeMagic1_end(&mm1);
}
previousp = pathheadp;
@ -439,7 +441,8 @@ CIFPaintWirePath(
/* Wire reverses direction. Break wire here, */
/* draw, and start new polygon. */
TxError("Warning: direction reversal in path.\n");
TxError("Warning: direction reversal in path at (%d, %d).\n",
pathp->cifp_x, pathp->cifp_y);
phi = theta;
if (endcap)
@ -451,7 +454,8 @@ CIFPaintWirePath(
firstpoint = TRUE;
}
else {
TxError("Error: mitre limit exceeded at wire junction.\n");
TxError("Error: mitre limit exceeded at wire junction at (%d, %d).\n",
pathp->cifp_x, pathp->cifp_y);
TxError("Route has been truncated.\n");
break;
}
@ -484,11 +488,13 @@ CIFPaintWirePath(
rectp = CIFPolyToRects(polypath, plane, ptable, ui, FALSE);
CIFFreePath(polypath);
free_magic1_t mm1 = freeMagic1_init();
for (; rectp != NULL ; rectp = rectp->r_next)
{
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
freeMagic((char *) rectp);
freeMagic1(&mm1, (char *) rectp);
}
freeMagic1_end(&mm1);
polypath = NULL;
}
else
@ -586,11 +592,13 @@ PaintPolygon(
rectlist = CIFPolyToRects(cifpath, plane, ptable, ui, FALSE);
CIFFreePath(cifpath);
free_magic1_t mm1 = freeMagic1_init();
for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next)
{
DBPaintPlane(plane, &rectp->r_r, ptable, ui);
if (!keep) freeMagic((char *) rectp);
if (!keep) freeMagic1(&mm1, (char *) rectp);
}
freeMagic1_end(&mm1);
return (keep) ? rectlist : (LinkedRect *)NULL;
}
@ -687,7 +695,8 @@ CIFParseWire(void)
width /= cifReadScale2;
savescale = cifReadScale1;
if (!CIFParsePath(&pathheadp, 2))
pathheadp = CIFParsePath(2);
if (pathheadp == NULL)
{
CIFReadError("wire, but improper path; ignored.\n");
CIFSkipToSemi();
@ -797,7 +806,8 @@ CIFParsePoly(void)
CIFSkipToSemi();
return FALSE;
}
if (!CIFParsePath(&pathheadp, 1))
pathheadp = CIFParsePath(1);
if (pathheadp == NULL)
{
CIFReadError("polygon, but improper path; ignored.\n");
CIFSkipToSemi();
@ -817,11 +827,13 @@ CIFParsePoly(void)
CIFSkipToSemi();
return FALSE;
}
free_magic1_t mm1 = freeMagic1_init();
for (; rectp != NULL ; rectp = rectp->r_next)
{
DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable,
(PaintUndoInfo *) NULL);
freeMagic((char *) rectp);
freeMagic1(&mm1, (char *) rectp);
}
freeMagic1_end(&mm1);
return TRUE;
}

View File

@ -329,8 +329,10 @@ cifNewReadStyle(void)
layer = cifCurReadStyle->crs_layers[i];
if (layer != NULL)
{
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->crl_ops; op != NULL; op = op->co_next)
freeMagic((char *)op);
freeMagic1(&mm1, (char *)op);
freeMagic1_end(&mm1);
freeMagic((char *)layer);
}
}
@ -408,11 +410,13 @@ CIFReadTechInit(void)
/* forget the list of styles */
free_magic1_t mm1 = freeMagic1_init();
for (style = cifReadStyleList; style != NULL; style = style->crs_next)
{
freeMagic(style->crs_name);
freeMagic(style);
freeMagic1(&mm1, style);
}
freeMagic1_end(&mm1);
cifReadStyleList = NULL;
}

View File

@ -276,8 +276,10 @@ CIFScaleCoord(
PlowAfterTech();
ExtTechScale(1, denom);
WireTechScale(1, denom);
#ifdef ROUTE_MODULE
MZAfterTech();
IRAfterTech();
#endif
#ifdef LEF_MODULE
LefTechScale(1, denom);
#endif
@ -649,12 +651,11 @@ CIFParsePoint(
* one or more points.
*
* Results:
* TRUE is returned if the path was parsed successfully,
* FALSE otherwise.
* non-NULL CIFPath* the caller takes ownership of
* if the path was parsed successfully, otherwise NULL.
*
* Side effects:
* Modifies the parameter pathheadpp to point to the path
* that is constructed.
* None
*
* Corrections:
* CIF coordinates are multiplied by 2 to cover the case where
@ -666,17 +667,16 @@ CIFParsePoint(
* ----------------------------------------------------------------------------
*/
bool
CIFPath *
CIFParsePath(
CIFPath **pathheadpp,
int iscale)
{
CIFPath *pathtailp, *newpathp;
CIFPath *pathheadp, *pathtailp, *newpathp;
bool nonManhattan = FALSE; /* diagnostic only */
CIFPath path;
int savescale;
*pathheadpp = NULL;
pathheadp = NULL;
pathtailp = NULL;
path.cifp_next = NULL;
while (TRUE)
@ -688,12 +688,12 @@ CIFParsePath(
savescale = cifReadScale1;
if (!CIFParsePoint(&path.cifp_point, iscale))
{
CIFFreePath(*pathheadpp);
return FALSE;
CIFFreePath(pathheadp);
return NULL;
}
if (savescale != cifReadScale1)
{
CIFPath *phead = *pathheadpp;
CIFPath *phead = pathheadp;
int newscale = cifReadScale1 / savescale;
while (phead != NULL)
{
@ -704,7 +704,7 @@ CIFParsePath(
}
newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath)));
*newpathp = path;
if (*pathheadpp)
if (pathheadp)
{
/*
* Check that this segment is Manhattan. If not, remember the
@ -721,10 +721,10 @@ CIFParsePath(
}
pathtailp->cifp_next = newpathp;
}
else *pathheadpp = newpathp;
else pathheadp = newpathp;
pathtailp = newpathp;
}
return (*pathheadpp != NULL);
return pathheadp;
}
/*
@ -1338,11 +1338,13 @@ void
CIFFreePath(
CIFPath *path) /* Path to be freed. */
{
free_magic1_t mm1 = freeMagic1_init();
while (path != NULL)
{
freeMagic((char *) path);
freeMagic1(&mm1, (char *) path);
path = path->cifp_next;
}
freeMagic1_end(&mm1);
}
/*

View File

@ -21,8 +21,8 @@
* rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFread.h,v 1.3 2010/08/25 17:33:55 tim Exp $
*/
#ifndef _CIFREAD_H
#define _CIFREAD_H
#ifndef _MAGIC__CIF__CIFREAD_H
#define _MAGIC__CIF__CIFREAD_H
#include "cif/CIFint.h"
@ -166,7 +166,7 @@ extern bool CIFParseUser(void);
extern bool CIFParseCall(void);
extern bool CIFParseTransform(Transform *transformp);
extern bool CIFParseInteger(int *valuep);
extern bool CIFParsePath(CIFPath **pathheadpp, int iscale);
extern CIFPath *CIFParsePath(int iscale);
extern bool CIFParsePoint(Point *pointp, int iscale);
extern bool CIFParseSInteger(int *valuep);
extern void CIFSkipToSemi(void);
@ -221,4 +221,4 @@ extern int cifParseLaChar;
? (cifParseLaAvail = FALSE, cifParseLaChar) \
: (cifParseLaChar = getc(cifInputFile)))
#endif /* _CIFREAD_H */
#endif /* _MAGIC__CIF__CIFREAD_H */

View File

@ -78,6 +78,7 @@ typedef struct {
int
cifPaintDBFunc(
Tile *tile, /* Tile of CIF information. */
TileType dinfo,
PaintLayerData *pld)
{
Rect area;
@ -106,7 +107,7 @@ cifPaintDBFunc(
if (DBPaintOnPlane(type, pNum))
{
ui.pu_pNum = pNum;
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
}
@ -219,6 +220,7 @@ CIFPaintLayer(
int
cifSeeFunc(
Tile *tile, /* Tile to be entered as feedback. */
TileType dinfo, /* Split tile information */
SeeLayerData *sld) /* Layer and explanation for the feedback. */
{
Rect area;
@ -233,10 +235,10 @@ cifSeeFunc(
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
}
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
sld->style |
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
/* (preserve information about the geometry of a diagonal tile) */
sld->style | ((TiGetTypeExact(tile) | dinfo) &
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
return 0;
}
@ -438,9 +440,11 @@ CIFCoverageLayer(
SearchContext scx;
TileTypeBitMask mask, depend;
float fcover;
int cifCoverageFunc(Tile *tile, ClientData *arg);
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
/* Forward declaration */
int cifCoverageFunc(Tile *tile, TileType dinfo, ClientData *arg);
/* Check out the CIF layer name. */
if (!CIFNameToMask(layer, &mask, &depend)) return;
@ -512,6 +516,7 @@ CIFCoverageLayer(
int
cifCoverageFunc(
Tile *tile,
TileType dinfo, /* (unused) */
ClientData *arg)
{
coverstats *cstats = (coverstats *)arg;

View File

@ -100,6 +100,7 @@ cifTechFreeStyle(void)
layer = CIFCurStyle->cs_layers[i];
if (layer != NULL)
{
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->cl_ops; op != NULL; op = op->co_next)
{
if (op->co_client != (ClientData)NULL)
@ -120,8 +121,9 @@ cifTechFreeStyle(void)
break;
}
}
freeMagic((char *)op);
freeMagic1(&mm1, (char *)op);
}
freeMagic1_end(&mm1);
freeMagic((char *)layer);
}
}
@ -234,7 +236,7 @@ cifParseLayers(
*/
{
TileTypeBitMask curCifMask, curPaintMask;
char curLayer[40], *p, *cp;
char curLayer[512], *p, *cp;
TileType paintType;
int i;
bool allResidues;
@ -246,6 +248,10 @@ cifParseLayers(
{
p = curLayer;
if (*string == '(')
while ((*string != ')') && (*string != 0))
*p++ = *string++;
if (*string == '*')
{
allResidues = TRUE;
@ -263,7 +269,22 @@ cifParseLayers(
if (paintMask != NULL)
{
paintType = DBTechNameTypes(curLayer, &curPaintMask);
if (*curLayer == '(')
{
TileType t;
/* Layer groups with parentheses can only be paint types,
* and will be parsed accordingly. Residues will be
* handled within the group. Set paintType to -3, which
* is flagged and handled below.
*/
DBTechNoisyNameMask(curLayer, &curPaintMask);
paintType = -3;
allResidues = FALSE;
}
else
paintType = DBTechNameTypes(curLayer, &curPaintMask);
if (paintType >= 0) goto okpaint;
}
else paintType = -2;
@ -299,7 +320,7 @@ okpaint:
TechError("Ambiguous layer (type) \"%s\".\n", curLayer);
continue;
}
if (paintType >= 0)
if ((paintType >= 0) || (paintType == -3))
{
if (paintType == TT_SPACE && spaceOK ==0)
TechError("\"Space\" layer not permitted in CIF rules.\n");
@ -369,11 +390,13 @@ CIFTechInit(void)
/* forget the list of styles */
free_magic1_t mm1 = freeMagic1_init();
for (style = CIFStyleList; style != NULL; style = style->cs_next)
{
freeMagic(style->cs_name);
freeMagic(style);
freeMagic1(&mm1, style);
}
freeMagic1_end(&mm1);
CIFStyleList = NULL;
}
@ -794,7 +817,7 @@ CIFTechLine(
else
{
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
if (!strcmp(tptr, CIFCurStyle->cs_name + l))
if ((l > 0) && !strcmp(tptr, CIFCurStyle->cs_name + l))
{
CIFCurStyle->cs_status = TECH_PENDING;
return TRUE;
@ -1758,7 +1781,8 @@ cifComputeHalo(
if (maxGrow > maxShrink)
style->cs_radius = 2*maxGrow;
else style->cs_radius = 2*maxShrink;
style->cs_radius /= style->cs_scaleFactor;
if (style->cs_scaleFactor > 0)
style->cs_radius /= style->cs_scaleFactor;
style->cs_radius++;
/* TxPrintf("Radius for %s CIF is %d.\n",

View File

@ -46,8 +46,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
/* Forward declarations */
extern int cifWriteInitFunc(CellDef *def);
extern int cifWriteMarkFunc(CellUse *use);
extern int cifWritePaintFunc(Tile *tile, FILE *f);
extern int cifWriteLabelFunc(Tile *tile, FILE *f);
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f);
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f);
extern int cifWriteUseFunc(CellUse *use, FILE *f);
extern void cifOutPreamble(FILE *outf, CellDef *cell);
extern void cifOut(FILE *outf);
@ -584,6 +584,7 @@ cifWriteUseFunc(
int
cifWriteLabelFunc(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information (unused) */
FILE *f) /* File in which to write. */
{
Rect r;
@ -643,7 +644,8 @@ cifWriteLabelFunc(
int
cifWritePaintFunc(
Tile *tile, /* Tile to be written out. */
FILE *f) /* File in which to write. */
TileType dinfo, /* Split tile information */
FILE *f) /* File in which to write. */
{
Rect r;
@ -662,7 +664,7 @@ cifWritePaintFunc(
Point points[5];
int i, np;
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile), points, &np);
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile) | dinfo, points, &np);
/* Write triangle as a CIF polygon */

View File

@ -20,8 +20,8 @@
* rcsid "$Header: /usr/cvsroot/magic-8.0/cif/cif.h,v 1.4 2010/06/24 12:37:15 tim Exp $
*/
#ifndef _CIF_H
#define _CIF_H
#ifndef _MAGIC__CIF__CIF_H
#define _MAGIC__CIF__CIF_H
#include "database/database.h"
@ -95,4 +95,4 @@ extern LinkedRect *PaintPolygon(Point *pointlist, int number, Plane *plane, Pain
/* C99 compat */
extern int CIFGetContactSize(TileType type, int *edge, int *spacing, int *border);
#endif /* _CIF_H */
#endif /* _MAGIC__CIF__CIF_H */

View File

@ -19,8 +19,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/cmwind/cmwind.h,v 1.2 2009/09/10 20:32:51 tim Exp $
*/
#ifndef _CMWIND_H
#define _CMWIND_H
#ifndef _MAGIC__CMWIND__CMWIND_H
#define _MAGIC__CMWIND__CMWIND_H
#include "windows/windows.h"
#include "textio/txcommands.h"
@ -81,4 +81,4 @@ extern bool CMWCheckWritten(void);
extern void CMWinit(void);
#endif /* _CMWIND_H */
#endif /* _MAGIC__CMWIND__CMWIND_H */

View File

@ -81,6 +81,70 @@ CmdAddPath(
PaAppend(&Path, cmd->tx_argv[1]);
}
/*
* ----------------------------------------------------------------------------
*
* CmdArchive --
*
* Save an entire database to a "crash recovery"-type archive file, or
* load a database from a "crash recovery"-type archive file. Option
* "writeall" writes everything, including read-only PDK cells, while
* "readref" does not dereference and will prefer files found in the
* search path over content in the archive.
*
*
* Usage:
* archive write|writeall|read|readref file
*
* Results:
* None.
*
* Side effects:
* Writes a single file with the contents of the entire database,
* or loads the database with multiple cells from the file.
*
* ----------------------------------------------------------------------------
*/
void
CmdArchive(
MagWindow *w,
TxCommand *cmd)
{
int option = -1;
char *filename = NULL;
static const char * const cmdArchiveOpt[] = {"write", "writeall",
"read", "readref", 0};
if (cmd->tx_argc != 3)
TxError("Usage: %s write|writeall|read|readref filename\n", cmd->tx_argv[0]);
else
{
option = Lookup(cmd->tx_argv[1], cmdArchiveOpt);
if (option < 0)
{
TxError("Usage: %s write|writeall|read|readref filename\n", cmd->tx_argv[0]);
return;
}
}
filename = cmd->tx_argv[2];
switch(option) {
case 0: /* write */
DBWriteBackup(filename, TRUE, FALSE);
break;
case 1: /* writeall */
DBWriteBackup(filename, TRUE, TRUE);
break;
case 2: /* read */
DBReadBackup(filename, TRUE, TRUE);
break;
case 3: /* readref */
DBReadBackup(filename, TRUE, FALSE);
break;
}
}
/* Linked-list structure for returning information about arrayed cells */
@ -274,14 +338,17 @@ CmdArray(
case ARRAY_WIDTH:
if (locargc == 2)
{
char *xsepvalue;
for (la = lahead; la != NULL; la = la->ar_next)
{
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_NewStringObj(xsepvalue, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@ -291,7 +358,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
TxPrintf("x separation %s\n", xsepvalue);
#ifdef MAGIC_WRAPPER
}
#endif
@ -310,14 +377,17 @@ CmdArray(
case ARRAY_HEIGHT:
if (locargc == 2)
{
char *ysepvalue;
for (la = lahead; la != NULL; la = la->ar_next)
{
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_NewStringObj(ysepvalue, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@ -327,7 +397,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
TxPrintf("y separation %s\n", ysepvalue);
#ifdef MAGIC_WRAPPER
}
#endif
@ -346,16 +416,21 @@ CmdArray(
case ARRAY_PITCH:
if (locargc == 2)
{
char *xpitch, *ypitch;
for (la = lahead; la != NULL; la = la->ar_next)
{
xpitch = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
ypitch = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_NewStringObj(xpitch, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_NewStringObj(ypitch, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@ -365,8 +440,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
TxPrintf("x separation %s ", xpitch);
TxPrintf("y separation %s\n", ypitch);
#ifdef MAGIC_WRAPPER
}
#endif
@ -386,16 +461,21 @@ CmdArray(
case ARRAY_POSITION:
if (locargc == 2)
{
char *xpos, *ypos;
for (la = lahead; la != NULL; la = la->ar_next)
{
xpos = DBWPrintValue(la->cellUse->cu_bbox.r_xbot,
w, TRUE);
ypos = DBWPrintValue(la->cellUse->cu_bbox.r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
if (doList)
{
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
Tcl_NewStringObj(xpos, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
Tcl_NewStringObj(ypos, -1));
Tcl_SetObjResult(magicinterp, tobj);
}
else
@ -405,8 +485,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
TxPrintf("x=%s ", xpos);
TxPrintf("y=%s\n", ypos);
#ifdef MAGIC_WRAPPER
}
#endif
@ -466,11 +546,15 @@ badusage:
}
freelist:
la = lahead;
while (la != NULL)
{
freeMagic((char *)la);
la = la->ar_next;
la = lahead;
while (la != NULL)
{
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *)la);
la = la->ar_next;
freeMagic1_end(&mm1);
}
}
return;
}
@ -806,13 +890,16 @@ CmdBox(
TxRebuildCommand(cmd);
return;
}
else if (DBWSnapToGrid != DBW_SNAP_USER)
else if (DBWUnits != DBW_UNITS_USER)
{
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
distancey = distancex;
}
else
{
/* For user units, the distance may be different in the X and Y
* directions for a given value.
*/
switch (direction)
{
case GEO_EAST: case GEO_WEST:
@ -840,15 +927,14 @@ CmdBox(
case BOX_WIDTH:
if (argc == 2)
{
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
w, TRUE);
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_xtop - boxptr->r_xbot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
#else
TxPrintf("%s box width is %d\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xtop - boxptr->r_xbot);
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root",
boxvalues);
#endif
return;
}
@ -860,15 +946,14 @@ CmdBox(
case BOX_HEIGHT:
if (argc == 2)
{
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_ytop - boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
#else
TxPrintf("%s box height is %d\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_ytop - boxptr->r_ybot);
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root",
boxvalues);
#endif
return;
}
@ -881,16 +966,24 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d",
boxptr->r_xtop - boxptr->r_xbot,
boxptr->r_ytop - boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluex, *boxvaluey;
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
w, TRUE);
boxvaluey = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box size is %d x %d\n",
TxPrintf("%s box size is %s x %s\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xtop - boxptr->r_xbot,
boxptr->r_ytop - boxptr->r_ybot);
boxvaluex, boxvaluey);
#endif
return;
}
@ -905,14 +998,22 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d",
boxptr->r_xbot, boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluex, *boxvaluey;
boxvaluex = DBWPrintValue(boxptr->r_xbot, w, TRUE);
boxvaluey = DBWPrintValue(boxptr->r_ybot, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box lower-left corner at (%d, %d)\n",
TxPrintf("%s box lower-left corner at (%s, %s)\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xbot, boxptr->r_ybot);
boxvaluex, boxvaluey);
#endif
return;
}
@ -944,16 +1045,31 @@ CmdBox(
if (argc == 2)
{
#ifdef MAGIC_WRAPPER
char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d %d %d %d",
boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
Tcl_Obj *tobj;
#endif
char *boxvaluellx, *boxvaluelly;
char *boxvalueurx, *boxvalueury;
boxvaluellx = DBWPrintValue(boxptr->r_xbot, w, TRUE);
boxvaluelly = DBWPrintValue(boxptr->r_ybot, w, FALSE);
boxvalueurx = DBWPrintValue(boxptr->r_xtop, w, TRUE);
boxvalueury = DBWPrintValue(boxptr->r_ytop, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluellx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluelly, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueurx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueury, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n",
(refEdit) ? "Edit" : "Root",
boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury);
#endif
return;
}

View File

@ -24,6 +24,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
@ -36,6 +37,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/main.h"
#include "commands/commands.h"
#include "utils/utils.h"
#include "utils/magic_zlib.h"
#include "textio/textio.h"
#include "drc/drc.h"
#include "graphics/graphics.h"
@ -429,7 +431,7 @@ CmdCalma(
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)CalmaMagScale));
#else
TxPrintf("Text magnification 1.0 = %g microns.\n");
TxPrintf("Text magnification 1.0 = %g microns.\n", (double)CalmaMagScale);
#endif
return;
}
@ -742,7 +744,7 @@ CmdCalma(
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaNoDuplicates));
#else
TxPrintf("Cell defs that exist before reading GDS will not be paresd.\n",
TxPrintf("Cell defs that exist before reading GDS will %sbe parsed.\n",
(CalmaNoDuplicates) ? "not " : "");
#endif
return;
@ -762,7 +764,7 @@ CmdCalma(
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaUnique));
#else
TxPrintf("Cell defs that exist before reading GDS will be renamed.\n",
TxPrintf("Cell defs that exist before reading GDS will %sbe renamed.\n",
(CalmaUnique) ? "not " : "");
#endif
return;
@ -2394,8 +2396,10 @@ CmdContact(
CCStruct ccs;
Rect area;
LinkedRect *lr = NULL;
int cmdContactFunc(Tile *tile, CCStruct *ccs); /* Forward declaration */
int cmdContactEraseFunc(Tile *tile, LinkedRect **lr); /* Forward declaration */
/* Forward declarations */
int cmdContactFunc(Tile *tile, TileType dinfo, CCStruct *ccs);
int cmdContactEraseFunc(Tile *tile, TileType dinfo, LinkedRect **lr);
windCheckOnlyWindow(&w, DBWclientID);
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
@ -2453,6 +2457,7 @@ CmdContact(
rmask = DBResidueMask(type);
free_magic1_t mm1 = freeMagic1_init();
while (lr != NULL)
{
GeoClip(&lr->r_r, &area);
@ -2463,9 +2468,10 @@ CmdContact(
if (TTMaskHasType(rmask, rtype))
DBPaint(EditCellUse->cu_def, &lr->r_r, rtype);
freeMagic(lr);
freeMagic1(&mm1, lr);
lr = lr->r_next;
}
freeMagic1_end(&mm1);
/* Refresh the layout drawing */
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
@ -2502,14 +2508,16 @@ CmdContact(
DBSrPaintArea((Tile *) NULL, EditCellUse->cu_def->cd_planes[DBPlane(rtype)],
&area, &smask, cmdContactFunc, (ClientData) &ccs);
free_magic1_t mm1 = freeMagic1_init();
while (ccs.lhead != NULL)
{
TTMaskSetOnlyType(&smask, type);
TTMaskAndMask(&smask, &DBActiveLayerBits);
DBPaintMask(EditCellUse->cu_def, &ccs.lhead->r_r, &smask);
freeMagic(ccs.lhead);
freeMagic1(&mm1, ccs.lhead);
ccs.lhead = ccs.lhead->r_next;
}
freeMagic1_end(&mm1);
/* Refresh the layout drawing */
DBWAreaChanged(EditCellUse->cu_def, &area, DBW_ALLWINDOWS, &smask);
@ -2525,11 +2533,14 @@ CmdContact(
int
cmdContactFunc(
Tile *tile,
TileType dinfo,
CCStruct *ccs)
{
TileType stype;
TileTypeBitMask smask;
int cmdContactFunc2(Tile *tile, CCStruct *ccs); /* Forward declaration */
/* Forward declaration */
int cmdContactFunc2(Tile *tile, TileType dinfo, CCStruct *ccs);
TiToRect(tile, &ccs->area);
GeoClip(&ccs->area, &ccs->clip);
@ -2539,14 +2550,16 @@ cmdContactFunc(
break;
TTMaskSetOnlyType(&smask, stype);
DBSrPaintArea((Tile *) NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
&ccs->area, &smask, cmdContactFunc2, (ClientData)ccs);
DBSrPaintNMArea((Tile *)NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
TiGetTypeExact(tile) | dinfo, &ccs->area, &smask,
cmdContactFunc2, (ClientData)ccs);
return 0;
}
int
cmdContactFunc2(
Tile *tile,
TileType dinfo, /* (unused) */
CCStruct *ccs)
{
LinkedRect *newlr;
@ -2569,6 +2582,7 @@ cmdContactFunc2(
int
cmdContactEraseFunc(
Tile *tile,
TileType dinfo, /* (unused) */
LinkedRect **lr)
{
LinkedRect *newlr;
@ -2822,14 +2836,15 @@ CmdCorner(
TileTypeBitMask maskBits;
Rect editBox;
SearchContext scx;
extern int cmdCornerFunc(Tile *tile, TreeContext *cxp);
bool hasErr = FALSE;
int locargc = cmd->tx_argc;
extern int cmdBevelFunc(Tile *tile, TreeContext *cxp);
bool dobevel = FALSE;
NMCornerPath cmdPathList;
/* Forward declarations */
extern int cmdCornerFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
extern int cmdBevelFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
{
TxError("Usage: %s direction1 direction2 [layers]\n",
@ -2950,14 +2965,22 @@ CmdCorner(
rectp = CIFPolyToRects(cmdPathList.pathlist->pathhead, plane,
resultTbl, &ui, FALSE);
for (; rectp != NULL; rectp = rectp->r_next)
{
DBPaintPlane(plane, &rectp->r_r, resultTbl, &ui);
freeMagic((char *)rectp);
free_magic1_t mm1 = freeMagic1_init();
for (; rectp != NULL; rectp = rectp->r_next)
{
DBPaintPlane(plane, &rectp->r_r, resultTbl, &ui);
freeMagic1(&mm1, (char *)rectp);
}
freeMagic1_end(&mm1);
}
CIFFreePath(cmdPathList.pathlist->pathhead);
freeMagic((char *)cmdPathList.pathlist);
cmdPathList.pathlist = cmdPathList.pathlist->cpl_next;
{
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *)cmdPathList.pathlist);
cmdPathList.pathlist = cmdPathList.pathlist->cpl_next;
freeMagic1_end(&mm1);
}
}
}
else
@ -2975,14 +2998,16 @@ CmdCorner(
/* Now that we've got all the material, scan over the list
* painting the material and freeing up the entries on the list.
*/
free_magic1_t mm1 = freeMagic1_init();
while (cmdCornerList != NULL)
{
DBPaint(EditCellUse->cu_def, &cmdCornerList->cca_area,
cmdCornerList->cca_type);
freeMagic((char *) cmdCornerList);
freeMagic1(&mm1, (char *) cmdCornerList);
cmdCornerList = cmdCornerList->cca_next;
}
}
freeMagic1_end(&mm1);
}
SelectClear();
DBAdjustLabels(EditCellUse->cu_def, &editBox);
@ -3014,6 +3039,7 @@ CmdCorner(
int
cmdCornerFunc(
Tile *tile, /* Tile to fill with. */
TileType dinfo, /* Split tile information (unused) */
TreeContext *cxp) /* Describes state of search. */
{
Rect r1, r2, r3;
@ -3180,6 +3206,7 @@ AddNewPoint(
int
cmdBevelFunc(
Tile *tile, /* Tile to fill with. */
TileType dinfo, /* Split tile information (unused) */
TreeContext *cxp) /* Describes state of search. */
{
Rect r1, r2, r3;
@ -3641,8 +3668,10 @@ cmdBevelFunc(
GeoClip(&r3, &cmdCornerRootBox);
if (GEO_RECTNULL(&r2) || GEO_RECTNULL(&r3))
{
free_magic1_t mm1 = freeMagic1_init();
for (pptr = pathhead; pptr != NULL; pptr = pptr->cifp_next)
freeMagic((char *)pptr);
freeMagic1(&mm1, (char *)pptr);
freeMagic1_end(&mm1);
return 0;
}
@ -3676,7 +3705,7 @@ cmdBevelFunc(
* Save cells to or recover cells from a crash backup file
*
* Usage:
* crash save|recover [file]
* crash save|recover|archive|read [file]
*
* Results:
* None.
@ -3711,7 +3740,7 @@ CmdCrash(
switch(option) {
case 0: /* save */
DBWriteBackup(filename);
DBWriteBackup(filename, FALSE, FALSE);
break;
case 1: /* recover */
DBFileRecovery(filename);
@ -4152,6 +4181,7 @@ CmdDrc(
rootUse = (CellUse *) window->w_surfaceID;
dcl = DRCCount(rootUse, &rootArea, doforall);
free_magic1_t mm1 = freeMagic1_init();
while (dcl != NULL)
{
if (count_total >= 0)
@ -4181,9 +4211,10 @@ CmdDrc(
}
#endif
}
freeMagic((char *)dcl);
freeMagic1(&mm1, (char *)dcl);
dcl = dcl->dcl_next;
}
freeMagic1_end(&mm1);
#ifdef MAGIC_WRAPPER
if ((count_total >= 0) || (!dolist))
@ -4306,6 +4337,8 @@ CmdDrc(
#endif
TxPrintf("Error area #%d:\n", result);
if (DRCWhy(dolist, rootUse, &area, findonly)) break;
/* Check for interrupt or this will go into an infinite loop */
else if (SigInterruptPending) break;
drc_nth++;
}
else if (result < 0)
@ -4332,12 +4365,14 @@ CmdDrc(
}
if (findonly)
{
free_magic1_t mm1 = freeMagic1_init();
/* Delete temporary rules */
while (DRCIgnoreRules != NULL)
{
freeMagic(DRCIgnoreRules);
freeMagic1(&mm1, DRCIgnoreRules);
DRCIgnoreRules = DRCIgnoreRules->li_next;
}
freeMagic1_end(&mm1);
/* Replace temporary set of rules */
DRCIgnoreRules = DRCSaveRules;
}
@ -4420,8 +4455,10 @@ CmdDrc(
{
while (DRCIgnoreRules != NULL)
{
freeMagic(DRCIgnoreRules);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, DRCIgnoreRules);
DRCIgnoreRules = DRCIgnoreRules->li_next;
freeMagic1_end(&mm1);
}
}
else
@ -4559,6 +4596,7 @@ CmdDrc(
int
cmdDropPaintCell(
Tile *tile,
TileType dinfo,
TreeContext *cxp)
{
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
@ -4567,7 +4605,7 @@ cmdDropPaintCell(
TileType type;
Rect area;
if (SplitSide(tile))
if (dinfo & TT_SIDE)
type = SplitRightType(tile);
else
type = SplitLeftType(tile);
@ -4600,6 +4638,7 @@ cmdDropPaintCell(
int
cmdDropFunc(
Tile *tile,
TileType dinfo,
ClientData clientData)
{
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
@ -4610,7 +4649,7 @@ cmdDropFunc(
scx.scx_use = EditCellUse;
scx.scx_trans = GeoIdentityTransform;
if (SplitSide(tile))
if (dinfo & TT_SIDE)
type = SplitRightType(tile);
else
type = SplitLeftType(tile);
@ -4763,9 +4802,10 @@ CmdDrop(
* Usage:
* dump cellName [child refPointChild] [parent refPointParent]
*
* where the refPoints are either a label name, e.g., SOCKET_A, or an x-y
* pair of integers, e.g., 100 200. The words "child" and "parent" are
* keywords, and may be abbreviated.
* where the refPoints are either "label" and a label name, e.g.,
* "label SOCKET_A", a corner position, e.g., "ur", or an x-y pair of
* coordinates, e.g., "100 200", or "1um 5um". The words "child",
* "parent", and "label" are keywords, and may be abbreviated.
*
* Results:
* None.
@ -4971,18 +5011,40 @@ cmdDumpParseArgs(
* points weren't provided. (Lower-left of the box tool is interpreted
* in root coordinates).
*/
// getcell cellname child 0 0 parent ll v 0 0
/*
* Examples: getcell cellname v child 0 0 parent ll
* getcell cellname child 0 0 parent 1um 1um
* getcell cellname child 0 0
* getcell cellname 90v child label VDD
* etc.
*/
av = &cmd->tx_argv[2];
ac = cmd->tx_argc - 2;
hasChild = hasRoot = hasTrans = FALSE;
while (ac > 0)
{
static const char * const kwdNames[] = { "child", "parent", "0", "90", "180", "270",
"v", "0v", "90v", "180v", "270v",
"h", "0h", "90h", "180h", "270h", 0 };
static const char * const refPointNames[] = { "ll", "lr", "ul", "ur", 0 };
static const char * const kwdNames[] = { "child", "parent",
"0", "90", "180", "270",
"v", "0v", "90v", "180v", "270v",
"h", "0h", "90h", "180h", "270h", 0 };
typedef enum {
IDX_CHILD, IDX_PARENT,
IDX_ZERO, IDX_90, IDX_180, IDX_270,
IDX_VERT, IDX_ZERO_VERT, IDX_90_VERT, IDX_180_VERT, IDX_270_VERT,
IDX_HORZ, IDX_ZERO_HORZ, IDX_90_HORZ, IDX_180_HORZ, IDX_270_HORZ
} optionType;
static const char * const refPointNames[] = {
"ll", "lr", "ul", "ur", "label", 0 };
typedef enum {
IDX_LL, IDX_LR, IDX_UL, IDX_UR, IDX_LABEL
} refPointType;
Label *lab;
int n,p;
int n, p;
Point locp;
n = Lookup(av[0], kwdNames);
if (n < 0)
@ -4992,130 +5054,143 @@ cmdDumpParseArgs(
}
switch (n)
{
case 0: /* Child */
case IDX_CHILD: /* "child" */
if (ac < 2)
{
TxError("Keyword must be followed by a reference point\n");
goto usage;
}
//else if (ac == 3) # error case: getcell cellname child 0 0 parent ll -> (ac > 3) -> read 0 as label
else if (ac >= 3 && StrIsInt(av[1]) && StrIsInt(av[2]))
{
childPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
childPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
av += 3;
ac -= 3;
}
else
{
p = Lookup(av[1], refPointNames);
if (p == 0) /* lower left */
if (p == IDX_LL) /* lower left */
{
childPoint.p_x = bbox.r_ll.p_x;
childPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 1) /* lower right */
else if (p == IDX_LR) /* lower right */
{
childPoint.p_x = bbox.r_ur.p_x;
childPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 2) /* upper left */
else if (p == IDX_UL) /* upper left */
{
childPoint.p_x = bbox.r_ll.p_x;
childPoint.p_y = bbox.r_ur.p_y;
}
else if (p == 3) /* upper right */
else if (p == IDX_UR) /* upper right */
{
childPoint.p_x = bbox.r_ur.p_x;
childPoint.p_y = bbox.r_ur.p_y;
}
else
else if ((p == IDX_LABEL) && (ac >= 3)) /* label */
{
childPoint = TiPlaneRect.r_ur;
(void) DBSrLabelLoc(dummy, av[1], cmdDumpFunc,
(void) DBSrLabelLoc(dummy, av[2], cmdDumpFunc,
&childPoint);
if (childPoint.p_x == TiPlaneRect.r_xtop &&
childPoint.p_y == TiPlaneRect.r_ytop)
{
TxError("Couldn't find label \"%s\" in cell \"%s\".\n",
av[1], cmd->tx_argv[1]);
av[2], cmd->tx_argv[1]);
return FALSE;
}
av += 1;
ac -= 1;
}
else if (ac >= 3) /* Coordinate pair */
{
childPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
childPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
av += 1;
ac -= 1;
}
else
{
TxError("Must provide two valid coordinates\n");
goto usage;
}
av += 2;
ac -= 2;
}
hasChild = TRUE;
break;
case 1: /* Parent */
case IDX_PARENT: /* "parent" */
if (ac < 2)
{
TxError("Keyword must be followed by a reference point\n");
goto usage;
}
//else if (ac == 3) # error case: getcell cellname child 0 0 parent ll v 0 0 -> (ac > 3) -> read 0 as label
else if (ac >= 3 && StrIsInt(av[1]) && StrIsInt(av[2]))
{
editPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
editPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
av += 3;
ac -= 3;
GeoTransPoint(&EditToRootTransform, &editPoint,
&rootPoint);
}
else
{
p = Lookup(av[1], refPointNames);
if (p == 0) /* lower left */
if (p == IDX_LL) /* lower left */
{
if (!ToolGetBox(&rootDef, &rootBox) ||
(rootDef != EditRootDef)) goto box_error;
rootPoint.p_x = rootBox.r_ll.p_x;
rootPoint.p_y = rootBox.r_ll.p_y;
}
else if (p == 1) /* lower right */
else if (p == IDX_LR) /* lower right */
{
if (!ToolGetBox(&rootDef, &rootBox) ||
(rootDef != EditRootDef)) goto box_error;
rootPoint.p_x = rootBox.r_ur.p_x;
rootPoint.p_y = rootBox.r_ll.p_y;
}
else if (p == 2) /* upper left */
else if (p == IDX_UL) /* upper left */
{
if (!ToolGetBox(&rootDef, &rootBox) ||
(rootDef != EditRootDef)) goto box_error;
rootPoint.p_x = rootBox.r_ll.p_x;
rootPoint.p_y = rootBox.r_ur.p_y;
}
else if (p == 3) /* upper right */
else if (p == IDX_UR) /* upper right */
{
if (!ToolGetBox(&rootDef, &rootBox) ||
(rootDef != EditRootDef)) goto box_error;
rootPoint.p_x = rootBox.r_ur.p_x;
rootPoint.p_y = rootBox.r_ur.p_y;
}
else
else if ((p == IDX_LABEL) && (ac >= 3)) /* label */
{
for (lab = editDef->cd_labels; lab; lab = lab->lab_next)
if (strcmp(lab->lab_text, av[1]) == 0)
if (strcmp(lab->lab_text, av[2]) == 0)
break;
if (lab == NULL)
{
TxError("Couldn't find label \"%s\" in edit cell.\n",
av[1]);
av[2]);
return FALSE;
}
editPoint = lab->lab_rect.r_ll;
GeoTransPoint(&EditToRootTransform, &editPoint,
&rootPoint);
av += 1;
ac -= 1;
}
else if (ac >= 3) /* Coordinate pair */
{
editPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
editPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
av += 1;
ac -= 1;
GeoTransPoint(&EditToRootTransform, &editPoint,
&rootPoint);
}
else
{
TxError("Must provide two valid coordinates\n");
goto usage;
}
av += 2;
ac -= 2;
}
hasRoot = TRUE;
break;
case 2: /* 0 */
case IDX_ZERO: /* "0" */
tx_cell = &GeoIdentityTransform;
transform_cell:
if (ac < 2 )
@ -5131,109 +5206,117 @@ default_action:
}
av += 1;
ac -= 1;
}
// error case: getcell cellname v 0 0 -> read 0 in kwdNames -> goto default transform
// av[1] = "0", "90", "180", "270" case -> av[1] must mean editpoint coordinate
else if (Lookup(av[1], kwdNames)>=0 && Lookup(av[1], kwdNames)!= 2 && strcmp(av[1],"90") && strcmp(av[1],"180") && strcmp(av[1],"270"))
}
/*
* Error case:
* getcell cellname v 0 0 ->
* read 0 in kwdNames
* goto default transform
* av[1] = "0", "90", "180", "270" case ->
* av[1] must mean editpoint coordinate
*/
else if (Lookup(av[1], kwdNames) >= 0 &&
Lookup(av[1], kwdNames) != 2 &&
strcmp(av[1], "90") &&
strcmp(av[1], "180") &&
strcmp(av[1], "270"))
{
goto default_action;
}
else
{
if (StrIsInt(av[1]))
p = Lookup(av[1], refPointNames);
if (p == IDX_LL) /* lower left */
{
editPoint.p_x = atoi(av[1]);
if (ac < 3 || !StrIsInt(av[2]))
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == IDX_LR) /* lower right */
{
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == IDX_UL) /* upper left */
{
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else if (p == IDX_UR) /* upper right */
{
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else if ((p == IDX_LABEL) && (ac >= 3)) /* label */
{
editPoint = TiPlaneRect.r_ur;
(void) DBSrLabelLoc(dummy, av[1], cmdDumpFunc, &editPoint);
if (editPoint.p_x == TiPlaneRect.r_xtop &&
editPoint.p_y == TiPlaneRect.r_ytop)
{
TxError("Must provide two coordinates\n");
goto usage;
TxError("Couldn't find label \"%s\" in cell \"%s\".\n",
av[1], cmd->tx_argv[1]);
return FALSE;
}
editPoint.p_y = atoi(av[2]);
av += 3;
ac -= 3;
av += 1;
ac -= 1;
}
else if (ac >= 3) /* Coordinate pair */
{
editPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
editPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
av += 1;
ac -= 1;
}
else
{
p = Lookup(av[1], refPointNames);
if (p == 0) /* lower left */
{
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 1) /* lower right */
{
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ll.p_y;
}
else if (p == 2) /* upper left */
{
editPoint.p_x = bbox.r_ll.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else if (p == 3) /* upper right */
{
editPoint.p_x = bbox.r_ur.p_x;
editPoint.p_y = bbox.r_ur.p_y;
}
else
{
editPoint = TiPlaneRect.r_ur;
(void) DBSrLabelLoc(dummy, av[1], cmdDumpFunc,
&editPoint);
if (editPoint.p_x == TiPlaneRect.r_xtop &&
editPoint.p_y == TiPlaneRect.r_ytop)
{
TxError("Couldn't find label \"%s\" in cell \"%s\".\n",
av[1], cmd->tx_argv[1]);
return FALSE;
}
}
av += 2;
ac -= 2;
TxError("Must provide two valid coordinates\n");
goto usage;
}
{
Point p;
av += 2;
ac -= 2;
GeoTransPoint(tx_cell, &editPoint, &p);
GeoTranslateTrans(tx_cell, editPoint.p_x - p.p_x,
editPoint.p_y - p.p_y, &trans_cell);
}
GeoTransPoint(tx_cell, &editPoint, &locp);
GeoTranslateTrans(tx_cell, editPoint.p_x - locp.p_x,
editPoint.p_y - locp.p_y,
&trans_cell);
}
hasTrans = TRUE;
break;
case 3: /* 90 */
case IDX_90: /* "90" */
tx_cell = &Geo90Transform;
goto transform_cell;
case 4: /* 180 */
case IDX_180: /* "180" */
tx_cell = &Geo180Transform;
goto transform_cell;
case 5: /* 270 */
case IDX_270: /* "270" */
tx_cell = &Geo270Transform;
goto transform_cell;
case 6: /* v */
case 7: /* 0v */
case IDX_VERT: /* "v" */
case IDX_ZERO_VERT: /* "0v" */
tx_cell = &GeoUpsideDownTransform;
goto transform_cell;
case 8: /* 90v */
case IDX_90_VERT: /* "90v" */
tx_cell = &GeoRef45Transform;
goto transform_cell;
case 9: /* 180v */
case IDX_180_VERT: /* "180v" */
tx_cell = &GeoSidewaysTransform;
goto transform_cell;
case 10: /* 270v */
case IDX_270_VERT: /* "270v" */
tx_cell = &GeoRef135Transform;
goto transform_cell;
case 11: /* h */
case 12: /* 0h */
case IDX_HORZ: /* "h" */
case IDX_ZERO_HORZ: /* "0h" */
tx_cell = &GeoSidewaysTransform;
goto transform_cell;
case 13: /* 90h */
case IDX_90_HORZ: /* "90h" */
tx_cell = &GeoRef135Transform;
goto transform_cell;
case 14: /* 180h */
case IDX_180_HORZ: /* "180h" */
tx_cell = &GeoUpsideDownTransform;
goto transform_cell;
case 15: /* 270h */
case IDX_270_HORZ: /* "270h" */
tx_cell = &GeoRef45Transform;
goto transform_cell;
}
@ -5293,15 +5376,17 @@ usage:
"Usage: %s cellName [child refPointChild] [parent refPointParent]\n",
cmdName);
TxError(" [transform [refPointTrans]],\n");
TxError(" where the refPoints are either a single label name,\n");
TxError(" where the refPoints are one of:\n");
TxError(
" or ll for lower left corner, or lr for lower right corner\n");
" 'label' followed by a single label name,\n");
TxError(
" or ul for upper left corner, or ur for upper right corner\n");
" or 'll' for lower left corner, 'lr' for lower right corner,\n");
TxError(
" or a pair of integer coordinates, and the transform is one of\n");
" 'ul' for upper left corner, 'ur' for upper right corner,\n");
TxError(
" 90, 180, 270, v, 90v, 180v, 270v, h, 90h, 180h, 270h.\n");
" or a pair of coordinates. The transform is one of:\n");
TxError(
" 90, 180, 270, v, 90v, 180v, 270v, h, 90h, 180h, or 270h.\n");
return FALSE;
}

View File

@ -930,6 +930,7 @@ cmdExpandFunc(
#define DORESISTANCE 6
#define DOLABELCHECK 7
#define DOALIASES 8
#define DOUNIQUE 9
#define LENCLEAR 0
#define LENDRIVER 1
@ -977,6 +978,7 @@ CmdExtract(
"resistance estimate resistance",
"labelcheck check for connections through sticky labels",
"aliases output all net name aliases",
"unique ensure unique node names during extraction",
NULL
};
static const char * const cmdExtLength[] =
@ -1120,12 +1122,13 @@ CmdExtract(
}
else if (argc == 2)
{
char *halodisp;
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
Tcl_SetObjResult(magicinterp, tobj);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
#else
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
TxPrintf("Side overlap halo is %s\n", halodisp);
#endif
return;
}
@ -1150,12 +1153,12 @@ CmdExtract(
}
else if (argc == 2)
{
char *stepdisp;
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
Tcl_SetObjResult(magicinterp, tobj);
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
#else
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
TxPrintf("Extraction step size is %s\n", stepdisp);
#endif
return;
}
@ -1280,6 +1283,7 @@ CmdExtract(
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
return;
#undef OPTSET
}
@ -1309,6 +1313,7 @@ CmdExtract(
case DORESISTANCE: option = EXT_DORESISTANCE; break;
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
case DOALIASES: option = EXT_DOALIASES; break;
case DOUNIQUE: option = EXT_DOUNIQUE; break;
case DOLOCAL:
/* "extract do local" and "extract no local" are kept for
* backwards compatibility, but now effectively implement

View File

@ -102,15 +102,17 @@ struct cmdFPArg
int
feedPolyFunc(
Tile *tile,
TileType dinfo,
struct cmdFPArg *arg)
{
Rect area;
TiToRect(tile, &area);
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
arg->style |
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
/* (preserve information about the geometry of a diagonal tile) */
((TiGetTypeExact(tile) | dinfo) &
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
return 0;
}
@ -507,13 +509,15 @@ struct cmdFillArea *cmdFillList; /* List of areas to fill. */
void
CmdFill(
MagWindow *w, /* Window in which command was invoked. */
MagWindow *w, /* Window in which command was invoked. */
TxCommand *cmd) /* Describes the command that was invoked. */
{
TileTypeBitMask maskBits;
Rect editBox;
SearchContext scx;
extern int cmdFillFunc(Tile *tile, TreeContext *cxp);
/* Forward declaration */
extern int cmdFillFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
{
@ -581,13 +585,15 @@ CmdFill(
/* Now that we've got all the material, scan over the list
* painting the material and freeing up the entries on the list.
*/
free_magic1_t mm1 = freeMagic1_init();
while (cmdFillList != NULL)
{
DBPaint(EditCellUse->cu_def, &cmdFillList->cfa_area,
cmdFillList->cfa_type);
freeMagic((char *) cmdFillList);
freeMagic1(&mm1, (char *) cmdFillList);
cmdFillList = cmdFillList->cfa_next;
}
freeMagic1_end(&mm1);
SelectClear();
DBAdjustLabels(EditCellUse->cu_def, &editBox);
@ -601,11 +607,16 @@ CmdFill(
* paint here it may mess up the search. Instead, the procedures
* save areas on a list. The list is post-processed to paint the
* areas once the search is finished.
*
* Split tile information is unused because there is no obvious
* meaning to "filling" from a split tile, although probably reasonable
* methods could be worked out.
*/
int
cmdFillFunc(
Tile *tile, /* Tile to fill with. */
TileType dinfo, /* Split tile information (unused) */
TreeContext *cxp) /* Describes state of search. */
{
Rect r1, r2;
@ -841,7 +852,7 @@ CmdFindLabel(
return;
};
labname = cmd->tx_argv[1 + (doglob) ? 1 : 0];
labname = cmd->tx_argv[1 + ((doglob) ? 1 : 0)];
labUse = EditCellUse;
if (labUse == NULL) labUse = (CellUse *)w->w_surfaceID;
@ -1208,7 +1219,7 @@ CmdGetnode(
TxError("Put the cursor in a layout window\n");
return;
}
if( is_fast == TRUE )
if (is_fast == TRUE)
{
SimRecomputeSel = TRUE;
SimGetsnode();
@ -1216,7 +1227,8 @@ CmdGetnode(
else
SimGetnode();
if (SimGetnodeAlias) { /* "erase" the hash table */
if (SimGetnodeAlias) /* "erase" the hash table */
{
HashKill(&SimGNAliasTbl);
HashInit(&SimGNAliasTbl, 120, STRINGS);
}
@ -1602,7 +1614,7 @@ CmdFindNetProc(
int pnum, xpos, ypos;
char *xstr, *ystr;
bool locvalid = FALSE, usefound = TRUE;
TileType ttype;
TileType ttype, dinfo = (TileType)0;
scx.scx_use = use;
scx.scx_trans = GeoIdentityTransform;
@ -1640,6 +1652,7 @@ CmdFindNetProc(
if ((xstr = strchr(s, '_')) != NULL)
{
char *hashpos;
bool isNeg = FALSE;
/* The characters up to the leading '_' should match one of the */
@ -1683,6 +1696,17 @@ CmdFindNetProc(
}
}
}
/* Format variant used for node regions where a split tile
* occupies the root position of the node but the tile type
* belonging to the node is on the right side of the tile,
* not at the location encoded into the name. An 'x' is
* added before the final hash sign.
*/
hashpos = strrchr(s, '#');
if (hashpos != NULL)
if (*(hashpos - 1) == 'r')
dinfo = TT_DIAGONAL | TT_SIDE;
}
}
@ -1705,17 +1729,23 @@ checklocal:
if (locvalid == TRUE)
{
int findTile(Tile *tile, TileType *rtype);
int findTile(Tile *tile, TileType dinfo, TileAndDinfo *tad);
CellDef *targetdef = use->cu_def;
Plane *plane = targetdef->cd_planes[pnum];
ttype = TT_SPACE; /* revert to space in case of failure */
TileAndDinfo tad;
/* Find the tile type of the tile at the specified point which */
/* exists on the plane pnum. */
/* exists on the plane pnum. Note that in the case of a split */
/* tile region marked with "x" in the name, it does not work to */
/* call DBSrPainNMArea() because the diagonal position is not */
/* known. findTile() determines the proper type and leaves it */
/* in the tad.tad_dinfo record. */
tad.tad_tile = (Tile *)NULL;
tad.tad_dinfo = dinfo;
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
(ClientData) &ttype);
(ClientData) &tad);
ttype = tad.tad_dinfo & TT_LEFTMASK;
}
else
{
@ -1783,7 +1813,7 @@ CmdGoto(
MagWindow *w,
TxCommand *cmd)
{
char *s, *nodename = cmd->tx_argv[1];
char *nodename = cmd->tx_argv[1];
Rect rect;
CellUse *use;
int locargc;
@ -1824,9 +1854,9 @@ CmdGoto(
/* are multiple layers drawn at the indicated point. */
#ifdef MAGIC_WRAPPER
Tcl_SetResult(magicinterp, DBTypeLongName(ttype), NULL);
Tcl_SetResult(magicinterp, (char*)DBTypeLongName(ttype), NULL); /* Tcl treats as const */
#else
TxPrintf("node %s is type %s\n", s, DBTypeLongName(ttype));
TxPrintf("node %s is type %s\n", nodename, DBTypeLongName(ttype));
#endif
}
@ -1839,20 +1869,31 @@ CmdGoto(
int
findTile(
Tile *tile,
TileType *rtype)
TileType dinfo, /* (unused) */
TileAndDinfo *tad)
{
TileType ttype;
/* Note that since all types are being searched, a split
* tile would cause the callback to be called twice. But
* this routine will pick the indicated side from the
* "tad" structure and return 1 so it does not get called
* a second time. The "dinfo" value passed is irrelevant.
*/
if (IsSplit(tile))
{
if (SplitSide(tile))
if (tad->tad_dinfo & TT_SIDE)
ttype = SplitRightType(tile);
else
ttype = SplitLeftType(tile);
}
else
ttype = TiGetTypeExact(tile);
*rtype = ttype;
/* Leave the tile type in tad_dinfo before returning */
tad->tad_dinfo = ttype;
return 1; /* stop search */
}

View File

@ -2176,11 +2176,15 @@ parseindex:
{
if ((int)sl->lab_port == idx)
{
TxError("Port index %d is already used by port %s.\n"
"Use command \"port index %d\" to force "
"equivalence after defining the port.\n",
idx, sl->lab_text, idx);
return;
/* This is only an error if port name doesn't match */
if (strcmp(sl->lab_text, lab->lab_text))
{
TxError("Port index %d is already used by port %s.\n"
"Use command \"port index %d\" to force "
"equivalence after defining the port.\n",
idx, sl->lab_text, idx);
return;
}
}
}
}
@ -2431,14 +2435,14 @@ printPropertiesFunc(
}
else
{
keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2);
sprintf(keyvalue, "%s %s", name, (char *)value);
keyvalue = (char *)mallocMagic(strlen(name) + strlen((const char *)value) + 2);
sprintf(keyvalue, "%s %s", name, (const char *)value);
}
Tcl_AppendElement(magicinterp, keyvalue);
freeMagic(keyvalue);
#else
TxPrintf("%s = %s\n", name, value);
TxPrintf("%s = %s\n", name, (const char *)value);
#endif
return 0; /* keep the search alive */

View File

@ -99,7 +99,7 @@ CmdRandom(
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(random()));
#else
TxPrintf("%d", random());
TxPrintf("%ld", random());
#endif
}
else if ((cmd->tx_argc >= 2) && (!strcmp(cmd->tx_argv[1], "seed")))
@ -220,8 +220,6 @@ CmdSave(
DBUpdateStamps(locDef);
if (cmd->tx_argc == 2)
{
char *fileName;
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
return;
@ -1086,25 +1084,33 @@ CmdSelect(
*/
case SEL_BBOX:
{
char *selllx, *sellly, *selurx, *selury;
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
selllx = DBWPrintValue(selarea.r_xbot, w, TRUE);
sellly = DBWPrintValue(selarea.r_ybot, w, FALSE);
selurx = DBWPrintValue(selarea.r_xtop, w, TRUE);
selury = DBWPrintValue(selarea.r_ytop, w, FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_xbot));
Tcl_NewStringObj(selllx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_ybot));
Tcl_NewStringObj(sellly, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_xtop));
Tcl_NewStringObj(selurx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(selarea.r_ytop));
Tcl_NewStringObj(selury, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Select bounding box: %d %d %d %d\n",
selarea.r_xbot, selarea.r_ybot,
selarea.r_xtop, selarea.r_ytop);
TxPrintf("Select bounding box: %s %s %s %s\n",
selllx, sellly, selurx, selury);
#endif
return;
}
/*--------------------------------------------------------------------
* Make a copy of the selection at its present loction but do not
@ -1121,14 +1127,36 @@ CmdSelect(
/*--------------------------------------------------------------------
* Move the selection relative to the cell def
* With two additional arguments: Arguments are X and Y position
* With no additional arugments: X and Y position taken from pointer.
*--------------------------------------------------------------------
*/
case SEL_MOVE:
if ((more) || (less) || (primargs != 4)) goto usageError;
if ((more) || (less) || ((primargs != 4) && (primargs != 2)))
goto usageError;
p.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
p.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
if (primargs == 2)
{
MagWindow *window;
Rect rootBox;
window = ToolGetPoint(&p, (Rect *)NULL);
if ((window == NULL) ||
!ToolGetBox(&SelectRootDef, &rootBox) ||
(EditRootDef != ((CellUse *) window->w_surfaceID)->cu_def))
{
TxError("Error: Pointer is not in the edit cell.\n");
return;
}
p.p_x -= rootBox.r_xbot;
p.p_y -= rootBox.r_ybot;
}
else
{
p.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
p.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
}
/* Erase first, then recompute the transform */
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
@ -1236,15 +1264,17 @@ CmdSelect(
/* of rlist) */
SelectClear();
free_magic1_t mm1 = freeMagic1_init();
while (rlist != NULL)
{
/* Paint rlist back into SelectDef */
DBPaint(SelectDef, &rlist->r_r, rlist->r_type);
/* cleanup as we go */
freeMagic(rlist);
freeMagic1(&mm1, rlist);
rlist = rlist->r_next;
}
freeMagic1_end(&mm1);
/* Force erase and redraw of the selection */
DBReComputeBbox(SelectDef);
@ -1963,23 +1993,25 @@ cmdLabelRectFunc(
if (rect == NULL)
{
char *labllx, *lablly, *laburx, *labury;
/* Note: Ideally, the MagWindow pointer should be passed to this function */
labllx = DBWPrintValue(label->lab_rect.r_xbot, (MagWindow *)NULL, TRUE);
lablly = DBWPrintValue(label->lab_rect.r_ybot, (MagWindow *)NULL, FALSE);
laburx = DBWPrintValue(label->lab_rect.r_xtop, (MagWindow *)NULL, TRUE);
labury = DBWPrintValue(label->lab_rect.r_ytop, (MagWindow *)NULL, FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_GetObjResult(magicinterp);
pobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_xbot));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_ybot));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_xtop));
Tcl_ListObjAppendElement(magicinterp, pobj,
Tcl_NewIntObj((double)label->lab_rect.r_ytop));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labllx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(lablly, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laburx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labury, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%d %d %d %d\n",
label->lab_rect.r_xbot, label->lab_rect.r_ybot,
label->lab_rect.r_xtop, label->lab_rect.r_ytop);
TxPrintf("%s %s %s %s\n", labllx, lablly, laburx,labury);
#endif
}
else if (!GEO_SAMERECT(label->lab_rect, *rect))
@ -2295,11 +2327,13 @@ CmdSetLabel(
{
if (locargc == 2)
{
char *labsize;
labsize = DBWPrintValue(DefaultLabel->lab_size, w, FALSE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp,
Tcl_NewIntObj(DefaultLabel->lab_size));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(labsize, -1));
#else
TxPrintf("%d\n", DefaultLabel->lab_size);
TxPrintf("%s\n", labsize);
#endif
}
else
@ -2338,16 +2372,20 @@ CmdSetLabel(
{
if (locargc == 2)
{
char *laboffx, *laboffy;
laboffx = DBWPrintValue(DefaultLabel->lab_offset.p_x, w,
TRUE);
laboffy = DBWPrintValue(DefaultLabel->lab_offset.p_y, w,
FALSE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(DefaultLabel->lab_offset.p_x));
Tcl_NewStringObj(laboffx, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(DefaultLabel->lab_offset.p_y));
Tcl_NewStringObj(laboffy, -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("%d %d\n", DefaultLabel->lab_offset.p_x,
DefaultLabel->lab_offset.p_y);
TxPrintf("%s %s\n", laboffx, laboffy);
#endif
}
else
@ -2514,7 +2552,7 @@ CmdSetLabel(
else
#ifdef MAGIC_WRAPPER
Tcl_SetResult(magicinterp,
DBTypeLongNameTbl[DefaultLabel->lab_type],
(char*)DBTypeLongNameTbl[DefaultLabel->lab_type], /* Tcl treats as const */
TCL_VOLATILE);
#else
TxPrintf("%s\n", DBTypeLongNameTbl[DefaultLabel->lab_type]);
@ -2764,7 +2802,7 @@ CmdSimCmd(
{
static char cmdbuf[200];
char *strptr;
char *nodeCmd;
const char *nodeCmd;
int i;
if (!SimRsimRunning) {
@ -2865,13 +2903,13 @@ CmdSnap(
switch (n)
{
case SNAP_OFF: case SNAP_INTERNAL:
DBWSnapToGrid = DBW_SNAP_INTERNAL;
DBWSnapToGrid = DBW_UNITS_INTERNAL;
return;
case SNAP_LAMBDA:
DBWSnapToGrid = DBW_SNAP_LAMBDA;
DBWSnapToGrid = DBW_UNITS_LAMBDA;
return;
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
DBWSnapToGrid = DBW_SNAP_USER;
DBWSnapToGrid = DBW_UNITS_USER;
return;
}
@ -2879,21 +2917,19 @@ printit:
if (n == SNAP_LIST) /* list */
#ifdef MAGIC_WRAPPER
Tcl_SetResult(magicinterp,
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"),
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"),
TCL_VOLATILE);
#else
TxPrintf("%s\n", (DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
TxPrintf("%s\n", (DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
#endif
else
TxPrintf("Box is aligned to %s grid\n",
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -73,9 +73,22 @@ TileTypeBitMask CmdYMAllButSpace;
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
* Units without any suffix are assumed to be in lambda if "snap"
* (DBWSnapToGrid) is set to lambda, grid units if "snap" is set to the
* user grid, and internal units otherwise.
* Traditional (backwards-compatible) behavior: Units without any suffix
* are assumed to be in lambda if "snap" (DBWSnapToGrid) is set to lambda,
* grid units if "snap" is set to the user grid, and internal units otherwise.
* Current behavior: Use of the "units" command to set the units to
* any value other than "default" causes cmdScaleCoord() to parse any
* units provided without an identifying suffix as the units indicted by
* the "units" command. Once the "units" command has been issued, the
* values are dependent on DBWUnits and not on DBWSnapToGrid.
*
* Additional behavior from magic version 8.3.596: A single command
* option can use simple expressions using '+', '-', '*', and '/'. These
* can be passed as a single token, without spaces, or within a string
* token deliniated by quotes or braces, per usual Tcl syntax. Unlike
* the Tcl "expr" command, this can solve arithmetic expressions of
* suffixed values, evaluated independently such that different suffixes
* may be used (e.g., "1g + 3um" meaning 1 grid pitch plus 3 microns).
*
* MagWindow argument w is used only with grid-based snapping, to find
* the value of the grid for the given window. In this case, because the
@ -99,6 +112,13 @@ TileTypeBitMask CmdYMAllButSpace;
* ----------------------------------------------------------------------------
*/
#define PARSEOP_NONE 0
#define PARSEOP_ADD 1
#define PARSEOP_SUB 2
#define PARSEOP_MUL 3
#define PARSEOP_DIV 4
#define PARSEOP_END 5
int
cmdScaleCoord(
MagWindow *w,
@ -109,107 +129,184 @@ cmdScaleCoord(
{
char *endptr;
double dval = 0;
int mscale = 1;
int mscale = 1, curunits;
int retval, curval, parseop;
DBWclientRec *crec;
if (*arg == '{') arg++;
while (isspace(*arg)) arg++;
if (*arg == '{' || *arg == '"') arg++;
while (isspace(*arg) && (*arg != '\0')) arg++;
dval = strtod(arg, &endptr);
dval *= (double)scale;
parseop = PARSEOP_NONE;
retval = 0;
while (*arg != '\0')
{
dval = strtod(arg, &endptr);
dval *= (double)scale;
mscale = -1;
if (endptr == arg)
{
/* strtod() error condition */
TxError("Coordinate value cannot be parsed: assuming 0\n");
return 0;
}
else if ((*endptr == 'l')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
{
/* lambda or default units */
dval *= (double)DBLambda[1];
dval /= (double)DBLambda[0];
return round(dval);
}
else if ((*endptr == 'i')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
{
/* internal units */
return round(dval);
}
else if ((*endptr == 'g')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
{
/* grid units */
if (w == (MagWindow *)NULL)
if (endptr == arg)
{
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *)NULL)
return round(dval); /* Default, if window is unknown */
/* strtod() error condition */
TxError("Coordinate value cannot be parsed: assuming 0\n");
curval = 0;
break;
}
crec = (DBWclientRec *) w->w_clientData;
if (is_x)
/* Original behavior was to accept un-suffixed values according to the
* "snap" setting. This behavior remains in effect until the "units"
* command is used, in which case units follow the selected units
* value indepedendently of the snap setting.
*/
if (DBWUnits == DBW_UNITS_DEFAULT)
curunits = DBWSnapToGrid;
else
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
if ((*endptr == 'l')
|| ((*endptr == '\0') && (curunits == DBW_UNITS_LAMBDA)))
{
dval *= (double)(crec->dbw_gridRect.r_xtop
/* lambda or default units */
dval *= (double)DBLambda[1];
dval /= (double)DBLambda[0];
}
else if ((*endptr == 'i')
|| ((*endptr == '\0') && (curunits == DBW_UNITS_INTERNAL)))
{
/* internal units */
}
else if ((*endptr == 'g')
|| ((*endptr == '\0') && (curunits == DBW_UNITS_USER)))
{
/* grid units */
if (w == (MagWindow *)NULL)
{
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *)NULL)
{
curval = round(dval); /* Default, if window is unknown */
break;
}
}
crec = (DBWclientRec *) w->w_clientData;
if (is_x)
{
dval *= (double)(crec->dbw_gridRect.r_xtop
- crec->dbw_gridRect.r_xbot);
if (!is_relative)
dval += (double)crec->dbw_gridRect.r_xbot;
if (!is_relative)
dval += (double)crec->dbw_gridRect.r_xbot;
}
else
{
dval *= (double)(crec->dbw_gridRect.r_ytop
- crec->dbw_gridRect.r_ybot);
if (!is_relative)
dval += (double)crec->dbw_gridRect.r_ybot;
}
}
else if (*endptr == '\0' && (curunits == DBW_UNITS_MICRONS))
{
mscale = 1000;
}
else
{
dval *= (double)(crec->dbw_gridRect.r_ytop
- crec->dbw_gridRect.r_ybot);
if (!is_relative)
dval += (double)crec->dbw_gridRect.r_ybot;
/* natural units referred to the current cifoutput style */
if (*(endptr + 1) == 'm')
{
switch (*endptr)
{
case 'n':
mscale = 1;
break;
case 'u':
mscale = 1000;
break;
case 'm':
mscale = 1000000;
break;
case 'c':
mscale = 10000000;
break;
default:
TxError("Unknown metric prefix \"%cm\"; assuming "
"internal units\n", *endptr);
mscale = -1;
}
}
else if ((*endptr == 'u') && !isalnum(*(endptr + 1)))
/* Maybe "u" is too ambiguous but it is very commonly used as
* an abbreviation for "micron".
*/
mscale = 1000;
else if (!strncmp(endptr, "micron", 6))
mscale = 1000;
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
mscale = 10;
else if (!isspace(*endptr) && (*endptr != '+') && (*endptr != '-') &&
(*endptr != '*') && (*endptr != '/'))
{
TxError("Unknown coordinate type at \"%s\"; assuming internal units\n",
endptr);
mscale = -1;
}
}
return round(dval);
}
else
{
/* natural units referred to the current cifoutput style */
if (*(endptr + 1) == 'm')
if ((mscale != -1) && !isspace(*endptr))
dval /= CIFGetOutputScale(mscale);
curval = round(dval);
switch (parseop)
{
case PARSEOP_NONE:
retval = curval;
break;
case PARSEOP_ADD:
retval += curval;
break;
case PARSEOP_SUB:
retval -= curval;
break;
case PARSEOP_MUL:
retval *= curval;
break;
case PARSEOP_DIV:
retval /= curval;
break;
}
parseop = PARSEOP_NONE;
while (*endptr != '\0')
{
switch (*endptr)
{
case 'n':
mscale = 1;
case '}':
case '"':
parseop = PARSEOP_END;
break;
case 'u':
mscale = 1000;
case '+':
parseop = PARSEOP_ADD;
endptr++;
break;
case 'm':
mscale = 1000000;
case '-':
parseop = PARSEOP_SUB;
endptr++;
break;
case 'c':
mscale = 10000000;
case '*':
parseop = PARSEOP_MUL;
endptr++;
break;
case '/':
parseop = PARSEOP_DIV;
endptr++;
break;
default:
TxError("Unknown metric prefix \"%cm\"; assuming internal units\n",
*endptr);
return round(dval);
endptr++;
break;
}
if (parseop != PARSEOP_NONE) break;
}
else if (!strcmp(endptr, "u"))
/* Maybe "u" is too ambiguous but it is very commonly used as
* an abbreviation for "micron".
*/
mscale = 1000;
else if (!strncmp(endptr, "micron", 6))
mscale = 1000;
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
mscale = 10;
else if (!isspace(*endptr))
{
TxError("Unknown coordinate type \"%s\"; assuming internal units\n",
endptr);
return round(dval);
}
arg = endptr;
while (isspace(*arg) && (*arg != '\0')) arg++;
}
if (!isspace(*endptr))
dval /= CIFGetOutputScale(mscale);
return round(dval);
return retval;
}
/*
@ -1196,6 +1293,17 @@ cmdGetSelFunc(
return 1; /* Skip any other selected cells. */
}
/* The Open Group, Sep 2006, Austin/317 deprecated isascii(),
* Apparently it cannot be used portably in a localized application.
*/
static int
magic_isascii(int c)
{
return (c & ~0x7f) == 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -1228,7 +1336,7 @@ CmdIllegalChars(
for (p = string; *p != 0; p++)
{
if (!isascii(*p)) goto error;
if (!magic_isascii(*p)) goto error;
if (iscntrl(*p)) goto error;
for (bad = illegal; *bad != 0; bad++)
{
@ -1237,7 +1345,7 @@ CmdIllegalChars(
continue;
error:
if (!isascii(*p) || iscntrl(*p))
if (!magic_isascii(*p) || iscntrl(*p))
{
TxError("%s contains illegal control character 0x%x\n",
msg, *p);

View File

@ -61,7 +61,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
int
existFunc(
Tile *tile)
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
return 1;
}
@ -453,15 +455,18 @@ CmdTech(
}
if (!strncmp(cmd->tx_argv[2], "width", 5))
{
char *techwidth;
tresult = DRCGetDefaultLayerWidth(t1);
techwidth = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techwidth, -1));
#else
TxPrintf("Minimum width is %d\n", tresult);
TxPrintf("Minimum width is %s\n", techwidth);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
{
char *techspace;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@ -473,14 +478,16 @@ CmdTech(
else
t2 = t1;
tresult = DRCGetDefaultLayerSpacing(t1, t2);
techspace = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techspace, -1));
#else
TxPrintf("Minimum spacing is %d\n", tresult);
TxPrintf("Minimum spacing is %s\n", techspace);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
{
char *techsurround;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@ -496,14 +503,17 @@ CmdTech(
}
tresult = DRCGetDefaultLayerSurround(t1, t2);
techsurround = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techsurround, -1));
#else
TxPrintf("Minimum surround is %d\n", tresult);
TxPrintf("Minimum surround is %s\n", techsurround);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
{
char *techdirec;
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
@ -519,10 +529,11 @@ CmdTech(
}
tresult = DRCGetDirectionalLayerSurround(t1, t2);
techdirec = DBWPrintValue(tresult, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techdirec, -1));
#else
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
TxPrintf("Minimum surround (in one orientation) is %s\n", techdirec);
#endif
}
}
@ -671,6 +682,15 @@ CmdTool(
if (strcmp(cmd->tx_argv[1], "info") == 0)
DBWPrintButtonDoc();
else if (strcmp(cmd->tx_argv[1], "type") == 0)
{
char *toolType = DBWGetButtonHandler();
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(toolType, -1));
#else
TxPrintf("Current tool is \"%s\".\n", toolType);
#endif /* MAGIC_WRAPPER */
}
else (void) DBWChangeButtonHandler(cmd->tx_argv[1]);
}
@ -743,6 +763,182 @@ cmdUnexpandFunc(
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* CmdUnits --
*
* Implement the "units" command.
*
* Usage:
* units [value] [print|noprint]
*
* where "value" may be one of "default", "internal", "lambda",
* "user" (equivalently "grid"), or "microns".
*
* Results:
* None.
*
* Side effects:
* The global variable DBWUnits may be changed, which changes the
* behavior of magic when interpreting un-suffixed values or
* displaying values.
*
* Notes:
* The units behavior was previously dependent on what command was
* issued, with results usually being given in internal units, and
* with un-suffixed values following the snap behavior. Backwards-
* compatible behavior is used on startup or at any time by setting
* the units to "default". Otherwise, unit display follows the
* given "units" setting.
*
* ----------------------------------------------------------------------------
*/
#define UNITS_DEFAULT 0
#define UNITS_INTERNAL 1
#define UNITS_LAMBDA 2
#define UNITS_GRID 3
#define UNITS_USER 4
#define UNITS_MICRONS 5
#define UNITS_LIST 6
#define UNITS_PRINT 7
#define UNITS_NOPRINT 8
void
CmdUnits(
MagWindow *w,
TxCommand *cmd)
{
static const char * const names[] = { "default", "internal", "lambda",
"grid", "user", "microns", "list", "print", "noprint", 0 };
int idx, n = UNITS_LIST, n2, saveflag;
DBWclientRec *crec;
if (cmd->tx_argc >= 2)
{
n = Lookup(cmd->tx_argv[1], names);
if (n < 0)
{
TxPrintf("Usage: units [default | internal | lambda | microns"
" | user] [print]\n");
return;
}
if (DBWUnits != DBW_UNITS_DEFAULT)
saveflag = DBWUnits & DBW_UNITS_PRINT_FLAG;
else
saveflag = -1;
switch (n)
{
case UNITS_DEFAULT:
DBWUnits = DBW_UNITS_DEFAULT;
break;
case UNITS_INTERNAL:
DBWUnits = DBW_UNITS_INTERNAL;
break;
case UNITS_LAMBDA:
DBWUnits = DBW_UNITS_LAMBDA;
break;
case UNITS_USER:
case UNITS_GRID:
DBWUnits = DBW_UNITS_USER;
break;
case UNITS_MICRONS:
DBWUnits = DBW_UNITS_MICRONS;
break;
case UNITS_PRINT:
saveflag = DBW_UNITS_PRINT_FLAG;
break;
case UNITS_NOPRINT:
saveflag = 0;
break;
}
if (n < 0)
{
TxError("Unrecognized units option %s\n.", cmd->tx_argv[1]);
return;
}
if (n != UNITS_LIST)
{
if ((cmd->tx_argc == 3) && (n != UNITS_DEFAULT))
{
n2 = Lookup(cmd->tx_argv[2], names);
switch (n2)
{
case UNITS_PRINT:
DBWUnits |= DBW_UNITS_PRINT_FLAG;
break;
case UNITS_NOPRINT:
DBWUnits &= DBW_UNITS_TYPE_MASK;
break;
default:
TxError("Unrecognized units option %s\n.", cmd->tx_argv[2]);
break;
}
}
else if ((n != UNITS_DEFAULT) && (saveflag != -1))
{
/* Preserve the previous value of the print/noprint flag */
DBWUnits &= DBW_UNITS_TYPE_MASK;
DBWUnits |= saveflag;
}
return;
}
}
if (DBWUnits == DBW_UNITS_DEFAULT)
idx = UNITS_DEFAULT;
else
switch (DBWUnits & DBW_UNITS_TYPE_MASK)
{
case DBW_UNITS_INTERNAL:
idx = UNITS_INTERNAL;
break;
case DBW_UNITS_LAMBDA:
idx = UNITS_LAMBDA;
break;
case DBW_UNITS_USER:
idx = UNITS_USER;
break;
case DBW_UNITS_MICRONS:
idx = UNITS_MICRONS;
break;
}
if (n == UNITS_LIST) /* list */
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj((char *)names[idx], -1));
if (idx != UNITS_DEFAULT)
{
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj("print", 5));
else
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj("noprint", 7));
}
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("%s", names[idx]);
if (idx != UNITS_DEFAULT)
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
TxPrintf(" print");
TxPrintf("\n");
#endif
}
else if (idx == UNITS_DEFAULT)
TxPrintf("Reported units follow the snap setting.\n");
else if (DBWUnits & DBW_UNITS_PRINT_FLAG)
TxPrintf("Values are reported as %s, along with the units.\n", names[idx]);
else
TxPrintf("Values are reported as %s\n", names[idx]);
}
/*
* ----------------------------------------------------------------------------
*
@ -830,7 +1026,8 @@ struct linked_id {
int
cmdWhatPrintCell(
Tile *tile,
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
TreeContext *cxp)
{
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
@ -885,6 +1082,7 @@ static LabelStore *labelBlockTop, *labelEntry;
int
cmdFindWhatTileFunc(
Tile *tile,
TileType dinfo,
ClientData clientData)
{
struct linked_id **lid = (struct linked_id **)clientData;
@ -896,7 +1094,7 @@ cmdFindWhatTileFunc(
scx.scx_use = EditCellUse;
scx.scx_trans = GeoIdentityTransform;
if (SplitSide(tile))
if (dinfo & TT_SIDE)
type = SplitRightType(tile);
else
type = SplitLeftType(tile);
@ -1094,11 +1292,13 @@ CmdWhat(
}
#endif
while (lid != NULL)
{
freeMagic(lid);
free_magic1_t mm1 = freeMagic1_init();
while (lid != NULL)
{
freeMagic1(&mm1, lid);
lid = lid->lid_next;
}
freeMagic1_end(&mm1);
#ifdef MAGIC_WRAPPER
if (doListAll)
Tcl_ListObjAppendElement(magicinterp, paintobj,
@ -1681,18 +1881,20 @@ CmdWire(
case VALUES:
if (locargc == 2)
{
char *wdisp;
width = WireGetWidth();
type = WireGetType();
wdisp = DBWPrintValue(width, w, TRUE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewIntObj(width));
Tcl_NewStringObj(wdisp, -1));
Tcl_ListObjAppendElement(magicinterp, lobj,
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Wire layer %s, width %d\n",
DBTypeLongNameTbl[type], width);
TxPrintf("Wire layer %s, width %s\n",
DBTypeLongNameTbl[type], wdisp);
#endif
}
break;
@ -1717,12 +1919,14 @@ CmdWire(
case WIDTH:
if (locargc == 2)
{
char *wdisp;
width = WireGetWidth();
wdisp = DBWPrintValue(width, w, TRUE);
#ifdef MAGIC_WRAPPER
lobj = Tcl_NewIntObj(width);
lobj = Tcl_NewStringObj(wdisp, -1);
Tcl_SetObjResult(magicinterp, lobj);
#else
TxPrintf("Wire width is %d\n", width);
TxPrintf("Wire width is %s\n", wdisp);
#endif
}
else if (locargc != 3)
@ -1945,7 +2149,7 @@ CmdWriteall(
option = Lookup(cmd->tx_argv[1], writeallOpts);
if (option < 0)
{
TxError("Usage: %s [force|modified|noupdate [cellname ...]]\n",
TxError("Usage: %s [force|modified [cellname ...]]\n",
cmd->tx_argv[0]);
return;
}

View File

@ -47,6 +47,10 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/utils.h"
#include "textio/txcommands.h"
/* For diagnostics */
#include "cif/CIFint.h"
#include "database/databaseInt.h"
/* C99 compat */
#include "extract/extract.h"
@ -189,6 +193,234 @@ CmdExtractTest(
}
#endif
/*
* ----------------------------------------------------------------------------
*
* tileCountProc --
*
* Routine to count tiles.
*
* Return:
* 0 to keep the search going
*
* Side effects:
* Keeps count in clientData
*
* ----------------------------------------------------------------------------
*/
int
tileCountProc(
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
int *tcount)
{
(*tcount)++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* showMem --
* CmdShowmem --
*
* Usage:
*
* showmem [outfile]
*
* Display all the (principle) internal memory usage for tiles, including
* all cell defs, and all CIF generated planes.
*
* Results:
* None.
*
* Side effects:
* May write to a disk file.
*
* ----------------------------------------------------------------------------
*/
void
showMem(
FILE *outf, /* File to which information is to be output */
bool verbose) /* If TRUE, output detailed erase table */
{
int ttotal, ttotal1, ttotal2;
int i;
Plane *plane;
CellDef *def;
int pNum;
HashSearch hs;
HashEntry *entry;
fprintf(outf, "Tile memory usage summary\n");
fprintf(outf, "Technology %s\n", DBTechName);
/* Search every cell def (including internal ones), count tiles,
* and add up the tile memory usage on every plane.
*/
/* Search the CIFPlanes and count tiles. */
/* CIFPlanes, CIFTotalPlanes, CIFComponentPlanes */
ttotal2 = 0;
if (CIFCurStyle != NULL)
{
fprintf(outf, "\nCIFPlanes:\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %d\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
fprintf(outf, "\nCIFTotalPlanes\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFTotalPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %d\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
fprintf(outf, "\nCIFComponentPlanes\n");
ttotal1 = 0;
for (i = 0; i < MAXCIFLAYERS; i++)
{
plane = CIFComponentPlanes[i];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
ttotal1 += ttotal;
if (CIFCurStyle->cs_layers[i])
fprintf(outf, " layer %s: %ld bytes\n",
CIFCurStyle->cs_layers[i]->cl_name,
(long)ttotal * (long)sizeof(Tile));
else
fprintf(outf, " layer %d: %ld bytes\n", i,
(long)ttotal * (long)sizeof(Tile));
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
}
else
{
fprintf(outf, "CIF planes: No memory usage\n");
}
HashStartSearch(&hs);
while ((entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
def = (CellDef *)HashGetValue(entry);
if (def != (CellDef *)NULL)
{
fprintf(outf, "\nCell def %s\n", def->cd_name);
ttotal1 = 0;
for (pNum = 0; pNum < DBNumPlanes; pNum++)
{
plane = def->cd_planes[pNum];
if (plane != NULL)
{
ttotal = 0;
DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllTypeBits, tileCountProc, &ttotal);
fprintf(outf, " plane %s: %ld bytes\n",
DBPlaneLongNameTbl[pNum],
(long)ttotal * (long)sizeof(Tile));
ttotal1 += ttotal;
}
}
fprintf(outf, " Subtotal: %ld bytes\n",
(long)ttotal1 * (long)sizeof(Tile));
ttotal2 += ttotal1;
}
}
fprintf(outf, " Grand total: %ld bytes\n",
(long)ttotal2 * (long)sizeof(Tile));
}
void
CmdShowmem(
MagWindow *w,
TxCommand *cmd)
{
FILE *outf;
bool verbose;
char **av;
int ac;
if (cmd->tx_argc > 3)
{
TxError("Usage: showmem [-v] [file]\n");
return;
}
verbose = FALSE;
av = &cmd->tx_argv[1];
ac = cmd->tx_argc - 1;
outf = stdout;
if (ac > 0 && strcmp(av[0], "-v") == 0)
{
verbose = TRUE;
av++, ac--;
}
if (ac > 0)
{
outf = fopen(av[0], "w");
if (outf == (FILE *) NULL)
{
perror(av[0]);
TxError("Nothing written\n");
return;
}
}
showMem(outf, verbose);
if (outf != stdout)
(void) fclose(outf);
}
/*
* ----------------------------------------------------------------------------
@ -232,7 +464,7 @@ showTech(
fprintf(outf, "\n");
fprintf(outf, "Types:\n");
for (i = 0; i < DBNumTypes; i++) {
int pl ; char *spl ;
int pl ; const char *spl ;
pl = DBPlane(i);
spl = ( pl <= 0 || pl > DBNumPlanes ) ? "??" : DBPlaneLongName(pl);
@ -569,11 +801,13 @@ cmdStatsCount(
CellDef *def,
struct countClient *cc)
{
int cmdStatsCountTile(Tile *tile, struct cellInfo *ci);
int pNum;
struct cellInfo *ci;
TileType t;
/* Forward declaration */
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
if (def->cd_client)
return (1);
@ -598,6 +832,7 @@ cmdStatsCount(
int
cmdStatsCountTile(
Tile *tile,
TileType dinfo, /* (unused) */
struct cellInfo *ci)
{
TileType type = TiGetType(tile);
@ -868,17 +1103,18 @@ CmdTsearch(
MagWindow *w,
TxCommand *cmd)
{
int cmdTsrFunc(Tile *tp);
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
char *rstatp;
static TileTypeBitMask mask;
static struct tms tlast, tdelta;
Rect rtool, rsearch;
/**** Rect *ebox; ****/
Plane *plane;
int i, pNum, count;
int usPerSearch, usPerTile, usPerL2, us, boxarea;
/* Forward declarations */
int cmdTsrFunc(Tile *tp, TileType dinfo, ClientData clientdata);
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
{
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
@ -978,10 +1214,12 @@ CmdTsearch(
int
cmdTsrFunc(
Tile *tp)
Tile *tp,
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
if (cmdTsearchDebug)
TxPrintf("%lx\n", (intmax_t) tp);
TxPrintf("%lx\n", (intptr_t) tp);
numTilesFound++;
return 0;
}
@ -1047,7 +1285,7 @@ CmdWatch(
pNum = DBTechNamePlane(cmd->tx_argv[1]);
if (pNum < 0)
{
char *cp;
const char *cp;
TxError("Unrecognized plane: %s. Legal names are:\n",
cmd->tx_argv[1]);
for(pNum=0; pNum < PL_MAXTYPES; pNum++) {

View File

@ -12,10 +12,9 @@ SRCS = CmdSubrs.c CmdAB.c CmdCD.c CmdE.c CmdFI.c \
module: ${MAGICDIR}/readline/readline lib${MODULE}.o
# Delegate this task to the readline/Makefile
${MAGICDIR}/readline/readline:
@if ( ! test -f ${MAGICDIR}/readline/readline ) ; then \
(cd ${MAGICDIR}/readline; ln -s `ls | grep readline` readline) ; \
fi
${MAKE} -C ${MAGICDIR}/readline readline-create-symlinks
include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak

View File

@ -20,8 +20,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/commands/commands.h,v 1.3 2009/01/19 15:43:03 tim Exp $
*/
#ifndef _COMMANDS_H
#define _COMMANDS_H
#ifndef _MAGIC__COMMANDS__COMMANDS_H
#define _MAGIC__COMMANDS__COMMANDS_H
#include "windows/windows.h"
#include "database/database.h"
@ -75,4 +75,4 @@ extern void CmdInit(void);
extern void CmdDoProperty(CellDef *def, TxCommand *cmd, int argstart);
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
#endif /* _COMMANDS_H */
#endif /* _MAGIC__COMMANDS__COMMANDS_H */

2
configure vendored
View File

@ -9,4 +9,4 @@
# script itself. It also sets up CFLAGS without the default optimizer
# flag (-O2).
( CFLAGS="-g"; export CFLAGS; cd scripts ; ./configure "$@" )
( CFLAGS=${CFLAGS:-"-g"}; export CFLAGS; cd scripts ; ./configure "$@" )

View File

@ -30,19 +30,32 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
typedef struct dbcellboundstruct
{
Rect *area;
bool extended;
Rect *extended;
bool found;
} DBCellBoundStruct;
/*
* --------------------------------------------------------------------
* DBBoundCellPlane ---
*
* Find the extents of all subcells of the cell "def", both the
* extent of geometry (rect) and the extent of geometry plus any
* labels extending outside the extent of geometry (extended).
*
* Results:
* TRUE if subcells were found and measured; FALSE if no subcells
* were found (in which case "extended" and "rect" may not be
* valid).
*
* Side effects:
* Values may be recorded in "extended" and "rect".
* --------------------------------------------------------------------
*/
int
DBBoundCellPlane(def, extended, rect)
CellDef *def;
bool extended;
Rect *extended;
Rect *rect;
{
TreeFilter filter;
@ -70,25 +83,19 @@ dbCellBoundFunc(use, fp)
CellUse *use;
TreeFilter *fp;
{
Rect *bbox;
DBCellBoundStruct *cbs;
cbs = (DBCellBoundStruct *)fp->tf_arg;
bbox = &use->cu_bbox;
if (cbs->found)
{
if (cbs->extended)
GeoInclude(&use->cu_extended, cbs->area);
else
GeoInclude(&use->cu_bbox, cbs->area);
GeoInclude(&use->cu_extended, cbs->extended);
GeoInclude(&use->cu_bbox, cbs->area);
}
else
{
if (cbs->extended)
*cbs->area = use->cu_extended;
else
*cbs->area = use->cu_bbox;
*cbs->extended = use->cu_extended;
*cbs->area = use->cu_bbox;
cbs->found = TRUE;
}
return 0;

View File

@ -108,16 +108,55 @@ DBCellFindDup(use, parent)
"DBCellFindDup");
while ((dupUse = BPEnumNext(&bpe)))
if (dupUse->cu_def == use->cu_def)
{
bool transMatch, arrayMatch, notXarray, notYarray;
/* Transforms must be equal---Aligned bounding boxes are
* an insufficient measure of exact overlap.
* an insufficient measure of exact overlap. Also, array
* counts and separation must match for arrayed devices
*/
if ((dupUse->cu_transform.t_a == use->cu_transform.t_a) &&
transMatch = ((dupUse->cu_transform.t_a == use->cu_transform.t_a) &&
(dupUse->cu_transform.t_b == use->cu_transform.t_b) &&
(dupUse->cu_transform.t_c == use->cu_transform.t_c) &&
(dupUse->cu_transform.t_d == use->cu_transform.t_d) &&
(dupUse->cu_transform.t_e == use->cu_transform.t_e) &&
(dupUse->cu_transform.t_f == use->cu_transform.t_f))
(dupUse->cu_transform.t_f == use->cu_transform.t_f));
/* First check if both use and dupUse are not arrays. */
notXarray = (dupUse->cu_xhi == dupUse->cu_xlo) &&
(use->cu_xhi == use->cu_xlo);
notYarray = (dupUse->cu_yhi == dupUse->cu_ylo) &&
(use->cu_yhi == use->cu_ylo);
arrayMatch = (notXarray && notYarray);
/* If they are arrays, then the array parameters must match. */
if (!notXarray && notYarray)
{
arrayMatch = ((dupUse->cu_xhi - dupUse->cu_xlo) ==
(use->cu_xhi - use->cu_xlo)) &&
(dupUse->cu_xsep == use->cu_xsep);
}
else if (!notYarray && notXarray)
{
arrayMatch = ((dupUse->cu_yhi - dupUse->cu_ylo) ==
(use->cu_yhi - use->cu_ylo)) &&
(dupUse->cu_ysep == use->cu_ysep);
}
else if (!notYarray && !notXarray)
{
arrayMatch = (((dupUse->cu_xhi - dupUse->cu_xlo) ==
(use->cu_xhi - use->cu_xlo)) &&
(dupUse->cu_xsep == use->cu_xsep)) &&
(((dupUse->cu_yhi - dupUse->cu_ylo) ==
(use->cu_yhi - use->cu_ylo)) &&
(dupUse->cu_ysep == use->cu_ysep));
}
if (transMatch && arrayMatch)
break;
}
BPEnumTerm(&bpe);
return dupUse;

View File

@ -619,8 +619,9 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
/*
* Include area of subcells separately
*/
if ((foundAny = DBBoundCellPlane(cellDef, TRUE, &rect)) > 0)
area = rect;
if (!((foundAny = DBBoundCellPlane(cellDef, &extended, &rect)) > 0))
extended = GeoNullRect;
area = rect;
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (pNum != PL_DRC_CHECK)
@ -634,7 +635,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
}
/*
* Include the area of labels, too.
* Include the area of label anchors, too.
*/
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
{
@ -656,7 +657,11 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
}
}
extended = area;
/* Make sure the extended bounding box includes the area of all
* paint material just found, then include the area of all text
* in the current cell.
*/
GeoInclude(&area, &extended);
if (foundAny)
{
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
@ -673,6 +678,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
degenerate = TRUE;
area.r_xbot = area.r_ybot = 0;
area.r_xtop = area.r_ytop = 1;
extended = area;
}
else degenerate = FALSE;
@ -687,7 +693,11 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
if (area.r_ybot == area.r_ytop)
area.r_ytop = area.r_ybot + 1;
if (degenerate) extended = area;
if (extended.r_xbot == extended.r_xtop)
extended.r_xtop = extended.r_xbot + 1;
if (extended.r_ybot == extended.r_ytop)
extended.r_ytop = extended.r_ybot + 1;
/* Did the bounding box change? If not then there's no need to
* recompute the parents. If the cell has no material, then

View File

@ -967,14 +967,15 @@ DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef)
*/
int
dbEraseSubFunc(tile, cxp)
dbEraseSubFunc(tile, dinfo, cxp)
Tile *tile; /* Pointer to source tile with shield type */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx;
Rect sourceRect, targetRect;
int pNum;
TileType type, loctype, subType;
TileType newdinfo, loctype, subType;
Plane *plane;
struct dbCopySubData *csd; /* Client data */
@ -983,12 +984,14 @@ dbEraseSubFunc(tile, cxp)
plane = csd->csd_plane;
pNum = csd->csd_pNum;
subType = csd->csd_subtype;
type = TiGetTypeExact(tile);
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
}
else
newdinfo = (TileType)0;
/* Construct the rect for the tile */
TITORECT(tile, &sourceRect);
@ -998,7 +1001,7 @@ dbEraseSubFunc(tile, cxp)
csd->csd_modified = TRUE;
return DBNMPaintPlane(plane, type, &targetRect, DBStdEraseTbl(subType, pNum),
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
(PaintUndoInfo *)NULL);
}
@ -1010,14 +1013,15 @@ dbEraseSubFunc(tile, cxp)
*/
int
dbPaintSubFunc(tile, cxp)
dbPaintSubFunc(tile, dinfo, cxp)
Tile *tile; /* Pointer to source tile with shield type */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx;
Rect sourceRect, targetRect;
int pNum;
TileType type, loctype, subType;
TileType newdinfo, loctype, subType;
Plane *plane;
struct dbCopySubData *csd; /* Client data */
@ -1026,12 +1030,14 @@ dbPaintSubFunc(tile, cxp)
plane = csd->csd_plane;
pNum = csd->csd_pNum;
subType = csd->csd_subtype;
type = TiGetTypeExact(tile);
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
}
else
newdinfo = (TileType)0;
/* Construct the rect for the tile */
TITORECT(tile, &sourceRect);
@ -1041,7 +1047,7 @@ dbPaintSubFunc(tile, cxp)
csd->csd_modified = TRUE;
return DBNMPaintPlane(plane, type, &targetRect, DBStdPaintTbl(subType, pNum),
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdPaintTbl(subType, pNum),
(PaintUndoInfo *)NULL);
}
@ -1054,14 +1060,15 @@ dbPaintSubFunc(tile, cxp)
*/
int
dbEraseNonSub(tile, cxp)
dbEraseNonSub(tile, dinfo, cxp)
Tile *tile; /* Pointer to tile to erase from target */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx;
Rect sourceRect, targetRect;
Plane *plane; /* Plane of target data */
TileType type, loctype, subType;
TileType newdinfo, loctype, subType;
struct dbCopySubData *csd;
int pNum;
@ -1072,12 +1079,14 @@ dbEraseNonSub(tile, cxp)
scx = cxp->tc_scx;
type = TiGetTypeExact(tile);
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
}
else
newdinfo = (TileType)0;
/* Construct the rect for the tile */
TITORECT(tile, &sourceRect);
@ -1086,7 +1095,7 @@ dbEraseNonSub(tile, cxp)
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
/* Erase the substrate type from the area of this tile in the target plane. */
return DBNMPaintPlane(plane, type, &targetRect, DBStdEraseTbl(subType, pNum),
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
(PaintUndoInfo *)NULL);
}
@ -1098,8 +1107,9 @@ dbEraseNonSub(tile, cxp)
*/
int
dbCopySubFunc(tile, csd)
dbCopySubFunc(tile, dinfo, csd)
Tile *tile; /* Pointer to tile to erase from target */
TileType dinfo; /* Split tile information */
struct dbCopySubData *csd; /* Client data */
{
Rect rect;
@ -1109,10 +1119,10 @@ dbCopySubFunc(tile, csd)
plane = csd->csd_plane;
pNum = csd->csd_pNum;
type = TiGetTypeExact(tile);
type = TiGetTypeExact(tile) | dinfo;
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
}
else
@ -1433,8 +1443,9 @@ DBCellCopyLabels(scx, mask, xMask, targetUse, pArea)
***/
int
dbCopyManhattanPaint(tile, cxp)
Tile *tile; /* Pointer to tile to copy */
dbCopyManhattanPaint(tile, dinfo, cxp)
Tile *tile; /* Pointer to tile to copy */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx = cxp->tc_scx;
@ -1480,8 +1491,9 @@ dbCopyManhattanPaint(tile, cxp)
***/
int
dbCopyAllPaint(tile, cxp)
Tile *tile; /* Pointer to tile to copy */
dbCopyAllPaint(tile, dinfo, cxp)
Tile *tile; /* Pointer to tile to copy */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx = cxp->tc_scx;
@ -1489,7 +1501,7 @@ dbCopyAllPaint(tile, cxp)
Rect sourceRect, targetRect;
PaintUndoInfo ui;
CellDef *def;
TileType type = TiGetTypeExact(tile);
TileType type = TiGetTypeExact(tile) | dinfo;
int pNum = cxp->tc_plane;
int result;
TileTypeBitMask *typeMask;
@ -1502,13 +1514,13 @@ dbCopyAllPaint(tile, cxp)
*/
bool splittile = FALSE;
TileType dinfo = 0;
TileType newdinfo = 0;
if (IsSplit(tile))
{
splittile = TRUE;
dinfo = DBTransformDiagonal(type, &scx->scx_trans);
type = (SplitSide(tile)) ? SplitRightType(tile) :
newdinfo = DBTransformDiagonal(type, &scx->scx_trans);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
SplitLeftType(tile);
}
@ -1568,7 +1580,7 @@ dbCopyAllPaint(tile, cxp)
Rect rrect, orect;
int np, i, j;
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, dinfo, points, &np);
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, newdinfo, points, &np);
if (np == 0)
return(0);
@ -1597,7 +1609,7 @@ dbCopyAllPaint(tile, cxp)
rrect.r_ybot = points[0].p_y;
rrect.r_ytop = points[2].p_y;
GeoCanonicalRect(&rrect, &targetRect);
dinfo = 0;
newdinfo = 0;
}
else if (np >= 4) /* Process extra rectangles in the area */
{
@ -1654,7 +1666,7 @@ topbottom:
splitdone:
result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
result = (*dbCurPaintPlane)(def, pNum, newdinfo | type, &targetRect, &ui);
if ((result != 0) && (arg->caa_func != NULL))
{
/* result == 1 used exclusively for DRC off-grid error flagging */

View File

@ -117,6 +117,14 @@ DBCellRename(cellname, newname, doforce)
return FALSE;
}
/* Cannot rename a cell with the name of an existing cell */
entry = HashLookOnly(&dbCellDefTable, newname);
if (entry != NULL)
{
TxError("Cannot rename; cell \"%s\" already exists!\n", newname);
return FALSE;
}
/* Disallow renaming if the cell has the READONLY flag set, */
/* because the cellname must match the name in the GDS */
/* file referenced. */
@ -312,6 +320,7 @@ DBCellDelete(cellname, force)
/* use. If so, load the window with (UNNAMED). */
UndoDisable();
free_magic1_t mm1 = freeMagic1_init();
for (celluse = celldef->cd_parents; celluse != (CellUse *) NULL;
celluse = celluse->cu_nextuse)
{
@ -320,8 +329,9 @@ DBCellDelete(cellname, force)
WindUnload(celluse);
freeMagic(celluse->cu_id);
}
freeMagic((char *)celluse);
freeMagic1(&mm1, (char *)celluse);
}
freeMagic1_end(&mm1);
celldef->cd_parents = (CellUse *)NULL;
DBWResetBox(celldef);
@ -1611,6 +1621,7 @@ dbAbutmentUseFunc(selUse, use, transform, data)
Rect bbox, refbox;
Transform *trans;
char *propvalue;
char *refllx, *reflly, *refurx, *refury;
bool found;
bool *dolist = (bool *)data;
@ -1643,21 +1654,25 @@ dbAbutmentUseFunc(selUse, use, transform, data)
}
GeoTransRect(trans, &bbox, &refbox);
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
refllx = DBWPrintValue(refbox.r_xbot, (MagWindow *)NULL, TRUE);
reflly = DBWPrintValue(refbox.r_ybot, (MagWindow *)NULL, FALSE);
refurx = DBWPrintValue(refbox.r_xtop, (MagWindow *)NULL, TRUE);
refury = DBWPrintValue(refbox.r_ytop, (MagWindow *)NULL, FALSE);
#ifdef MAGIC_WRAPPER
if (*dolist)
{
pobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xbot));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ybot));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xtop));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ytop));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refllx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(reflly, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refurx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refury, -1));
Tcl_SetObjResult(magicinterp, pobj);
}
else
#endif
TxPrintf("Abutment box: %d %d %d %d\n", refbox.r_xbot, refbox.r_ybot,
refbox.r_xtop, refbox.r_ytop);
TxPrintf("Abutment box: %s %s %s %s\n", refllx, reflly, refurx, refury);
return 0;
}
@ -1936,6 +1951,7 @@ DBCellDeleteDef(cellDef)
entry = HashFind(&dbCellDefTable, cellDef->cd_name);
ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef");
HashSetValue(entry, (ClientData) NULL);
HashRemove(&dbCellDefTable, cellDef->cd_name);
if (cellDef->cd_props)
DBPropClearAll(cellDef);
@ -1997,8 +2013,10 @@ DBCellDefFree(cellDef)
cellDef->cd_planes[pNum] = (Plane *) NULL;
}
free_magic1_t mm1 = freeMagic1_init();
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
freeMagic((char *) lab);
freeMagic1(&mm1, (char *) lab);
freeMagic1_end(&mm1);
SigEnableInterrupts();
HashKill(&cellDef->cd_idHash);

View File

@ -85,11 +85,13 @@ struct seeTypesArg
int
DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg)
{
BPEnum sbpe;
BPEnum *bpe;
CellUse *use;
int rval = 0;
bpe = (BPEnum *)mallocMagic(sizeof(BPEnum));
/* bpe = (BPEnum *)mallocMagic(sizeof(BPEnum)); */
bpe = &sbpe;
BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
while ((use = BPEnumNext(bpe)))
@ -102,7 +104,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
}
BPEnumTerm(bpe);
freeMagic(bpe);
/* freeMagic(bpe); */
return rval;
}
@ -118,6 +120,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
* int
* func(tile, cxp)
* Tile *tile;
* TileType dinfo;
* TreeContext *cxp;
* {
* }
@ -414,6 +417,7 @@ dbCellUniqueTileSrFunc(scx, fp)
* int
* func(tile, cxp)
* Tile *tile;
* TileType dinfo;
* TreeContext *cxp;
* {
* }
@ -912,8 +916,9 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
*/
int
dbSeeTypesAllSrFunc(tile, cxp)
dbSeeTypesAllSrFunc(tile, dinfo, cxp)
Tile *tile;
TileType dinfo;
TreeContext *cxp;
{
Rect tileRect;
@ -924,7 +929,7 @@ dbSeeTypesAllSrFunc(tile, cxp)
if (GEO_OVERLAP((&tileRect), area))
{
if (IsSplit(tile))
TTMaskSetType(mask, SplitSide(tile) ?
TTMaskSetType(mask, (dinfo & TT_SIDE) ?
SplitRightType(tile) : SplitLeftType(tile));
else
TTMaskSetType(mask, TiGetType(tile));
@ -1514,19 +1519,22 @@ DBScaleEverything(scalen, scaled)
}
/* Free the linked CellDef list */
free_magic1_t mm1 = freeMagic1_init();
lcd = lhead;
while (lcd != NULL)
{
freeMagic((char *)lcd);
freeMagic1(&mm1, (char *)lcd);
lcd = lcd->cd_next;
}
freeMagic1_end(&mm1);
/* Scale all elements */
DBWScaleElements(scalen, scaled);
#ifdef ROUTE_MODULE
/* Recovery of global plane pointers */
MZAttachHintPlanes();
#endif
/* Modify root box */
ToolScaleBox(scalen, scaled);
@ -1602,8 +1610,9 @@ dbScalePlane(oldplane, newplane, pnum, scalen, scaled, doCIF)
*/
int
dbTileScaleFunc(tile, scvals)
dbTileScaleFunc(tile, dinfo, scvals)
Tile *tile;
TileType dinfo;
struct scaleArg *scvals;
{
TileType type;
@ -1626,12 +1635,15 @@ dbTileScaleFunc(tile, scvals)
return 0;
}
type = TiGetTypeExact(tile);
type = TiGetTypeExact(tile) | dinfo;
exact = type;
if (IsSplit(tile))
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
((scvals->doCIF) ? CIFPaintTable :
(
#ifdef CIF_MODULE
(scvals->doCIF) ? CIFPaintTable :
#endif
DBStdPaintTbl(type, scvals->pnum)),
(PaintUndoInfo *)NULL);
return 0;
@ -1681,8 +1693,9 @@ dbMovePlane(oldplane, newplane, pnum, origx, origy)
*/
int
dbTileMoveFunc(tile, mvvals)
dbTileMoveFunc(tile, dinfo, mvvals)
Tile *tile;
TileType dinfo;
struct moveArg *mvvals;
{
TileType type;
@ -1695,10 +1708,10 @@ dbTileMoveFunc(tile, mvvals)
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
type = TiGetTypeExact(tile);
type = TiGetTypeExact(tile) | dinfo;
exact = type;
if (IsSplit(tile))
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
DBStdPaintTbl(type, mvvals->pnum),
(PaintUndoInfo *)NULL);
@ -1762,12 +1775,14 @@ DBSrCellUses(cellDef, func, arg)
}
/* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead;
while (lu != NULL)
{
freeMagic((char *)lu);
freeMagic1(&mm1, (char *)lu);
lu = lu->cu_next;
}
freeMagic1_end(&mm1);
return retval;
}
@ -1995,12 +2010,14 @@ dbScaleCell(cellDef, scalen, scaled)
BPFree(cellPlaneOrig);
/* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead;
while (lu != NULL)
{
freeMagic((char *)lu);
freeMagic1(&mm1, (char *)lu);
lu = lu->cu_next;
}
freeMagic1_end(&mm1);
/* Scale all of the paint tiles in this cell by creating a new plane */
/* and copying all tiles into the new plane at scaled dimensions. */
@ -2203,12 +2220,14 @@ DBMoveCell(cellDef, origx, origy)
BPFree(cellPlaneOrig);
/* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead;
while (lu != NULL)
{
freeMagic((char *)lu);
freeMagic1(&mm1, (char *)lu);
lu = lu->cu_next;
}
freeMagic1_end(&mm1);
/* Move all of the paint tiles in this cell by creating a new plane */
/* and copying all tiles into the new plane at the new position. */

View File

@ -218,8 +218,10 @@ DBCellClearDef(cellDef)
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_ytop = 1;
cellDef->cd_extended.r_xbot = cellDef->cd_extended.r_ybot = 0;
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_ytop = 1;
free_magic1_t mm1 = freeMagic1_init();
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
freeMagic((char *) lab);
freeMagic1(&mm1, (char *) lab);
freeMagic1_end(&mm1);
cellDef->cd_labels = (Label *) NULL;
cellDef->cd_lastLabel = (Label *) NULL;

View File

@ -128,85 +128,6 @@ DBInvTransformDiagonal(oldtype, trans)
return dinfo;
}
/*
* ----------------------------------------------------------------------------
*
* DBSrConnectOnePlane --
*
* Search from a starting tile to find all paint that is electrically
* connected to that tile in the same plane.
*
* Results:
* 0 is returned if the search finished normally. 1 is returned
* if the search was aborted.
*
* Side effects:
* For every paint tile that is electrically connected to the initial
* tile, func is called. Func should have the following form:
*
* int
* func(tile, clientData)
* Tile *tile;
* ClientData clientData;
* {
* }
*
* The clientData passed to func is the same one that was passed
* to us. Func returns 0 under normal conditions; if it returns
* 1 then the search is aborted.
*
* *** WARNING ***
*
* Func should not modify any paint during the search, since this
* will mess up pointers kept by these procedures and likely cause
* a core-dump.
*
* ----------------------------------------------------------------------------
*/
int
DBSrConnectOnePlane(startTile, connect, func, clientData)
Tile *startTile; /* Starting tile for search */
TileTypeBitMask *connect; /* Pointer to a table indicating what tile
* types connect to what other tile types.
* Each entry gives a mask of types that
* connect to tiles of a given type.
*/
int (*func)(); /* Function to apply at each connected tile. */
ClientData clientData; /* Client data for above function. */
{
struct conSrArg csa;
int result;
result = 0;
csa.csa_def = (CellDef *)NULL;
csa.csa_bounds = TiPlaneRect;
/* Pass 1. During this pass the client function gets called. */
csa.csa_clientFunc = func;
csa.csa_clientData = clientData;
csa.csa_clientDefault = startTile->ti_client;
csa.csa_clear = FALSE;
csa.csa_connect = connect;
csa.csa_pNum = -1;
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
/* Pass 2. Don't call any client function, just clear the marks.
* Don't allow any interruptions.
*/
SigDisableInterrupts();
csa.csa_clientFunc = NULL;
csa.csa_clear = TRUE;
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
SigEnableInterrupts();
return result;
}
/*
* ----------------------------------------------------------------------------
*
@ -276,7 +197,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
{
struct conSrArg csa;
int startPlane, result;
Tile *startTile; /* Starting tile for search. */
TileAndDinfo start_tad; /* Starting tile and split information */
result = 0;
csa.csa_def = def;
@ -287,17 +208,18 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
* the tile address and returns.
*/
startTile = NULL;
start_tad.tad_tile = NULL;
start_tad.tad_next = NULL; /* unused */
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
{
csa.csa_pNum = startPlane;
if (DBSrPaintArea((Tile *) NULL,
def->cd_planes[startPlane], startArea, mask,
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
dbSrConnectStartFunc, PTR2CD(&start_tad)) != 0) break;
}
if (startTile == NULL) return 0;
if (start_tad.tad_tile == NULL) return 0;
/* The following lets us call DBSrConnect recursively */
else if (startTile->ti_client == (ClientData)1) return 0;
else if (start_tad.tad_tile->ti_client == (ClientData)1) return 0;
/* Pass 1. During this pass the client function gets called. */
@ -306,7 +228,8 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
csa.csa_clientDefault = CLIENTDEFAULT;
csa.csa_clear = FALSE;
csa.csa_connect = connect;
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
if (dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo,
PTR2CD(&csa)) != 0) result = 1;
/* Pass 2. Don't call any client function, just clear the marks.
* Don't allow any interruptions.
@ -315,7 +238,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
SigDisableInterrupts();
csa.csa_clientFunc = NULL;
csa.csa_clear = TRUE;
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
(void) dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo, PTR2CD(&csa));
SigEnableInterrupts();
return result;
@ -325,11 +248,12 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
int
dbSrConnectStartFunc(
Tile *tile, /* This will be the starting tile. */
ClientData cdata) /* We store tile's address here. */
/* (Tile **pTile) */
TileType dinfo, /* (unused) */
ClientData cdata) /* We store tile and split info here. */
{
Tile **pTile = (Tile **)CD2PTR(cdata);
*pTile = tile;
TileAndDinfo *tad = (TileAndDinfo *)CD2PTR(cdata);
tad->tad_tile = tile;
tad->tad_dinfo = dinfo;
return 1;
}
@ -367,7 +291,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
{
struct conSrArg csa;
int startPlane, result;
Tile *startTile; /* Starting tile for search. */
TileAndDinfo tad;
result = 0;
csa.csa_def = def;
@ -378,17 +302,18 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
* the tile address and returns.
*/
startTile = NULL;
tad.tad_tile = NULL;
tad.tad_next = NULL; /* unused */
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
{
csa.csa_pNum = startPlane;
if (DBSrPaintArea((Tile *) NULL,
def->cd_planes[startPlane], startArea, mask,
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
dbSrConnectStartFunc, PTR2CD(&tad)) != 0) break;
}
if (startTile == NULL) return 0;
if (tad.tad_tile == NULL) return 0;
/* The following lets us call DBSrConnect recursively */
else if (startTile->ti_client == (ClientData)1) return 0;
else if (tad.tad_tile->ti_client == (ClientData)1) return 0;
/* Pass 1. During this pass the client function gets called. */
@ -397,7 +322,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
csa.csa_clientDefault = CLIENTDEFAULT;
csa.csa_clear = FALSE;
csa.csa_connect = connect;
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
if (dbSrConnectFunc(tad.tad_tile, tad.tad_dinfo, PTR2CD(&csa)) != 0) result = 1;
return result;
}
@ -420,12 +345,15 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
*/
int
dbcFindTileFunc(tile, arg)
dbcFindTileFunc(tile, dinfo, arg)
Tile *tile;
TileType dinfo;
ClientData arg;
{
Tile **tptr = (Tile **)arg;
*tptr = tile;
TileAndDinfo *tad = (TileAndDinfo *)arg;
tad->tad_tile = tile;
tad->tad_dinfo = dinfo;
return 1;
}
@ -465,6 +393,7 @@ dbcFindTileFunc(tile, arg)
int
dbSrConnectFunc(
Tile *tile, /* Tile that is connected. */
TileType dinfo, /* Split tile information */
ClientData cdata) /* Contains information about the search. */
/* (struct conSrArg *csa) */
{
@ -484,11 +413,13 @@ dbSrConnectFunc(
/* Drop the first entry on the stack */
pNum = csa->csa_pNum;
STACKPUSH(INT2CD(tile), dbConnectStack);
STACKPUSH(INT2CD(dinfo), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
while (!StackEmpty(dbConnectStack))
{
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
dinfo = (int)CD2INT(STACKPOP(dbConnectStack));
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
if (result == 1) continue;
@ -522,7 +453,7 @@ dbSrConnectFunc(
if (callClient && (csa->csa_clientFunc != NULL))
{
if ((*csa->csa_clientFunc)(tile, pNum, csa->csa_clientData) != 0)
if ((*csa->csa_clientFunc)(tile, dinfo, pNum, csa->csa_clientData) != 0)
{
result = 1;
continue;
@ -536,7 +467,7 @@ dbSrConnectFunc(
if (IsSplit(tile))
{
if (SplitSide(tile))
if (dinfo & TT_SIDE)
loctype = SplitRightType(tile);
else
loctype = SplitLeftType(tile);
@ -547,7 +478,7 @@ dbSrConnectFunc(
/* Left side: */
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
{
@ -564,9 +495,11 @@ dbSrConnectFunc(
if (t2->ti_client == csa->csa_clientDefault) continue;
}
else if (t2->ti_client == (ClientData) 1) continue;
if (IsSplit(t2))
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE)); /* bit set */
STACKPUSH(INT2CD(t2), dbConnectStack);
if (IsSplit(t2))
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
}
@ -574,7 +507,7 @@ dbSrConnectFunc(
/* Bottom side: */
bottomside:
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
if (IsSplit(tile) && ((!((dinfo & TT_SIDE) ? 1 : 0)) ^ SplitDirection(tile)))
goto rightside;
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
@ -592,16 +525,17 @@ bottomside:
if (t2->ti_client == csa->csa_clientDefault) continue;
}
else if (t2->ti_client == (ClientData) 1) continue;
STACKPUSH(INT2CD(t2), dbConnectStack);
if (IsSplit(t2))
{
if (SplitDirection(t2))
/* bit set */
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
else
/* bit clear */
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
STACKPUSH(INT2CD(0), dbConnectStack);
}
STACKPUSH(INT2CD(t2), dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
}
@ -609,7 +543,7 @@ bottomside:
/* Right side: */
rightside:
if (IsSplit(tile) && !SplitSide(tile)) goto topside;
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto topside;
for (t2 = TR(tile); ; t2 = LB(t2))
{
@ -626,9 +560,8 @@ rightside:
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
}
else if (t2->ti_client == (ClientData) 1) goto nextRight;
if (IsSplit(t2))
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE)); /* bit clear */
STACKPUSH(INT2CD(t2), dbConnectStack);
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
@ -637,7 +570,8 @@ rightside:
/* Top side: */
topside:
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides;
if (IsSplit(tile) && (((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile)))
goto donesides;
for (t2 = RT(tile); ; t2 = BL(t2))
{
@ -654,16 +588,18 @@ topside:
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
}
else if (t2->ti_client == (ClientData) 1) goto nextTop;
STACKPUSH(INT2CD(t2), dbConnectStack);
if (IsSplit(t2))
{
if (SplitDirection(t2))
/* bit clear */
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
STACKPUSH(INT2CD(0), dbConnectStack);
else
/* bit set */
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
}
STACKPUSH(INT2CD(t2), dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
@ -682,6 +618,7 @@ donesides:
{
Rect newArea;
GEO_EXPAND(&tileArea, 1, &newArea);
TileAndDinfo tad;
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
{
@ -689,18 +626,20 @@ donesides:
if (IsSplit(tile))
{
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
TiGetTypeExact(tile), &newArea, connectMask,
dbcFindTileFunc, (ClientData)&t2) != 0)
TiGetTypeExact(tile) | dinfo, &newArea, connectMask,
dbcFindTileFunc, (ClientData)&tad) != 0)
{
STACKPUSH(INT2CD(t2), dbConnectStack);
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
STACKPUSH(INT2CD(i), dbConnectStack);
}
}
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
&newArea, connectMask, dbcFindTileFunc,
(ClientData)&t2) != 0)
(ClientData)&tad) != 0)
{
STACKPUSH(INT2CD(t2), dbConnectStack);
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
STACKPUSH(INT2CD(i), dbConnectStack);
}
}
@ -734,9 +673,10 @@ donesides:
/** @typedef cb_database_srpaintnmarea_t */
/** @typedef cb_database_srpaintarea_t */
int
dbcUnconnectFunc(tile, clientData)
dbcUnconnectFunc(tile, dinfo, clientData)
Tile *tile; /* Current tile */
ClientData clientData; /* Unused. */
TileType dinfo; /* Split tile information, unused */
ClientData clientData; /* Unused. */
{
return 1;
@ -828,6 +768,7 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
CellDef *orig_def = scx->scx_use->cu_def;
Label *slab;
int lidx = lab->lab_port;
bool foundOne;
const TileTypeBitMask *connectMask;
/* Check for equivalent ports. For any found, call */
@ -839,6 +780,7 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
/* are more equivalent ports, they will be found when */
/* processing this label's area. */
foundOne = FALSE;
for (slab = orig_def->cd_labels; slab != NULL; slab = slab->lab_next)
if ((slab->lab_flags & PORT_DIR_MASK) && (slab != lab))
if (slab->lab_port == lidx)
@ -899,6 +841,20 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
csa2->csa2_list[csa2->csa2_top].dinfo = 0;
#if 0
/* This warning is useful but currently is generating
* multiple messages per instance and so its more of
* an annoyance than an aid.
*/
if (foundOne == FALSE)
TxError("Warning: Port %s at location (%d %d) connects"
" a net across multiple disconnected areas!\n",
lab->lab_text, lab->lab_rect.r_xbot,
lab->lab_rect.r_ybot);
#endif
foundOne = TRUE;
/* See above: Process only one equivalent port at a time */
break;
}
@ -933,8 +889,9 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
*/
int
dbcConnectFunc(tile, cx)
dbcConnectFunc(tile, dinfo, cx)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information */
TreeContext *cx; /* Describes context of search. The client
* data is a pointer to a conSrArg2 record
* containing various required information.
@ -947,8 +904,8 @@ dbcConnectFunc(tile, cx)
Rect *srArea;
SearchContext *scx = cx->tc_scx;
SearchContext scx2;
TileType loctype = TiGetTypeExact(tile);
TileType dinfo = 0;
TileType loctype = TiGetTypeExact(tile) | dinfo;
TileType newdinfo = 0;
int retval, i, pNum = cx->tc_plane;
CellDef *def;
@ -980,8 +937,8 @@ dbcConnectFunc(tile, cx)
if (IsSplit(tile))
{
dinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
newdinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
loctype = ((dinfo & TT_SIDE)) ? SplitRightType(tile) : SplitLeftType(tile);
}
/* See if the destination cell contains stuff over the whole
@ -1019,7 +976,7 @@ dbcConnectFunc(tile, cx)
def = csa2->csa2_use->cu_def;
retval = 1;
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
dinfo, &newarea, &notConnectMask, dbcUnconnectFunc,
newdinfo, &newarea, &notConnectMask, dbcUnconnectFunc,
(ClientData) NULL) == 0)
retval = 0;
@ -1028,7 +985,7 @@ dbcConnectFunc(tile, cx)
* the storage for the current list element.
*/
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
DBNMPaintPlane(def->cd_planes[pNum], newdinfo,
&newarea, DBStdPaintTbl(loctype, pNum),
(PaintUndoInfo *) NULL);
@ -1045,14 +1002,14 @@ dbcConnectFunc(tile, cx)
/* Only extend those sides bordering the diagonal tile */
if (dinfo & TT_DIAGONAL)
if (newdinfo & TT_DIAGONAL)
{
if (dinfo & TT_SIDE) /* right */
if (newdinfo & TT_SIDE) /* right */
newarea.r_xtop += 1;
else /* left */
newarea.r_xbot -= 1;
if (((dinfo & TT_SIDE) >> 1)
== (dinfo & TT_DIRECTION)) /* top */
if (((newdinfo & TT_SIDE) >> 1)
== (newdinfo & TT_DIRECTION)) /* top */
newarea.r_ytop += 1;
else /* bottom */
newarea.r_ybot -= 1;
@ -1092,7 +1049,7 @@ dbcConnectFunc(tile, cx)
csa2->csa2_list[csa2->csa2_top].area = newarea;
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
csa2->csa2_list[csa2->csa2_top].dinfo = dinfo;
csa2->csa2_list[csa2->csa2_top].dinfo = newdinfo;
return 0;
}
@ -1247,7 +1204,8 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse)
if (DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype,
dbcConnectLabelFunc, (ClientData) &csa2) != 0)
{
TxError("Connection search hit memory limit and stopped.\n");
TxError("Connection search was interrupted or hit "
"memory limit and stopped.\n");
break;
}
}

View File

@ -40,8 +40,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
@ -52,6 +60,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/geometry.h"
#include "tiles/tile.h"
#include "utils/utils.h"
#include "utils/magic_zlib.h"
#include "utils/hash.h"
#include "database/database.h"
#include "database/databaseInt.h"
@ -89,6 +98,9 @@ extern bool FileLocking;
/* Suffix for all Magic files */
char *DBSuffix = ".mag";
#ifdef HAVE_ZLIB
char *DBZSuffix = ".mag.gz";
#endif
/* Magic units per lambda (2 integers, representing (n / d) */
int DBLambda[2] = {1, 1};
@ -158,6 +170,24 @@ file_is_not_writeable(name)
return(0);
}
static int
path_is_dir(const char *dirname, const char *filename)
{
struct stat statbuf;
char path[PATH_MAX];
const char *sep = filename ? "/" : "";
if (!filename)
filename = "";
size_t n = snprintf(path, sizeof(path), "%s%s%s", dirname, sep, filename);
ASSERT(n < sizeof(path), "path");
if (n >= sizeof(path))
return -1;
int err = stat(path, &statbuf);
if (err != 0)
return 0;
return S_ISDIR(statbuf.st_mode) ? 1 : 0;
}
/* Linked string record used to hold directory contents */
typedef struct _linkedDirent {
@ -243,13 +273,20 @@ DBSearchForTech(techname, techroot, pathroot, level)
for (ld = dlist; ld; ld = ld->ld_next)
{
tdent = ld->ld_dirent;
if (tdent->d_type != DT_DIR)
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
int is_dir = tdent->d_type == DT_DIR;
#else
int is_dir = path_is_dir(pathroot, tdent->d_name) > 0; /* treat error as false */
#endif
if (!is_dir)
{
if (!strcmp(tdent->d_name, techname))
{
closedir(tdir);
free_magic1_t mm1 = freeMagic1_init();
for (ld = dlist; ld; ld = ld->ld_next)
freeMagic(ld);
freeMagic1(&mm1, ld);
freeMagic1_end(&mm1);
return pathroot;
}
}
@ -262,8 +299,10 @@ DBSearchForTech(techname, techroot, pathroot, level)
if (found)
{
closedir(tdir);
free_magic1_t mm1 = freeMagic1_init();
for (ld = dlist; ld; ld = ld->ld_next)
freeMagic(ld);
freeMagic1(&mm1, ld);
freeMagic1_end(&mm1);
return found;
}
}
@ -271,8 +310,12 @@ DBSearchForTech(techname, techroot, pathroot, level)
closedir(tdir);
}
for (ld = dlist; ld; ld = ld->ld_next)
freeMagic(ld);
{
free_magic1_t mm1 = freeMagic1_init();
for (ld = dlist; ld; ld = ld->ld_next)
freeMagic1(&mm1, ld);
freeMagic1_end(&mm1);
}
return NULL;
}
@ -315,7 +358,12 @@ DBAddStandardCellPaths(pathptr, level)
while ((tdent = readdir(tdir)) != NULL)
{
if ((tdent->d_type == DT_DIR) &&
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
int is_dir = tdent->d_type == DT_DIR;
#else
int is_dir = path_is_dir(pathptr, tdent->d_name) > 0; /* treat error as false */
#endif
if (is_dir &&
(strcmp(tdent->d_name, ".") && strcmp(tdent->d_name, "..")))
{
/* Scan the directory contents of tdir for more subdirectories */
@ -324,7 +372,7 @@ DBAddStandardCellPaths(pathptr, level)
paths += DBAddStandardCellPaths(newpath, level + 1);
freeMagic(newpath);
}
else if (tdent->d_type != DT_DIR)
else if (!is_dir)
{
/* Scan the directory contents of tdir for .mag files */
if (!strcmp(tdent->d_name + strlen(tdent->d_name) - 4, ".mag"))
@ -1149,7 +1197,7 @@ DBFileRecovery(filename)
switch(action)
{
case 0: /* Read */
if (DBReadBackup(DBbackupFile) == TRUE)
if (DBReadBackup(DBbackupFile, FALSE, TRUE) == TRUE)
DBRemoveBackup();
break;
case 1: /* Cancel */
@ -1185,24 +1233,38 @@ DBFileRecovery(filename)
*/
bool
DBReadBackup(name)
DBReadBackup(name, archive, usederef)
char *name; /* Name of the backup file */
bool archive; /* TRUE if this is an archive file */
bool usederef; /* If TRUE, then dereference all cells */
{
FILETYPE f;
char *filename, *rootname, *chrptr;
static const char *filetypes[] = {"archive", "backup", 0};
char *filename, *rootname, *chrptr, *suffix, *filetype;
char line[256];
CellDef *cellDef;
bool result = TRUE;
if ((f = PaZOpen(name, "r", NULL, "", NULL, NULL)) == NULL)
if (archive)
{
TxError("Cannot open backup file \"%s\"\n", name);
suffix = DBSuffix;
filetype = (char *)filetypes[0];
}
else
{
suffix = NULL;
filetype = (char *)filetypes[1];
}
if ((f = PaZOpen(name, "r", suffix, Path, NULL, NULL)) == NULL)
{
TxError("Cannot open %s file \"%s\"\n", filetype, name);
return FALSE;
}
if (dbFgets(line, sizeof(line), f) == NULL)
{
TxError("Bad backup file %s; can't restore!\n", name);
TxError("Bad %s file %s; can't read!\n", filetype, name);
return FALSE;
}
@ -1236,22 +1298,26 @@ DBReadBackup(name)
cellDef->cd_flags &= ~CDNOTFOUND;
cellDef->cd_flags |= CDAVAILABLE;
if (dbCellReadDef(f, cellDef, TRUE, FALSE) == FALSE)
if (dbCellReadDef(f, cellDef, TRUE, usederef) == FALSE)
return FALSE;
if (dbFgets(line, sizeof(line), f) == NULL)
{
TxError("Error in backup file %s; partial restore only!\n",
name);
TxError("Error in %s file %s; partial restore only!\n",
filetype, name);
return FALSE;
}
/* Update timestamp flags from dbCellReadDef() */
DBFlagMismatches(cellDef);
/* Update bounding boxes */
DBReComputeBbox(cellDef);
}
else
{
TxError("Error in backup file %s; expected keyword"
" \"file\", got \"%s\"!\n", name, line);
TxError("Error in %s file %s; expected keyword"
" \"file\", got \"%s\"!\n", filetype, name, line);
return FALSE;
}
}
@ -1262,6 +1328,7 @@ DBReadBackup(name)
*chrptr = '\0';
DBWreload(line + 4);
}
return TRUE;
}
@ -1427,15 +1494,28 @@ dbReadOpen(cellDef, setFileName, dereference, errptr)
/* If dereferencing, then use search paths first */
if (!dereference)
{
f = PaLockZOpen(cellDef->cd_file, "r", DBSuffix, ".",
(char *) NULL, &filename, &is_locked, &fd);
#ifdef HAVE_ZLIB
if (f == NULL)
f = PaLockZOpen(cellDef->cd_file, "r", DBZSuffix, ".",
(char *) NULL, &filename, &is_locked, &fd);
#endif
}
/* Fall back on the original method of using search paths. */
if (f == NULL)
{
f = PaLockZOpen(cellDef->cd_name, "r", DBSuffix, Path,
CellLibPath, &filename, &is_locked, &fd);
#ifdef HAVE_ZLIB
if (f == NULL)
f = PaLockZOpen(cellDef->cd_file, "r", DBZSuffix, Path,
CellLibPath, &filename, &is_locked, &fd);
#endif
if (f != NULL)
{
@ -1468,6 +1548,11 @@ dbReadOpen(cellDef, setFileName, dereference, errptr)
{
f = PaLockZOpen(cellDef->cd_file, "r", DBSuffix, ".",
(char *) NULL, &filename, &is_locked, &fd);
#ifdef HAVE_ZLIB
if (f == NULL)
f = PaLockZOpen(cellDef->cd_file, "r", DBZSuffix, ".",
(char *) NULL, &filename, &is_locked, &fd);
#endif
if (f != NULL)
if (DBVerbose)
TxError("Warning: Dereferenced cell \"%s\" not "
@ -1485,6 +1570,11 @@ dbReadOpen(cellDef, setFileName, dereference, errptr)
{
f = PaLockZOpen(cellDef->cd_name, "r", DBSuffix, Path,
CellLibPath, &filename, &is_locked, &fd);
#ifdef HAVE_ZLIB
if (f == NULL)
f = PaLockZOpen(cellDef->cd_name, "r", DBZSuffix, Path,
CellLibPath, &filename, &is_locked, &fd);
#endif
if (errptr != NULL) *errptr = errno;
}
@ -3080,7 +3170,7 @@ int
DBCellFindScale(cellDef)
CellDef *cellDef;
{
int dbFindGCFFunc(), dbFindCellGCFFunc();
int dbFindGCFFunc(), dbFindCellGCFFunc(), dbFindPropGCFFunc();
TileType type;
TileTypeBitMask typeMask;
int pNum;
@ -3124,8 +3214,13 @@ DBCellFindScale(cellDef)
}
}
/* Finally, cell uses */
/* Properties, where they are coordinates. This includes
* FIXED_BBOX and MASKHINTS_*
*/
if (DBPropEnum(cellDef, dbFindPropGCFFunc, (ClientData)&ggcf))
return 1;
/* Finally, cell uses */
if (DBCellEnum(cellDef, dbFindCellGCFFunc, (ClientData) &ggcf))
return 1;
@ -3133,8 +3228,9 @@ DBCellFindScale(cellDef)
}
int
dbFindGCFFunc(tile, ggcf)
dbFindGCFFunc(tile, dinfo, ggcf)
Tile *tile;
TileType dinfo; /* (unused) */
int *ggcf;
{
Rect r;
@ -3193,6 +3289,73 @@ dbFindCellGCFFunc(cellUse, ggcf)
return (*ggcf == 1) ? 1 : 0;
}
int
dbFindPropGCFFunc(key, value, ggcf)
char *key;
ClientData value;
int *ggcf; /* Client data */
{
Rect bbox;
char *vptr = value, *sptr;
int numvals, n;
if (!strcmp(key, "FIXED_BBOX"))
{
if (sscanf(value, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) == 4)
{
/* Check bounding box */
if (bbox.r_xtop % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_xtop, *ggcf);
if (bbox.r_xbot % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_xbot, *ggcf);
if (bbox.r_ytop % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_ytop, *ggcf);
if (bbox.r_ybot % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_ybot, *ggcf);
}
else
TxError("Error: Cannot parse FIXED_BBOX property value!\n");
}
else if (!strncmp(key, "MASKHINTS_", 10))
{
while (TRUE)
{
numvals = sscanf(vptr, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop);
if (numvals <= 0)
break;
else if (numvals != 4)
{
TxError("Error: Cannot parse %s property value at \"%s\"!\n",
key, vptr);
break;
}
else
{
/* Check bounding box */
if (bbox.r_xtop % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_xtop, *ggcf);
if (bbox.r_xbot % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_xbot, *ggcf);
if (bbox.r_ytop % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_ytop, *ggcf);
if (bbox.r_ybot % (*ggcf) != 0)
*ggcf = FindGCF(bbox.r_ybot, *ggcf);
}
/* Skip forward four values in value */
for (n = 0; n < 4; n++)
{
while (!isspace(*vptr) && (*vptr != '\0')) vptr++;
while (isspace(*vptr) && (*vptr != '\0')) vptr++;
}
}
}
return (*ggcf == 1) ? 1 : 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -3822,6 +3985,361 @@ dbWritePropFunc(key, value, cdata)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DBCellWriteCommandFile --
*
* Write out the contents of a cell to the specified file as a sequence
* of magic commands. Sourcing the resulting file will regenerate the
* cell.
*
* Results:
* TRUE if the cell could be written successfully, FALSE otherwise.
*
* Side effects:
* Writes a file to disk.
* Does NOT close the file 'f', but does fflush(f) before returning.
*
* ----------------------------------------------------------------------------
*/
bool
DBCellWriteCommandFile(cellDef, f)
CellDef *cellDef; /* Pointer to definition of cell to be written out */
FILE *f; /* The FILE to write to */
{
int dbWritePaintCommandsFunc();
int dbWriteUseCommandsFunc();
int dbWritePropCommandsFunc();
Label *lab;
struct writeArg arg;
int pNum;
TileType type, stype;
TileTypeBitMask typeMask, *sMask;
static const char *directionNames[] = {"c", "n", "ne", "e", "se",
"s", "sw", "w", "nw", 0};
if (f == NULL) return FALSE;
SigDisableInterrupts();
/* Write a descriptive header */
fprintf(f, "# Command script for generating cell %s\n", cellDef->cd_name);
fprintf(f, "\n");
fprintf(f, "suspendall\n");
fprintf(f, "tech unlock *\n");
fprintf(f, "snap internal\n");
fprintf(f, "load %s -silent\n", cellDef->cd_name);
fprintf(f, "box values 0 0 0 0\n");
/* These routines only need the file stream pointer */
arg.wa_name = NULL;
arg.wa_file = f;
arg.wa_reducer = 1;
for (type = TT_PAINTBASE; type < DBNumUserLayers; type++)
{
if ((pNum = DBPlane(type)) < 0)
continue;
arg.wa_found = FALSE;
arg.wa_type = type;
arg.wa_plane = pNum;
TTMaskSetOnlyType(&typeMask, type);
/* Add to the mask all generated (stacking) types which */
/* have this type as a residue. */
for (stype = DBNumUserLayers; stype < DBNumTypes; stype++)
{
sMask = DBResidueMask(stype);
if (TTMaskHasType(sMask, type))
TTMaskSetType(&typeMask, stype);
}
if (DBSrPaintArea((Tile *) NULL, cellDef->cd_planes[pNum],
&TiPlaneRect, &typeMask, dbWritePaintCommandsFunc, (ClientData) &arg))
goto ioerror;
}
if (DBCellEnum(cellDef, dbWriteUseCommandsFunc, (ClientData)&arg))
goto ioerror;
/* Now labels */
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
{
if (strlen(lab->lab_text) == 0) continue; // Shouldn't happen
fprintf(f, "box values %d %d %d %d\n",
lab->lab_rect.r_xbot,
lab->lab_rect.r_ybot,
lab->lab_rect.r_xtop,
lab->lab_rect.r_ytop);
if (lab->lab_font < 0)
{
fprintf(f, "label %s %s %s\n",
lab->lab_text,
directionNames[lab->lab_just],
DBTypeLongName(lab->lab_type));
}
else
{
fprintf(f, "label %s %s %d %d %d %d %s %s\n",
lab->lab_text,
DBFontList[lab->lab_font]->mf_name,
lab->lab_size >> 3,
lab->lab_rotate,
lab->lab_offset.p_x,
lab->lab_offset.p_y,
directionNames[lab->lab_just],
DBTypeLongName(lab->lab_type));
}
if (lab->lab_flags & LABEL_STICKY)
{
fprintf(f, "select area label\n");
fprintf(f, "setlabel sticky true\n");
}
if (lab->lab_flags & PORT_DIR_MASK)
{
if (!(lab->lab_flags & LABEL_STICKY))
fprintf(f, "select area label\n");
fprintf(f, "port make %d\n", lab->lab_port);
if (lab->lab_flags & (PORT_DIR_NORTH | PORT_DIR_SOUTH | PORT_DIR_EAST
| PORT_DIR_WEST))
fprintf(f, "port connections");
if (lab->lab_flags & PORT_DIR_NORTH) fprintf(f, " n");
if (lab->lab_flags & PORT_DIR_SOUTH) fprintf(f, " s");
if (lab->lab_flags & PORT_DIR_EAST) fprintf(f, " e");
if (lab->lab_flags & PORT_DIR_WEST) fprintf(f, " w");
fprintf(f, "\n");
if (lab->lab_flags & PORT_USE_MASK)
{
fprintf(f, "port %d use ", lab->lab_port);
switch (lab->lab_flags & PORT_USE_MASK)
{
case PORT_USE_SIGNAL:
fprintf(f, "signal\n");
break;
case PORT_USE_ANALOG:
fprintf(f, "analog\n");
break;
case PORT_USE_POWER:
fprintf(f, "power\n");
break;
case PORT_USE_GROUND:
fprintf(f, "ground\n");
break;
case PORT_USE_CLOCK:
fprintf(f, "clock\n");
break;
}
}
if (lab->lab_flags & PORT_CLASS_MASK)
{
fprintf(f, "port %d class ", lab->lab_port);
switch (lab->lab_flags & PORT_CLASS_MASK)
{
case PORT_CLASS_INPUT:
fprintf(f, "input\n");
break;
case PORT_CLASS_OUTPUT:
fprintf(f, "output\n");
break;
case PORT_CLASS_TRISTATE:
fprintf(f, "tristate\n");
break;
case PORT_CLASS_BIDIRECTIONAL:
fprintf(f, "bidirectional\n");
break;
case PORT_CLASS_FEEDTHROUGH:
fprintf(f, "feedthrough\n");
break;
}
}
if (lab->lab_flags & PORT_SHAPE_MASK)
{
fprintf(f, "port %d shape ", lab->lab_port);
switch (lab->lab_flags & PORT_SHAPE_MASK)
{
case PORT_SHAPE_ABUT:
fprintf(f, "abutment\n");
break;
case PORT_SHAPE_RING:
fprintf(f, "ring\n");
break;
case PORT_SHAPE_THRU:
fprintf(f, "feedthrough\n");
break;
}
}
}
}
/* Note: Persistant elements should be handled (see dbwind/DBWelement.c) */
/* And any properties */
DBPropEnum(cellDef, dbWritePropCommandsFunc, (ClientData)&arg);
fprintf(f, "select clear\n");
fprintf(f, "view\n");
fprintf(f, "tech revert\n");
fprintf(f, "resumeall\n");
if (fflush(f) == EOF || ferror(f))
{
ioerror:
TxError("Warning: I/O error in writing file\n");
SigEnableInterrupts();
return (FALSE);
}
SigEnableInterrupts();
TxPrintf("Saved cell %s as a sequence of magic commands (file %s.tcl).\n",
cellDef->cd_name, cellDef->cd_name);
return (TRUE);
}
/*
* ----------------------------------------------------------------------------
*
* dbWritePaintCommandsFunc ---
*
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell layout geometry.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePaintCommandsFunc(tile, dinfo, cdarg)
Tile *tile;
TileType dinfo;
ClientData cdarg;
{
char pstring[256];
struct writeArg *arg = (struct writeArg *) cdarg;
FILE *f = arg->wa_file;
TileType type = TiGetType(tile);
TileTypeBitMask *lMask, *rMask;
int diridx;
static const char *directionNames[] = {"nw", "se", "sw", "ne", 0};
/* Don't write out error tiles */
if ((type == TT_ERROR_P) || (type == TT_ERROR_S) || (type == TT_ERROR_PS))
return 0;
/* This could be refined by merging metal areas across contacts,
* but the brute force procedure will do the job.
*/
if (IsSplit(tile))
{
diridx = (SplitDirection(tile) << 1) + ((dinfo & TT_SIDE) ? 1 : 0);
fprintf(f, "box values %d %d %d %d\n",
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
type = TiGetLeftType(tile);
if (type != TT_SPACE)
{
fprintf(f, "splitpaint %s %s\n", directionNames[diridx],
DBTypeLongNameTbl[type]);
}
type = TiGetRightType(tile);
if (type != TT_SPACE)
{
fprintf(f, "splitpaint %s %s\n", directionNames[diridx],
DBTypeLongNameTbl[type]);
}
}
else
{
type = TiGetType(tile);
fprintf(f, "box values %d %d %d %d\n",
LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile));
fprintf(f, "paint %s\n", DBTypeLongNameTbl[type]);
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbWriteUseCommandsFunc ---
*
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to cell uses in the layout.
*
* ----------------------------------------------------------------------------
*/
int
dbWriteUseCommandsFunc(cellUse, cdarg)
CellUse *cellUse;
ClientData cdarg;
{
struct writeArg *arg = (struct writeArg *) cdarg;
FILE *f = arg->wa_file;
fprintf(f, "box position %d %d\n", cellUse->cu_bbox.r_ll.p_x,
cellUse->cu_bbox.r_ll.p_y);
fprintf(f, "getcell %s\n", cellUse->cu_def->cd_name);
fprintf(f, "identify %s\n", cellUse->cu_id);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* dbWritePropCommandsFunc ---
*
* Callback function used by DBCellWriteCommandFile() to output
* commands corresponding to properties in the layout.
*
* ----------------------------------------------------------------------------
*/
int
dbWritePropCommandsFunc(key, value, cdarg)
char *key;
char *value;
ClientData cdarg;
{
struct writeArg *arg = (struct writeArg *) cdarg;
char *escstr, *p, *v;
int vallen;
FILE *f = arg->wa_file;
/* Probably need to escape more than just quotes here. */
vallen = strlen(value) + 1;
for (v = value; *v != '\0'; v++)
if (*v == '"') vallen++;
escstr = (char *)mallocMagic(vallen);
p = escstr;
for (v = value; *v != '\0'; v++)
{
if (*v == '"')
*p++ = '\\';
*p++ = *v;
}
*p = '\0';
fprintf(f, "property %s \"%s\"\n", key, escstr);
freeMagic(escstr);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -3882,11 +4400,27 @@ DBCellWrite(cellDef, fileName)
result = FALSE;
/*
* Figure out the name of the file we will eventually write.
*/
if (!fileName)
if (fileName)
{
/* Feature added 9/4/2025: If the filename ends with ".tcl",
* then write the cell as a series of magic commands, and don't
* otherwise alter the cell.
*/
if ((strlen(fileName) > 4) && (!strcmp(fileName + strlen(fileName) - 4, ".tcl")))
{
if ((realf = fopen(fileName, "w")))
{
result = DBCellWriteCommandFile(cellDef, realf);
fclose(realf);
return result;
}
}
}
else
{
/*
* Figure out the name of the file we will eventually write.
*/
if (cellDef->cd_file)
fileName = cellDef->cd_file;
else if (cellDef->cd_name)
@ -4175,8 +4709,9 @@ cleanup:
*/
int
dbWritePaintFunc(tile, cdarg)
dbWritePaintFunc(tile, dinfo, cdarg)
Tile *tile;
TileType dinfo; /* (unused) */
ClientData cdarg;
{
char pstring[256];
@ -4238,7 +4773,7 @@ dbWritePaintFunc(tile, cdarg)
sprintf(pstring, "rect %d %d %d %d\n",
LEFT(tile) / arg->wa_reducer, BOTTOM(tile) / arg->wa_reducer,
RIGHT(tile) / arg->wa_reducer, TOP(tile) / arg->wa_reducer);
FPUTSR(arg->wa_file,pstring);
FPUTSR(arg->wa_file, pstring);
return 0;
}
@ -4507,7 +5042,7 @@ DBGetTech(cellName)
static char line[512];
char *p;
f = PaZOpen(cellName, "r", DBSuffix, Path, CellLibPath, (char **) NULL);
f = PaZOpen(cellName, "r", DBSuffix, ".", CellLibPath, (char **) NULL);
if (f == NULL) return NULL;
p = (char *) NULL;
@ -4527,6 +5062,15 @@ ret:
return (p);
}
/* File and flags record used to hold information for dbWriteBackupFunc()
* in DBWriteBackup()
*/
typedef struct _fileAndFlags {
FILE *ff_file;
int ff_flags;
} FileAndFlags;
/*
* ----------------------------------------------------------------------------
*
@ -4540,6 +5084,13 @@ ret:
* is set to this name, erasing any previous value. If "filename" is
* an empty string, then the DBbackupFile reverts to NULL.
*
* If "archive" is TRUE, then save all read/write files, not just modified
* ones, and do not remove the file when magic exits.
*
* If "doforall" is TRUE, the save all files including read-only PDK
* cells. By definition, if "archive" is not chosen, then "doforall"
* has no impact, since read-only cells cannot be modified.
*
* Results:
* TRUE if the backup file was created, FALSE if an error was
* encountered.
@ -4553,25 +5104,39 @@ ret:
*/
bool
DBWriteBackup(filename)
DBWriteBackup(filename, archive, doforall)
char *filename;
bool archive;
bool doforall;
{
FILE *f;
int fd, pid;
char *tempdir;
char *tempdir, *saveName = NULL;
MagWindow *mw;
FileAndFlags ff;
int dbWriteBackupFunc(), dbCheckModifiedCellsFunc();
int flags = CDMODIFIED;
int flags = 0;
int result;
/* First check if there are any modified cells that need to be written */
result = DBCellSrDefs(flags, dbCheckModifiedCellsFunc, (ClientData)NULL);
if (result == 0) return TRUE; /* Nothing to write */
if (archive == FALSE)
{
flags = CDMODIFIED;
result = DBCellSrDefs(flags, dbCheckModifiedCellsFunc, (ClientData)NULL);
/*
* Avoid unnecessary backups: If there's nothing modified, then
* there's nothing to write.
*/
if (result == 0) return TRUE;
}
if (filename == NULL)
{
/* A NULL filename is used by the backup mechanism to save to /tmp/. */
if (DBbackupFile == (char *)NULL)
{
char *doslash, *template;
@ -4605,8 +5170,14 @@ DBWriteBackup(filename)
StrDup(&DBbackupFile, (char *)NULL);
return TRUE;
}
if (archive == TRUE)
{
TxPrintf("Created database archive file %s\n", filename);
saveName = StrDup((char **)NULL, DBbackupFile);
}
else
TxPrintf("Created database crash recovery file %s\n", DBbackupFile);
StrDup(&DBbackupFile, filename);
TxPrintf("Created database crash recovery file %s\n", DBbackupFile);
}
f = fopen(filename, "w");
@ -4616,7 +5187,15 @@ DBWriteBackup(filename)
return FALSE;
}
result = DBCellSrDefs(flags, dbWriteBackupFunc, (ClientData)f);
ff.ff_file = f;
/* Flags for recognizing which cells to ignore. Note that flags
* for recognizing which cells to search is in "flags".
*/
ff.ff_flags = CDINTERNAL | CDNOTFOUND;
if (!doforall) ff.ff_flags |= CDNOEDIT;
result = DBCellSrDefs(flags, dbWriteBackupFunc, (ClientData)&ff);
/* End by printing the keyword "end" followed by the cell to load */
/* into the first available window, so that we don't have a default */
@ -4628,6 +5207,17 @@ DBWriteBackup(filename)
else
fprintf(f, "end\n");
fclose(f);
/* If archiving, put DBbackupFile back to the name that it contained
* prior to doing the archive, so that the archive does not interfere
* with the backup mechanism.
*/
if (archive == TRUE)
{
StrDup(&DBbackupFile, saveName);
if (saveName)
freeMagic(saveName);
}
return TRUE;
}
@ -4639,14 +5229,18 @@ DBWriteBackup(filename)
*/
int
dbWriteBackupFunc(def, f)
dbWriteBackupFunc(def, clientData)
CellDef *def; /* Pointer to CellDef to be saved */
FILE *f; /* File to append to */
ClientData clientData;
{
char *name = def->cd_file;
int result, save_flags;
FileAndFlags *ff = (FileAndFlags *)clientData;
if (def->cd_flags & (CDINTERNAL | CDNOEDIT | CDNOTFOUND)) return 0;
FILE *f = ff->ff_file;
int flags = ff->ff_flags;
if (def->cd_flags & flags) return 0;
else if (!(def->cd_flags & CDAVAILABLE)) return 0;
if (name == NULL) name = def->cd_name;

View File

@ -280,6 +280,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
bool erasedAny = FALSE;
TileType newType;
free_magic1_t mm1 = freeMagic1_init();
labPrev = NULL;
lab = cellDef->cd_labels;
while (lab != NULL)
@ -313,7 +314,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
if ((lab->lab_font >= 0) && areaReturn)
GeoInclude(&lab->lab_bbox, areaReturn);
freeMagic((char *) lab);
freeMagic1(&mm1, (char *) lab);
lab = lab->lab_next;
erasedAny = TRUE;
continue;
@ -321,6 +322,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
nextLab: labPrev = lab;
lab = lab->lab_next;
}
freeMagic1_end(&mm1);
if (erasedAny)
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
@ -442,6 +444,7 @@ DBEraseLabelsByContent(def, rect, type, text)
{
Label *lab, *labPrev;
free_magic1_t mm1 = freeMagic1_init();
for (labPrev = NULL, lab = def->cd_labels;
lab != NULL;
labPrev = lab, lab = lab->lab_next)
@ -457,7 +460,7 @@ DBEraseLabelsByContent(def, rect, type, text)
else labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev;
freeMagic((char *) lab);
freeMagic1(&mm1, (char *) lab);
/* Don't iterate through loop, since this will skip a label:
* just go back to top. This is tricky!
@ -467,6 +470,7 @@ DBEraseLabelsByContent(def, rect, type, text)
if (lab == NULL) break;
else goto nextCheck;
}
freeMagic1_end(&mm1);
}
/*
@ -495,6 +499,7 @@ DBRemoveLabel(def, refLab)
{
Label *lab, *labPrev;
free_magic1_t mm1 = freeMagic1_init();
for (labPrev = NULL, lab = def->cd_labels;
lab != NULL;
labPrev = lab, lab = lab->lab_next)
@ -508,7 +513,7 @@ DBRemoveLabel(def, refLab)
else labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev;
freeMagic((char *) lab);
freeMagic1(&mm1, (char *) lab);
/* Don't iterate through loop, since this will skip a label:
* just go back to top. This is tricky!
@ -518,6 +523,7 @@ DBRemoveLabel(def, refLab)
if (lab == NULL) break;
else goto nextCheck;
}
freeMagic1_end(&mm1);
}
/*
@ -577,8 +583,9 @@ DBReOrientLabel(cellDef, area, newPos)
*/
int
dbGetLabelArea(tile, area)
dbGetLabelArea(tile, dinfo, area)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information (unused) */
Rect *area; /* Area to be modified. */
{
Rect r;
@ -760,8 +767,10 @@ DBAdjustLabelsNew(def, area)
def->cd_lastLabel = labPrev;
DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
freeMagic((char *) lab);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *) lab);
lab = lab->lab_next;
freeMagic1_end(&mm1);
modified = TRUE;
continue;
}
@ -1077,14 +1086,15 @@ DBPickLabelLayer(def, lab, doCalma)
*/
int
dbPickFunc1(tile, mask)
dbPickFunc1(tile, dinfo, mask)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information */
TileTypeBitMask *mask; /* Mask to be modified. */
{
TileType type;
if (IsSplit(tile))
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
else
type = TiGetType(tile);
@ -1103,15 +1113,16 @@ dbPickFunc1(tile, mask)
*/
int
dbPickFunc2(tile, mask)
dbPickFunc2(tile, dinfo, mask)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information */
TileTypeBitMask *mask; /* Mask to be modified. */
{
TileType type;
TileTypeBitMask tmp, *rMask;
if (IsSplit(tile))
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
else
type = TiGetType(tile);
@ -1744,8 +1755,10 @@ DBLoadFont(fontfile, scale)
}
/* Remove the pointlist */
free_magic1_t mm1 = freeMagic1_init();
for (newPath = pathStart; newPath != NULL; newPath = newPath->fp_next)
freeMagic(newPath);
freeMagic1(&mm1, newPath);
freeMagic1_end(&mm1);
pathStart = NULL;
}
else

View File

@ -59,6 +59,8 @@ Tile *TiNMMergeRight();
Tile *TiNMMergeLeft();
#ifdef PAINTDEBUG
void dbPaintShowTile(Tile *tile, PaintUndoInfo *undo, char *str);
int dbPaintDebug = 0;
#endif /* PAINTDEBUG */
@ -271,6 +273,7 @@ DBPaintPlane0(plane, area, resultTbl, undo, method)
* search.
*/
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane);
@ -310,6 +313,11 @@ enumerate:
* Set up the directions in which we will have to
* merge initially. Clipping can cause some of these
* to be turned off.
*
* The search runs from left to right, top to bottom.
* Therefore always merge left and up, but never right
* and down, unless at or beyond the each of the search
* area.
*/
mergeFlags = MRG_TOP | MRG_LEFT;
if (RIGHT(tile) >= area->r_xtop) mergeFlags |= MRG_RIGHT;
@ -339,6 +347,7 @@ enumerate:
* Merging is only necessary if we clip to the left or to
* the right, and then only to the top or the bottom.
* We do the merge in-line for efficiency.
* Clipping of split tiles is more complicated.
*/
/* Clip up */
@ -353,13 +362,17 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType];
tile = TiNMMergeLeft(tile, plane);
TiNMMergeRight(TR(newtile), plane);
if (mergeFlags & MRG_LEFT)
tile = TiNMMergeLeft(tile, plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(newtile) == 1)
TiNMMergeRight(TR(newtile), plane);
}
else
{
TiNMMergeLeft(newtile, plane);
TiNMMergeRight(TR(tile), plane);
if (mergeFlags & MRG_LEFT)
TiNMMergeLeft(newtile, plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(tile) == 1)
TiNMMergeRight(TR(tile), plane);
}
}
else
@ -388,13 +401,17 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType];
tile = TiNMMergeLeft(tile, plane);
TiNMMergeRight(TR(newtile), plane);
if (mergeFlags & MRG_LEFT)
tile = TiNMMergeLeft(tile, plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(newtile) == 0)
TiNMMergeRight(TR(newtile), plane);
}
else
{
TiNMMergeLeft(newtile, plane);
TiNMMergeRight(TR(tile), plane);
if (mergeFlags & MRG_LEFT)
TiNMMergeLeft(newtile, plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(tile) == 0)
TiNMMergeRight(TR(tile), plane);
}
}
else
@ -423,13 +440,17 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType];
tile = TiNMMergeLeft(tile, plane);
TiNMMergeRight(LB(newtile), plane);
if (mergeFlags & MRG_LEFT)
tile = TiNMMergeLeft(tile, plane);
if (mergeFlags & MRG_RIGHT)
TiNMMergeRight(LB(newtile), plane);
}
else
{
TiNMMergeRight(newtile, plane);
TiNMMergeLeft(LB(tile), plane);
if (mergeFlags & MRG_LEFT)
TiNMMergeRight(newtile, plane);
if (mergeFlags & MRG_RIGHT)
TiNMMergeLeft(LB(tile), plane);
}
}
else
@ -439,11 +460,11 @@ enumerate:
/* Merge the outside tile to its top */
tp = RT(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its bottom */
tp = LB(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane);
}
mergeFlags &= ~MRG_RIGHT;
}
@ -466,13 +487,13 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType];
// tile = TiNMMergeRight(tile, plane);
TiNMMergeLeft(LB(newtile), plane);
if (mergeFlags & MRG_LEFT)
TiNMMergeLeft(LB(newtile), plane);
}
else
{
TiNMMergeLeft(newtile, plane);
// TiNMMergeRight(LB(tile), plane);
if (mergeFlags & MRG_LEFT)
TiNMMergeLeft(newtile, plane);
}
}
else
@ -483,11 +504,11 @@ enumerate:
/* Merge the outside tile to its top */
tp = RT(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its bottom */
tp = LB(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane);
}
mergeFlags &= ~MRG_LEFT;
}
@ -579,7 +600,7 @@ clipdone:
if (mergeFlags & MRG_TOP)
{
tp = RT(tile);
if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged up (CHEAP)");
@ -588,7 +609,7 @@ clipdone:
if (mergeFlags & MRG_BOTTOM)
{
tp = LB(tile);
if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged down (CHEAP)");
@ -697,6 +718,7 @@ enum2:
done2:
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -1032,6 +1054,7 @@ DBMergeNMTiles0(plane, area, undo, mergeOnce)
int clipTop;
Tile *tile, *tp, *tp2, *newtile, *tpnew;
int aspecta, aspectb;
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype, ltype, rtype;
start.p_x = area->r_xbot;
@ -1121,23 +1144,23 @@ nmenum:
newtile = TiSplitY(tp2, TOP(tile));
TiSetBody(newtile, ltype);
if (CANMERGE_X(newtile, BL(newtile)))
TiJoinX(newtile, BL(newtile), plane);
TiJoinX1(&delayed, newtile, BL(newtile), plane);
if (CANMERGE_X(newtile, TR(newtile)))
TiJoinX(newtile, TR(newtile), plane);
TiJoinX1(&delayed, newtile, TR(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY(newtile, RT(newtile), plane);
TiJoinY1(&delayed, newtile, RT(newtile), plane);
}
if (LEFT(tp2) < LEFT(tp))
{
newtile = TiSplitX(tp2, LEFT(tp));
TiSetBody(newtile, ltype);
if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY(tp2, LB(tp2), plane);
TiJoinY1(&delayed, tp2, LB(tp2), plane);
if (CANMERGE_Y(tp2, RT(tp2)))
TiJoinY(tp2, RT(tp2), plane);
TiJoinY1(&delayed, tp2, RT(tp2), plane);
tp2 = newtile;
}
TiJoinY(tp2, tp, plane);
TiJoinY1(&delayed, tp2, tp, plane);
tp = tp2;
tp2 = RT(tp2);
}
@ -1151,11 +1174,11 @@ nmenum:
newtile = TiSplitY(tp2, BOTTOM(tp));
TiSetBody(newtile, rtype);
if (CANMERGE_X(tp2, BL(tp2)))
TiJoinX(tp2, BL(tp2), plane);
TiJoinX1(&delayed, tp2, BL(tp2), plane);
if (CANMERGE_X(tp2, TR(tp2)))
TiJoinX(tp2, TR(tp2), plane);
TiJoinX1(&delayed, tp2, TR(tp2), plane);
if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY(tp2, LB(tp2), plane);
TiJoinY1(&delayed, tp2, LB(tp2), plane);
tp2 = newtile;
}
if (RIGHT(tp2) > RIGHT(tile))
@ -1163,16 +1186,16 @@ nmenum:
newtile = TiSplitX(tp2, RIGHT(tile));
TiSetBody(newtile, rtype);
if (CANMERGE_Y(newtile, LB(newtile)))
TiJoinY(newtile, LB(newtile), plane);
TiJoinY1(&delayed, newtile, LB(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY(newtile, RT(newtile), plane);
TiJoinY1(&delayed, newtile, RT(newtile), plane);
}
TiJoinY(tp2, tile, plane);
TiJoinY1(&delayed, tp2, tile, plane);
tile = tp2;
tp2 = LB(tp2);
}
/* Merge tp and tile */
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
TiSetBody(tile, ttype);
}
else /* split direction 1 */
@ -1213,11 +1236,11 @@ nmenum:
newtile = TiSplitY(tp2, BOTTOM(tp));
TiSetBody(newtile, ltype);
if (CANMERGE_X(tp2, BL(tp2)))
TiJoinX(tp2, BL(tp2), plane);
TiJoinX1(&delayed, tp2, BL(tp2), plane);
if (CANMERGE_X(tp2, TR(tp2)))
TiJoinX(tp2, TR(tp2), plane);
TiJoinX1(&delayed, tp2, TR(tp2), plane);
if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY(tp2, LB(tp2), plane);
TiJoinY1(&delayed, tp2, LB(tp2), plane);
tp2 = newtile;
}
if (LEFT(tp2) < LEFT(tile))
@ -1225,12 +1248,12 @@ nmenum:
newtile = TiSplitX(tp2, LEFT(tile));
TiSetBody(newtile, ltype);
if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY(tp2, LB(tp2), plane);
TiJoinY1(&delayed, tp2, LB(tp2), plane);
if (CANMERGE_Y(tp2, RT(tp2)))
TiJoinY(tp2, RT(tp2), plane);
TiJoinY1(&delayed, tp2, RT(tp2), plane);
tp2 = newtile;
}
TiJoinY(tp2, tile, plane);
TiJoinY1(&delayed, tp2, tile, plane);
tile = tp2;
tp2 = LB(tp2);
}
@ -1245,27 +1268,27 @@ nmenum:
newtile = TiSplitY(tp2, TOP(tile));
TiSetBody(newtile, rtype);
if (CANMERGE_X(newtile, BL(newtile)))
TiJoinX(newtile, BL(newtile), plane);
TiJoinX1(&delayed, newtile, BL(newtile), plane);
if (CANMERGE_X(newtile, TR(newtile)))
TiJoinX(newtile, TR(newtile), plane);
TiJoinX1(&delayed, newtile, TR(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY(newtile, RT(newtile), plane);
TiJoinY1(&delayed, newtile, RT(newtile), plane);
}
if (RIGHT(tp2) > RIGHT(tp))
{
newtile = TiSplitX(tp2, RIGHT(tp));
TiSetBody(newtile, rtype);
if (CANMERGE_Y(newtile, LB(newtile)))
TiJoinY(newtile, LB(newtile), plane);
TiJoinY1(&delayed, newtile, LB(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY(newtile, RT(newtile), plane);
TiJoinY1(&delayed, newtile, RT(newtile), plane);
}
TiJoinY(tp2, tp, plane);
TiJoinY1(&delayed, tp2, tp, plane);
tp = tp2;
tp2 = RT(tp2);
}
/* Merge tp and tile */
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
TiSetBody(tile, ttype);
}
/* Now repeat until no more merging is possible */
@ -1307,6 +1330,7 @@ nmenum:
nmdone:
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -1411,10 +1435,6 @@ DBDiagonalProc(oldtype, dinfo)
else
return -1;
/* For purposes of "undo" recording, record which side we just painted */
if (dinfo->side)
newtype |= TT_SIDE;
return newtype;
}
@ -1768,12 +1788,14 @@ nextrect:
lr = lr->r_next;
}
free_magic1_t mm1 = freeMagic1_init();
lr = lhead;
while (lr != NULL)
{
freeMagic((char *) lr);
freeMagic1(&mm1, (char *) lr);
lr = lr->r_next;
}
freeMagic1_end(&mm1);
}
else
result = DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
@ -1794,14 +1816,15 @@ nextrect:
*/
int
dbNMEnumFunc(tile, arg)
dbNMEnumFunc(tile, dinfo, arg)
Tile *tile;
TileType dinfo;
LinkedRect **arg;
{
LinkedRect *lr;
/* Ignore the second call to any diagonal---only count once! */
if (IsSplit(tile) && SplitSide(tile)) return 0;
if (IsSplit(tile) && (dinfo & TT_SIDE)) return 0;
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
TiToRect(tile, &lr->r_r);
@ -1885,6 +1908,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
PaintUndoInfo *undo; /* See DBPaintPlane() above */
bool mark; /* Mark tiles that were processed */
{
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast;
int ysplit;
@ -1991,7 +2015,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mark) dbMarkClient(tile, area);
}
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -2007,7 +2031,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mark) dbMarkClient(tile, area);
}
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
@ -2016,7 +2040,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mergeFlags&MRG_TOP)
{
tp = RT(tile);
if (CANMERGE_Y(tp, tile)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tp, tile)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2025,13 +2049,14 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mergeFlags&MRG_BOTTOM)
{
tp = LB(tile);
if (CANMERGE_Y(tp, tile)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tp, tile)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
#endif /* PAINTDEBUG */
}
TiFreeIf(delayed);
return (tile);
}
@ -2094,6 +2119,7 @@ DBPaintType(plane, area, resultTbl, client, undo, tileMask)
* search.
*/
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane);
@ -2186,14 +2212,14 @@ enumerate:
if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY(newtile, tp, plane);
TiJoinY1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its bottom */
tp = LB(newtile);
if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY(newtile, tp, plane);
TiJoinY1(&delayed, newtile, tp, plane);
}
/* Clip left */
@ -2210,14 +2236,14 @@ enumerate:
if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY(newtile, tp, plane);
TiJoinY1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its bottom */
tp = LB(newtile);
if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY(newtile, tp, plane);
TiJoinY1(&delayed, newtile, tp, plane);
}
#ifdef PAINTDEBUG
@ -2276,7 +2302,7 @@ enumerate:
{
tp = RT(tile);
if (CANMERGE_Y(tile, tp) && (tp->ti_client == client))
TiJoinY(tile, tp, plane);
TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged up (CHEAP)");
@ -2286,7 +2312,7 @@ enumerate:
{
tp = LB(tile);
if (CANMERGE_Y(tile, tp) && (tp->ti_client == client))
TiJoinY(tile, tp, plane);
TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged down (CHEAP)");
@ -2334,6 +2360,7 @@ paintdone:
done:
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
}
/*
@ -2380,6 +2407,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
PaintUndoInfo *undo; /* See DBPaintPlane() above */
ClientData client;
{
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast;
int ysplit;
@ -2481,7 +2509,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
TiSetClient(tpLast, client);
}
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -2497,7 +2525,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
TiSetClient(tpLast, client);
}
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
@ -2506,7 +2534,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
if (mergeFlags&MRG_TOP)
{
tp = RT(tile);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2515,13 +2543,14 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
if (mergeFlags&MRG_BOTTOM)
{
tp = LB(tile);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
#endif /* PAINTDEBUG */
}
TiFreeIf(delayed);
return (tile);
}
@ -2581,6 +2610,7 @@ DBPaintPlaneVert(plane, area, resultTbl, undo)
* search.
*/
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane);
@ -2662,11 +2692,11 @@ enumerate:
/* Merge the outside tile to its left */
tp = BL(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its right */
tp = TR(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane);
}
/* Clip down */
@ -2678,11 +2708,11 @@ enumerate:
/* Merge the outside tile to its left */
tp = BL(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane);
/* Merge the outside tile to its right */
tp = TR(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane);
}
#ifdef PAINTDEBUG
@ -2740,7 +2770,7 @@ enumerate:
if (mergeFlags & MRG_LEFT)
{
tp = BL(tile);
if (CANMERGE_X(tile, tp)) TiJoinX(tile, tp, plane);
if (CANMERGE_X(tile, tp)) TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged left (CHEAP)");
@ -2749,7 +2779,7 @@ enumerate:
if (mergeFlags & MRG_RIGHT)
{
tp = TR(tile);
if (CANMERGE_X(tile, tp)) TiJoinX(tile, tp, plane);
if (CANMERGE_X(tile, tp)) TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged right (CHEAP)");
@ -2797,6 +2827,7 @@ paintdone:
done:
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -2849,6 +2880,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
int mergeFlags; /* Specify which directions to merge */
PaintUndoInfo *undo; /* See DBPaintPlane() above */
{
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast;
int xsplit;
@ -2943,7 +2975,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile));
if (RIGHT(tp) > RIGHT(tile))
tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType);
TiJoinY(tile, tp, plane);
TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2956,7 +2988,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile));
if (RIGHT(tp) > RIGHT(tile))
tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType);
TiJoinY(tile, tp, plane);
TiJoinY1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
@ -2966,7 +2998,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (mergeFlags&MRG_LEFT)
{
tp = BL(tile);
if (CANMERGE_X(tp, tile)) TiJoinX(tile, tp, plane);
if (CANMERGE_X(tp, tile)) TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -2975,13 +3007,14 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (mergeFlags&MRG_RIGHT)
{
tp = TR(tile);
if (CANMERGE_X(tp, tile)) TiJoinX(tile, tp, plane);
if (CANMERGE_X(tp, tile)) TiJoinX1(&delayed, tile, tp, plane);
#ifdef PAINTDEBUG
if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
#endif /* PAINTDEBUG */
}
TiFreeIf(delayed);
return (tile);
}
@ -3004,7 +3037,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
* ----------------------------------------------------------------------------
*/
#include "styles.h"
#include "utils/styles.h"
void
dbPaintShowTile(tile, undo, str)
@ -3027,6 +3060,16 @@ dbPaintShowTile(tile, undo, str)
TxPrintf("%s --more--", str); fflush(stdout);
(void) TxGetLine(answer, sizeof answer);
DBWFeedbackClear(NULL);
/* To debug tile operations that happen away from the active layout
* window, it may be advantageous to replace the display code above
* with the print statement below.
*/
/*
TxPrintf("Debug %s: Tile (%d %d) to (%d %d) type %d\n",
str, LEFT(tile), BOTTOM(tile), RIGHT(tile), TOP(tile),
TiGetBody(tile));
*/
}
#endif /* PAINTDEBUG */
@ -3316,6 +3359,7 @@ TiNMMergeRight(tile, plane)
Tile *tile;
Plane *plane;
{
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype = TiGetTypeExact(tile);
Tile *tp, *tp2, *newtile;
@ -3347,7 +3391,7 @@ TiNMMergeRight(tile, plane)
else
newtile = tile;
// Join tp to newtile
TiJoinX(newtile, tp, plane);
TiJoinX1(&delayed, newtile, tp, plane);
}
tp = tp2;
}
@ -3364,11 +3408,13 @@ TiNMMergeRight(tile, plane)
newtile = TiSplitY(tp, BOTTOM(tile));
TiSetBody(newtile, ttype);
// join newtile to tile
TiJoinX(tile, newtile, plane);
TiJoinX1(&delayed, tile, newtile, plane);
// merge up if possible
if (CANMERGE_Y(tile, RT(tile))) TiJoinY(tile, RT(tile), plane);
if (CANMERGE_Y(tile, RT(tile))) TiJoinY1(&delayed, tile, RT(tile), plane);
}
}
TiFreeIf(delayed);
return tile;
}
@ -3396,6 +3442,7 @@ TiNMMergeLeft(tile, plane)
Tile *tile;
Plane *plane;
{
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype = TiGetTypeExact(tile);
Tile *tp, *tp2, *newtile;
@ -3428,7 +3475,7 @@ TiNMMergeLeft(tile, plane)
else
newtile = tile;
// Join tp to tile
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
tile = newtile;
}
tp = tp2;
@ -3446,14 +3493,16 @@ TiNMMergeLeft(tile, plane)
newtile = TiSplitY(tp, TOP(tile));
TiSetBody(newtile, ttype);
// join tp to tile
TiJoinX(tile, tp, plane);
TiJoinX1(&delayed, tile, tp, plane);
}
}
else
{
// Merge up if possible
if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane);
}
TiFreeIf(delayed);
return tile;
}

View File

@ -119,8 +119,9 @@ DBPaint (cellDef, rect, type)
*/
int
dbResolveImages(tile, cellDef)
dbResolveImages(tile, dinfo, cellDef)
Tile *tile;
TileType dinfo;
CellDef *cellDef;
{
Rect rect;
@ -130,7 +131,7 @@ dbResolveImages(tile, cellDef)
/* Recursive call back to DBPaint---this will ensure that */
/* all of the planes of the image type are painted. */
DBPaint(cellDef, &rect, TiGetTypeExact(tile));
DBPaint(cellDef, &rect, TiGetTypeExact(tile) | dinfo);
return 0;
}

View File

@ -327,11 +327,11 @@ DBTechNoisyNamePlane(planename)
* ----------------------------------------------------------------------------
*/
char *
DBTypeShortName(type)
TileType type;
const char *
DBTypeShortName(
TileType type)
{
NameList *tbl;
const NameList *tbl;
for (tbl = dbTypeNameLists.sn_next;
tbl != &dbTypeNameLists;
@ -347,11 +347,11 @@ DBTypeShortName(type)
return ("???");
}
char *
DBPlaneShortName(pNum)
int pNum;
const char *
DBPlaneShortName(
int pNum)
{
NameList *tbl;
const NameList *tbl;
for (tbl = dbPlaneNameLists.sn_next;
tbl != &dbPlaneNameLists;
@ -478,7 +478,7 @@ DBTechPrintTypes(mask, dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, " ", (char *)NULL);
#else
TxPrintf(" ", keepname);
TxPrintf(" ");
#endif
}
}
@ -530,7 +530,7 @@ DBTechPrintTypes(mask, dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, " ", (char *)NULL);
#else
TxPrintf(" ", keepname);
TxPrintf(" ");
#endif
}
}

View File

@ -38,14 +38,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Types and their names */
int DBNumTypes;
char *DBTypeLongNameTbl[NT];
const char *DBTypeLongNameTbl[NT];
int DBTypePlaneTbl[NT]; /* Normally accessed as macro "DBPlane(x)" */
NameList dbTypeNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
HashTable DBTypeAliasTable;
/* Planes and their names */
int DBNumPlanes;
char *DBPlaneLongNameTbl[PL_MAXTYPES];
const char *DBPlaneLongNameTbl[PL_MAXTYPES];
NameList dbPlaneNameLists = {NULL, NULL, NULL, (ClientData)0, FALSE};
@ -116,22 +116,24 @@ NameList *dbTechNameAddOne();
*/
void
DBTechInitPlane()
DBTechInitPlane(void)
{
DefaultPlane *dpp;
char *cp;
const char *cp;
/* Clear out any old information */
if (dbPlaneNameLists.sn_next != NULL)
{
NameList *tbl;
free_magic1_t mm1 = freeMagic1_init();
for (tbl = dbPlaneNameLists.sn_next; tbl != &dbPlaneNameLists;
tbl = tbl->sn_next)
{
freeMagic(tbl->sn_name);
freeMagic(tbl);
freeMagic1(&mm1, tbl);
}
freeMagic1_end(&mm1);
}
/* Tables of short names */
@ -205,12 +207,14 @@ DBTechInitType()
{
NameList *tbl;
free_magic1_t mm1 = freeMagic1_init();
for (tbl = dbTypeNameLists.sn_next; tbl != &dbTypeNameLists;
tbl = tbl->sn_next)
{
freeMagic(tbl->sn_name);
freeMagic(tbl);
freeMagic1(&mm1, tbl);
}
freeMagic1_end(&mm1);
}
/* Tables of short names */
@ -264,12 +268,12 @@ DBTechInitType()
/*ARGSUSED*/
bool
DBTechAddPlane(sectionName, argc, argv)
char *sectionName;
int argc;
char *argv[];
DBTechAddPlane(
const char *sectionName,
int argc,
char *argv[])
{
char *cp;
const char *cp;
if (DBNumPlanes >= PL_MAXTYPES)
{

View File

@ -44,6 +44,296 @@ struct dbCheck
int dbCheckMaxHFunc(), dbCheckMaxVFunc();
/*
* --------------------------------------------------------------------
*
* dbEvalCorner --
*
* Used by DBTestNMInteract() to determine whether two non-
* Manhattan areas have crossing diagonals by evaluating the
* corner points of the area of intersection between the two
* tiles. This routine finds the distance from a point in
* the second triangle to the diagonal of the first, in both
* x and y. If the point is below or to the left, the
* distance is negative; otherwise the distance is positive.
*
* Results:
* 1 for a positive result, -1 for a negative result, and 0
* for the same result (point touches the diagonal).
*
* Side effects:
* None.
*
* --------------------------------------------------------------------
*/
int
dbEvalCorner(Point *p, // Point to evaluate
Rect *rect, // Triangular area bounding rectangle
TileType di) // Diagonal information for split rect
{
dlong D;
/* D is the distance from a point to the diagonal of the rectangle.
* The magnitude is not important. It only matters what the sign
* is, so return 1 for positive, -1 for negative, or 0.
*/
if (di & TT_DIRECTION)
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
(rect->r_xtop - p->p_x) * (rect->r_ytop - rect->r_ybot);
else
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
(p->p_x - rect->r_xbot) * (rect->r_ytop - rect->r_ybot);
if (D > 0) return 1;
if (D < 0) return -1;
return 0;
}
/*
* --------------------------------------------------------------------
*
* DBTestNMInteract --
*
* Determine if a tile (t2) interacts with (touches or overlaps)
* a triangular area (rect1, with diagonal split information in
* di1). Tile t2 may or may not be a split tile. If t2 is
* split, then diagonal split information is in di2.
*
* There are two distinct cases: DBSrPaintNMArea() looks for
* tiles that overlap the area of rect1, but extTestNMInteract()
* looks for tiles that both overlap or touch (indicating
* electrical connectivity between the two). "overlap_only"
* distinguishes between the two use cases. Set "overlap_only"
* to TRUE for overlap searches, and FALSE for interaction
* searches.
*
* Results:
*
* If overlap_only is TRUE:
* Return TRUE if the indicated areas overlap, FALSE if not.
* If overlap_only is FALSE:
* Return TRUE if the indicated areas touch or overlap, FALSE if not.
*
* Side effects:
* None.
*
* --------------------------------------------------------------------
*/
bool
DBTestNMInteract(Rect *rect1,
TileType tt1,
Tile *t2,
TileType di2,
bool overlap_only)
{
Rect rect2, r;
Point p;
int rheight, rwidth, rmax;
dlong f1, f2, f3, f4;
TileType tt2;
int pos, neg, touch, sign;
TiToRect(t2, &rect2);
/* Assuming that rect1 is a split area, then check if any part of t2
* overlaps the split side of interest in rect1, regardless of whether
* t2 is split or not. If there is no overlap, then return FALSE.
*/
rheight = rect1->r_ytop - rect1->r_ybot;
rwidth = rect1->r_xtop - rect1->r_xbot;
rmax = MAX(rheight, rwidth);
f1 = (rect2.r_ybot > MINFINITY + 2) ?
((dlong)(rect1->r_ytop - rect2.r_ybot) * rwidth) : DLONG_MAX;
f2 = (rect2.r_ytop < INFINITY - 2) ?
((dlong)(rect2.r_ytop - rect1->r_ybot) * rwidth) : DLONG_MAX;
if (tt1 & TT_SIDE)
{
/* Outside-of-triangle check---ignore sub-integer slivers */
if (rect2.r_xtop < INFINITY - 2)
{
f3 = (dlong)(rect1->r_xtop - rect2.r_xtop) * rheight;
f3 += rmax;
}
else
f3 = DLONG_MIN;
if ((tt1 & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
return FALSE;
}
else
{
/* Outside-of-triangle check---ignore sub-integer slivers */
if (rect2.r_xbot > MINFINITY + 2)
{
f4 = (dlong)(rect2.r_xbot - rect1->r_xbot) * rheight;
f4 += rmax;
}
else
f4 = DLONG_MIN;
if ((tt1 & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
return FALSE;
}
/* If t2 is not split, or its diagonal is the opposite of t1,
* or its side is the same as that of t1, then they overlap.
*/
if (!IsSplit(t2)) return TRUE;
tt2 = TiGetTypeExact(t2) | di2;
if ((tt1 & TT_DIRECTION) != (tt2 & TT_DIRECTION)) return TRUE;
// if ((tt1 & TT_SIDE) == (tt2 & TT_SIDE)) return TRUE;
/* Hard case: Same diagonal direction, opposite sides. To determine
* overlap, count which of the three points of triangle t2 land on
* one side or the other of the rect1 split diagonal. From those
* counts, determine if the triangles are overlapping, touching,
* or disjoint.
*/
/* Evaluate the three corners of the rect2 triangle */
pos = neg = touch = 0;
if (!(tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
{
/* Evaluate the lower left corner */
sign = dbEvalCorner(&rect2.r_ll, rect1, tt1);
if (sign == 1)
pos++;
else if (sign == -1)
neg++;
else
touch++;
}
if (!(tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
{
/* Evaluate the upper right corner */
sign = dbEvalCorner(&rect2.r_ur, rect1, tt1);
if (sign == 1)
pos++;
else if (sign == -1)
neg++;
else
touch++;
}
if ((tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
{
/* Evaluate the upper left corner */
p.p_x = rect2.r_xbot;
p.p_y = rect2.r_ytop;
sign = dbEvalCorner(&p, rect1, tt1);
if (sign == 1)
pos++;
else if (sign == -1)
neg++;
else
touch++;
}
if ((tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
{
/* Evaluate the lower right corner */
p.p_x = rect2.r_xtop;
p.p_y = rect2.r_ybot;
sign = dbEvalCorner(&p, rect1, tt1);
if (sign == 1)
pos++;
else if (sign == -1)
neg++;
else
touch++;
}
/* If side and direction match, then pos and neg need to be swapped */
if (((tt1 & TT_SIDE) && (tt1 & TT_DIRECTION)) ||
(!(tt1 & TT_SIDE) && !(tt1 & TT_DIRECTION)))
{
int temp = neg;
neg = pos;
pos = temp;
}
/* Return TRUE or FALSE depending on the values of pos, neg, and
* touch, and depending on whether overlap_only is set or not.
*/
if (pos == 3)
return FALSE; /* Fully disjoint */
else if (neg == 3)
{
if ((tt1 & TT_SIDE) != (tt2 & TT_SIDE))
return TRUE; /* Fully enclosed */
else
{
/* This is a trickier situation. Both triangles have
* the same TT_SIDE bit, but the triangular area of t2
* could still be outside of rect1. Need to check where
* the inside corner of rect1 lands with respect to the
* t2 diagonal.
*/
if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) != 0))
{
sign = dbEvalCorner(&rect1->r_ll, &rect2, tt2);
}
else if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) == 0))
{
p.p_x = rect1->r_ll.p_x;
p.p_y = rect1->r_ur.p_y;
sign = dbEvalCorner(&p, &rect2, tt2);
}
else if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) == 0))
{
p.p_x = rect1->r_ur.p_x;
p.p_y = rect1->r_ll.p_y;
sign = dbEvalCorner(&p, &rect2, tt2);
}
else /* if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) != 0)) */
{
sign = dbEvalCorner(&rect1->r_ur, &rect2, tt2);
}
/* Again, if side and direction match, then sign is backwards
*/
if (((tt2 & TT_SIDE) && (tt2 & TT_DIRECTION)) ||
(!(tt2 & TT_SIDE) && !(tt2 & TT_DIRECTION)))
sign = -sign;
if (sign == 1)
return FALSE; /* Fully disjoint */
else if (sign == -1)
return TRUE; /* Fully overlapping */
else if (overlap_only)
return FALSE; /* Touching but not overlapping */
else
return TRUE; /* Touching but not overlapping */
}
}
else if (overlap_only)
{
if ((touch > 0) && (neg + touch == 3))
return TRUE; /* Enclosed and touching */
else if ((touch > 0) && (pos + touch == 3))
return FALSE; /* Unenclosed but touching */
else
return TRUE; /* Partially overlapping */
}
else /* overlap_only == FALSE */
{
if ((touch > 0) && (neg + touch == 3))
return TRUE; /* Enclosed and touching */
else if ((touch > 0) && (pos + touch == 3))
return TRUE; /* Unenclosed but touching */
else
return TRUE; /* Partially overlapping */
}
}
/*
* --------------------------------------------------------------------
*
@ -56,6 +346,7 @@ int dbCheckMaxHFunc(), dbCheckMaxVFunc();
* int
* func(tile, cdata)
* Tile *tile;
* TileType dinfo;
* ClientData cdata;
* {
* }
@ -92,7 +383,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
* provide a hint tile in case hintTile == NULL.
* The hint tile in the plane is updated to be
* the last tile visited in the area
* enumeration.
* enumeration, if plane is non-NULL.
*/
TileType ttype; /* Information about the non-manhattan area to
* search; zero if area is manhattan.
@ -111,7 +402,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
TileType tpt;
int rheight, rwidth, rmax;
dlong f1, f2, f3, f4;
bool ignore_sides;
int ignore_sides;
/* If the search area is not diagonal, return the result of the */
/* standard (manhattan) search function. */
@ -129,7 +420,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
{
/* Each iteration enumerates another tile */
nm_enum:
PlaneSetHint(plane, tp);
if (plane != (Plane *)NULL) PlaneSetHint(plane, tp);
if (SigInterruptPending)
return (1);
@ -137,147 +428,26 @@ nm_enum:
/* the tile enumeration if it is not. */
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
rheight = rect->r_ytop - rect->r_ybot;
rwidth = rect->r_xtop - rect->r_xbot;
rmax = MAX(rheight, rwidth);
f1 = (BOTTOM(tp) > MINFINITY + 2) ?
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
f2 = (TOP(tp) < INFINITY - 2) ?
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
if (ttype & TT_SIDE)
{
/* Outside-of-triangle check---ignore sub-integer slivers */
if (RIGHT(tp) < INFINITY - 2)
{
f3 = (dlong)(rect->r_xtop - RIGHT(tp)) * rheight;
f3 += rmax;
}
else
f3 = DLONG_MIN;
if ((ttype & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
goto enum_next;
}
else
{
/* Outside-of-triangle check---ignore sub-integer slivers */
if (LEFT(tp) > MINFINITY + 2)
{
f4 = (dlong)(LEFT(tp) - rect->r_xbot) * rheight;
f4 += rmax;
}
else
f4 = DLONG_MIN;
if ((ttype & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
goto enum_next;
}
/* Secondary checks---if tile is also non-Manhattan, is */
/* either side of it outside the area? If so, restrict it. */
/* This check is only necessary if the split directions are */
/* the same, so we have to see if either of the neighboring */
/* points is also inside the search triangle. */
ignore_sides = 0;
if (IsSplit(tp))
{
if (!TTMaskHasType(mask, SplitLeftType(tp)))
ignore_sides |= IGNORE_LEFT;
if (!TTMaskHasType(mask, SplitRightType(tp)))
ignore_sides |= IGNORE_RIGHT;
TileType tpdi = TiGetTypeExact(tp);
tpt = TiGetTypeExact(tp);
if ((tpt & TT_DIRECTION) == (ttype & TT_DIRECTION))
{
f3 = (LEFT(tp) > MINFINITY + 2) ?
((dlong)(rect->r_xtop - LEFT(tp)) * rheight) : DLONG_MAX;
f4 = (RIGHT(tp) < INFINITY - 2) ?
((dlong)(RIGHT(tp) - rect->r_xbot) * rheight) : DLONG_MAX;
if (ttype & TT_SIDE)
{
/* Ignore sub-integer slivers */
if (f4 != DLONG_MAX) f4 -= rmax;
if (f3 != DLONG_MAX) f3 += rmax;
if (ttype & TT_DIRECTION)
{
if ((f2 < f3) && (f1 > f4))
/* Tile bottom left is outside search area */
ignore_sides |= IGNORE_LEFT;
}
else
{
if ((f1 < f3) && (f2 > f4))
/* Tile top left is outside search area */
ignore_sides |= IGNORE_LEFT;
}
}
else
{
/* Ignore sub-integer slivers */
if (f4 != DLONG_MAX) f4 += rmax;
if (f3 != DLONG_MAX) f3 -= rmax;
if (ttype & TT_DIRECTION)
{
if ((f2 > f3) && (f1 < f4))
/* Tile top right is outside search area */
ignore_sides |= IGNORE_RIGHT;
}
else
{
if ((f1 > f3) && (f2 < f4))
/* Tile bottom right is outside search area */
ignore_sides |= IGNORE_RIGHT;
}
}
}
/* If the tile is larger than the search area or overlaps */
/* the search area, we need to check if one of the sides */
/* of the tile is disjoint from the search area. */
rheight = TOP(tp) - BOTTOM(tp);
rwidth = RIGHT(tp) - LEFT(tp);
rmax = MAX(rheight, rwidth);
f1 = (TOP(tp) < INFINITY - 2) ?
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
f2 = (BOTTOM(tp) > MINFINITY + 2) ?
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
f3 = (RIGHT(tp) < INFINITY - 2) ?
((dlong)(RIGHT(tp) - rect->r_xtop) * rheight) : DLONG_MAX;
f4 = (LEFT(tp) > MINFINITY + 2) ?
((dlong)(rect->r_xbot - LEFT(tp)) * rheight) : DLONG_MAX;
/* ignore sub-integer slivers */
if (f4 < DLONG_MAX) f4 += rmax;
if (f3 < DLONG_MAX) f3 += rmax;
if (SplitDirection(tp) ? (f1 < f4) : (f2 < f4))
ignore_sides |= IGNORE_LEFT;
if (SplitDirection(tp) ? (f2 < f3) : (f1 < f3))
ignore_sides |= IGNORE_RIGHT;
/* May call function twice to paint both sides of */
/* the split tile, if necessary. */
if (!(ignore_sides & IGNORE_LEFT))
{
TiSetBody(tp, INT2CD(tpt & ~TT_SIDE)); /* bit clear */
if ((*func)(tp, arg)) return (1);
}
if (!(ignore_sides & IGNORE_RIGHT))
{
TiSetBody(tp, INT2CD(tpt | TT_SIDE)); /* bit set */
if ((*func)(tp, arg)) return (1);
}
}
if (TTMaskHasType(mask, SplitLeftType(tp)))
if (DBTestNMInteract(rect, ttype, tp, tpdi, TRUE))
if ((*func)(tp, (TileType)TT_DIAGONAL, arg))
return 1;
if (TTMaskHasType(mask, SplitRightType(tp)))
if (DBTestNMInteract(rect, ttype, tp, tpdi | TT_SIDE, TRUE))
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg))
return 1;
}
else
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
return (1);
{
if (TTMaskHasType(mask, TiGetType(tp)))
if (DBTestNMInteract(rect, ttype, tp, (TileType)0, TRUE))
if ((*func)(tp, (TileType)0, arg))
return 1;
}
enum_next:
tpnew = TR(tp);
@ -325,6 +495,7 @@ enum_next:
* int
* func(tile, cdata)
* Tile *tile;
* TileType dinfo;
* ClientData cdata;
* {
* }
@ -416,9 +587,7 @@ enumerate:
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
{
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
& ~TT_SIDE)); /* bit clear */
if ((*func)(tp, arg)) return (1);
if ((*func)(tp, (TileType)TT_DIAGONAL, arg)) return (1);
}
}
@ -429,14 +598,12 @@ enumerate:
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
{
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
| TT_SIDE)); /* bit set */
if ((*func)(tp, arg)) return (1);
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg)) return (1);
}
}
}
else
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, (TileType)0, arg))
return (1);
tpnew = TR(tp);
@ -485,6 +652,7 @@ enumerate:
* int
* func(tile, cdata)
* Tile *tile;
* TileType dinfo;
* ClientData cdata;
* {
* }
@ -576,9 +744,7 @@ enumerate:
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
{
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
& ~TT_SIDE)); /* bit clear */
if ((tp->ti_client == client) && (*func)(tp, arg))
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL, arg))
return (1);
}
}
@ -590,16 +756,15 @@ enumerate:
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
{
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
| TT_SIDE)); /* bit set */
if ((tp->ti_client == client) && (*func)(tp, arg))
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL
| TT_SIDE, arg))
return (1);
}
}
}
else
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
&& (*func)(tp, arg))
&& (*func)(tp, (TileType)0, arg))
return (1);
tpnew = TR(tp);
@ -665,7 +830,7 @@ DBResetTilePlane(plane, cdata)
/* Each iteration visits another tile on the LHS of the search area */
while (TOP(tp) > rect->r_ybot)
{
/* Each iteration frees another tile */
/* Each iteration resets another tile */
enumerate:
tp->ti_client = cdata;
@ -701,6 +866,88 @@ enumerate:
}
}
/*
* --------------------------------------------------------------------
*
* DBResetTilePlaneSpecial --
*
* This routine works like DBResetTilePlane(), but is designed
* specifically to be run after extFindNodes() or ExtFindRegions()
* to check for split tiles that have an allocated ExtSplitRegion
* structure in the ClientData; this needs to be freed before
* resetting the ClientData value to "cdata". It is not necessary
* to know anything about the ExtSplitRegion structure other than
* the condition under which it can be expected to be present,
* which is a split tile with neither side having type TT_SPACE.
*
* Results:
* None.
*
* Side effects:
* Resets the ti_client fields of all tiles.
*
* --------------------------------------------------------------------
*/
void
DBResetTilePlaneSpecial(plane, cdata)
Plane *plane; /* Plane whose tiles are to be reset */
ClientData cdata;
{
Tile *tp, *tpnew;
const Rect *rect = &TiPlaneRect;
/* Start with the leftmost non-infinity tile in the plane */
tp = TR(plane->pl_left);
/* Each iteration visits another tile on the LHS of the search area */
while (TOP(tp) > rect->r_ybot)
{
/* Each iteration resets another tile */
enumerate:
if (IsSplit(tp))
if ((TiGetLeftType(tp) != TT_SPACE) && (TiGetRightType(tp) != TT_SPACE))
if (tp->ti_client != cdata)
{
ASSERT(TiGetBody((Tile *)tp->ti_client) == CLIENTDEFAULT,
"DBResetTilePlaneSpecial");
freeMagic(tp->ti_client);
}
tp->ti_client = cdata;
/* Move along to the next tile */
tpnew = TR(tp);
if (LEFT(tpnew) < rect->r_xtop)
{
while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* Each iteration returns one tile further to the left */
while (LEFT(tp) > rect->r_xbot)
{
if (BOTTOM(tp) <= rect->r_ybot)
return;
tpnew = LB(tp);
tp = BL(tp);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* At left edge -- walk down to next tile along the left edge */
for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp))
/* Nothing */;
}
}
/*
* --------------------------------------------------------------------
*
@ -723,9 +970,7 @@ enumerate:
*
* This procedure uses a carfully constructed non-recursive area
* enumeration algorithm. Care is taken to not access a tile that has
* been deallocated. The only exception is for a tile that has just been
* passed to free(), but no more calls to free() or malloc() have been made.
* Magic's malloc allows this.
* been deallocated.
*
* --------------------------------------------------------------------
*/
@ -740,6 +985,7 @@ DBFreePaintPlane(plane)
/* Start with the bottom-right non-infinity tile in the plane */
tp = BL(plane->pl_right);
Tile *delayed = NULL;
/* Each iteration visits another tile on the RHS of the search area */
while (BOTTOM(tp) < rect->r_ytop)
{
@ -762,9 +1008,9 @@ enumerate:
/* Each iteration returns one tile further to the right */
while (RIGHT(tp) < rect->r_xtop)
{
TiFree(tp);
tpnew = RT(tp);
tp = TR(tp);
TiFree1(&delayed, tp);
tpnew = RT(tp); /* deref of delayed */
tp = TR(tp); /* deref of delayed */
if (CLIP_TOP(tpnew) <= CLIP_TOP(tp) && BOTTOM(tpnew) < rect->r_ytop)
{
tp = tpnew;
@ -772,13 +1018,14 @@ enumerate:
}
}
TiFree(tp);
TiFree1(&delayed, tp);
/* At right edge -- walk up to next tile along the right edge */
tp = RT(tp);
tp = RT(tp); /* deref of delayed */
if (BOTTOM(tp) < rect->r_ytop) {
while(LEFT(tp) >= rect->r_xtop) tp = BL(tp);
}
}
TiFreeIf(delayed);
}
/*
@ -918,8 +1165,9 @@ DBCheckMaxHStrips(plane, area, proc, cdata)
*/
int
dbCheckMaxHFunc(tile, dbc)
dbCheckMaxHFunc(tile, dinfo, dbc)
Tile *tile;
TileType dinfo; /* (unused) */
struct dbCheck *dbc;
{
Tile *tp;
@ -1010,8 +1258,9 @@ DBCheckMaxVStrips(plane, area, proc, cdata)
*/
int
dbCheckMaxVFunc(tile, dbc)
dbCheckMaxVFunc(tile, dinfo, dbc)
Tile *tile;
TileType dinfo; /* (unused) */
struct dbCheck *dbc;
{
Tile *tp;

View File

@ -137,8 +137,10 @@ DBFixMismatch()
cellDef = mismatch->mm_cellDef;
oldArea = mismatch->mm_oldArea;
freeMagic((char *) mismatch);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *) mismatch);
mismatch = mismatch->mm_next;
freeMagic1_end(&mm1);
if (cellDef->cd_flags & CDPROCESSED) continue;
(void) DBCellRead(cellDef, TRUE, TRUE, NULL);
@ -182,13 +184,15 @@ DBFixMismatch()
}
SigEnableInterrupts();
TxPrintf("Timestamp mismatches found in these cells: ");
free_magic1_t mm1 = freeMagic1_init();
while (cl != NULL)
{
TxPrintf("%s", cl->cl_cell->cd_name);
if (cl->cl_next != NULL) TxPrintf(", ");
freeMagic(cl);
freeMagic1(&mm1, cl);
cl = cl->cl_next;
}
freeMagic1_end(&mm1);
TxPrintf(".\n");
TxFlush();
if (redisplay) WindAreaChanged((MagWindow *) NULL, (Rect *) NULL);
@ -227,7 +231,7 @@ DBUpdateStamps(def)
else if (def->cd_flags & CDGETNEWSTAMP)
{
if (def->cd_flags & CDFIXEDSTAMP)
if (def->cd_flags & (CDNOEDIT | CDFIXEDSTAMP))
def->cd_flags &= ~CDGETNEWSTAMP;
else
dbStampFunc(def);
@ -247,6 +251,26 @@ dbStampFunc(cellDef)
if (cellDef->cd_timestamp == timestamp) return 0;
/* Non-editable cells should not try to update timestamps, as the
* new timestamp cannot be written back to the file. This is
* basically a hack solution for the problem that running DRC on
* all cells causes all cells, including non-editable ones, to be
* marked as modified, even if there were no DRC changes in the
* cell. It is possible to get into trouble this way by modifying
* a cell and then marking it as non-editable
*/
if (cellDef->cd_flags & CDNOEDIT)
{
cellDef->cd_flags &= ~CDGETNEWSTAMP;
return 0;
}
/*
* Do not force a non-edit cell or a cell with a fixed timestamp
* to update its timestamp, as it cannot or should not. Just clear
* any flag suggesting that it needs a new timestamp.
*/
if (!(cellDef->cd_flags & CDFIXEDSTAMP))
cellDef->cd_timestamp = timestamp;

View File

@ -15,6 +15,18 @@ SRCS = DBbound.c DBcell.c DBcellbox.c DBcellcopy.c \
include ${MAGICDIR}/defs.mak
LIB_OBJS += ${MAGICDIR}/tiles/libtiles.o ${MAGICDIR}/utils/libutils.o
CLEANS += database.h
# database.h is managed by the toplevel Makefile, because it has a build dependency
# order affecting multiple modules that need it. Both the creation time and the
# removal time (during 'clean') are managed by toplevel Makefile.
# if it was additionally removed by this clause here, it only causes bogus errors
# to be seen during some make operations due to race conditions caused by the
# unexpected removal by this clause in parallel MAKE execution of other modules
# that thought the file existed. FWIW database.h should be created first (near the
# start of top level build) and removed last (near the end of a top level clean).
#CLEANS += database.h
# This is delegated back to the top level Makefile
database.h: ${MAGICDIR}/database/database.h.in
${MAKE} -C ${MAGICDIR} database/database.h
include ${MAGICDIR}/rules.mak

62
database/arrayinfo.h Normal file
View File

@ -0,0 +1,62 @@
/*
* arrayinfo.h --
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*
*/
#ifndef _MAGIC__DATABASE__ARRAYINFO_H
#define _MAGIC__DATABASE__ARRAYINFO_H
/*
* Description of an array.
* The bounds xlo .. xhi and ylo .. yhi are transformed versions
* of the bounds xlo' .. xhi' and ylo' .. yhi' supplied by the
* user:
*
* User supplies:
* xlo' index of leftmost array element in root coordinates
* xhi' index of rightmost array element in root coordinates
* ylo' index of bottommost array element in root coordinates
* yhi' index of topmost array element in root coordinates
*
* There is no constraint on the order of any of these indices; xlo' may
* be less than, equal to, or greater than xhi', and similarly for ylo'
* and yhi'.
*
* In addition, the separations xsep and ysep are transformed versions
* of the separations xsep' and ysep' supplied by the user:
*
* User supplies:
* xsep' (positive) X spacing between array elements in root coords
* ysep' (positive) Y spacing between array elements in root coords
*
* When the array is made via DBMakeArray, both the indices and the spacings
* are transformed down to the coordinates of the CellDef that is the child
* of the use containing the ArrayInfo.
*
* The significance of the various values is as follows: the [xlo, ylo]
* element of the array is gotten by transforming the celldef by the
* transformation in the celluse. the [x, y] element is gotten by
* transforming the celldef by xsep*abs(x-xlo) in x, ysep*abs(y-ylo) in
* y, and then transforming by the transformation in the celluse.
*/
typedef struct
{
int ar_xlo, ar_xhi; /* Inclusive low/high X bounds */
int ar_ylo, ar_yhi; /* Inclusive low/high Y bounds */
int ar_xsep, ar_ysep; /* X,Y sep between array elements */
} ArrayInfo;
#endif /* _MAGIC__DATABASE__ARRAYINFO_H */

View File

@ -22,24 +22,24 @@
* rcsid "$Header: /usr/cvsroot/magic-8.0/database/database.h.in,v 1.8 2010/08/25 17:33:55 tim Exp $"
*/
#ifndef _DATABASE_H
#define _DATABASE_H
#ifndef _MAGIC__DATABASE__DATABASE_H
#define _MAGIC__DATABASE__DATABASE_H
#ifndef _TILES_H
#ifndef _MAGIC__TILES__TILE_H
#include "tiles/tile.h"
#endif /* _TILES_H */
#endif
#ifndef _HASH_H
#ifndef _MAGIC__UTILS__HASH_H
#include "utils/hash.h"
#endif /* _HASH_H */
#endif
#ifndef _STACK_H
#ifndef _MAGIC__UTILS__STACK_H
#include "utils/stack.h"
#endif /* _STACK_H */
#endif
#ifndef _BPLANE_H
#ifndef _MAGIC__BPLANE__BPLANE_H
#include "bplane/bplane.h"
#endif /* _BPLANE_H */
#endif
/* ----------------------- Tunable constants -------------------------- */
@ -303,9 +303,14 @@ typedef struct label
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
#define PORT_VISITED 0x2000 /* Bit for checking if a port */
#define LABEL_STICKY 0x2000 /* Label does not change layers */
#define LABEL_UNIQUE 0x4000 /* Temporary unique label */
/* The last two flags are never used at the same time and so can share
* a flag bit.
*/
#define PORT_VISITED 0x8000 /* Bit for checking if a port */
/* has been previously visited. */
#define LABEL_STICKY 0x4000 /* Label does not change layers */
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
/*
@ -403,6 +408,9 @@ typedef struct celldef
* is added to the magic database. The flag is used to identify
* whether the cell has been processed when forcing the GDS
* stream data to be read in post-order.
* CDPRELOADED is similar to CDPROCESSEDGDS but is used in cases
* other than forced post-order reading, such as flattening
* or flatten-by-name.
* CDVENDORGDS indicates that the cell was read from a GDS stream
* with the option "gds readonly true".
* CDVISITED indicates that at least one instance of the cell was
@ -434,53 +442,15 @@ typedef struct celldef
#define CDFLATGDS 0x00400
#define CDFLATTENED 0x00800
#define CDPROCESSEDGDS 0x01000
#define CDVENDORGDS 0x02000
#define CDVISITED 0x04000
#define CDDEREFERENCE 0x08000
#define CDFIXEDSTAMP 0x10000
#define CDNOEXTRACT 0x20000
#define CDDONTUSE 0x40000
#define CDPRELOADED 0x02000
#define CDVENDORGDS 0x04000
#define CDVISITED 0x08000
#define CDDEREFERENCE 0x10000
#define CDFIXEDSTAMP 0x20000
#define CDNOEXTRACT 0x40000
#define CDDONTUSE 0x80000
/*
* Description of an array.
* The bounds xlo .. xhi and ylo .. yhi are transformed versions
* of the bounds xlo' .. xhi' and ylo' .. yhi' supplied by the
* user:
*
* User supplies:
* xlo' index of leftmost array element in root coordinates
* xhi' index of rightmost array element in root coordinates
* ylo' index of bottommost array element in root coordinates
* yhi' index of topmost array element in root coordinates
*
* There is no constraint on the order of any of these indices; xlo' may
* be less than, equal to, or greater than xhi', and similarly for ylo'
* and yhi'.
*
* In addition, the separations xsep and ysep are transformed versions
* of the separations xsep' and ysep' supplied by the user:
*
* User supplies:
* xsep' (positive) X spacing between array elements in root coords
* ysep' (positive) Y spacing between array elements in root coords
*
* When the array is made via DBMakeArray, both the indices and the spacings
* are transformed down to the coordinates of the CellDef that is the child
* of the use containing the ArrayInfo.
*
* The significance of the various values is as follows: the [xlo, ylo]
* element of the array is gotten by transforming the celldef by the
* transformation in the celluse. the [x, y] element is gotten by
* transforming the celldef by xsep*abs(x-xlo) in x, ysep*abs(y-ylo) in
* y, and then transforming by the transformation in the celluse.
*/
typedef struct
{
int ar_xlo, ar_xhi; /* Inclusive low/high X bounds */
int ar_ylo, ar_yhi; /* Inclusive low/high Y bounds */
int ar_xsep, ar_ysep; /* X,Y sep between array elements */
} ArrayInfo;
#include "database/arrayinfo.h" /* ArrayInfo */
/*
* Since a cell may be used in an orientation different from that
@ -586,6 +556,18 @@ typedef struct diag_info
bool side;
} DiagInfo;
/* Where search functions need to return a Tile pointer and tile split */
/* information, use this structure. Contains a pointer to its own */
/* structure type so that it may also be used to create a linked list */
/* of tiles including split side information. */
typedef struct tile_and_dinfo
{
struct tile_and_dinfo *tad_next;
Tile *tad_tile;
TileType tad_dinfo;
} TileAndDinfo;
/* This would normally go in geometry.h except that it uses TileType. */
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
@ -808,7 +790,7 @@ extern void DBTechInit();
extern bool DBTechSetTech();
extern void DBTechInitVersion();
extern bool DBTechSetVersion();
extern bool DBTechAddPlane();
extern bool DBTechAddPlane(const char *sectionName, int argc, char *argv[]);
extern bool DBTechAddType();
extern bool DBTechAddAlias();
extern void DBTechFinalType();
@ -820,7 +802,7 @@ extern int DBTechNamePlane(), DBTechNoisyNamePlane();
extern PlaneMask DBTechNameMask(), DBTechNoisyNameMask();
extern PlaneMask DBTechTypesToPlanes();
extern bool DBTechTypesOnPlane();
extern void DBTechInitPlane();
extern void DBTechInitPlane(void);
extern void DBTypeInit();
extern void DBTechInitType();
extern void DBTechInitCompose();
@ -955,9 +937,10 @@ extern int DBArraySr();
extern bool DBNearestLabel();
extern int DBSrLabelLoc();
extern TileType DBTransformDiagonal();
extern int dbcUnconnectFunc(Tile *tile, ClientData clientData); /* (notused) */
extern int dbSrConnectFunc(Tile *tile, ClientData clientData); /* (struct conSrArg *csa) */
extern int dbSrConnectStartFunc(Tile *tile, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
extern bool DBTestNMInteract(Rect *rect1, TileType tt1, Tile *t2, TileType di2, bool overlap_only);
extern int dbcUnconnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (notused) */
extern int dbSrConnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (struct conSrArg *csa) */
extern int dbSrConnectStartFunc(Tile *tile, TileType dinfo, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
/* C99 compat */
extern void DBEraseValid();
@ -1004,10 +987,10 @@ extern int dbIsPrimary();
extern void dbTechMatchResidues();
extern void DBUndoInit();
extern void DBResetTilePlane();
extern void DBResetTilePlaneSpecial();
extern void DBNewYank();
extern int DBSrPaintClient();
extern int DBSrConnect();
extern int DBSrConnectOnePlane();
extern char *dbFgets();
extern void DBAdjustLabelsNew();
extern bool DBScaleValue();
@ -1094,10 +1077,10 @@ extern int DBNumPlanes;
extern HashTable DBTypeAliasTable;
/* Gives the official long name of each plane: */
extern char *DBPlaneLongNameTbl[NP];
extern const char *DBPlaneLongNameTbl[NP];
/* Gives a short name for each plane: */
extern char *DBPlaneShortName();
extern const char *DBPlaneShortName();
/* Gives for each plane a mask of all tile types stored in that plane: */
extern TileTypeBitMask DBPlaneTypes[NP];
@ -1156,10 +1139,10 @@ extern int DBTypePlaneTbl[TT_MAXTYPES];
extern PlaneMask DBTypePlaneMaskTbl[TT_MAXTYPES];
/* Gives the long name for each tile type: */
extern char *DBTypeLongNameTbl[TT_MAXTYPES];
extern const char *DBTypeLongNameTbl[TT_MAXTYPES];
/* Gives a short name for a tile type: */
extern char *DBTypeShortName();
extern const char *DBTypeShortName(TileType type);
/*
* The following give masks of all planes that may be affected

View File

@ -20,8 +20,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/database/databaseInt.h,v 1.3 2010/06/24 12:37:15 tim Exp $
*/
#ifndef _DATABASEINT_H
#define _DATABASEINT_H
#ifndef _MAGIC__DATABASE__DATABASEINT_H
#define _MAGIC__DATABASE__DATABASEINT_H
#include "database/database.h"
@ -194,6 +194,8 @@ typedef struct
extern int dbNumSavedRules;
extern Rule dbSavedRules[];
extern HashTable dbCellDefTable; /* Exported for diagnostics */
/* -------------------- Internal procedure headers -------------------- */
extern void DBUndoPutLabel();
@ -247,4 +249,4 @@ extern TileTypeBitMask dbNotDefaultPaintTbl[];
#define ERASEAFFECTS(t, s) \
((t) != TT_SPACE && DBStdEraseEntry((t), (s), DBPlane(t)) != (t))
#endif /* _DATABASEINT_H */
#endif /* _MAGIC__DATABASE__DATABASEINT_H */

View File

@ -10,12 +10,12 @@
* rcsid "$$"
*/
#ifndef _FONTS_H
#define _FONTS_H
#ifndef _MAGIC__DATABASE__FONTS_H
#define _MAGIC__DATABASE__FONTS_H
#ifndef _TILES_H
#ifndef _MAGIC__TILES__TILE_H
#include "tiles/tile.h"
#endif /* _TILES_H */
#endif
/* ---------------------------- Fonts --------------------------------- */
@ -39,4 +39,4 @@ typedef struct
extern MagicFont **DBFontList; /* List of loaded font vectors */
extern int DBNumFonts; /* Number of loaded fonts */
#endif /* _FONTS_H */
#endif /* _MAGIC__DATABASE__FONTS_H */

View File

@ -27,6 +27,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h>
#include <string.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
@ -240,6 +241,38 @@ DBWChangeButtonHandler(name)
return oldName;
}
/*
* ----------------------------------------------------------------------------
*
* DBWGetButtonHandler --
*
* Return the name of the current button handler. This does the same
* thing as DBWChangeButtonHandler(name) with an invalid name, but
* without printing the error messages. However, if magic is running
* with the Tcl interpreter wrapper, then return the string value of
* $Opts(tool), if it exists.
*
* Results:
* A pointer to the name of the current button handler.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
char *
DBWGetButtonHandler()
{
#ifdef MAGIC_WRAPPER
char *toolName;
toolName = (char *)Tcl_GetVar2(magicinterp, "Opts", "tool", TCL_GLOBAL_ONLY);
if (toolName != NULL) return toolName;
#endif
return dbwButtonHandlers[dbwButtonCurrentIndex];
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* Standard DBWind command set
*/
extern void CmdAddPath(), CmdAntennaCheck(), CmdArray();
extern void CmdAddPath(), CmdAntennaCheck(), CmdArchive(), CmdArray();
extern void CmdBox(), CmdCellname(), CmdClockwise();
extern void CmdContact(), CmdCopy(), CmdCorner();
extern void CmdCrash(), CmdCrosshair();
@ -54,7 +54,7 @@ extern void CmdRandom(), CmdSave(), CmdScaleGrid(), CmdSee();
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
extern void CmdShell(), CmdSnap();
extern void CmdStretch(), CmdStraighten();
extern void CmdTech(), CmdTool(), CmdUnexpand();
extern void CmdTech(), CmdTool(), CmdUnexpand(), CmdUnits();
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
@ -75,6 +75,7 @@ extern void CmdExtResis();
extern void CmdPsearch();
extern void CmdPlowTest();
extern void CmdShowtech();
extern void CmdShowmem();
extern void CmdTilestats();
extern void CmdTsearch();
extern void CmdWatch();
@ -208,6 +209,9 @@ DBWInitCommands()
WindAddCommand(DBWclientID,
"*psearch plane count invoke point search over box area",
CmdPsearch, FALSE);
WindAddCommand(DBWclientID,
"*showmem [file] print internal memory usage",
CmdShowmem, FALSE);
WindAddCommand(DBWclientID,
"*showtech [file] print internal technology tables",
CmdShowtech, FALSE);
@ -223,9 +227,15 @@ DBWInitCommands()
WindAddCommand(DBWclientID,
"addpath [path] append to current search path",
CmdAddPath, FALSE);
#ifdef LEF_MODULE
WindAddCommand(DBWclientID,
"antennacheck [path] check for antenna violations",
CmdAntennaCheck, FALSE);
#endif
WindAddCommand(DBWclientID,
"archive write|read file\n"
" write or read the archive file \"file\".",
CmdArchive, FALSE);
WindAddCommand(DBWclientID,
"array xsize ysize OR\n"
"array xlo xhi ylo yhi\n"
@ -464,6 +474,9 @@ DBWInitCommands()
WindAddCommand(DBWclientID,
"unexpand unexpand subcells under box",
CmdUnexpand, FALSE);
WindAddCommand(DBWclientID,
"units [type] set type of units parsed and displayed",
CmdUnits, FALSE);
WindAddCommand(DBWclientID,
"upsidedown flip selection and box upside down",
CmdUpsidedown, FALSE);

View File

@ -571,8 +571,9 @@ DBWredisplay(w, rootArea, clipArea)
*/
int
dbwPaintFunc(tile, cxp)
Tile *tile; /* Tile to be redisplayed. */
dbwPaintFunc(tile, dinfo, cxp)
Tile *tile; /* Tile to be redisplayed. */
TileType dinfo; /* Split tile information */
TreeContext *cxp; /* From DBTreeSrTiles */
{
SearchContext *scx = cxp->tc_scx;
@ -652,7 +653,7 @@ dbwPaintFunc(tile, cxp)
/* whether to render the outline with a fast rectangle- */
/* drawing routine or to render it segment by segment. */
GrBox(dbwWindow, &scx->scx_trans, tile);
GrBox(dbwWindow, &scx->scx_trans, tile, dinfo);
return 0;
}
@ -1075,8 +1076,10 @@ dbwBBoxFunc(scx)
*/
int
dbwTileFunc(tile)
dbwTileFunc(tile, dinfo, clientdata)
Tile *tile; /* A tile to be redisplayed. */
TileType dinfo; /* Split tile information (unused) */
ClientData clientdata; /* (unused) */
{
Rect r, r2;
int xoffset, yoffset;
@ -1113,7 +1116,7 @@ dbwTileFunc(tile)
if (dbwSeeTypes)
{
(void) sprintf(string, "%s",DBTypeShortName(TiGetType(tile)));
(void) sprintf(string, "%s", DBTypeShortName(TiGetType(tile)));
}
else
{
@ -1129,7 +1132,7 @@ dbwTileFunc(tile)
#define XYOFFSET 12
for (i=0; i<4; i++)
for (i = 0; i < 4; i++)
{
xoffset = 0;
yoffset = 0;
@ -1172,13 +1175,13 @@ dbwTileFunc(tile)
yoffset = temp;
}
if ( (dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0) )
if ((dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0))
{
/* mirror in x */
xoffset = -xoffset;
}
if ( (dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0) )
if ((dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0))
{
/* mirror in y */
yoffset = -yoffset;

View File

@ -588,10 +588,12 @@ DBWElementDelete(MagWindow *w, char *name)
if (elem->flags & DBW_ELEMENT_PERSISTENT)
elem->rootDef->cd_flags |= CDMODIFIED;
free_magic1_t mm1 = freeMagic1_init();
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
{
freeMagic(stylePtr);
freeMagic1(&mm1, stylePtr);
}
freeMagic1_end(&mm1);
if (elem->type == ELEMENT_TEXT)
freeMagic(elem->text);
@ -1156,8 +1158,10 @@ DBWElementStyle(MagWindow *w, char *ename, int style, bool add)
(elem->stylelist->style == style))
{
dbwElementUndraw(w, elem);
freeMagic(elem->stylelist);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, elem->stylelist);
elem->stylelist = elem->stylelist->next;
freeMagic1_end(&mm1);
if (elem->stylelist == NULL)
TxPrintf("Warning: Element %s has no styles!\n", ename);
}
@ -1169,8 +1173,10 @@ DBWElementStyle(MagWindow *w, char *ename, int style, bool add)
else if (sptr->next != NULL)
{
dbwElementUndraw(w, elem);
freeMagic(sptr->next);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, sptr->next);
sptr->next = sptr->next->next;
freeMagic1_end(&mm1);
}
}
/* mark element's cell as having been modified */
@ -1279,8 +1285,10 @@ DBWElementClearDef(cellDef)
if (!elem) continue;
if (elem->rootDef != cellDef) continue;
free_magic1_t mm1 = freeMagic1_init();
for (stylePtr = elem->stylelist; stylePtr != NULL; stylePtr = stylePtr->next)
freeMagic(stylePtr);
freeMagic1(&mm1, stylePtr);
freeMagic1_end(&mm1);
if (elem->type == ELEMENT_TEXT)
freeMagic(elem->text);

View File

@ -249,7 +249,10 @@ DBWFeedbackRedraw(window, plane)
}
int
dbwFeedbackAlways1()
dbwFeedbackAlways1(
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
return 1;
}

View File

@ -392,8 +392,9 @@ DBWHLRedrawWind(window)
*/
int
dbwhlEraseFunc(tile, window)
dbwhlEraseFunc(tile, dinfo, window)
Tile *tile; /* Tile describing area to be erased. */
TileType dinfo; /* Split tile information (unused) */
MagWindow *window; /* Window that is being altered. */
{
Rect area;

View File

@ -25,6 +25,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <string.h>
#include <sys/stat.h>
#include "tcltk/tclmagic.h"
#include "utils/main.h"
#include "utils/magic.h"
#include "utils/geometry.h"
@ -33,6 +34,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/hash.h"
#include "database/database.h"
#include "utils/main.h"
#include "cif/cif.h"
#include "commands/commands.h"
#include "dbwind/dbwind.h"
#include "graphics/graphics.h"
@ -653,6 +655,311 @@ DBWexit()
return (CmdWarnWrite() == 1);
}
/*
* ----------------------------------------------------------------------------
*
* dbwValueFormat ---
*
* Remove unnecessary trailing zeros and decimal from a floating-point
* value formatted with "%.Nf" where N is the expected maximum number
* of places after the decimal, matching the argument "places".
* This makes the "%f" formatting work like "%g" formatting, but
* works around the limitation of "%.Ng" that it operates on the number
* of significant digits, not the number of decimal places.
*
* Results:
* None.
*
* Side effects:
* The string "buf" may be altered with a new terminating null character.
*
* ----------------------------------------------------------------------------
*/
void
dbwValueFormat(char *buf,
int places)
{
char *p = buf + strlen(buf) - 1;
while (p > buf && *p == '0') *p-- = '\0';
if (p > buf && *p == '.') *p = '\0';
}
/*
* ----------------------------------------------------------------------------
*
* dbwPrintValue0 --
*
* Convert a value in internal database units to a string based on
* the chosen display units as defined by DBWUnits (which is set
* with the "units" command). If DBWUnits has not been changed
* since startup, then the behavior is to print the internal units
* in string form. If DBWUnits has been set, then the units type
* determines how the output is displayed.
*
* If "is_square" is TRUE, then the value is in units squared, and
* scaling is done accordingly. In the case of DBW_UNITS_USER,
* where values are in grid multiples, the units for X and Y may
* differ, and "is_x" = TRUE indicates a measurement in the X direction,
* while false indicase a measurements in the Y direction. Naturally,
* if "is_square" is TRUE then "is_x" is ignored. "is_x" is also ignored
* for any output units other than user/grid units.
*
* If "is_cif" is true, then "value" is in CIF database units
* (centimicrons, nanometers, or angstroms, according to the
* scalefactor line in the tech file), rather than internal units.
*
* This routine is generally meant to be called as one of the three
* variants defined below it: DBWPrintValue(), DBWPrintSqValue(),
* or DBWPrintCIFValue().
*
* Results:
* A pointer to a string. To facilitate printing up to four values
* (e.g., rectangle coordinates, such as from "box values"), a static
* string partitioned into four parts is created in this subroutine,
* and the result points to one position in the string, which is cycled
* through every four calls to the subroutine. The caller does not
* free the returned string.
*
* Side effects:
* None.
*
* NOTE: Prior to the introduction of the "units" command, magic had the
* inconsistent behavior that parsed input values on the command line
* would be interpreted per the "snap" setting, but output values were
* (almost) always given in internal units. This routine keeps the
* original behavior backwards-compatible, as inconsistent as it is.
*
* ----------------------------------------------------------------------------
*/
char *
dbwPrintValue0(int value, /* value to print, in internal units */
MagWindow *w, /* current window, for use with grid */
bool is_x, /* TRUE if value is an X dimension */
bool is_square, /* TRUE if value is a dimension squared */
bool is_cif) /* TRUE if value is in centimicrons */
{
char *result;
float oscale, dscale, fvalue;
DBWclientRec *crec;
int locunits;
/* This routine is called often, so avoid constant use of malloc and
* free by keeping up to four printed results in static memory.
*/
static char resultstr[128];
static unsigned char resultpos = 0;
result = &resultstr[resultpos];
resultpos += 32;
resultpos &= 127; /* At 128, cycle back to zero */
/* CIF database units are centimicrons/nanometers/angstroms as
* set by the "scalefactor" line in the tech file. When "is_cif"
* is TRUE, then "value" is in these units. Find the conversion
* factor to convert "value" to internal units, and then it can
* be subsequently converted to lambda, microns, etc.
*/
if (is_cif == TRUE)
dscale = CIFGetScale(100) / CIFGetOutputScale(1000);
else
dscale = 1.0;
/* When printing user/grid units, check for a valid window */
locunits = DBWUnits;
if (locunits != DBW_UNITS_DEFAULT) locunits &= DBW_UNITS_TYPE_MASK;
/* The MagWindow argument is only needed for user units, since the
* user grid values are found there. Setting MagWindow to NULL
* effectively disables printing values in user grid units, which
* then default to internal units.
*/
if (locunits == DBW_UNITS_USER)
{
if (w == (MagWindow *)NULL)
{
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *)NULL)
locunits = DBW_UNITS_DEFAULT;
}
}
switch (locunits)
{
case DBW_UNITS_DEFAULT:
snprintf(result, 32, "%d", value);
break;
case DBW_UNITS_INTERNAL:
if (is_cif)
{
if (is_square)
{
snprintf(result, 32, "%.6f", value * dscale * dscale);
dbwValueFormat(result, 6);
}
else
{
snprintf(result, 32, "%.3f", value * dscale);
dbwValueFormat(result, 3);
}
}
else
snprintf(result, 32, "%d", value);
if (is_square)
{
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
strcat(result, "i^2");
}
else
{
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
strcat(result, "i");
}
break;
case DBW_UNITS_LAMBDA:
oscale = (float)DBLambda[0];
oscale /= (float)DBLambda[1];
if (is_square)
{
fvalue = (float)value * oscale * oscale * dscale * dscale;
snprintf(result, 32, "%0.6f", (double)fvalue);
dbwValueFormat(result, 6);
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
strcat(result, "l^2");
}
else
{
fvalue = (float)value * oscale * dscale;
snprintf(result, 32, "%0.3f", (double)fvalue);
dbwValueFormat(result, 3);
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
strcat(result, "l");
}
break;
case DBW_UNITS_MICRONS:
oscale = CIFGetOutputScale(1000);
if (is_square)
{
fvalue = (float)value * oscale * oscale * dscale * dscale;
snprintf(result, 32, "%0.6f", (double)fvalue);
dbwValueFormat(result, 6);
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 28))
strcat(result, "um^2");
}
else
{
fvalue = (float)value * oscale * dscale;
snprintf(result, 32, "%0.3f", (double)fvalue);
dbwValueFormat(result, 3);
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
strcat(result, "um");
}
break;
case DBW_UNITS_USER:
if (is_square)
{
oscale = (float)((crec->dbw_gridRect.r_xtop -
crec->dbw_gridRect.r_xbot) *
(crec->dbw_gridRect.r_ytop -
crec->dbw_gridRect.r_ybot));
}
else if (is_x)
{
oscale = (float)(crec->dbw_gridRect.r_xtop -
crec->dbw_gridRect.r_xbot);
}
else
{
oscale = (float)(crec->dbw_gridRect.r_ytop -
crec->dbw_gridRect.r_ybot);
}
fvalue = (float)value * oscale * dscale;
if (is_square)
{
fvalue *= dscale;
snprintf(result, 32, "%0.6f", (double)fvalue);
dbwValueFormat(result, 6);
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 27))
strcat(result, "gx*gy");
}
else
{
snprintf(result, 32, "%0.3f", (double)fvalue);
dbwValueFormat(result, 3);
if (is_x)
{
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
strcat(result, "gx");
}
else
{
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
strcat(result, "gy");
}
}
break;
}
return result;
}
/*
* ----------------------------------------------------------------------------
*
* DBWPrintValue --
* DBWPrintSqValue --
* DBWPrintCIFValue --
* DBWPrintCIFSqValue --
*
* Convenience functions which call dbwPrintValue0() with specific
* fixed arguments, so that the calls are not full of boolean values.
* The "is_x" boolean is retained because it is used often.
*
* ----------------------------------------------------------------------------
*/
char *
DBWPrintValue(int value, /* value to print, in internal units */
MagWindow *w, /* current window, for use with grid */
bool is_x) /* TRUE if value is an X dimension */
{
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = FALSE */
return dbwPrintValue0(value, w, is_x, FALSE, FALSE);
}
char *
DBWPrintSqValue(int value, /* value to print, in internal units */
MagWindow *w) /* current window, for use with grid */
{
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = FALSE */
/* is_x is set to TRUE although it is unused. */
return dbwPrintValue0(value, w, TRUE, TRUE, FALSE);
}
char *
DBWPrintCIFValue(int value, /* value to print, in internal units */
MagWindow *w, /* current window, for use with grid */
bool is_x) /* TRUE if value is an X dimension */
{
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = TRUE */
return dbwPrintValue0(value, w, is_x, FALSE, TRUE);
}
char *
DBWPrintCIFSqValue(int value, /* value to print, in internal units */
MagWindow *w) /* current window, for use with grid */
{
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = TRUE */
/* is_x is set to TRUE although it is unused. */
return dbwPrintValue0(value, w, TRUE, TRUE, TRUE);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -65,11 +65,21 @@ typedef struct _crosshairRec {
static CrosshairRec curCrosshair; /* Crosshair position */
/*
* If the following is DBW_SNAP_USER, the box gets snapped to the user's
* If the following is DBW_UNITS_USER, the box gets snapped to the user's
* grid always, instead of snapping to the usual 1x1 grid. If the value
* is DBW_SNAP_INTERNAL, the box gets snapped to the internal grid.
* is DBW_UNITS_INTERNAL, the box gets snapped to the internal grid.
*/
int DBWSnapToGrid = DBW_SNAP_LAMBDA;
int DBWSnapToGrid = DBW_UNITS_LAMBDA;
/*
* The original behavior with respect to units was that un-suffixed
* values follow whatever the snap setting is (DBWSnapToGrid, above).
* Current behavior is that the original behavior is followed while
* DBWUnits is set to DBW_UNITS_DEFAULT. However, if the "units"
* command is given, then displayed and entered units follow that
* value independently of the snap setting.
*/
int DBWUnits = DBW_UNITS_DEFAULT;
/* Forward reference: */
@ -82,8 +92,8 @@ extern int DBWToolDraw();
* toolFindPoint --
*
* Returns the point in root coordinates.
* If DBWSnapToGrid is DBW_SNAP_USER, pick the nearest point that is
* aligned with the window's grid. If DBWSnapToGrid is DBW_SNAP_LAMBDA,
* If DBWSnapToGrid is DBW_UNITS_USER, pick the nearest point that is
* aligned with the window's grid. If DBWSnapToGrid is DBW_UNITS_LAMBDA,
* pick the nearest point that is an integer lambda value.
*
* Results:
@ -120,7 +130,7 @@ toolFindPoint(p, rootPoint, rootArea)
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
if (DBWSnapToGrid != DBW_SNAP_INTERNAL)
if (DBWSnapToGrid != DBW_UNITS_INTERNAL)
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
return WindCurrentWindow;
@ -764,7 +774,10 @@ DBWDrawBox(window, plane)
}
int
dbwBoxAlways1()
dbwBoxAlways1(
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
return 1;
}
@ -841,8 +854,8 @@ DBWResetBox(CellDef *def)
* Repositions the box by one of its corners.
* If the point given to reposition the box is in screen coordinates,
* the box corner is snapped to the user's grid (set with the :grid
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
* lambda value.
*
* Results:
@ -945,8 +958,8 @@ ToolMoveBox(corner, point, screenCoords, rootDef)
*
* If the point given to reposition the box is in screen coordinates,
* the box corner is snapped to the user's grid (set with the :grid
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
* lambda value.
*
* Results:
@ -1089,7 +1102,7 @@ ToolSnapToGrid(w, p, rEnclose)
if (crec == NULL || p == NULL)
return;
if (DBWSnapToGrid == DBW_SNAP_LAMBDA)
if (DBWSnapToGrid == DBW_UNITS_LAMBDA)
{
lr.r_xbot = lr.r_ybot = 0;
lr.r_xtop = DBLambda[1] / DBLambda[0];

View File

@ -20,8 +20,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/dbwind/dbwind.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
*/
#ifndef _DBWIND_H
#define _DBWIND_H
#ifndef _MAGIC__DBWIND__DBWIND_H
#define _MAGIC__DBWIND__DBWIND_H
#include "database/database.h"
#include "windows/windows.h"
@ -113,6 +113,7 @@ typedef struct DBW1 {
extern WindClient DBWclientID;
extern int DBWSnapToGrid;
extern int DBWUnits;
extern int DBWMaxTechStyles;
extern int DBWMaxTileStyles;
@ -121,13 +122,17 @@ extern int DBWNumStyles;
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
/*
* Exported procedure headers for redisplay
* Exported procedure headers for redisplay and output
*/
extern int DBWWatchTiles();
extern void DBWAreaChanged();
extern void DBWLabelChanged();
extern void DBWDrawLabel();
extern char *DBWPrintValue(int value, MagWindow *w, bool is_x);
extern char *DBWPrintSqValue(int value, MagWindow *w);
extern char *DBWPrintCIFValue(int value, MagWindow *w, bool is_x);
extern char *DBWPrintCIFSqValue(int value, MagWindow *w);
/*
* Exported procedures and variables related to the technology file
@ -145,6 +150,7 @@ extern void (*DBWButtonCurrentProc)();
typedef void (*cb_database_buttonhandler_t)(MagWindow *w, TxCommand *cmd);
extern void DBWAddButtonHandler(const char *name, const cb_database_buttonhandler_t proc,
int cursor, const char *doc);
extern char *DBWGetButtonHandler();
extern char *DBWChangeButtonHandler();
extern void DBWPrintButtonDoc();
extern void DBWBoxHandler();
@ -168,14 +174,36 @@ extern void DBWBoxHandler();
#define TOOL_ILG -1
/* The following defines are used to indicate which coordinate system
* the cursor box snaps to when moved with mouse clicks (values for
* DBWSnapToGrid).
* is used when displaying or returning values. By default this is
* set to DBW_UNITS_INTERNAL. From magic version 8.3.595, this is
* independently set from "snap". For backwards compatibility,
* the value starts as DBW_UNITS_DEFAULT which implements the original
* behavior in which the "snap" setting dictates the dispaly units.
* Only if set to a non-negative value do the display units operate
* independently of the snap setting.
*
* NOTES:
* Lambda units are fixed by the tech file.
* Internal units are scalable.
* User units are scalable; this can be used, for example, to
* set a box position according to multiples of a track
* pitch, but is most often used manually with the "g"
* (for "grid") suffix; e.g., "move box e 1g"
* Micron units are dependent on the specified cifoutput style
* and how the tech file defines the scalefactor for it.
*/
#define DBW_SNAP_INTERNAL 0 /* internal units (fine grid) */
#define DBW_SNAP_LAMBDA 1 /* lambda units (coarse grid) */
#define DBW_SNAP_USER 2 /* user grid units (user grid) */
#define DBW_SNAP_MICRONS 3 /* micron units */
#define DBW_UNITS_DEFAULT -1 /* backwards-compatible behavior */
#define DBW_UNITS_INTERNAL 0 /* internal units */
#define DBW_UNITS_LAMBDA 1 /* lambda units */
#define DBW_UNITS_USER 2 /* user grid units */
#define DBW_UNITS_MICRONS 3 /* micron units */
#define DBW_UNITS_TYPE_MASK 3 /* everything but the flag field(s) */
#define DBW_UNITS_PRINT_FLAG 4 /* flag used to indicate that
* the units should be printed
* with the value; e.g.,
* "10um" instead of "10".
*/
/* The following window mask can be used to select all database windows
* for things like the mask parameter to DBWAreaChanged.
@ -261,4 +289,4 @@ extern void dbwElementInit();
extern void dbwCrosshairInit();
#endif /* _DBWIND_H */
#endif /* _MAGIC__DBWIND__DBWIND_H */

View File

@ -8,8 +8,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/dbwind/dbwtech.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
*/
#ifndef _DBWTECH_H
#define _DBWTECH_H
#ifndef _MAGIC__DBWIND__DBWTECH_H
#define _MAGIC__DBWIND__DBWTECH_H
extern TileTypeBitMask *DBWStyleToTypesTbl;
@ -23,4 +23,4 @@ extern void DBWElementStyle();
extern void DBWElementText();
extern void DBWSetCrosshair();
#endif /* _DBWTECH_H */
#endif /* _MAGIC__DBWIND__DBWTECH_H */

View File

@ -21,8 +21,8 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/debug/debug.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
*/
#ifndef _DEBUG_H
#define _DEBUG_H
#ifndef _MAGIC__DEBUG__DEBUG_H
#define _MAGIC__DEBUG__DEBUG_H
#include "utils/magic.h"
@ -76,4 +76,4 @@ extern int DebugAddFlag(ClientData clientID, const char *name);
extern void DebugShow(ClientData clientID);
extern void DebugSet(ClientData clientID, int argc, char *argv[], int value);
#endif /* _DEBUG_H */
#endif /* _MAGIC__DEBUG__DEBUG_H */

67
doc/html/archive.html Normal file
View File

@ -0,0 +1,67 @@
<HTML>
<HEAD>
<STYLE type="text/css">
H1 {color: black }
H2 {color: maroon }
H3 {color: #007090 }
A.head:link {color: #0060a0 }
A.head:visited {color: #3040c0 }
A.head:active {color: white }
A.head:hover {color: yellow }
A.red:link {color: red }
A.red:visited {color: maroon }
A.red:active {color: yellow }
</STYLE>
</HEAD>
<TITLE>Magic-8.3 Command Reference</TITLE>
<BODY BACKGROUND=graphics/blpaper.gif>
<H1> <IMG SRC=graphics/magic_title8_3.png ALT="Magic VLSI Layout Tool Version 8.3">
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
<H2>archive</H2>
<HR>
Handle archive files
<HR>
<H3>Usage:</H3>
<BLOCKQUOTE>
<B>archive write</B> | <B>read</B> <I>filename</I> <BR><BR>
</BLOCKQUOTE>
<H3>Summary:</H3>
<BLOCKQUOTE>
The <B>archive</B> command handles archive files. The exact
operation depends on the option, and are outlined below:
<DL>
<DT> <B>archive write</B> <I>filename</I>
<DD> creates and writes to the file <I>filename</I> a copy of
the contents of all database cells. <P>
<DT> <B>archive read</B> <I>filename</I>
<DD> recovers the database from the contents of the saved archive
file <I>filename</I>. <P>
</DL>
</BLOCKQUOTE>
Archive files use the same format as crash recovery files, which is a
single file containing all database files with additional metadata
about the original location of each file.
<H3>Implementation Notes:</H3>
<BLOCKQUOTE>
<B>archive</B> is implemented as a built-in command in <B>magic</B>.
</BLOCKQUOTE>
<H3>See Also:</H3>
<BLOCKQUOTE>
<A HREF=crash.html><B>crash</B></A> <BR>
</BLOCKQUOTE>
<P><IMG SRC=graphics/line1.gif><P>
<TABLE BORDER=0>
<TR>
<TD> <A HREF=commands.html>Return to command index</A>
</TR>
</TABLE>
<P><I>Last updated:</I> January 12, 2021 at 10:10am <P>
</BODY>
</HTML>

View File

@ -334,23 +334,23 @@
</TR>
<TR>
<TD> <A HREF=undo.html> <B>undo</B></A> </TD>
<TD> <A HREF=units.html> <B>units</B></A> </TD>
<TD> <A HREF=updatedisplay.html> <B>updatedisplay</B></A> </TD>
<TD> <A HREF=version.html> <B>version</B></A> </TD>
</TR>
<TR>
<TD> <A HREF=version.html> <B>version</B></A> </TD>
<TD> <A HREF=view.html> <B>view</B></A> </TD>
<TD> <A HREF=windowborder.html> <B>windowborder</B></A> </TD>
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
</TR>
<TR>
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
<TD> <A HREF=windownames.html> <B>windownames</B></A> </TD>
<TD> <A HREF=windowscrollbars.html> <B>windowscrollbars</B></A> </TD>
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
</TR>
<TR>
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
<TD> <A HREF=zoom.html> <B>zoom</B></A> </TD>
<TD> <A HREF=tk_path_name.html> <I>tk_path_name</I></A> </TD>
<TD> </TD>
</TR>
</TBODY>
</TABLE>
@ -362,184 +362,189 @@
cellpadding="5" bgcolor="#ccccff">
<TBODY>
<TR>
<TD> <A HREF=addcommandentry.html><B>addcommandentry</B></A><TD>
<TD> <A HREF=addpath.html> <B>addpath</B></A><TD>
<TD> <A HREF=antennacheck.html> <B>antennacheck</B></A><TD>
<TD> <A HREF=addcommandentry.html><B>addcommandentry</B></A></TD>
<TD> <A HREF=addpath.html> <B>addpath</B></A></TD>
<TD> <A HREF=antennacheck.html> <B>antennacheck</B></A></TD>
</TR>
<TR>
<TD> <A HREF=array.html> <B>array</B></A><TD>
<TD> <A HREF=box.html> <B>box</B></A><TD>
<TD> <A HREF=calma.html> <B>calma</B></A><TD>
<TD> <A HREF=archive.html> <B>array</B></A></TD>
<TD> <A HREF=array.html> <B>array</B></A></TD>
<TD> <A HREF=box.html> <B>box</B></A></TD>
</TR>
<TR>
<TD> <A HREF=caption.html> <B>caption</B></A><TD>
<TD> <A HREF=cellmanager.html> <B>cellmanager</B></A><TD>
<TD> <A HREF=cellname.html> <B>cellname</B></A><TD>
<TD> <A HREF=calma.html> <B>calma</B></A></TD>
<TD> <A HREF=caption.html> <B>caption</B></A></TD>
<TD> <A HREF=cellmanager.html> <B>cellmanager</B></A></TD>
</TR>
<TR>
<TD> <A HREF=cellsearch.html> <B>cellsearch</B></A><TD>
<TD> <A HREF=channels.html> <B>channels</B></A><TD>
<TD> <A HREF=cif.html> <B>cif</B></A><TD>
<TD> <A HREF=cellname.html> <B>cellname</B></A></TD>
<TD> <A HREF=cellsearch.html> <B>cellsearch</B></A></TD>
<TD> <A HREF=channels.html> <B>channels</B></A></TD>
</TR>
<TR>
<TD> <A HREF=clockwise.html> <B>clockwise</B></A><TD>
<TD> <A HREF=closewrapper.html> <B>closewrapper</B></A><TD>
<TD> <A HREF=contact.html> <B>contact</B></A><TD>
<TD> <A HREF=cif.html> <B>cif</B></A></TD>
<TD> <A HREF=clockwise.html> <B>clockwise</B></A></TD>
<TD> <A HREF=closewrapper.html> <B>closewrapper</B></A></TD>
</TR>
<TR>
<TD> <A HREF=copy.html> <B>copy</B></A><TD>
<TD> <A HREF=corner.html> <B>corner</B></A><TD>
<TD> <A HREF=crash.html> <B>crash</B></A><TD>
<TD> <A HREF=contact.html> <B>contact</B></A></TD>
<TD> <A HREF=copy.html> <B>copy</B></A></TD>
<TD> <A HREF=corner.html> <B>corner</B></A></TD>
</TR>
<TR>
<TD> <A HREF=crashbackups.html> <B>crashbackups</B></A><TD>
<TD> <A HREF=crosshair.html> <B>crosshair</B></A><TD>
<TD> <A HREF=def.html> <B>def</B></A><TD>
<TD> <A HREF=crash.html> <B>crash</B></A></TD>
<TD> <A HREF=crashbackups.html> <B>crashbackups</B></A></TD>
<TD> <A HREF=crosshair.html> <B>crosshair</B></A></TD>
</TR>
<TR>
<TD> <A HREF=delete.html> <B>delete</B></A><TD>
<TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A><TD>
<TD> <A HREF=down.html> <B>down</B></A><TD>
<TD> <A HREF=def.html> <B>def</B></A></TD>
<TD> <A HREF=delete.html> <B>delete</B></A></TD>
<TD> <A HREF=deletecommandentry.html> <B>deletecommandentry</B></A></TD>
</TR>
<TR>
<TD> <A HREF=drc.html> <B>drc</B></A><TD>
<TD> <A HREF=dump.html> <B>dump</B></A><TD>
<TD> <A HREF=edit.html> <B>edit</B></A><TD>
<TD> <A HREF=down.html> <B>down</B></A></TD>
<TD> <A HREF=drc.html> <B>drc</B></A></TD>
<TD> <A HREF=dump.html> <B>dump</B></A></TD>
</TR>
<TR>
<TD> <A HREF=element.html> <B>element</B></A><TD>
<TD> <A HREF=erase.html> <B>erase</B></A><TD>
<TD> <A HREF=expand.html> <B>expand</B></A><TD>
<TD> <A HREF=edit.html> <B>edit</B></A></TD>
<TD> <A HREF=element.html> <B>element</B></A></TD>
<TD> <A HREF=erase.html> <B>erase</B></A></TD>
</TR>
<TR>
<TD> <A HREF=ext.html> <B>ext</B></A><TD>
<TD> <A HREF=ext2sim.html> <B>ext2sim</B></A><TD>
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A><TD>
<TD> <A HREF=expand.html> <B>expand</B></A></TD>
<TD> <A HREF=ext.html> <B>ext</B></A></TD>
<TD> <A HREF=ext2sim.html> <B>ext2sim</B></A></TD>
</TR>
<TR>
<TD> <A HREF=extract.html> <B>extract</B></A><TD>
<TD> <A HREF=extresist.html> <B>extresist</B></A><TD>
<TD> <A HREF=ext2sim.html> <B>exttosim</B></A><TD>
<TD> <A HREF=ext2spice.html> <B>ext2spice</B></A></TD>
<TD> <A HREF=extract.html> <B>extract</B></A></TD>
<TD> <A HREF=extresist.html> <B>extresist</B></A></TD>
</TR>
<TR>
<TD> <A HREF=ext2spice.html> <B>exttospice</B></A><TD>
<TD> <A HREF=feedback.html> <B>feedback</B></A><TD>
<TD> <A HREF=fill.html> <B>fill</B></A><TD>
<TD> <A HREF=ext2sim.html> <B>exttosim</B></A></TD>
<TD> <A HREF=ext2spice.html> <B>exttospice</B></A></TD>
<TD> <A HREF=feedback.html> <B>feedback</B></A></TD>
</TR>
<TR>
<TD> <A HREF=findbox.html> <B>findbox</B></A><TD>
<TD> <A HREF=findlabel.html> <B>findlabel</B></A><TD>
<TD> <A HREF=flatten.html> <B>flatten</B></A><TD>
<TD> <A HREF=fill.html> <B>fill</B></A></TD>
<TD> <A HREF=findbox.html> <B>findbox</B></A></TD>
<TD> <A HREF=findlabel.html> <B>findlabel</B></A></TD>
</TR>
<TR>
<TD> <A HREF=flush.html> <B>flush</B></A><TD>
<TD> <A HREF=garoute.html> <B>garoute</B></A><TD>
<TD> <A HREF=gds.html> <B>gds</B></A><TD>
<TD> <A HREF=flatten.html> <B>flatten</B></A></TD>
<TD> <A HREF=flush.html> <B>flush</B></A></TD>
<TD> <A HREF=garoute.html> <B>garoute</B></A></TD>
</TR>
<TR>
<TD> <A HREF=get.html> <B>get</B></A><TD>
<TD> <A HREF=getcell.html> <B>getcell</B></A><TD>
<TD> <A HREF=getnode.html> <B>getnode</B></A><TD>
<TD> <A HREF=gds.html> <B>gds</B></A></TD>
<TD> <A HREF=get.html> <B>get</B></A></TD>
<TD> <A HREF=getcell.html> <B>getcell</B></A></TD>
</TR>
<TR>
<TD> <A HREF=goto.html> <B>goto</B></A><TD>
<TD> <A HREF=grid.html> <B>grid</B></A><TD>
<TD> <A HREF=help.html> <B>help</B></A><TD>
<TD> <A HREF=getnode.html> <B>getnode</B></A></TD>
<TD> <A HREF=goto.html> <B>goto</B></A></TD>
<TD> <A HREF=grid.html> <B>grid</B></A></TD>
</TR>
<TR>
<TD> <A HREF=identify.html> <B>identify</B></A><TD>
<TD> <A HREF=initialize.html> <B>initialize</B></A><TD>
<TD> <A HREF=instance.html> <B>instance</B></A><TD>
<TD> <A HREF=help.html> <B>help</B></A></TD>
<TD> <A HREF=identify.html> <B>identify</B></A></TD>
<TD> <A HREF=initialize.html> <B>initialize</B></A></TD>
</TR>
<TR>
<TD> <A HREF=iroute.html> <B>iroute</B></A><TD>
<TD> <A HREF=irsim.html> <B>irsim</B></A><TD>
<TD> <A HREF=label.html> <B>label</B></A><TD>
<TD> <A HREF=instance.html> <B>instance</B></A></TD>
<TD> <A HREF=iroute.html> <B>iroute</B></A></TD>
<TD> <A HREF=irsim.html> <B>irsim</B></A></TD>
</TR>
<TR>
<TD> <A HREF=lef.html> <B>lef</B></A><TD>
<TD> <A HREF=load.html> <B>load</B></A><TD>
<TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A><TD>
<TD> <A HREF=label.html> <B>label</B></A></TD>
<TD> <A HREF=lef.html> <B>lef</B></A></TD>
<TD> <A HREF=load.html> <B>load</B></A></TD>
</TR>
<TR>
<TD> <A HREF=move.html> <B>move</B></A><TD>
<TD> <A HREF=measure.html> <B>measure</B></A><TD>
<TD> <A HREF=openwrapper.html> <B>openwrapper</B></A><TD>
<TD> <A HREF=maketoolbar.html> <B>maketoolbar</B></A></TD>
<TD> <A HREF=move.html> <B>move</B></A></TD>
<TD> <A HREF=measure.html> <B>measure</B></A></TD>
</TR>
<TR>
<TD> <A HREF=paint.html> <B>paint</B></A><TD>
<TD> <A HREF=path.html> <B>path</B></A><TD>
<TD> <A HREF=peekbox.html> <B>peekbox</B></A><TD>
<TD> <A HREF=openwrapper.html> <B>openwrapper</B></A></TD>
<TD> <A HREF=paint.html> <B>paint</B></A></TD>
<TD> <A HREF=path.html> <B>path</B></A></TD>
</TR>
<TR>
<TD> <A HREF=plot.html> <B>plot</B></A><TD>
<TD> <A HREF=plow.html> <B>plow</B></A><TD>
<TD> <A HREF=polygon.html> <B>polygon</B></A><TD>
<TD> <A HREF=peekbox.html> <B>peekbox</B></A></TD>
<TD> <A HREF=plot.html> <B>plot</B></A></TD>
<TD> <A HREF=plow.html> <B>plow</B></A></TD>
</TR>
<TR>
<TD> <A HREF=popbox.html> <B>popbox</B></A><TD>
<TD> <A HREF=popstack.html> <B>popstack</B></A><TD>
<TD> <A HREF=port.html> <B>port</B></A><TD>
<TD> <A HREF=polygon.html> <B>polygon</B></A></TD>
<TD> <A HREF=popbox.html> <B>popbox</B></A></TD>
<TD> <A HREF=popstack.html> <B>popstack</B></A></TD>
</TR>
<TR>
<TD> <A HREF=promptload.html> <B>promptload</B></A><TD>
<TD> <A HREF=promptsave.html> <B>promptsave</B></A><TD>
<TD> <A HREF=property.html> <B>property</B></A><TD>
<TD> <A HREF=port.html> <B>port</B></A></TD>
<TD> <A HREF=promptload.html> <B>promptload</B></A></TD>
<TD> <A HREF=promptsave.html> <B>promptsave</B></A></TD>
</TR>
<TR>
<TD> <A HREF=pushbox.html> <B>pushbox</B></A><TD>
<TD> <A HREF=pushstack.html> <B>pushstack</B></A><TD>
<TD> <A HREF=render3d.html> <B>render3d</B></A><TD>
<TD> <A HREF=property.html> <B>property</B></A></TD>
<TD> <A HREF=pushbox.html> <B>pushbox</B></A></TD>
<TD> <A HREF=pushstack.html> <B>pushstack</B></A></TD>
</TR>
<TR>
<TD> <A HREF=resumeall.html> <B>resumeall</B></A><TD>
<TD> <A HREF=rotate.html> <B>rotate</B></A><TD>
<TD> <A HREF=route.html> <B>route</B></A><TD>
<TD> <A HREF=render3d.html> <B>render3d</B></A></TD>
<TD> <A HREF=resumeall.html> <B>resumeall</B></A></TD>
<TD> <A HREF=rotate.html> <B>rotate</B></A></TD>
</TR>
<TR>
<TD> <A HREF=save.html> <B>save</B></A><TD>
<TD> <A HREF=scalegrid.html> <B>scalegrid</B></A><TD>
<TD> <A HREF=search.html> <B>search</B></A><TD>
<TD> <A HREF=route.html> <B>route</B></A></TD>
<TD> <A HREF=save.html> <B>save</B></A></TD>
<TD> <A HREF=scalegrid.html> <B>scalegrid</B></A></TD>
</TR>
<TR>
<TD> <A HREF=see.html> <B>see</B></A><TD>
<TD> <A HREF=select.html> <B>select</B></A><TD>
<TD> <A HREF=setlabel.html> <B>setlabel</B> <I>(version 8.0)</I></A><TD>
<TD> <A HREF=search.html> <B>search</B></A></TD>
<TD> <A HREF=see.html> <B>see</B></A></TD>
<TD> <A HREF=select.html> <B>select</B></A></TD>
</TR>
<TR>
<TD> <A HREF=shell.html> <B>shell</B></A><TD>
<TD> <A HREF=sideways.html> <B>sideways</B></A><TD>
<TD> <A HREF=snap.html> <B>snap</B></A><TD>
<TD> <A HREF=setlabel.html> <B>setlabel</B> <I>(version 8.0)</I></A></TD>
<TD> <A HREF=shell.html> <B>shell</B></A></TD>
<TD> <A HREF=sideways.html> <B>sideways</B></A></TD>
</TR>
<TR>
<TD> <A HREF=spliterase.html> <B>spliterase</B></A><TD>
<TD> <A HREF=splitpaint.html> <B>splitpaint</B></A><TD>
<TD> <A HREF=startup.html> <B>startup</B></A><TD>
<TD> <A HREF=snap.html> <B>snap</B></A></TD>
<TD> <A HREF=spliterase.html> <B>spliterase</B></A></TD>
<TD> <A HREF=splitpaint.html> <B>splitpaint</B></A></TD>
</TR>
<TR>
<TD> <A HREF=straighten.html> <B>straighten</B></A><TD>
<TD> <A HREF=stretch.html> <B>stretch</B></A><TD>
<TD> <A HREF=suspendall.html> <B>suspendall</B></A><TD>
<TD> <A HREF=startup.html> <B>startup</B></A></TD>
<TD> <A HREF=straighten.html> <B>straighten</B></A></TD>
<TD> <A HREF=stretch.html> <B>stretch</B></A></TD>
</TR>
<TR>
<TD> <A HREF=tag.html> <B>tag</B></A><TD>
<TD> <A HREF=tech.html> <B>tech</B></A><TD>
<TD> <A HREF=techmanager.html> <B>techmanager</B></A><TD>
<TD> <A HREF=suspendall.html> <B>suspendall</B></A></TD>
<TD> <A HREF=tag.html> <B>tag</B></A></TD>
<TD> <A HREF=tech.html> <B>tech</B></A></TD>
</TR>
<TR>
<TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A><TD>
<TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A><TD>
<TD> <A HREF=unexpand.html> <B>unexpand</B></A><TD>
<TD> <A HREF=techmanager.html> <B>techmanager</B></A></TD>
<TD> <A HREF=tool.html> <B>tool</B> <I>(non-Tcl version)</I></A></TD>
<TD> <A HREF=changetool.html> <B>tool</B> <I>(Tcl version)</I></A></TD>
</TR>
<TR>
<TD> <A HREF=unmeasure.html> <B>unmeasure</B></A><TD>
<TD> <A HREF=upsidedown.html> <B>upsidedown</B></A><TD>
<TD> <A HREF=what.html> <B>what</B></A><TD>
<TD> <A HREF=unexpand.html> <B>unexpand</B></A></TD>
<TD> <A HREF=unmeasure.html> <B>unmeasure</B></A></TD>
<TD> <A HREF=upsidedown.html> <B>upsidedown</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wire.html> <B>wire</B></A><TD>
<TD> <A HREF=writeall.html> <B>writeall</B></A><TD>
<TD> <A HREF=xload.html> <B>xload</B></A><TD>
<TD> <A HREF=what.html> <B>what</B></A></TD>
<TD> <A HREF=wire.html> <B>wire</B></A></TD>
<TD> <A HREF=writeall.html> <B>writeall</B></A></TD>
</TR>
<TR>
<TD> <A HREF=xload.html> <B>xload</B></A></TD>
<TD> </TD>
<TD> </TD>
</TR>
</TBODY>
</TABLE>
@ -551,38 +556,38 @@
cellpadding="5" bgcolor="#ffcccc">
<TBODY>
<TR>
<TD> <A HREF=netlist/add.html><B>add</B></A><TD>
<TD> <A HREF=netlist/cleanup.html><B>cleanup</B></A><TD>
<TD> <A HREF=netlist/cull.html><B>cull</B></A><TD>
<TD> <A HREF=netlist/add.html><B>add</B></A></TD>
<TD> <A HREF=netlist/cleanup.html><B>cleanup</B></A></TD>
<TD> <A HREF=netlist/cull.html><B>cull</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/dnet.html><B>dnet</B></A><TD>
<TD> <A HREF=netlist/dterm.html><B>dterm</B></A><TD>
<TD> <A HREF=netlist/extract.html><B>extract</B></A><TD>
<TD> <A HREF=netlist/dnet.html><B>dnet</B></A></TD>
<TD> <A HREF=netlist/dterm.html><B>dterm</B></A></TD>
<TD> <A HREF=netlist/extract.html><B>extract</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/find.html><B>find</B></A><TD>
<TD> <A HREF=netlist/flush.html><B>flush</B></A><TD>
<TD> <A HREF=netlist/join.html><B>join</B></A><TD>
<TD> <A HREF=netlist/find.html><B>find</B></A></TD>
<TD> <A HREF=netlist/flush.html><B>flush</B></A></TD>
<TD> <A HREF=netlist/join.html><B>join</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/netlist.html><B>netlist</B></A><TD>
<TD> <A HREF=netlist/orient.html><B>orient</B></A><TD>
<TD> <A HREF=netlist/pushbutton.html><B>pushbutton</B></A><TD>
<TD> <A HREF=netlist/netlist.html><B>netlist</B></A></TD>
<TD> <A HREF=netlist/orient.html><B>orient</B></A></TD>
<TD> <A HREF=netlist/pushbutton.html><B>pushbutton</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/print.html><B>print</B></A><TD>
<TD> <A HREF=netlist/ripup.html><B>ripup</B></A><TD>
<TD> <A HREF=netlist/savenetlist.html><B>savenetlist</B></A><TD>
<TD> <A HREF=netlist/print.html><B>print</B></A></TD>
<TD> <A HREF=netlist/ripup.html><B>ripup</B></A></TD>
<TD> <A HREF=netlist/savenetlist.html><B>savenetlist</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/shownet.html><B>shownet</B></A><TD>
<TD> <A HREF=netlist/showterms.html><B>showterms</B></A><TD>
<TD> <A HREF=netlist/trace.html><B>trace</B></A><TD>
<TD> <A HREF=netlist/shownet.html><B>shownet</B></A></TD>
<TD> <A HREF=netlist/showterms.html><B>showterms</B></A></TD>
<TD> <A HREF=netlist/trace.html><B>trace</B></A></TD>
</TR>
<TR>
<TD> <A HREF=netlist/verify.html><B>verify</B></A><TD>
<TD> <A HREF=netlist/writeall.html><B>writeall</B></A><TD>
<TD> <A HREF=netlist/verify.html><B>verify</B></A></TD>
<TD> <A HREF=netlist/writeall.html><B>writeall</B></A></TD>
<TD></TD>
</TR>
</TBODY>
@ -595,24 +600,24 @@
cellpadding="5" bgcolor="#ccffcc">
<TBODY>
<TR>
<TD> <A HREF=wind3d/cif.html><B>cif</B></A><TD>
<TD> <A HREF=wind3d/closewindow.html><B>closewindow</B></A><TD>
<TD> <A HREF=wind3d/cutbox.html><B>cutbox</B></A><TD>
<TD> <A HREF=wind3d/cif.html><B>cif</B></A></TD>
<TD> <A HREF=wind3d/closewindow.html><B>closewindow</B></A></TD>
<TD> <A HREF=wind3d/cutbox.html><B>cutbox</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wind3d/defaults.html><B>defaults</B></A><TD>
<TD> <A HREF=wind3d/help.html><B>help</B></A><TD>
<TD> <A HREF=wind3d/level.html><B>level</B></A><TD>
<TD> <A HREF=wind3d/defaults.html><B>defaults</B></A></TD>
<TD> <A HREF=wind3d/help.html><B>help</B></A></TD>
<TD> <A HREF=wind3d/level.html><B>level</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wind3d/refresh.html><B>refresh</B></A><TD>
<TD> <A HREF=wind3d/render.html><B>render</B></A><TD>
<TD> <A HREF=wind3d/scroll.html><B>scroll</B></A><TD>
<TD> <A HREF=wind3d/refresh.html><B>refresh</B></A></TD>
<TD> <A HREF=wind3d/render.html><B>render</B></A></TD>
<TD> <A HREF=wind3d/scroll.html><B>scroll</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wind3d/see.html><B>see</B></A><TD>
<TD> <A HREF=wind3d/view.html><B>view</B></A><TD>
<TD> <A HREF=wind3d/zoom.html><B>zoom</B></A><TD>
<TD> <A HREF=wind3d/see.html><B>see</B></A></TD>
<TD> <A HREF=wind3d/view.html><B>view</B></A></TD>
<TD> <A HREF=wind3d/zoom.html><B>zoom</B></A></TD>
</TR>
</TBODY>
</TABLE>
@ -624,12 +629,12 @@
cellpadding="5" bgcolor="#ffccff">
<TBODY>
<TR>
<TD> <A HREF=color/pushbutton.html><B>pushbutton</B></A><TD>
<TD> <A HREF=color/color.html><B>color</B></A><TD>
<TD> <A HREF=color/load.html><B>load</B></A><TD>
<TD> <A HREF=color/pushbutton.html><B>pushbutton</B></A></TD>
<TD> <A HREF=color/color.html><B>color</B></A></TD>
<TD> <A HREF=color/load.html><B>load</B></A></TD>
</TR>
<TR>
<TD> <A HREF=color/save.html><B>save</B></A><TD>
<TD> <A HREF=color/save.html><B>save</B></A></TD>
<TD></TD>
<TD></TD>
</TR>
@ -643,19 +648,19 @@
cellpadding="5" bgcolor="#ffffcc">
<TBODY>
<TR>
<TD> <A HREF=wizard/bypass.html><B>*bypass</B></A><TD>
<TD> <A HREF=wizard/coord.html><B>*coord</B></A><TD>
<TD> <A HREF=wizard/extract.html><B>*extract</B></A><TD>
<TD> <A HREF=wizard/bypass.html><B>*bypass</B></A></TD>
<TD> <A HREF=wizard/coord.html><B>*coord</B></A></TD>
<TD> <A HREF=wizard/extract.html><B>*extract</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wizard/plow.html><B>*plow</B></A><TD>
<TD> <A HREF=wizard/psearch.html><B>*psearch</B></A><TD>
<TD> <A HREF=wizard/showtech.html><B>*showtech</B></A><TD>
<TD> <A HREF=wizard/plow.html><B>*plow</B></A></TD>
<TD> <A HREF=wizard/psearch.html><B>*psearch</B></A></TD>
<TD> <A HREF=wizard/showtech.html><B>*showtech</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wizard/tilestats.html><B>*tilestats</B></A><TD>
<TD> <A HREF=wizard/tsearch.html><B>*tsearch</B></A><TD>
<TD> <A HREF=wizard/watch.html><B>*watch</B></A><TD>
<TD> <A HREF=wizard/tilestats.html><B>*tilestats</B></A></TD>
<TD> <A HREF=wizard/tsearch.html><B>*tsearch</B></A></TD>
<TD> <A HREF=wizard/watch.html><B>*watch</B></A></TD>
</TR>
</TBODY>
</TABLE>
@ -667,14 +672,14 @@
cellpadding="5" bgcolor="#cccccc">
<TBODY>
<TR>
<TD> <A HREF=wizard/crash.html><B>*crash</B></A><TD>
<TD> <A HREF=wizard/files.html><B>*files</B></A><TD>
<TD> <A HREF=wizard/grstats.html><B>*grstats</B></A><TD>
<TD> <A HREF=wizard/crash.html><B>*crash</B></A></TD>
<TD> <A HREF=wizard/files.html><B>*files</B></A></TD>
<TD> <A HREF=wizard/grstats.html><B>*grstats</B></A></TD>
</TR>
<TR>
<TD> <A HREF=wizard/pause.html><B>*pause</B></A><TD>
<TD> <A HREF=wizard/winddebug.html><B>*winddebug</B></A><TD>
<TD> <A HREF=wizard/winddump.html><B>*winddump</B></A><TD>
<TD> <A HREF=wizard/pause.html><B>*pause</B></A></TD>
<TD> <A HREF=wizard/winddebug.html><B>*winddebug</B></A></TD>
<TD> <A HREF=wizard/winddump.html><B>*winddump</B></A></TD>
</TR>
</TBODY>
</TABLE>

Some files were not shown because too many files have changed in this diff Show More