Compare commits

...

1110 Commits

Author SHA1 Message Date
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
R. Timothy Edwards 490fc6f9d7 Added a quick hack solution from Darryl Miles to prevent the
database corruption discovered recently that was uncovered by a
commit on Jan. 31 and is caused by DBMergeNMTiles0() using a
freed tile (reported in github issue #404).
2025-06-12 19:54:33 -04:00
R. Timothy Edwards 5ecc55b37d Added some alternative key bindings to the keypad for "stretch"
commands, because the keypad numerical values no longer work
regardless of the setting of Num Lock.  The keypad arrow keys
alone implement "move", while Shift + keypad arrow keys
implement "stretch".
2025-05-22 08:47:03 -04:00
R. Timothy Edwards f1f4b82a30 Corrected an error caused by extending the parsing of the FOREIGN
keyword in LEF.  FOREIGN may take an origin offset, but it is
optional.  The routine to check that there were no offset values
in the statement incorrectly checked for a NULL token instead of
a value ";" which would indicate an end-of-statement.
2025-05-16 19:36:16 -04:00
R. Timothy Edwards 02669de267 Updated the version number to go along with a bunch of pull request
merges for PRs by Darryl Miles.
2025-04-09 15:27:18 -04:00
Darryl L. Miles 31400dd45f plotPNM.c: Fix crash due to uninited rtl_args.outfile
I introduced this issue in recent commit e88dcba1c
2025-04-09 15:26:54 -04:00
Darryl L. Miles e592122199 ASSERT fixes (typo in variable and bad integer casting)
routerLayer => routeLayer (my typo from a recent commit, compile fix)
MINFINITY compiler warning
2025-04-09 15:26:06 -04:00
Darryl L. Miles 44bb9327a2 ExtTech.c: fix uninitialized exts_linearResist value leaks into extresist
This value appears to be initialised at only one spot in the codebase
(under very narrow conditions) but extresist will read it and make
branching decisions based on the uninitialised state.

This 'X' state propagation appears to eventually get processed in
ResWriteExtFile() near where final output formatting is occurring.

It is unclear (at this time) if it perturbs output values in a
problematic way, or if due to algorithmic reasons the data is
discarded before output anyway.  I have at least one trace run (with
multiple triggers) of printf formatters handling uninitialised data
in ResWriteExtFile().
2025-04-09 15:25:02 -04:00
Darryl L. Miles 2c9e3a558d git rm SimSelect.c.new (was this always here?) 2025-04-09 15:23:21 -04:00
Darryl L. Miles 739f0f27fe sim: DBCellSrArea() cb_database_cellsrarea_t SimCellTileSrFunc() 2025-04-09 15:23:21 -04:00
Darryl L. Miles 56bdf9ce28 sim: DBSrPaintArea() cb_database_srpaintarea_t SimSelectFunc() 2025-04-09 15:23:21 -04:00
Darryl L. Miles dceb5cfad7 database.h.in: dbSrConnectFunc()/dbSrConnectStartFunc() add public prototype 2025-04-09 15:23:21 -04:00
Darryl L. Miles ef123be806 database.h.in: dbcUnconnectFunc() add public prototype 2025-04-09 15:23:21 -04:00
Darryl L. Miles fa1f1583df database: DBPrintUseId() K&R removal 2025-04-09 15:23:21 -04:00
Darryl L. Miles cface55c5b sim: various cleanups (non existent funcs) 2025-04-09 15:23:21 -04:00
Darryl L. Miles 67f7db9540 sim: remove declaration for getenv() 2025-04-09 15:23:21 -04:00
Darryl L. Miles b5ac7e4f92 sim: use pid_t where appropiate 2025-04-09 15:23:21 -04:00
Darryl L. Miles 559eb94f3e sim: use 'const' with 'sccsid' 2025-04-09 15:23:21 -04:00
Darryl L. Miles ef79d33dd4 database.h.in constify various TileTypeBitMask* data usages 2025-04-09 15:23:21 -04:00
Darryl L. Miles 6ec826fb8b sim: constify various APIs 2025-04-09 15:23:21 -04:00
Darryl L. Miles 1fbba4408f K&R sim/*.c: bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2025-04-09 15:23:21 -04:00
Darryl L. Miles b3384f9104 K&R sim.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2025-04-09 15:23:21 -04:00
Darryl L. Miles be09d8d402 SimRsim.c: update with const API change to utils module 2025-04-09 15:23:21 -04:00
Darryl L. Miles 120cea3921 SimRsim.c: remove declaration SimGetReplyLine() as it is in sim.h 2025-04-09 15:23:21 -04:00
Darryl L. Miles 10f82355f5 txCommands.c TxGetInputEvent() rework main loop to iterate less
Original version would iterate exhaustively, even when it was not
necessary.

This version seeks to do the minimum amount of iteration work based
on the information available.
2025-04-09 15:19:25 -04:00
Darryl L. Miles 3c3ebcfd2b txCommands.c txInputDevRec FD select() usage overhaul
There are numerous concerns with the original code from a read through.

The #define TX_MAX_OPEN_FILES 20 is badly named, the txCommand.c uses
fd_set to hold active FD for each device, and makes no attempt to bounds
check the 'fd' or 'fd_set' of any TxAdd1InputDevice() is in range.

The real name of this variable should be TX_MAX_INPUT_DEVICES as it
related to the fixed compile time slots available for devices, each input
device must have at least one active FD and it can be in the range
that fd_set allows, which is 0..1023 on linux.

So based on this being the original intention, due to the way the code is
constructed and API calls made available, the file has been reworked
to allow all these considerations at the same time.

Now the design should be FD clean for FDs in the range 0..1023 instead of
being artificially clamped to the first 20 FDs being valid input devices.

Renaming of variable 'i' to 'fd' when it relates to an fd number, so all
uses of FD_XXXX() should use fd, this helps clarify the different domain
the number relates to.
When 'i' is used it relates to the index into the txInputDevRec array.
A large part of the concerns relate to trying to mix the two numbering
domains interchangeably, just using a different name really clears up
understanding to the reader.

Other items that look like errors TxDelete1InputDevice() will
shuffle-remove entries with no active FD, but it is iterating an array
it is also modifying, so it looks like it would have incorrectly skipped
the next item that should be inspected just after a shuffle-removal
occurred.

The various iterators that works from 0..TX_MAX_OPEN_FILES incorrectly
limited the visibility of the routines to the first 20 FDs instead of
the full FD_SETSIZE the TxAddInputDevice API call allows to be
registered.

Passing in TxAdd1InputDevice with an fd above 19 would have resulted in
everything looking successful until select() was used, then the kernel
would likely not sleep/wait because the input fd_set would look blank due
to being clipped by nfds=TX_MAX_OPEN_FILES (instead of that plus 1).

The use of TX_MAX_OPEN_FILES in select instead of TX_MAX_OPEN_FILES+1 for
the 'nfds' field would have meant a device with fd=19 would not work as
the design intended.

The define definition has been removed from the module public header,
I assume it was there for use by another module, but the incorrect
select() usage has been corrected over there in a previous commit.
So now the define can be maintained near the array it relates to.

While the code might looks less 'efficient' as it is now sweeping all
1024 FDs when input devices during add/remove (hopefully there maybe some
compiler auto-vectorization/tzcnt use there).  The main event loop is
slightly more 'efficient' (especially for the single device with input
fd=0 case) as it will only check the 1 FD each input event loop iteration,
not check all 20 FDs for data readyness everytime.
2025-04-09 15:19:25 -04:00
Darryl L. Miles 6d2d4353d3 select() API usages add ASSERT() to validate fd number is in-range
This encapsulates the expectation the 'fd' is in the permitted range for
the standard sizes 'fd_set'.

This is so there is some form of detection with issues in this area, if
the RLIMIT_NOFILE limit is increased.
2025-04-09 15:19:25 -04:00
Darryl L. Miles 8d6571066d grMain.c select() usage fix and protect from higher numbered fd's
The old code would only work is the fileno(stream) returned an fd
in the range 0 <= 19.  It would silently fail, if the fd was in
the range 20..1023 because FD_SET() would work and syscall select()
would be limited to only look at the first 20 fd's.  Ignoring any
fd's higher even if set.
This would theoretically cause high CPU usage due to select()
never blocking because there are no active fd's in the fd_set
as far as the kernel interprets the request and the kernel would
immediately return.

But reading the code the 1st argument to select() seems self
limiting for no good reason.  It should be fileno(stream)+1 as
documented in man select(2).

Added the assertion as well, because we are trying to allow magic
to use fd's beyond the standard environmental limits.  So it
becomes an assertion condition if the fd is outside the range
0..1023 because the FD_SET() macro will not operate correctly /
undefined-behaviour.

I can't find any user of this func in the codebase right now.

If you look at sim/SimRsim.c and the use of select() there, it is
correctly using select() to wait on a single fd over there.  This
commit changes this code to match this correct usage.
2025-04-09 15:19:25 -04:00
Darryl L. Miles bcd81c74b2 tclmagic.c: RLIMIT_NOFILE to 4096 on startup (only for TCL9 envs) 2025-04-09 15:19:25 -04:00
Darryl L. Miles f5f59846da configure: autoconf regen (2.69) getrlimit setrlimit sys/resource.h 2025-04-09 15:19:25 -04:00
Darryl L. Miles c676c6b1d3 configure.in: getrlimit setrlimit sys/resource.h 2025-04-09 15:19:25 -04:00
Darryl L. Miles 61e4e155ec ext2sim.c: remove unused mergeAttr()
If this is ever restored please audit the implementation as it does
not look sound.
2025-04-09 15:11:48 -04:00
Darryl L. Miles e7c46102d6 ext2spice: mergeAttr() fix, leak removal and restore original intention 2025-04-09 15:11:48 -04:00
Darryl L. Miles b3617f603d extract: DBSrCellPlaneArea() cb_database_srcellplanearea_t extContainsCellFunc() 2025-04-09 15:07:28 -04:00
Darryl L. Miles 321b2d61c7 extract: DBSrCellPlaneArea() const Rect * arg2 2025-04-09 15:07:28 -04:00
Darryl L. Miles 5c8510355f extract: DBSrCellPlaneArea() cb_database_srcellplanearea_t extContainsCellFunc 2025-04-09 15:07:28 -04:00
Darryl L. Miles 5b03081d03 cif: TiPlaneRect const ripple 2025-04-09 15:07:28 -04:00
Darryl L. Miles 16efabe9ee calma: TiPlaneRect const ripple 2025-04-09 15:07:28 -04:00
Darryl L. Miles 00b479301f tiles: TiPlaneRect const ripple 2025-04-09 15:07:28 -04:00
Darryl L. Miles 51ec834f6c This attempts to remove the number of active lines of code, branches from
the TiAlloc() and TiFree() code path.

The rationale of the changes:

Performing the one-time initialization check (first call to
mmapTileStore()) for every TiAlloc() is unnecessary if the decision code
is reworked to allow NULL pointers to exist in the computation and still
make the correct decision.

Use of 'unsigned long' for pointer arithmetic is not compatible with _WIN64
compiler model LLP64.  Changed to 'pointertype'.

The computations addition/subtraction/greater-than were performed
multiple times.  Seemed a convoulted method when a single operation
should be good enough.

The use of a single-linked-list with HEAD and TAIL does not make sense.
My gut is telling me that for the purpose of memory allocation a LIFO is
better as a free-and-reuse of the most recently freed item is more likely
to already be in the CPU cache and the oldest freed item is more likely
to have been evicted from CPU cache.  So given the use of a custom
allocator and no support to reclaim/compact or manage fragmentation
other factor didn't carry any weight.
Technically TiAlloc() returns undefined memory and the first action of
the caller is to write new values, but the point remains that write is
more likely to cause eviction of something else from cache with the
original FIFO scheme.
Due to the free list use during TiFree() there is a write to each alloc
which will make the cache-line hotter in the cache (less likely to have
been evicted) when using LIFO scheme than FIFO scheme.

Further more the use of HEAD and TAIL had a far more complex
TileStoreFree() than was necessary even for such a list.  A 4 line
method turned into 7 with multiple conditions tested when branching.
The TileStoreFreeList/TileStoreFreeList_end were public symbols which may
also impact the freedom the compiler has to optimise around them.

Using LIFO single-linked-list resulted in the removal of
TileStoreFreeList_end and associated simplification.

Use of 'static' for the methods mmapTileStore() and getTimeFromTileStore()
these are not public API so adding the 'static' give the compiler a hint
these methods maybe inlined as they are not accessile from outside this
compliation unit.

The -O3 assembly result looks quite healthy in achieving the original
goal of instruction and branch reductions with the compiler able to
inline all 3 methods into a single TiAlloc().
2025-04-09 15:07:28 -04:00
Darryl L. Miles 1c3a059031 tiles: TileStoreFreeList_end removal 2025-04-09 15:07:28 -04:00
Darryl L. Miles e1238633ac tiles: simplify TileStoreFree() and TileStoreFreeList_end management 2025-04-09 15:07:28 -04:00
Darryl L. Miles b9dd4bfb7c tiles: reorder TileStoreFree() 2025-04-09 15:07:27 -04:00
Darryl L. Miles 52fced3544 K&R: tile/*.c bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2025-04-09 15:07:27 -04:00
Darryl L. Miles 69df88520c bplane: constify BPEnumInit() 2025-04-09 15:07:27 -04:00
Darryl L. Miles 650d800b12 tiles: use 'const' with 'rcsid' 2025-04-09 15:07:27 -04:00
Darryl L. Miles 686adc13b3 tiles: unclear why TileStoreFreeList is an exported global
Looks private internal implementation detail that may benefit from
compiler single compile unit optimisations.
2025-04-09 15:07:27 -04:00
Darryl L. Miles 0f19a20c8c tiles: pointer arithmetic with 'unsigned long' is too narrow for _WIN64
is mmap() is available the type 'size_t' is better suited
2025-04-09 15:07:27 -04:00
Darryl L. Miles 34dfd3686b tiles: treat ti_client as pointer and use macros 2025-04-09 15:07:27 -04:00
Darryl L. Miles cc6e7ebe84 tiles: constify data and API call arguments as appropriate 2025-04-09 15:07:27 -04:00
Darryl L. Miles d082c67b03 K&R tile.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2025-04-09 15:07:27 -04:00
Darryl L. Miles e8ad7c9ac8 tiles: remove non-existent function prototype TiSrArea() 2025-04-09 15:07:27 -04:00
Darryl L. Miles 1a84eab4ce Plane[GS]etHint() added to encapsulate access to Plane->pl_hint
This is ground work to intercept usage and validate changes in
this area.

Fixed conflicts with earler patch in extract/ExtNghbors.c
2025-04-09 15:02:59 -04:00
Darryl L. Miles f942ae6e78 TiGetClient() excessive use hotspots
This is reducing nearby calls to TiGetClient() API when the value
can be looked up one time and stored in a local variable to make
other decisions about.

This is due to TiGetClient() potentially having a slightly higher
cost to call than previously, this is a kind of peephole
optimization approach (if I can see multiple getters used within
the window it got optmized).

'ticlient' was used for retrieval as ClientData so that future
greps across the codebase for `ti_client` should only match naked
access.
2025-04-09 14:55:58 -04:00
Darryl L. Miles 606f37cc80 Ti[GS]etClient() usage enforcement
All naked access to `ti_client` now uses the function-like-macro
to encapsulate this action.  This macro existed before this just
makes all sites utilize it.

Added additional INT and PTR variants to remove the programmer
load on thinking about casing and casts polluting the point
of use.  So the use now looks cleaner.

Equivalent prototypes:

 void TiSetClient(Tile*, ClientData)
 void TiSetClientINT(Tile*, intptr_t) /* pointertype */
 void TiSetClientPTR(Tile*, void*)

 ClientData TiGetClient(Tile*)
 intptr_t TiGetClientINT(Tile*) /* pointertype */
 void *TiGetClientPTR(Tile*)
2025-04-09 14:55:58 -04:00
R. Timothy Edwards 6e83cbe2d3 Added handling of coordinates in a FOREIGN statement in a LEF
macro.  Based on observation of cells in PDKs where ORIGIN and/or
FOREIGN are non-zero, added code that forces a correction of LEF
macro coordinates to match the GDS coordinates, with an
equivalent negative shift of the LEF macro ORIGIN to compensate.
Normally, both ORIGIN and FOREIGN will be zero and the added code
will do nothing.  Note that this code does not handle the
additional optional orientation.  A LEF macro with a different
coordinate system than its GDS is already weird;  a LEF macro
with a different rotation than its GDS is hopefully something
that nobody ever does in practice.  If needed, I'll cross that
bridge when I come to it.
2025-03-29 15:46:23 -04:00
R. Timothy Edwards 6b9efefc02 Added a new "orthogonal" operator to cifoutput to allow non-
manhattan shapes (especially minimum-sized ones) to be eliminated,
as these can survive a shrink-grow operation intended to get rid
of such shapes.  This implementation may not be in its final form
but should suffice for now.
2025-03-28 10:11:17 -04:00
R. Timothy Edwards dde7144966 Modified the behavior of SelectCopy() so that it surveys cell
instance names in both the selection and in the root edit CellDef,
and then wipes duplicate names from the selection and regenerates
unique IDs.  This avoids the unexpected behavior displayed by
magic in which a "copy" function renames the *original* instance
and gives the original name to the copied instance.  This is not
only unexpected, but causes an error in which "undo" after
multiple copies fails to remove earlier copies because the name
change was not recorded, and the instance can no longer be found
by name.
2025-03-26 14:45:46 -04:00
Darryl L. Miles 705b4da105 TxParseString() refactor to 1-arg public form
Only the txCommands.c file needs the 3-arg form locally
2025-02-23 10:24:40 -05:00
Darryl L. Miles 9aef87c355 database: TxDialog() constification ripple 2025-02-23 10:24:40 -05:00
Darryl L. Miles aa35a612b0 tclmagic.c: match new textio prototypes for constified implementations 2025-02-23 10:24:40 -05:00
Darryl L. Miles 6ed8f17136 textio: create callback typedef cb_textio_input_t 2025-02-23 10:24:40 -05:00
Darryl L. Miles c8ca1d242e txOutput.c: FILR -> FILE (typo fix)
Long standing typo, I guess no configuration compiles this code.
2025-02-23 10:24:40 -05:00
Darryl L. Miles 1166a56cff textio: getenv() comes from <stdlib.h> remove declaration 2025-02-23 10:24:40 -05:00
Darryl L. Miles 934fe32436 textio: constify various internal
This maybe a little gratuitous (as I'm not convinced all changed lines
are being compiled)
2025-02-23 10:24:40 -05:00
Darryl L. Miles c92ded99df textio: constify various data 2025-02-23 10:24:40 -05:00
Darryl L. Miles 7e1692800b textio: contify various APIs 2025-02-23 10:24:40 -05:00
Darryl L. Miles 906e02c898 K&R textio/*.c: bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2025-02-23 10:24:40 -05:00
Darryl L. Miles 8cce1bdb7e K&R textio: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2025-02-23 10:24:40 -05:00
Darryl L. Miles 6c6e48a9a3 textioInt.h: add assumed prototype for Tcl_printf() 2025-02-23 10:24:40 -05:00
Darryl L. Miles f63dc318a7 textio: removed prototypes for non-existant functions
extern void TxVisChar();
extern void TxPromptOnNewLine();
extern TxCommand *TxDeviceStdin();
extern TxCommand *TxButtonMaskToCommand();

Found during K&R removal of textio/**
2025-02-23 10:24:40 -05:00
Darryl L. Miles 12c6ccc97b ResReadSim.c remove existing fclose() as conflict with recent change
After futher review of this function it looks like the existing
fclose() is not in the correct place, and recent patches have
added fclose() to this function in better places (covering all
returns) but did not take into account the existing misplaced
fclose().
2025-02-23 10:23:51 -05:00
Darryl L. Miles dd84be9172 CmdCD.c: fix missing 'else' from my recent commit e88dcba1c 2025-02-23 10:23:51 -05:00
Darryl L. Miles 78f2c0696c wiring: forward declaration prototypes and consistency 2025-02-23 10:21:41 -05:00
Darryl L. Miles 154c3efa5c wiring: use 'const' with 'rcsid' 2025-02-23 10:21:41 -05:00
Darryl L. Miles 922abe6b8d wiring: constify API call arguments where possible
mark cb_database_buttonhandler_t
2025-02-23 10:21:41 -05:00
Darryl L. Miles 81d526562c dbwind: DBWAddButtonHandler() cb_database_buttonhandler_t
constify API call arguments as appropiate
2025-02-23 10:21:41 -05:00
Darryl L. Miles 4f54bcf4f4 K&R wiring/*.c: bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2025-02-23 10:21:41 -05:00
Darryl L. Miles 5058152c8f K&R wiring.h wireInt.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2025-02-23 10:21:41 -05:00
Darryl L. Miles 92c4fc35db ResMain.c: use-after-free: simple reorder of statements 2025-02-23 10:20:41 -05:00
Tim Edwards 48708c52a4 Removed two unused statements from EFantenna.c, per the discussion
in github pull request #377.
2025-02-23 10:15:48 -05:00
Darryl L. Miles 983f4cb76f lef: constify remaining .data into .rodata 2025-02-22 21:48:17 -05:00
Darryl L. Miles ac37927186 lef: constify static data and LefNextToken() return
LefHelper_DBTechNameType_LefLower() identified and introduced during
conversion to const data usage.

Only side-effect is some log messages will use original verbatim token
now instead of lowercase version (but this seems ok when file parsing,
to quote the problematic information source verbatim)
2025-02-22 21:48:17 -05:00
Darryl L. Miles 451dab4b9b lef: constify strings in data structures of lef module 2025-02-22 21:48:17 -05:00
Darryl L. Miles ed87c3a98b lef: cleanup mark unnecessary call to function with no side-effects
Maybe these function call can be removed or at least their return
value discarded (as the returned value is never used).
2025-02-22 21:48:17 -05:00
Darryl L. Miles 56bf27548d lef: cleanup remove unused local/static variables
Many appear to be the result of copy-and-paste from a similar func
nearby.
2025-02-22 21:48:17 -05:00
Darryl L. Miles 9d0cd63a4e lef: use 'const' with 'rcsid' 2025-02-22 21:48:17 -05:00
Darryl L. Miles ad6ecb5bbb lef/*.h: constify string function arguments 2025-02-22 21:48:17 -05:00
Darryl L. Miles 695692b620 K&R lef/*.c: bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2025-02-22 21:48:17 -05:00
Darryl L. Miles 05a5b169bc defWrite.c: defHNsprintfPrefix() constify implementation 2025-02-22 21:48:17 -05:00
Darryl L. Miles 4930e0307a tcllef.c: missing include textio/textio.h (due to TxPrint usage) 2025-02-22 21:48:17 -05:00
Darryl L. Miles 19e03fc4f8 K&R lef/*.c: bulk function implementation conversion
Some function parameters (char *sname) have been made const due
referencing const data sources.

K&R obsolete syntax removal for C23 compatibility series
2025-02-22 21:48:17 -05:00
Darryl L. Miles a1f7e4ed5e lef: post K&R constify ripple
These functions are using data that is already const.
2025-02-22 21:48:17 -05:00
Darryl L. Miles f7c550e82f defRead.c: DefRead() incorrect arg0 to LefParseEndStatement() 2025-02-22 21:48:17 -05:00
Darryl L. Miles 25ec9fccef K&R lef.h lefInt.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2025-02-22 21:48:17 -05:00
Darryl L. Miles acf0e474e8 K&R lefInt.h: missing prototype removal
Function does not appear to exist:
 extern char *LefGetInput();

K&R obsolete syntax removal for C23 compatibility series
2025-02-22 21:48:17 -05:00
Darryl L. Miles a764fdbbd1 CodeQL MemoryMayNotBeFreed.ql grTCairo1.c GrTCairoPlotSVG()
created use of 'alloc' local variable to track when an allocation occurred
so exit path logic is more straight forward for compiler/analyser to see
potential optimisations.

the previous version was probably working just fine
2025-02-22 21:35:23 -05:00
Darryl L. Miles e565b4c360 CodeQL MemoryMayNotBeFreed.ql NMnetlist.c NMWriteNetlist()
created use of 'alloc' local variable to track when an allocation occurred
so exit path logic is more straight forward for compiler/analyser to see
potential optimisations.

no attempt to free memory was made previously
2025-02-22 21:35:23 -05:00
Darryl L. Miles 37fa75dd77 CodeQL MemoryMayNotBeFreed.ql ResRex.c ResCheckSimNodes()
created use of 'alloc' local variable to track when an allocation occurred
so exit path logic is more straight forward for compiler/analyser to see
potential optimisations.
2025-02-22 21:35:23 -05:00
Darryl L. Miles c33b6be2bb CodeQL MemoryMayNotBeFreed.ql rtrChannel.c RtrChannelRoute()
Unclear with all the flip operations if there is some kind of attachment
(exchange of channels), the other 2 channels created in the function
are also cleaned up.
2025-02-22 21:35:23 -05:00
Darryl L. Miles b5d068b0ea CodeQL MemoryMayNotBeFreed.ql rtrCmd.c CmdRoute() 2025-02-22 21:35:23 -05:00
Darryl L. Miles cb9333804a CodeQL MemoryMayNotBeFreed.ql rtrCmd.c CmdRoute()
temporary channel created to run command is not cleaned up
2025-02-22 21:35:23 -05:00
Darryl L. Miles 822a95ab35 CodeQL MemoryMayNotBeFreed.ql antennacheckVisit()
Looks like straight forward exit path doesn't cleanup locally malloc
block.
2025-02-22 21:35:23 -05:00
Darryl L. Miles 7508a9e6b7 CodeQL MemoryMayNotBeFreed.ql calma/**
Looks straight forward lost pointer to recently malloced block
2025-02-22 21:35:23 -05:00
Darryl L. Miles 99c448407c CodeQL LargeParameter.ql: large objects returned (around fd_set usage)
now using pointers (fd_set*)
constify API where possible
2025-02-22 21:31:22 -05:00
Darryl L. Miles 6a537c4659 CodeQL IncorrectNotOperatorUsage.ql rtrDcmppose.c rtrCLEAR() usages
Maybe it was a single bit and '!' operator inverted a single bit, but it
 appears to be a 4-bit mask today.

TODO check rtrMARKED() this looks like it uses '&' operator is in use
 but from the context of a bitmask maybe this should be '|' operator.
2025-02-22 21:31:22 -05:00
Darryl L. Miles ca9229b35a CodeQL MissingNegativtyTest.ql ttype>=0 ResSimSubckt()
This variable is used as array index, but the extGetDevType() API allows
a negative return to occur.
2025-02-22 21:31:22 -05:00
Darryl L. Miles ad1d9923f9 CodeQL MissingNegativtyTest.ql magictype>=0 defWrite.c
defnodeVisit()
defblockageVisit()

This variable is used as array index, but the DBTechNameType() API allows
a negative return to occur.
2025-02-22 21:31:22 -05:00
Darryl L. Miles 38b25c5d34 CodeQL InconsistentNullnessTest.ql ourgl != NULL
ourgl local variable is set to a non-NULL value (first initialization)
in code that is in lines below where it is dereferenced in a loop.
Somewhere in the loop there is a point where the precondition of ourgl
being set to non-null is expected.
ASSERT added.
2025-02-22 21:31:22 -05:00
Darryl L. Miles d18b40d401 CodeQL LateNegativeTest.ql defRead.c routerLayer>=0
Code nearby tests 'routeLayer' for negativeness, but it is set and then
used as array index without such a test.
ASSERT added.
2025-02-22 21:31:21 -05:00
Tim Edwards 8ebad7d1a9 Implemented the fix to an expression that should have been logical-
AND and not bitwise-AND, as pointed out in PR #376 by Darryl Miles.
2025-02-22 21:15:45 -05:00
Darryl L. Miles a60259ab63 CodeQL FileMayNotBeClosed.ql PaCheckCompressed() apparently leaks an 'fd'
CodeQL complains of a _potential_ leak (I can't see it), seems false
positive but also a clear case to use POSIX access(R_OK) instead.
2025-02-22 21:02:49 -05:00
Darryl L. Miles e88dcba1c5 CodeQL File{MayNot,Never}BeClosed.ql file-handle resource leaks
Guided by CodeQL static code analyser.

FileMayNotBeClosed.ql
FileMayNeverBeClosed.ql

The trick with "if(fp != stdout)" is problematic (to analyser) as
technically 'stdout' can be a global pointer that COULD be modified any
time, so it might have changed between the fopen() and fclose() calls so
the close MAY NEVER occurs (which is problem the analyzer can see).

So local state is maintained as a bool which will also clarify to the
compiler see the intention without concern for external stdout
modification.

Some items appear to be out and out leaks when certain commands are use.
2025-02-22 21:02:49 -05:00
Tim Edwards 7960020f7c Updated the HTML documentation on the "wire" command to add the
new syntax implemented earlier today that preserves interactive
wiring moves when logging commands.
2025-02-22 21:00:04 -05:00
Darryl L. Miles 554327f1d3 plowSrShadowXxx() callback plowShowShadow() correct return type
was void, now int.
2025-02-22 20:58:59 -05:00
Darryl L. Miles 97ff043c1a plowInitRule() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 93054eb4e6 plowPropagateRect() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 8ee328811c plowSrShadowInitial() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 86bb97948f plowSrShadowBack() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles cfd71f1b5d plowSrShadow() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles d149c83a8a plowSrOutline() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles cf0f9311ab plowFindWidthBack() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 2ff6d6113d plowFindWidth() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles bc5a4a0fb1 Plow() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 6db34b6aa9 gaMazeRoute() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 97189f6219 irRoute.c: LayerInTouchingContact() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles 90c03738ce ExtPerim.c: extEnumTilePerim() pass by-pointer const TileTypeBitMask* instead of by-value
sizeof(TileTypeBitMask) == 32
2025-02-22 20:58:59 -05:00
Darryl L. Miles e8d7888300 extract.h/EFVisit.h include database.h for TileTypeBitMask
This has a knock on effect of causing EFvisit.c to require database.h
to be defined BEFORE the EFint.h due to an identical copy of ArrayInfo
type being present in both files.

Maybe there should be database_arrayinfo.h ?  To remove the copy.
2025-02-22 20:58:59 -05:00
Tim Edwards 144c22f579 Added the ability to translate pointer-based "wire" commands from
interactive wiring into coordinate-based commands.  Added new
command extensions for "wire leg", "wire vertical", "wire type",
and "wire horizontal".  Modified the command logging such that
"wire show" (which does not modify layout) does not get logged,
which avoids unnecessary logging of mouse movement.
2025-02-22 17:06:06 -05:00
Tim Edwards c4a2a54cb7 Corrected a syntax error in the old (non-Tcl/Tk) grX11su1.c code
that was introduced with a slew of updates back in October, as
noticed and reported (with solution) by J. Schonberg.
2025-02-15 22:20:50 -05:00
Tim Edwards 09ff52cdc0 One additional fix which allows "gds write" to continue after a
cell is found to be missing, if "gds allow undefined" has been
set.
2025-02-15 13:49:14 -05:00
Tim Edwards 41d77558b7 Fixed an error in which using the command option "gds allow undefined"
will cause a segmentation fault.
2025-02-15 13:43:01 -05:00
Tim Edwards df84a36659 Added code to handle the case where GDS_FILE points to a filename
that has since been compressed and given a ".gz" extension.
Removed code that uses a system call to "gunzip" and "gzip" when
the target file is compressed, since the compression is handled
in the code.
2025-02-12 16:28:43 -05:00
Tim Edwards 38b3d53b5f Modified the behavior of "select area subcell" so that it no longer
requires that subcells be unexpanded in order to select them.  This
seems to be more in line with what one would expect from the
documented description of the "select area" command, and more in
line with common-sense expectations.
2025-02-09 14:51:40 -05:00
Tim Edwards cd80d38d52 Fixed a rather long-standing error, which is that when scaling of
"MASK_HINTS" was implemented, it was put into a routine that
scales all coordinate-related properties, including "FIXED_BBOX",
but the original code that scaled only "FIXED_BBOX" was never
removed, resulting in the bounding box getting incorrectly scaled
twice by any grid scaling.
2025-02-09 12:48:22 -05:00
Tim Edwards 619191c6dd Corrected a crash condition caused by yesterday's commit, if the
new CIF operator is used in a tech file.  Reworked yesterday's
commit to add more related operators, so there are now four new
ones (also renamed them):  interacting, noninteracting, overlapping,
and nonoverlapping.  "interacting" now means overlapping or touching;
so the four cases allow all variations of adjacency between the two
material types.
2025-02-05 14:49:32 -05:00
Tim Edwards a5653c8fca Added a new CIF operator "not-interact" which is complementary to
"interact", because it was trivially easy to implement and saves
processing vs. doing the same thing with two templayers and an
"and-not" operator.
2025-02-04 20:43:30 -05:00
Tim Edwards 21b810b375 Added a new CIF operator "interact" which enumerates disjoint
regions of a given type and retains only those regions which
interact with (overlap) another given type.  Both sets of types
can be either magic database types or CIF temp layers.  This will
allow the implementation of rules that were not previously
possible.
2025-02-04 17:21:26 -05:00
Tim Edwards 72368a3d13 Added a fallback method for "extresist" whenever a device terminal
connection to a net that has been decomposed into a resistor array
cannot be found.  This indicates some fundamental error in the way
extresist works.  However, it should not be producing an invalid
and unsimulatable netlist.  Instead, it makes an arbitrary connection
from the device terminal to the resistor array and adds an entry in
the output netlist (.res.ext file).  This results in a poor
representation of the resistor network to that terminal, but an
otherwise simulatable netlist.  A warning is issued to note that an
arbitrary connection has been made.  This is most typically a
"garbage in, garbage out" situation in which insufficient information
exists in a layout to inform magic on which direction current is
traveling through a net.  However, it should be possible to rewrite
the extresist code so that magic makes somewhat informed decisions
about current paths and produces a halfway decent representation of
the actual net, instead of just giving up on the detailed extraction.
2025-01-15 10:38:10 -05:00
Tim Edwards 4445663cb1 Modified a routine to return a valid string when attempting to
generate a name for an instance that is set to NULL.  It is not
clear to me by an instance would have a NULL name, but apparently
it can happen, and should not crash magic.
2025-01-12 17:36:05 -05:00
Tim Edwards 1cec414618 Added the contents of the "readline" module back. This is
generally unused, as it is incompatible with the Tcl/Tk build of
magic.  However, I had not intended to remove it, only move the
name from "readline-4.3" to "readline".  But "readline/readline"
was in .gitignore, which caused the contents to be removed from
the repository.  This commit restores those files, and also
prevents the readline directory Makefile from making a symbolic
link called "readline" to itself, which was causing compile-time
issues.  The readline code is only kept for backwards compatibility
with ancient versions of magic not using the Tcl/Tk interpreter.
2025-01-10 09:58:57 -05:00
Tim Edwards 82a1dc98b4 Updated the version to go along with the merge of pul request 2025-01-10 09:21:28 -05:00
Mamoru TASAKA cb2a79d6b1 gcc: support -Werror=format-security
Support gcc -Werror=format-security which is used by default on Fedora.

ext2spice/ext2spice.c: format not a string literal and no format arguments
extflat/EFargs.c: likewise
windows/windCmdNR.c: likewise
2025-01-10 14:19:52 +09:00
Tim Edwards 2afa222414 Updated the version number to go along with the merge of several
pull requests from Darryl Miles.
2025-01-07 14:02:58 -05:00
Darryl L. Miles f010d4d20b resis.h: create RESTRUE to replace use of TRUE macro ((bool)1)
Looks to be used as integer bitmask which is flagged by compiler warning
as dubious, when using compiler provided type 'bool' from stdbool.h
in C99 instead of unsigned char type.

C29 bool type compatibility
2025-01-07 14:02:07 -05:00
Darryl L. Miles 4887f71ca3 CIFread.h: fix struct cifrstyle.crs_layers type bool -> enum (unsigned char)
The type is actually an enum (assumed to be int by default) but relies
on the magic typedef to (unsigned char) so we make this explicit and
better document what the real type is.

I guess in the past it was really a bool with only 2 states NONE|TEXT.

C29 bool type compatibility
2025-01-07 14:02:07 -05:00
Darryl L. Miles b1a9e10be7 feat: quit [exit_status], option support
Affecting process exit status.
2025-01-07 13:58:45 -05:00
Darryl L. Miles faadb774b4 docs: quit -noprompt
Was looking to implement this feature and found it was already
implemented but is a secret feature.

Updated documentation and modified implementation so it is possible
a user can discover the feature via usage such as "quit -help -invalid"
like other commands.
2025-01-07 13:58:45 -05:00
Darryl L. Miles b694827bcb feat: flush [-noprompt], option support 2025-01-07 13:58:45 -05:00
Darryl L. Miles cfdd50aa63 Revert "commands/CmdFI.c: added CmdFlush_NoConfirm option to disable flush prompt"
This reverts commit 772bfe2f71.

See #341
2025-01-07 13:58:45 -05:00
Darryl L. Miles 3fc1c7e452 gcc11 -Wall -Wpedantic document for the next person 2025-01-06 16:33:22 +00:00
Darryl L. Miles 065f31f689 gcc11 -Wall -Wpedantic cleanup (post __attribute__ DLONG_PREFIX) 2025-01-06 16:27:10 +00:00
Darryl L. Miles 6afadf9809 gcc11 -Wall -Wpedantic cleanup (post __attribute__) 2025-01-06 16:25:38 +00:00
Darryl L. Miles 48c99a7b1d gcc11 -Wall -Wpedantic cleanup (post TCL9) FUN2CD() CD2FUN()
FUN2CD() on a function pointer still raises -Wpedantic warning due to the
officially undefined behaviour as defined by C standards.

So added FUN2CD() and CD2FUN() to at least mark the call-sites to help
with identification and ignoring -Wpedantic based on the source file
context given in the compiler output.
2025-01-06 16:25:15 +00:00
Darryl L. Miles c21e182b2c gcc11 -Wall -Wpedantic cleanup (post TCL9) 2025-01-06 16:24:57 +00:00
Darryl L. Miles aa5ddbaa58 database/database.h.in: const PaintResultType *resultTbl
Probably forgot to edit database.h.in template file (and edited
database.h) when working locally.
2025-01-06 16:24:02 +00:00
Darryl L. Miles 7e9d4cc15e ihash.c: cleanup warning use of void* with pointer arithmetic
Use of (void*) with pointer arithmetic warning removal.

But more so as it is in a macro (all be it local to file) which will
take on the form of the type passed as argument when the 'offset' looks
to be always be specified in bytes.
2025-01-06 16:21:22 +00:00
Darryl L. Miles 60c64db33a extflat: K&R various converted to ANSI (mainly due to bool use) 2025-01-06 16:18:41 +00:00
Darryl L. Miles ff9487de1f hash.c: K&R conversion to ANSI and constify arguments / callback
cb_heap_kill_t callback typedef created

Invoked from HeapKill()

No active callback implementation in the codebase.

callback interface (from hash.h):
  marked @invoke call-site
2025-01-06 16:15:58 +00:00
Darryl L. Miles d9cfd64d60 utils/*.c: K&R conversion to ANSI 2025-01-06 16:14:34 +00:00
Darryl L. Miles 07f9bbe1fb gcc11 -Wall -Wpedantic cleanup 2025-01-06 16:12:11 +00:00
Tim Edwards 3df2aaaa16 Modified the code in ext2spice.c that prints parameter values;
the former code attempted to determine the precision and generate
an output without unnecessary trailing zeros.  Unfortunately there
were counterexamples that fail to be formatted correctly, as found
by Mark Martin, and which generate output that has roundoff error.
Reimplemented the method using code found on StackOverflow, which
appears to solve the problem more robustly.
2025-01-06 11:49:29 -05:00
Tim Edwards 32138ccbc7 Modified some lines in tkcon.tcl that make it compatible with both
Tcl 8.6 and Tcl 9.0, fixing some features that got broken with an
attempt to update the script for version 9.0.
2025-01-04 14:09:58 -05:00
Tim Edwards e334fb919f Updating the revision number to go along with the merging of a
series of pull requests from Darryl Miles.
2025-01-04 11:45:11 -05:00
Darryl L. Miles af5b7f10cf lef/defWrite.c: reworked kareefardi_fix-def-write 2025-01-04 11:42:07 -05:00
Kareem Farid a6aac9c309 fix infinite def write
Signed-off-by: Kareem Farid <kareefardi@users.noreply.github.com>
2025-01-04 11:42:07 -05:00
Darryl L. Miles efcf36f348 Remove superfluous parenthesis around regular type declarations 2025-01-04 11:31:17 -05:00
Darryl L. Miles 1241e95dab debug/debug.c: constify and add prototype 2025-01-04 11:31:17 -05:00
Darryl L. Miles 195dda1e06 debug/hist.c: constify and add prototype 2025-01-04 11:31:17 -05:00
Darryl L. Miles eb89ab181c debug: use 'const' with 'rcsid' 2025-01-04 11:31:17 -05:00
Darryl L. Miles 0376430702 command: use 'const' with readonly data
This then required a cascade of function APIs to also now receive
const arguments.

This reduces the .data segment use of this module.
2025-01-04 11:31:17 -05:00
Darryl L. Miles 5c410e9dcb command: use 'const' with 'rcsid' 2025-01-04 11:31:17 -05:00
Darryl L. Miles 6b4d409d74 cmwind: use 'const' with readonly data
This then required a cascade of function APIs to also now receive
const arguments.

This reduces the .data segment use of this module.
2025-01-04 11:31:17 -05:00
Darryl L. Miles 34038ee687 cmwind: use 'const' with 'rcsid' 2025-01-04 11:31:17 -05:00
Darryl L. Miles ac56dd71a9 cif: use 'const' with readonly data (also consumer DBpaint)
This then required a cascade of function APIs to also now receive
const arguments.

This reduces the .data segment use of this module.
2025-01-04 11:31:17 -05:00
Darryl L. Miles 4e768d5a3d CIFrdpoly.c: qsort 'compar' function argument prototype fix
This makes it strictly conform to function pointer prototype.
2025-01-04 11:31:17 -05:00
Darryl L. Miles b6775f902b cif: use 'const' with 'rcsid' 2025-01-04 11:31:17 -05:00
Darryl L. Miles a616dbc113 calma: use 'const' with 'rcsid' 2025-01-04 11:31:17 -05:00
Darryl L. Miles 4cd1235575 calma: use 'const' with readonly data
This then required a cascade of function APIs to also now receive
const arguments.

This reduces the .data segment use of this module.
2025-01-04 11:31:17 -05:00
Darryl L. Miles 378755e083 CalmaRdpt.c: simplfy use of sprintf()
This replacement pattern is easier to reason about and less error prone.
2025-01-04 11:31:17 -05:00
Darryl L. Miles 46eb71491c GHA: MacOS maintenance update
GHA obsoleted macos-12 so we move to macos-13 for Intel.  Building with oldest
Intel image to provide feedback of continued expected support on that platform,
while ARM64 builds with latest to check the other end of their SDKs.

Lock the TCL version via brew to 8.6+ (currently the project is not expected to
build on TCL9 until other work is completed) so this is causing build failure.

Added additional diagnostics to show the location of executables/DSOs if they
got built from the tree.

Introduced GHA timeout clamping (MacOS default shell seems not to behave under
CI as well as Linux does, re signal/pipe handling)

'brew install tcl-tk@8' appears to append the @8 to the installed path such as
/usr/local/opt/tcl-tk@8 which configure needs to know.  configure_mac updated
to detect this now TCL9 is the default version that maybe installed at the old
location.  Then there is the issue of both TCL versions being installed
side-by-side on the same system causing more issues over selection.
2025-01-04 11:23:39 -05:00
Darryl L. Miles 3f85689985 cif/CIFgen.c: fix incorrect type bool -> int
There are 3 states for CLOSE_xxxxxx with 3 different values.

Issue introduced from 2f7f76bf9 merged since tag:8.3.509

This affected the scenarios using non-zero non-one values such as:
  #define CLOSE_DONE   2

This looks the result of an original bug where the forward declaration
 had a type mismatch with the real method, so the method implementation
 prototype was taken as the correct one.  The forward decl was rewritten
 with the correct prototype signature.
Maybe this is the cause of CIF data once drawn into view does not always
 seem to always erase after disabling and a redraw ?
2025-01-04 11:20:08 -05:00
Darryl L. Miles 76a515ca25 HACK tkcon.tcl to get it running 2025-01-04 11:08:01 -05:00
Darryl L. Miles c2a5a84a03 Revert "TCL9: *.tcl changes $::tcl_platform"
This reverts commit 8adbd75760aeeb4f39507dcd3e746287381b7b38.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 7e5d0b0688 TCL9: FIXME OPTIONAL magic.h ClientData
This did not work as expected.  Maybe that indicate this should have
a slighlt restructure so the tcl.h definition is always given a chance
to provide type.

Or maybe autoconf should detect the type and provide in config.h ?
2025-01-04 11:08:01 -05:00
Darryl L. Miles 3931c4aff1 TCL9: *.tcl changes $::tcl_platform 2025-01-04 11:08:01 -05:00
Darryl L. Miles 272dda3c84 TCL9: TxResetTerminal(bool force) added arguments
This seems like it has 2 use cases.

Internal console management around reprinting command prompt, but many
 modes of operation delegate the prompt processing to tkcon or readline.
Process termination to restore the termios.
2025-01-04 11:08:01 -05:00
Darryl L. Miles c339e9b845 TCL9: CmdLQ.c Tcl_AppendResult(... (char*)NULL) cast sentinal
In the TCL8 to TCL9 porting information it was indicated the
sentinal NULL termination should be cast (char *) with API
call Tcl_AppendResult().

This was already in place for most of the codebase this
resolves the last few places.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 4a32a82841 TCL9: Tcl_GetIntFromObj() call checked
This API uses address of operator to Tcl API with (int) type, but
does not use Tcl_Size in TCL9, it remained an (int) type.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 661b66a143 TCL9: Tcl_InitStubs(version="9.0") 2025-01-04 11:08:01 -05:00
Darryl L. Miles 77a7afc8e2 TCL9: Tcl_SetExitProc() API was removed
The Tcl_Exit() replacement proc takes charge of calling exit()

So this function can be easily migrated to libc atexit() which will
now run during exit() not just before.  Which seems ok for the purpose
of restoring the termios state of the tty.

This solution seems compatible with TCL8 as well so all calls to this
removed API are removed.

Note this patch also removes the invalidation (of the callback so
the deefault use of Tcl_Exit() is restored) before returning from
this function.  atexit() usage can not be invalidated after
registration but that can be controlled with application flag
checked inside the callback function if needed.
I have observed scenarios where I need to issue 'reset' manually
after exiting magic, still understanding better the build types
and scenarios that triggers this.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 0ce8265570 TCL9: ClientData macro assignment and access usage 2025-01-04 11:08:01 -05:00
Darryl L. Miles 79f2ab0f4b TCL9: ClientData macro header file changes
Header files documentation indicates the macros are of type ClientData
but previously did not cast to ensure that. So now follow this intention.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 17fe81107a TCL9: plugin createProc() function signature change ImgLayerCreate()
Tk_ImageType.createProc() uses new Tcl_Size type now.
2025-01-04 11:08:01 -05:00
Darryl L. Miles db7a1fe20a TCL9: Tk_ConfigureWidget() function signature change 2025-01-04 11:08:01 -05:00
Darryl L. Miles e81ead5ad2 TCL9: Tcl_Size type introduction 2025-01-04 11:08:01 -05:00
Darryl L. Miles 33b9c63c41 TCL9: Tcl_xxxxxxx() API changes around Tcl_SaveResult() 2025-01-04 11:08:01 -05:00
Darryl L. Miles e27b8a9d19 TCL9: CONST84 removal (all current compilers support const keyword)
Legacy compiler support macro provided by TCL from a time when 'const'
did not exist.

This looks like it was put in place around the time of TCL 8.4
(from 2002 until 2013) which introduced APIs with 'const' types,
that were previously non-const.  Probably due to legacy compiler
support across target platforms at the time.

Since the minimum TCL level is hardwired to 8.5 (from 2007 until
2016) it does not seem like that compatiblity is a current
requirement.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 2066077c4e TCL9: CONST removal (all current compilers support const keyword)
Legacy compiler support macro provided by TCL from a time when 'const'
did not exist.
2025-01-04 11:08:01 -05:00
Darryl L. Miles d999e20b73 TCL9: Tk_Offset() macro removal
Modern compiler have support for 'offsetof' keyword.
2025-01-04 11:08:01 -05:00
Darryl L. Miles 60463e31be TCL9: _ANSI_ARGS_ compatibility macro removal 2025-01-04 11:08:01 -05:00
Darryl L. Miles 93c16c8431 TCL9: magic.h ClientData type change helper macros
Now a (void *) but previously an integer.

These macros resolve the codebase allowing it to be built against both
tcl8 (8.5, 8.6) and tcl9 (9.0).

tar -zxvf tcl9.0.0-src.tar.gz
cd tcl9.0.0/unix
./configure --enable-symbols --prefix=/opt/tktcl9
make install

tar -zxvf tk9.0.0-src.tar.gz
cd tk9.0.0/unix
./configure --enable-symbols --prefix=/opt/tktcl9 --with-tcl=/opt/tktcl9/lib
make install

cd magic
./configure --with-tk=/opt/tktcl9/lib --with-tcl=/opt/tktcl9/lib
2025-01-04 11:08:01 -05:00
Darryl Miles a756fe08bd ext2spice.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles 6520aa19a3 extflat.h: efReadError() printf ATTR_FORMAT_PRINTF_1 2025-01-03 09:08:14 +00:00
Darryl Miles 2bac418b44 EFerr.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles 8c28342322 ext2hier.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles 6d0dca2551 ext2sim.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles fd5511d622 DRCtech.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles c4373d74aa LIBtextio.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles ff73a1328f txOutput.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl Miles 0259fdc990 tclmagic.c: printf style constify fmt call-site 2025-01-03 09:08:14 +00:00
Darryl L. Miles 5770da2abd geometry.c: TxError() constify call-site 2025-01-03 09:08:14 +00:00
Darryl Miles 1aee10ef4d utils/magic.h: ANALYSER_xxxxxxxxxx __attribute__ 2025-01-03 09:08:14 +00:00
Darryl Miles 2fcd024bdb utils/magic.h: ATTR_SENTINEL __attribute__ ((sentinel)) 2025-01-03 09:08:14 +00:00
Darryl L. Miles 91bb9935f9 grOGL1.c: use ATTR_UNREACHABLE to help analyser 2025-01-03 09:08:14 +00:00
Darryl L. Miles c8974ed2ec utils/main.h: MainExit() add ATTR_NORETURN hint 2025-01-03 09:08:14 +00:00
Darryl L. Miles 31d7130833 utils/magic.h: ATTR_UNREACHABLE ATTR_NORETURN
Add optional compiler support for these attribute hints.
2025-01-03 09:08:14 +00:00
Darryl L. Miles fc02f57d73 magic.h: add macro __unused__
__attribute__((unused))

use like:

void myFunc(int arg0, __unused__(arg1)) { ... }
2025-01-03 09:08:14 +00:00
Darryl Miles bf96348502 printf: vararg functions use 'const' for format string 2025-01-03 09:08:14 +00:00
Darryl Miles 94ec5cf98f printf: use compiler __attribute__((format (printf,fff,aaa))) 2025-01-03 09:08:14 +00:00
Tim Edwards f80540af46 Applied patch from Darryl Miles that prevents a segfault on an
error in "extresist".  The underlying error still exists and
causes a "Bad Device" error but no longer crashes magic.  See
github Issue #353.
2024-12-26 16:39:23 -05:00
Tim Edwards df19d62f51 Corrected code in DBtpaint2.c handling the setup of paint/erase
tables for contacts, where an error was pointed out by Darryl
Miles (github issue #339).
2024-12-26 16:28:43 -05:00
Tim Edwards 8371d797ad Revised some code from PR#352 in response to questions from Darryl
Miles.  Updated the version number to go along with the merge of
a number of pull requests done today.
2024-12-26 15:29:54 -05:00
Darryl L. Miles 55d15ffaa5 extflat/EFdef.c: hash constify freeMalloc() constness cast
This is a result of hash.[ch] constification
2024-12-26 15:20:59 -05:00
Darryl L. Miles a11352970f dbwind/DBWelement.c: constify args to AppendFlag/AppendString
non-static file local functions
2024-12-26 15:20:59 -05:00
Darryl L. Miles bbc52ecd41 util/hash.c: fix use after free (not quite)
Dereference of 'h' after calling freeMagic(h)
Found while putting in cast.

Initially this is what was thought however....

freeMagic() has this one allocation to free latency, which is a matter
to resolve another day.
2024-12-26 15:20:58 -05:00
Darryl L. Miles fadd2d98b4 irouter/irCommand.c: fix SetNoisyDI() usage
WARNING 64bit to 32bit truncation

Was directly overwriting a 32bit storage location with a 64bit value.
2024-12-26 15:20:58 -05:00
Darryl L. Miles fd5050b2b5 util/lookup*.c: fix integer pointer arithmetic not using pointertype
This would be a bug on WIN64 and other LLP64 models.
2024-12-26 15:20:58 -05:00
Darryl L. Miles f22ecda44a set.c: SetNoisyBool() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 2b69b07860 set.c: SetNoisyDI() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles f51ad56aea set.c: SetNoisyInt() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 5b97638ac7 port.c: MagAtof() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 14a8409e40 utils.h: Wait()/WaitPid() add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles bd51438c15 database/DBio.c: PaExpand() constify update call-site 2024-12-26 15:20:58 -05:00
Darryl L. Miles 265ace5c9f path.c: PaEnum() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 6bccbef0d4 path.c: PaSubsWD() constify and no prototype exists
This function does not appear used across the codebase.
No prototype exists in utils.h
2024-12-26 15:20:58 -05:00
Darryl L. Miles c77d3852d5 path.c: PaOpen() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles fd7eab2193 path.c: PaZOpen() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles d077368436 path.c: PaLockOpen() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 875d825afb path.c: PaLockZOpen() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles bfb411d19f path.c: nextName() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles feef9730f3 path.c: PaExpand() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 6a6f85862e path.c: PaAppend() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles fca164715e PaCheckCompressed() constify implementation 2024-12-26 15:20:58 -05:00
Darryl L. Miles e22e5d63b9 PaCheckCompressed() removed API quirkiness
When constifying there is this inconsistent quirk in this API returning
'filename' or a malloced storage.  When special handling needs to be
made by the caller to detect this to decide if it needs a free.

This appears to done to save a strdup().

Make it always return a malloc block so the API contract is
strightforward to the caller.  A non-NULL return requires
free() by the caller.
2024-12-26 15:20:58 -05:00
Darryl L. Miles e7bfa72298 args.c: ArgStr() constify and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles 2ba1d20ab4 utils/match.c constify Match() and add prototype 2024-12-26 15:20:58 -05:00
Darryl L. Miles b8dae95515 Lookup() constify call-site
extflat/EFantenna.c: Lookup() constify call-site
drc/DRCtech.c: Lookup() constify call-site
dbwind/DBWelement.c: Lookup() constify call-site
database/DBtpaint.c: Lookup() constify call-site
commands/CmdTZ.c: Lookup() constify call-site
commands/CmdRS.c: Lookup() constify call-site
commands/CmdLQ.c: Lookup() constify call-site
commands/CmdFI.c: Lookup() constify call-site
commands/CmdE.c: Lookup() constify call-site
commands/CmdCD.c: Lookup() constify call-site
commands/CmdAB.c: Lookup() constify call-site
cmwind/CMWcmmnds.c: Lookup() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles 6851f27284 extract/ExtBasic.c: Lookup() constify call-site 2024-12-26 15:20:58 -05:00
Darryl L. Miles 3dbcb0759e Lookup() constify call-site
plow/PlowCmd.c: Lookup() constify call-site
plot/plotVers.c: Lookup() constify call-site
plot/plotMain.c: Lookup() constify call-site
plot/plotCmd.c: Lookup() constify call-site
netmenu/NMnetlist.c: Lookup() constify call-site
netmenu/NMcmdLZ.c: Lookup() constify call-site
netmenu/NMcmdAK.c: Lookup() constify call-site
lef/lefTech.c: Lookup() constify call-site
lef/lefCmd.c: Lookup() constify call-site
irouter/irRoute.c: Lookup() constify call-site
irouter/irCommand.c: Lookup() constify call-site
router/rtrCmd.c: Lookup() constify call-site
resis/ResRex.c: Lookup() constify call-site
gcr/gcrShwFlgs.c: Lookup() constify call-site
windows/windCmdSZ.c: Lookup() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles c2d533af3b windows/windCmdNR.c: Lookup() constify call-site (extern data) 2024-12-26 15:20:58 -05:00
Darryl L. Miles 586e9f1e36 Lookup() constify WindGetCommandTable() returns 'const'
This commit related to the dynamic creation of data that is used
to parse commands and options via Lookup.

windows/windows.h: Lookup() constify call-site
tcltk/tclmagic.c: Lookup() constify call-site
graphics/W3Dmain.c: Lookup() constify call-site
windows/windSend.c: Lookup() constify call-site
windows/windMain.c: Lookup() constify call-site
windows/windInt.h: Lookup() constify call-site
textio/txMain.c: Lookup() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles 882d82a8ae Lookup() constify call-site with Tcl_SetResult()
ext2spice/ext2spice.c: Lookup() constify call-site
ext2sim/ext2sim.c: Lookup() constify call-site
windows/windCmdAM.c: Lookup() constify call-site

Tcl_SetResult() uses cast to remove 'const' from type, the pointer
is only used to take a copy of the data, the lack of 'const' is due
to Tcl heritage when supporting C89 era compilers.

TCL9 appears to fix this, in that the macro used ends up at
Tcl_NewStringObj() which has 'const' here.
2024-12-26 15:20:58 -05:00
Darryl L. Miles a3dce62887 LookupFull() constify call-site
lef/lefRead.c LookupFull() constify call-site
lef/defRead.c LookupFull() constify call-site
graphics/grDStyle.c: LookupFull() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles 14b6453707 LookupStruct() constify call-site
irouter/irTestCmd.c: LookupStruct() constify call-site
irouter/irCommand.c: LookupStruct() constify call-site
mzrouter/mzTestCmd.c: LookupStruct() constify call-site
mzrouter/mzTech.c: LookupStruct() constify call-site
router/rtrCmd.c: LookupStruct() constify call-site
plow/PlowTest.c: LookupStruct() constify call-site
plow/PlowTech.c: LookupStruct() constify call-site
plot/plotVers.c: LookupStruct() constify call-site
grouter/grouteTest.c: LookupStruct() constify call-site
garouter/gaTest.c: LookupStruct() constify call-site
extract/ExtTest.c: LookupStruct() constify call-site
extract/ExtTech.c: LookupStruct() constify call-site
extflat/EFread.c: LookupStruct() constify call-site
DRCtech.c: LookupStruct() constify call-site
debugFlags.c: LookupStruct() constify call-site
CmdSubrs.c: LookupStruct() constify call-site
geometry.c: LookupStruct() constify call-site
set.c: LookupStruct() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles fb8f7b94aa LookupStructFull() constify call-site
txInput.c: LookupStructFull() constify call-site
DBlabel.c: LookupStructFull() constify call-site
2024-12-26 15:20:58 -05:00
Darryl L. Miles f5b41a06d6 utils/lookup*.c: constify the API
extern int Lookup(const char *str, const char * const *table);
extern int LookupAny(char, const char * const *);
extern int LookupFull(const char *, const char **);
extern int LookupStruct(const char *str, const LookupTable *table_start, int size);
extern int LookupStructFull(const char *str, const char * const *table, int size);
2024-12-26 15:20:58 -05:00
Darryl L. Miles aa43cc164e geometry.h: constify global wellknown Geometry data values
This then rippled through into callers

Fixed merge conflicts in cif/CIFrdutils.c and cif/CIFread.h
2024-12-26 15:20:39 -05:00
Darryl L. Miles a224c7e21a GeoDisjoint() unify return type of callback to bool
GeoDisjoint() handles this as 'bool' type internally so make all
consumer call-sites consistent with this type.
2024-12-26 15:10:35 -05:00
Darryl L. Miles fd6c30a380 geometry.c: constify and add prototypes 2024-12-26 15:10:35 -05:00
Darryl L. Miles efb5d9001c util/hash.[ch]: const hash 'key' for API and internal type
This is mainly to modify the function signature to accept const
data pointers to keys.

Patch required to ease use of const by API consumers.
2024-12-26 15:10:35 -05:00
Darryl L. Miles 91da638579 utils/strdup.c: StrDup() and mode constifiy impl 2024-12-26 15:10:35 -05:00
Darryl L. Miles 77f04b4e80 K&R debug.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:15:29 -05:00
Darryl L. Miles c7f99e076e DBcount.c: DBTreeCountPaint() unify return type of hiercount() callback
The call-site does not expect a return value.
The use case in command/Cmdwizard.c is written to be void.

So a resolution was needed.
2024-12-26 13:13:14 -05:00
Darryl L. Miles bd03a550d3 CmdCD.c: DBOrientUse() called with too many arguments.
Comment added to come back to later.

DBOrientUse(cellname, dodef/*, orient*/);
2024-12-26 13:13:13 -05:00
Darryl L. Miles f08793ddd7 CmdTZ.c: use strict prototype for qsort() compar callback function 2024-12-26 13:13:13 -05:00
Darryl L. Miles 2123f7090d CmdCD.c: removed unnecessary fwd decl for function in included header
commands.h contains the prototype for cmdFlushCell() which is already
being included in CmdCD.c
2024-12-26 13:13:13 -05:00
Darryl L. Miles 7ebaba6b39 DBcount.c: clarify function documentation of hiercount() callback
DBTreeCountPaint(def, count, hiercount, cleanup, cdata)
 callback hiercount()

The K&R function prototype syntax in the documentation might confuse
reader into which argument order is correct (as a modern developer
might be out of practice with interpreting K&R syntax)
2024-12-26 13:13:13 -05:00
Darryl L. Miles 3a41bf6ae2 DBWprocs.c: removed fwd decl for non-existant function
void DisplayWindow();

Found during K&R removal of commands/**
2024-12-26 13:13:13 -05:00
Darryl L. Miles 56139b48eb K&R commands/*.c: bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles afd1b0b2df K&R commands: 2 x missing forward declaration removal
Functions do not appear to exist:
 extern void DisplayWindow();
 extern void DisplayWindow();

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles b3d4ab7980 K&R commands/*.c: bulk function implementation conversion
Argument order and type declaration mismatches:

Label *
portFindLabel(editDef, port, unique, nonEdit)
    CellDef *editDef;
    bool unique;
    bool port;         // If TRUE, only look for labels that are ports
    bool *nonEdit;     // TRUE if label is not in the edit cell

This warrants inspection at call site CmdLQ.c:1712 as both types are bool
is it not so straightforward to check.

It looks like when PORT_MAKE is the option 'port make [index] [dir...]'
  port=FALSE is this the correct intention ?  This looks ok in that
 we're searching for labels to make (upgrade) into ports.
Where as all other 'port ....' commands are operating on items that are
 already ports, and ignoring labels.
So the K&R argument name order is also how the call-sites are using it.

void
cmdStatsHier(parent, nuses, child)
    CellDef *parent, *child;
    int nuses;

This was checked and found ok as callback to ../database/DBcount.c
DBTreeCountPaint(... hiercount, ...)

Due to this not-obvious K&R style also being used in the documentation
this was changed as well (in another commit0.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles 8a4464f443 commands.h: add #include "textio/txcommands.h"
The type TxCommand is used in the function signatures.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles 06b5870035 K&R commands.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles 866699f353 K&R commands.h: 3 x missing prototype removal
Functions do not appear to exist:
 extern MagWindow *CmdGetRootBox();
 extern void CmdAddSlop();
 extern void CmdDoMacro();

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:13:13 -05:00
Darryl L. Miles 7a7d1ab25b K&R cmwind/*.c: bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:07:52 -05:00
Darryl L. Miles 2a4c66e222 K&R CMWundo.c: move typedef to before forward declaration usage
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:07:52 -05:00
Darryl L. Miles 0e715ce98e K&R: cmwind/*.c bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:07:52 -05:00
Darryl L. Miles b716aaa59d K&R: cmwind.h conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:07:52 -05:00
Darryl L. Miles 83f7a71ff3 GHA: canary-matrix.yml 2024-12-26 13:06:26 -05:00
Darryl L. Miles 102f7ad3f2 CIFrdcl.c: bool to int filetype
This direction was chosen due to #define integer use of special values
instead of TRUE/FALSE.  This makes the prototype and use consistent
removing compiler warning from recent K&R removal.
2024-12-26 13:05:14 -05:00
Darryl L. Miles 2f7f76bf9c K&R: cif/*.c bulk function implementation conversion
Beware of the MISMATCH with the prototype found in original
source, with the type declaration below.

External call sites checked to confirm argument order is
correct with the argument name order.

// nedges <> dir
bool
cifOrient(edges, nedges, dir)
    CIFPath *edges[],          /* Array of edges to be categorized. */
    int dir[],                 /* Array to hold directions. */
    int nedges)                        /* Size of arrays. */

// spacing <> border
int
CIFGetContactSize(type, edge, spacing, border)
    TileType type,
    int *edge,
    int *border,
    int *spacing)

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles ff412b74d8 K&R graphics/W3Dmain.c: too few args in CIFNameToMask()
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles f92d9d469f K&R: cif/*.h move function prototypes to the correct file
The data types CIFPath and CIFReadStyle are part of CIFread.h
and all users outside include CIFread.h already.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles 4e83c7fcdd CIFgen.c:309:10: warning: prototype for ‘SetMinBoxGrid’ follows non-prototype definition
This reference is not a forward reference, the function implementation
for SetMinBoxGrid() is above this line being removed.
2024-12-26 13:05:14 -05:00
Darryl L. Miles bf45f9ea31 K&R: cif/*.c bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles 89ed5d735c K&R: CIFread.h conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles ca2d6d40dd K&R: CIFint.h conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles b8c3060f3b K&R: cif.h conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles a1ae272dc5 K&R: prototype for non-existent function: CIFGetDefaultContactSize()
Remove prototype from header file to correct error.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 13:05:14 -05:00
Darryl L. Miles 114ddf1b0c grX11su1.c: GrX11IconUpdate() potential -1 out-of-bound access
SonarCloud
Access of 'char' element in the region at index -1
https://sonarcloud.io/project/issues?open=AZJB163RNGfDNup0Ri4r&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 3a35d4d28d grTOGL1.c: GrTOGLIconUpdate() potential -1 out-of-bound access
SonarCloud
Access of 'char' element in the region at index -1
This was not picked up, even though similar code was.
2024-12-26 13:01:24 -05:00
Darryl L. Miles 89fa935416 grTk1.c: GrTkIconUpdate() potential -1 out-of-bound access
SonarCloud
Access of 'char' element in the region at index -1
This was not picked up, even though similar code was.
2024-12-26 13:01:24 -05:00
Darryl L. Miles ef7f989da6 grTCairo1.c: GrTCairoIconUpdate() potential -1 out-of-bound access
SonarCloud
Access of 'char' element in the region at index -1
This was not picked up, even though similar code was.
2024-12-26 13:01:24 -05:00
Darryl L. Miles ee9d4df081 lefRead.c: LefError() add ASSERT(type) for incorrect caller usage
'type' maybe used as array index without being initialized.

Sonarcloud
Array subscript is undefined
https://sonarcloud.io/project/issues?open=AZJB17LDNGfDNup0Rjyn&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 86b5d591d6 grOGL3.c: add GrOGLTextSize() error return
'textrect' is not filled in when GrOGLTextSize() fails.

Add error return and abort groglPutText() easrly on error.

graphics/grOGL3.c:783 Rect textrect;

SonarCloud
The right operand of '+' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB160qNGfDNup0Riv5&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 56317e6583 grOGL3.c: font, The left operand of '==' is a garbage value
SonarCloud
The left operand of '==' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB160qNGfDNup0Riv4&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 55413d6b3a grOGL1.c: GrOGLIconUpdate() potential -1 out-of-bound access
SonarCloud
Access of 'char' element in the region at index -1
https://sonarcloud.io/project/issues?open=AZJB16z6NGfDNup0Rist&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles da80d5c75d grOGL1.c: pipehandler() XEvent processing NULL deref
SonarCloud
Access to field 'w_flags' results in a dereference of a null pointer (loaded from variable 'mw')
https://sonarcloud.io/project/issues?open=AZJB16z6NGfDNup0Risq&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 26d6af464a grDStyle.c: newres, Branch condition evaluates to a garbage value
'newres' initialization is performed the wrong side of the label
to be effective to the code that uses it.

SonarCloud
Branch condition evaluates to a garbage value
https://sonarcloud.io/project/issues?open=AZJB16zUNGfDNup0RiqG&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 60f308826d grDStyle.c: GrLoadStyles() scount, The left operand of '<' is a garbage value
The use of 'scount' in this function looks complex, it seems to be reset to
zero sometimes and incremented at others.  Analysis shows there is a possible
path where is maybe used uninitialized.

Setting to zero seems like a good choice.

SonarCloud
grDStyle.c:514 The left operand of '<' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB16zUNGfDNup0RiqE&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles bbe447423b gaStem.c: type, The left operand of '==' is a garbage value
Theoretical use of unintialized data.

Added 'default' case into switch to throw ASSERT(), otherwise
when assertions disabled treat consistently as GEO_NORTH.

SonarCloud
The left operand of '==' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB17fSNGfDNup0Rkoh&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 1e916ee361 ExtBasic.c: oppdir, The right operand of '==' is a garbage value
BD_xxxxx are a bitmask.  So it makes sense due to equality check to
set to zero so it becomes a no-op situation.

I assume lb->dir not matching one of the 4 BD_xxxxx labels would be
a data error anyway and should never occur.

SonarCloud
The right operand of '==' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB16p0NGfDNup0RiW9&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 6eff1c2132 extflat/EFname.c: EFHNBest() add argument ASSERT to convey intention
Adding ASSERT() to arguments to ensure passed arguments are non-NULL
better conveys API intent to both mitigate this false positive
but also allow analysis to inspect caller for correct usage.

SonarCloud
Null pointer passed as 1st argument to string length function
https://sonarcloud.io/project/issues?open=AZJB167jNGfDNup0RjGw&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 6a513d01a1 EFname.c: potential dereference of a null pointer
Theoretical NULL pointer deref, assumes no iteration occurs.
Seems like false positive from incorrect caller use, from
passing suffix==NULL.

SonarCloud
Access to field 'hn_parent' results in a dereference of a null pointer (loaded from variable 'prev')
https://sonarcloud.io/project/issues?open=AZJB167jNGfDNup0RjGu&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles db85521449 EFbuild.c:1330 ASSERT(nn) added
ASSERT(nn) added to indicate programming intention.

SonarCloud
Access to field 'efnn_node' results in a dereference of a null pointer (loaded from variable 'nn')
https://sonarcloud.io/project/issues?open=AZJB168PNGfDNup0RjKF&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles fcb8bf57c6 ext2spice.c: pname used before initialization
In order for pname to be assigned a value the loop must have performed
an interation.  The order of assignment and use of 'pname' is not the
natural order you'd expect.  It also looks like the TxPrint message
may display the incorrect port name from the previous loop iteration.

The code block looks like the resolution of 'pname' has no side-effects.
So should be done first so the correct port name is output in the log message.

SonarCloud
2nd function call argument is an uninitialized value
https://sonarcloud.io/project/issues?open=AZJB17lqNGfDNup0Rk6f&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles 97913ab08c calma/CalmaWrite.c: calmaProcessBoundaryZ() Dereference of null pointer
Theoretical NULL pointer deref.  Seems like false positive as a
BOUNDARY record does not make sense with no points.

This guards against a potential crash from a bad data model.

SonarCloud
Dereference of null pointer
https://sonarcloud.io/project/issues?open=AZJB17hwNGfDNup0Rkub&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles dd6bb9baf4 calma/CalmaWrite.c: calmaProcessBoundary() Dereference of null pointer
Theoretical NULL pointer deref.  Seems like false positive as a
BOUNDARY record does not make sense with no points.

This guards against a potential crash from a bad data model.

SonarCloud
Dereference of null pointer
https://sonarcloud.io/project/issues?open=AZJB17hXNGfDNup0Rktk&id=dlmiles_magic
2024-12-26 13:01:24 -05:00
Darryl L. Miles a3a40bee73 main-macos.yml add Prepare archive and Upload archive steps 2024-12-26 12:52:26 -05:00
Darryl L. Miles ecba1b38d2 main-macos.yml add Summary step 2024-12-26 12:52:26 -05:00
Darryl L. Miles fa07bd0067 main-macos.yml log output extract CONFIGURE_ARGS 2024-12-26 12:52:25 -05:00
Darryl L. Miles be2f8f9a19 main-macos.yml install libglu freeglut on x86_64 2024-12-26 12:52:25 -05:00
Darryl L. Miles f1acfee34a MacOSX diagnostics Search 2024-12-26 12:52:25 -05:00
Darryl L. Miles 90b61caff0 GHA: main.yml move MacOSX to its own workflow 2024-12-26 12:52:25 -05:00
Darryl L. Miles e54111cf6f configure.in: X11 detection and option order
The -L option needs to be placed before the -l it needs to affect.
This maybe important on MacOSX where a nonstandard/optional package
provides X11 support so the locations are not in system locations.
2024-12-26 12:52:25 -05:00
Darryl L. Miles 3f1344570c MacOSX diagnostics Kick The Tyres 2024-12-26 12:52:25 -05:00
Darryl L. Miles dc79b14739 scripts/configure_mac --x-includes=... --x-libraries=... 2024-12-26 12:52:25 -05:00
Darryl L. Miles bfc82e43db MacOS: FREAD rename to magicFREAD due to sys/fcntl.h definition
Example build issue using MacOS 12 (Xcode 14.2 from MacOSX.platform).

In file included from grTk1.c:23:
In file included from ../utils/main.h:26:
In file included from ../windows/windows.h:26:
../utils/magic.h:143:13: warning: 'FREAD' macro redefined [-Wmacro-redefined]
    #define FREAD(a,b,c,d)    gzread(d,a,b*c)
            ^
/Applications/Xcode_14.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/fcntl.h:110:9: note: previous definition is here
 #define FREAD           0x00000001
2024-12-26 12:52:25 -05:00
Darryl L. Miles 48f8707753 GHA: main-macos.yml 2024-12-26 12:52:25 -05:00
Carsten Wulff 772bfe2f71 commands/CmdFI.c: added CmdFlush_NoConfirm option to disable flush prompt 2024-12-26 12:49:33 -05:00
Darryl L. Miles d79533a255 K&R calma: move internal prototypes and typedef to calmaInt.h
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles d92e2b70b6 K&R CalmaWrite.c: move typedef to before forward declaration usage
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 5f55ab825a K&R CalmaWriteZ.c: move typedef to before forward declaration
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 979c810c38 K&R calma: missing HAVE_ZLIB ifdef around function using type gzFile
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 603ce8b887 K&R CalmaRead.c: too many args for calmaLookCell()
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles a9ea08a597 K&R calma/*.c: bulk function implementation conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles f3ace65a78 K&R calma/*.c: bulk forward reference function prototype conversion
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 7696f673df configure: autoconf regen (2.69) to add HAVE_SYS_TIME_H 2024-12-26 12:44:50 -05:00
Darryl L. Miles cd63fa3c14 K&R calma: remove system header time() K&R style prototype
time.h has existed since C89 so is a standard header expected
to always be available.

sys/time.h was an optional header that historically only some
platforms provided.

If there is a conflict on specific platforms it is better to
'#if !defined()' that specific niche platform with the problem
if both headers are included in the same compile unit.  But I
don't think this is a problem in modern times.

So this results in a resolution that removes #ifdef around
time.h and the detection by configure for the availabiltiy
of sys/time.h.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 3f4eb4120e K&R calma: prototype for non-existent function: calmaMergeBoundaries()
Remove forward declaration prototype to correct error.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles f0b6231017 K&R calma: prototype for non-existent function: calmaWriteMarkFunc()
Remove forward declaration prototype to correct error.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 1fdd8bc185 K&R calmaInt.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 40b317979d K&R calma.h: conversion to ANSI
K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Darryl L. Miles 5ee3b180d3 K&R calma: missing prototype: calmaWriteContacts()
Rename existing prototype method name to correct error.

K&R obsolete syntax removal for C23 compatibility series
2024-12-26 12:44:50 -05:00
Tim Edwards 48abe30ea4 Implemented a new CIF/GDS generation operator option for
"bloat-all" which is "bloat-all types1 types2 distance" where the
"distance" value is a maximum amount to grow.  It is not (that I
know of) particularly useful for generating output GDS, but it is
very useful for generating temporary layers for DRC checks,
especially things like determining tap distance for latch-up
rules.  The alternative (used in the sky130 tech file) is a
tedious step-by-step "grow" followed by "and-not".  This rule
option is much cleaner to implement and computes faster (although
it is still a boolean operator and is much slower than an edge
rule).
2024-12-25 20:46:25 -05:00
Tim Edwards 89b6f4f92b Corrected an error with the bloat-all CIF operator in which
bloat-all would fail to operate from the top layer of a contact
type due to the use of DBplane(type) instead of counting all
planes of the contact.
2024-12-16 21:52:11 -05:00
Tim Edwards 5ebbed4c12 Corrected the run-length wide-spacing rule so that it correctly
identifies areas which meet the proper definition of run-length
(both edges are parallel for the run-length distance or more).
Previously, errors were getting triggered for geometry where
only one edge exceeded the run-length distance.
2024-12-12 14:10:03 -05:00
Tim Edwards 37dfe07edf Extended the "cifmaxwidth" function to include the option "both",
which has the same meaning as the "maxwidth" function ("both"
checks either tile dimension to see if it exceeds the maximum).
This is a simple per-tile check and assumes that violations do
not occur across multiple tiles.  This should be sufficient for
most checks.
2024-12-08 12:14:38 -05:00
Tim Edwards dc87a8c693 Corrected two errors with the wiring tool: (1) Ignore
"angles"-type width rules when calculating the default metal
width DRC rule (this width when present will always be
larger than the minimum metal width), and (2) If an exiting
wire is larger than the contact size, then set the contact
size such that the contact PLUS the surrounding metal is the
width of the exiting wire.  The existing code sets the
contact size itself to the width of the exiting wire, such
that when surrounding material is added, the contact is
larger than it needs to be.  The fix to (1) will also fix
other places where the default DRC width rule is computed,
which includes LEF and DEF handling and computing rendered
text sizes when reading GDS.
2024-12-06 21:45:02 -05:00
Tim Edwards e0c95d6d78 Additional coding to handle discovery of terminal types on
different planes of a device that are connected to a multi-tile
device.  This is a more general solution than previously coded,
in which only the first tile of a device would be searched for
terminals on other planes, which was only guaranteed to work
if the device was represented by a single tile.
2024-12-06 20:51:59 -05:00
Tim Edwards 0a67151292 Extended the device parameters to allow a terminal width that is
different from the device (i.e., gate) width, for devices that do
not define a MOS-like gate spanning the width of the device.  This
is restricted to the assumption that the terminal is rectangular
and therefore a simple width and length can be derived from the
area and perimeter.  Also, length is defined as the smaller
dimension and width as the larger dimension.  For additional
restrictions, see the updated documentation.  This was added to
allow correct width and length extraction of a bipolar emitter
window, but may be more generally useful.
2024-12-06 16:42:43 -05:00
Tim Edwards 9184ccd395 Corrected an error in which DRC rules for width of material drawn
at a 45 degree angle will shadow the DRC rule for the material
drawn orthogonally (that is, the DRC rule for the distance between
orthogonal shapes will be eliminated from the rule deck).
2024-12-02 10:00:20 -05:00
Tim Edwards 8b34aa78a9 Corrected a long-standing crash condition that happens when a
generated cell is modified multiple times.  If the original cell
is orphaned (no longer used anywhere in the design), it is deleted.
However, an instance of the cell may exist in the secondary
select buffer if the cell was previously moved or copied, and
an attempt to do another move or copy will clear the secondary
select buffer, encounter the deleted cell, and crash the program.
2024-11-26 13:43:27 -05:00
Tim Edwards ea29aa3306 Modified behavior of the "property device" value. It was
previously ignoring the parameters of the entire cell including
the device being overridden by the property, causing the output
to be wrong.  The parameters should always be written out to the
.ext file, including the device whose output is being overridden.
2024-11-19 16:16:48 -05:00
Tim Edwards 1fdca3a57a Tracked down an obscure error that was causing a property
mismatch in the SkyWater sky130_fd_io__top_pwrdetv2 circuit
because a resistor with ends shorted together was being assigned
an incorrect length and width.  This was due to the similarity
in characteristics of the boundary vector between a shorted
resistor and an annular resistor.  The terminals need to be
checked for shorted ends to disambiguate the two cases.
2024-11-14 22:22:27 -05:00
Tim Edwards 22c22228b3 Coded around an issue where the antenna violation checker comes up
with zero gate error (and was reporting an infinite antenna ratio).
For now, just ignoring the zero-area case.  However, since the
procedure is supposed to be looping through nets connected to
specific devices in the .ext file, then every entry is supposed to
have non-zero area, so there is some underlying problem here that
needs to be fixed.
2024-11-07 11:59:07 -05:00
Tim Edwards a35993a81b Corrected a long-standing but rare error in which diagonal tiles
surrounding a device tile may cause the device to be extracted
with the wrong node (picking up the node from the wrong side of
the diagonal tile).  Added extra handling to capture the case
where two ports on two different nets are merged when using
"ext2spice short" (previously it was handling only ports on the
same net).  Also:  Removed the redundant readline-4.3 from the
readline/ directory;  only readline/readline is left, which is
version 4.3.
2024-11-02 11:00:05 -04:00
Tim Edwards b7942cffe6 Revised the previous commit after discussion with Darryl Miles on
the possible ways that other textio routines could affect the
string contents.
2024-10-10 17:48:59 -04:00
Tim Edwards 0864f8b728 Corrected an error introduced in yesterday's commits by a combination
of a syntax cleanup and an incorrect declaration.  See github issue
2024-10-10 15:27:52 -04:00
Tim Edwards d0eb5349a5 Updated the version to go along with a bunch of pull request
merges from syntax and error cleanup work done by Darryl Miles
(thanks, Darryl!).
2024-10-09 21:38:03 -04:00
Darryl L. Miles 95d3e9f85d CalmaRead.c: warning: variable 'libnameptr' is used uninitialized
The local variable 'libnameptr' is used from the 'goto done;' label cleanup
but it may not be initiailzied at the time of the first use of the label.

When evaluating this I also notice the global 'calmaErrorFile' when closed
does not have the handle invalidated.

CalmaRead.c:233:9: warning: variable 'libnameptr' is used uninitialized whenever 'if' condition is true
CalmaRead.c:231:9: warning: variable 'libnameptr' is used uninitialized whenever 'if' condition is true
CalmaRead.c:225:9: warning: variable 'libnameptr' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles d5ef80acda gaStem.c: warning: variable '...' is used uninitialized
An error return indication was added, as there as no other way to abort
execution but indicate to caller the data was not filled in.

No call sites have been modified to check the error return as the
assertion is still in place and expects to catch this unexpected scenario.

gaStem.c:914:2: warning: variable 'start' is used uninitialized whenever switch default is taken
gaStem.c:914:2: warning: variable 'min' is used uninitialized whenever switch default is taken
gaStem.c:914:2: warning: variable 'max' is used uninitialized whenever switch default is taken

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 38c14a0ad9 gaMain.c: warning: variable 'errs' is used uninitialized
gaMain.c:287:9: warning: variable 'errs' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 7fd116c828 tclmagic.c: warning: variable 'arg0' is used uninitialized
tclmagic.c:448:9: warning: variable 'arg0' is used uninitialized whenever 'if' condition is false

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 35604400ed irRoute.c: warning: variable '...' is used uninitialized
"shouldn't happen" but if it did.

irRoute.c:594:2: warning: variable 'startPt' is used uninitialized whenever switch default is taken
irRoute.c:719:2: warning: variable 'destRect' is used uninitialized whenever switch default is taken

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 1bb6a7f6c5 plotPNM.c: warning: variable 'strip' is used uninitialized
The compiler warning concerns the use of 'goto done;' has cleanup
that accesses 'strip' before initialization.

While evaluating this I also notice the other 2 variables 'rtile'
and 'lkstep' are globals, but their pointers are not invalidated
at the time of free.

plotPNM.c:821:6: warning: variable 'strip' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 60e78f4ab4 CalmaWriteZ.c: warning: variable 'rtype' is used uninitialized
CalmaWriteZ.c:418:5: warning: variable 'rtype' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles fca0c2945d CalmaWrite.c: warning: variable 'rtype' is used uninitialized
CalmaWrite.c:442:5: warning: variable 'rtype' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles fece689c43 CalmaRdpt.c: warning: variable 'rtype' is used uninitialized
CalmaRdpt.c:525:5: warning: variable 'rtype' is used uninitialized whenever 'if' condition is true
CalmaRdpt.c:792:5: warning: variable 'rtype' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 2b06c8cee5 CalmaRdcl.c: warning: variable 'rtype' is used uninitialized
FEOF condition of PEEKRH causes variable to possibly not get
initialized before use.

CalmaRdcl.c:372:5: warning: variable 'rtype' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 2f22ec6293 set.c: warning: variable 'result' is used uninitialized
set.c:124:9: warning: variable 'result' is used uninitialized whenever 'if' condition is false

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles ea41b21f67 macros.c: warning: variable 'kc' is used uninitialized
macros.c:557:12: warning: variable 'kc' is used uninitialized whenever 'if' condition is false

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 817efbbccc txCommands.c: warning: variable ... is used uninitialized whenever
Maybe ASSERT are not always active, so defensive coding solution.

txCommands.c:883:6: warning: variable 'but' is used uninitialized whenever switch default is taken
txCommands.c:888:6: warning: variable 'act' is used uninitialized whenever switch default is taken

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles fa3a01c486 selOps.c: warning: variable 'type' is used uninitialized
selOps.c:1942:11: warning: variable 'type' is used uninitialized whenever 'if' condition is false

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 3919cc5b63 PlowRandom.c: warning: variable 'f2' is used uninitialized
PlowRandom.c:301:9: warning: variable 'f2' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 4206ed2436 grTOGL3.c: warning: variable 'font' is used uninitialized
grTOGL3.c:230:5: warning: variable 'font' is used uninitialized whenever switch default is taken

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 4520112a55 grTk3.c: warning: variable 'font' is used uninitialized
grTk3.c:203:5: warning: variable 'font' is used uninitialized whenever switch default is taken

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 7feb298f7a ExtBasic.c: warning: variable ... is used uninitialized whenever
ExtBasic.c:408:7: warning: variable 'urx' is used uninitialized whenever '||' condition is true
ExtBasic.c:417:7: warning: variable 'ury' is used uninitialized whenever '||' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 4380310e5b EFvisit.c: warning: misleading indentation;
I think the warning is bringing to attention the hidden fall-thru
case situation.

EFvisit.c:897:50: warning: misleading indentation; statement is not part of the previous 'if'

clang18 -Wall warning cleanup  [-Wmisleading-indentation]
2024-10-09 21:34:12 -04:00
Darryl L. Miles cbf97f77ee DRCcif.c: 'thislayer' is used uninitialized
DRCcif.c:1193:17: warning: variable 'thislayer' is used uninitialized whenever 'for' loop exits because its condition is false
DRCcif.c:1255:17: warning: variable 'thislayer' is used uninitialized whenever 'for' loop exits because its condition is false

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles 489de7fdb4 CmdCD.c: 'option' is used uninitialized
CmdCD.c:3693:14: warning: variable 'option' is used uninitialized whenever 'if' condition is false
CmdCD.c:3691:9: warning: variable 'option' is used uninitialized whenever 'if' condition is true

clang18 -Wall warning cleanup [-Wsometimes-uninitialized]
2024-10-09 21:34:12 -04:00
Darryl L. Miles fc49b40c52 netlist.c: etext symbol for __clang__
clang does this differently, this method mirrors the linux man page.

clang18 default warning cleanup (strict)
2024-10-09 21:22:37 -04:00
Darryl L. Miles 9ca8697659 strings.h: add #include required when strict
Due to use of strcasecmp() or similar C API.

Maybe HAVE_STRINGS_H is needed ?  If so which platforms needs this ?

clang18 default warning cleanup (strict)
2024-10-09 21:22:37 -04:00
Darryl L. Miles 8f2acb83f9 plotHP.c: warning: incompatible pointer types passing 'int *' to ...
Perform pointer arithmatic with (int *) first then cast just for calling function.

plotHP.c:335:25: warning: incompatible pointer types passing 'int *' to parameter of type 'unsigned char *'
plotHP.c:339:25: warning: incompatible pointer types passing 'int *' to parameter of type 'unsigned char *'
plotHP.c:343:25: warning: incompatible pointer types passing 'int *' to parameter of type 'unsigned char *'

clang18 default warning cleanup [-Wincompatible-pointer-types]
2024-10-09 21:22:37 -04:00
Darryl L. Miles 165f1b35b4 ExtBasic.c: warning: incompatible pointer types passing 'NodeRegion *' ...
The NodeRegion is an extended form of LabRegion (which is smaller) and
has the same layout.  So we cast into the smaller type.

ExtBasic.c:1025:31: warning: incompatible pointer types passing 'NodeRegion *' (aka 'struct nreg *') to parameter of type 'LabRegion *' (aka 'struct lreg *')
ExtBasic.c:2291:29: warning: incompatible pointer types passing 'NodeRegion *' (aka 'struct nreg *') to parameter of type 'LabRegion *' (aka 'struct lreg *')
ExtBasic.c:2335:46: warning: incompatible pointer types passing 'NodeRegion *' (aka 'struct nreg *') to parameter of type 'LabRegion *' (aka 'struct lreg *')
ExtBasic.c:2339:47: warning: incompatible pointer types passing 'NodeRegion *' (aka 'struct nreg *') to parameter of type 'LabRegion *' (aka 'struct lreg *')

clang18 default warning cleanup [-Wincompatible-pointer-types]
2024-10-09 21:22:37 -04:00
Darryl L. Miles ade50dfc88 irRoute.c: warning: expression which evaluates to zero treated as a null pointer ...
Use of FALSE instead of NULL on a pointer type.

irRoute.c:1101:19: warning: expression which evaluates to zero treated
  as a null pointer constant of type 'RouteContact *'
  (aka 'struct routecontact *')

clang18 default warning cleanup [-Wnon-literal-null-conversion]
2024-10-09 21:22:37 -04:00
Darryl L. Miles 4460c5f1f5 DBio.c: warning: 'sscanf' may overflow; destination buffer in argument ...
DBio.c:2358:21: warning: 'sscanf' may overflow; destination buffer in
  argument 4 has size 2048, but the corresponding specifier may require
  size 2049

clang18 default warning cleanup [-Wfortify-source]
2024-10-09 21:22:37 -04:00
Darryl L. Miles ef48e40f39 lefRead.c:1334:63: warning: too few arguments in call to 'LefPaintPolygon'
When keep!=FALSE a malloc list is returned, so this looks like a memory leak.

clang18 default warning cleanup
2024-10-09 21:17:28 -04:00
Darryl L. Miles f734e27587 selOps.c:1000:70: warning: too many arguments in call to 'selShortFindForward'
Unclear if there is a programming intention here that hasn't been
implemented.

clang18 default warning cleanup
2024-10-09 21:17:28 -04:00
Darryl L. Miles b723dc15d8 DBio.c:1604:65: warning: too many arguments in call to 'dbReadOpen'
DBio.c:1604:52: warning: expression which evaluates to zero treated as
 a null pointer constant of type 'int *' [-Wnon-literal-null-conversion]

DBOpenOnly() function only has one use which always passed name==NULL.

clang18 default warning cleanup
2024-10-09 21:17:28 -04:00
Darryl L. Miles 59bfe8f6c0 DBcellsrch.c:2249:22: warning: too many arguments in call to 'dbMovePlane'
clang18 default warning cleanup
2024-10-09 21:17:28 -04:00
Darryl L. Miles c1aeaa9be5 DRCtech.c:4141:21: warning: suggest parentheses around comparison in operand of '=='
the expression (a == b == 1) works out like:

a, b = result (XNOR)
0, 0 = 1
0, 1 = 0
1, 0 = 0
1, 1 = 1

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 04bc9032b9 plotPNM.c:521:5: warning: statement with no effect
GCC14 -Wall cleanup series [-Wunused-value]
2024-10-09 21:12:55 -04:00
Darryl L. Miles be09edb8d8 12 x warning: suggest parentheses around '&&' within '||'
The '&' has higher precedence, so the expression of the '&' side receive
extra parentheses.

ResMakeRes.c:671:37: warning: suggest parentheses around '&&' within '||'
ResMakeRes.c:942:32: warning: suggest parentheses around '&&' within '||'
ResSimple.c:201:70: warning: suggest parentheses around '&&' within '||'
ResRex.c:1036:28: warning: suggest parentheses around '&&' within '||'
ResRex.c:1038:50: warning: suggest parentheses around '&&' within '||'
ext2sim.c:1341:47: warning: suggest parentheses around '&&' within '||'
ext2spice.c:172:44: warning: suggest parentheses around '&&' within '||'
ext2spice.c:173:49: warning: suggest parentheses around '&&' within '||'
ext2spice.c:3655:50: warning: suggest parentheses around '&&' within '||'
ext2hier.c:1412:50: warning: suggest parentheses around '&&' within '||'
gcrDebug.c:638:55: warning: suggest parentheses around '&&' within '||'
selEnum.c:323:28: warning: suggest parentheses around '&&' within '||'

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 239366d4b6 grTk3.c: warning: suggest parentheses around '-' in operand of '&'
GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 4bfed56924 17 x warning: suggest parentheses around assignment used as truth value
gaStem.c:225:9: warning: suggest parentheses around assignment used as truth value
gaStem.c:350:9: warning: suggest parentheses around assignment used as truth value
grouteMain.c:363:12: warning: suggest parentheses around assignment used as truth value
grouteMaze.c:573:17: warning: suggest parentheses around assignment used as truth value
groutePath.c:127:13: warning: suggest parentheses around assignment used as truth value
irCommand.c:901:12: warning: suggest parentheses around assignment used as truth value
irCommand.c:999:12: warning: suggest parentheses around assignment used as truth value
irCommand.c:1275:13: warning: suggest parentheses around assignment used as truth value
irCommand.c:1375:13: warning: suggest parentheses around assignment used as truth value
irCommand.c:1931:17: warning: suggest parentheses around assignment used as truth value
rtrDcmpose.c:435:12: warning: suggest parentheses around assignment used as truth value
rtrPin.c:174:17: warning: suggest parentheses around assignment used as truth value
rtrStem.c:373:21: warning: suggest parentheses around assignment used as truth value
rtrStem.c:479:9: warning: suggest parentheses around assignment used as truth value
rtrStem.c:952:17: warning: suggest parentheses around assignment used as truth value
gcrInit.c:239:9: warning: suggest parentheses around assignment used as truth value
net2ir.c:123:13: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles a6e1596ba6 22 x warning: suggest parentheses around assignment used as truth value
lefTech.c:107:16: warning: suggest parentheses around assignment used as truth value
lefTech.c:160:16: warning: suggest parentheses around assignment used as truth value
lefTech.c:426:16: warning: suggest parentheses around assignment used as truth value
lefTech.c:453:16: warning: suggest parentheses around assignment used as truth value
lefTech.c:486:16: warning: suggest parentheses around assignment used as truth value
lefWrite.c:190:9: warning: suggest parentheses around assignment used as truth value
lefWrite.c:303:12: warning: suggest parentheses around assignment used as truth value
lefWrite.c:315:12: warning: suggest parentheses around assignment used as truth value
lefWrite.c:377:16: warning: suggest parentheses around assignment used as truth value
lefWrite.c:439:16: warning: suggest parentheses around assignment used as truth value
lefWrite.c:1222:12: warning: suggest parentheses around assignment used as truth value
lefWrite.c:2246:12: warning: suggest parentheses around assignment used as truth value
defWrite.c:415:12: warning: suggest parentheses around assignment used as truth value
defWrite.c:447:12: warning: suggest parentheses around assignment used as truth value
defWrite.c:2039:16: warning: suggest parentheses around assignment used as truth value
defWrite.c:2104:16: warning: suggest parentheses around assignment used as truth value
defWrite.c:2478:16: warning: suggest parentheses around assignment used as truth value
defWrite.c:2498:20: warning: suggest parentheses around assignment used as truth value
defWrite.c:3066:16: warning: suggest parentheses around assignment used as truth value
defWrite.c:3084:28: warning: suggest parentheses around assignment used as truth value
defWrite.c:3111:28: warning: suggest parentheses around assignment used as truth value
lefRead.c:651:12: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 76d8c8c911 35 x warning: suggest parentheses around assignment used as truth value
PlowRules1.c:439:9: warning: suggest parentheses around assignment used as truth value
PlowTech.c:645:17: warning: suggest parentheses around assignment used as truth value
PlowTech.c:652:17: warning: suggest parentheses around assignment used as truth value
PlowTech.c:1019:17: warning: suggest parentheses around assignment used as truth value
ResReadSim.c:270:13: warning: suggest parentheses around assignment used as truth value
ResReadSim.c:871:9: warning: suggest parentheses around assignment used as truth value
ResRex.c:1840:17: warning: suggest parentheses around assignment used as truth value
getrect.c:72:9: warning: suggest parentheses around assignment used as truth value
getrect.c:79:9: warning: suggest parentheses around assignment used as truth value
getrect.c:86:9: warning: suggest parentheses around assignment used as truth value
getrect.c:93:9: warning: suggest parentheses around assignment used as truth value
hash.c:732:16: warning: suggest parentheses around assignment used as truth value
heap.c:328:17: warning: suggest parentheses around assignment used as truth value
heap.c:344:17: warning: suggest parentheses around assignment used as truth value
netlist.c:323:17: warning: suggest parentheses around assignment used as truth value
niceabort.c:121:9: warning: suggest parentheses around assignment used as truth value
path.c:1102:12: warning: suggest parentheses around assignment used as truth value
pathvisit.c:245:13: warning: suggest parentheses around assignment used as truth value
pathvisit.c:295:17: warning: suggest parentheses around assignment used as truth value
tech.c:656:17: warning: suggest parentheses around assignment used as truth value
ext2spice.c:1591:16: warning: suggest parentheses around assignment used as truth value
ext2spice.c:1622:16: warning: suggest parentheses around assignment used as truth value
ext2spice.c:1813:12: warning: suggest parentheses around assignment used as truth value
ext2spice.c:1862:12: warning: suggest parentheses around assignment used as truth value
ext2spice.c:3808:16: warning: suggest parentheses around assignment used as truth value
CalmaRdio.c:437:9: warning: suggest parentheses around assignment used as truth value
CalmaWrite.c:396:9: warning: suggest parentheses around assignment used as truth value
CalmaWrite.c:1772:29: warning: suggest parentheses around assignment used as truth value
CalmaWriteZ.c:372:9: warning: suggest parentheses around assignment used as truth value
CalmaWriteZ.c:1608:29: warning: suggest parentheses around assignment used as truth value
CIFrdtech.c:209:9: warning: suggest parentheses around assignment used as truth value
CIFrdtech.c:214:9: warning: suggest parentheses around assignment used as truth value
CIFrdtech.c:220:9: warning: suggest parentheses around assignment used as truth value
CIFrdtech.c:226:9: warning: suggest parentheses around assignment used as truth value
CIFrdutils.c:1258:12: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 64772655dc 38 x warning: suggest parentheses around assignment used as truth value
EFdef.c:110:12: warning: suggest parentheses around assignment used as truth value
EFdef.c:154:12: warning: suggest parentheses around assignment used as truth value
EFdef.c:167:12: warning: suggest parentheses around assignment used as truth value
EFflat.c:546:17: warning: suggest parentheses around assignment used as truth value
EFflat.c:798:12: warning: suggest parentheses around assignment used as truth value
EFflat.c:930:13: warning: suggest parentheses around assignment used as truth value
EFflat.c:1152:12: warning: suggest parentheses around assignment used as truth value
EFflat.c:1157:13: warning: suggest parentheses around assignment used as truth value
EFhier.c:84:12: warning: suggest parentheses around assignment used as truth value
EFhier.c:261:12: warning: suggest parentheses around assignment used as truth value
EFhier.c:489:12: warning: suggest parentheses around assignment used as truth value
EFhier.c:682:12: warning: suggest parentheses around assignment used as truth value
EFname.c:325:12: warning: suggest parentheses around assignment used as truth value
EFname.c:584:13: warning: suggest parentheses around assignment used as truth value
EFname.c:632:16: warning: suggest parentheses around assignment used as truth value
EFname.c:765:16: warning: suggest parentheses around assignment used as truth value
EFname.c:977:12: warning: suggest parentheses around assignment used as truth value
EFsym.c:113:13: warning: suggest parentheses around assignment used as truth value
EFsym.c:164:9: warning: suggest parentheses around assignment used as truth value
EFvisit.c:322:12: warning: suggest parentheses around assignment used as truth value
EFvisit.c:627:12: warning: suggest parentheses around assignment used as truth value
EFvisit.c:881:16: warning: suggest parentheses around assignment used as truth value
EFvisit.c:917:12: warning: suggest parentheses around assignment used as truth value
grTk1.c:1325:9: warning: suggest parentheses around assignment used as truth value
grTk1.c:1342:9: warning: suggest parentheses around assignment used as truth value
grTk1.c:1757:9: warning: suggest parentheses around assignment used as truth value
grTk1.c:1766:9: warning: suggest parentheses around assignment used as truth value
grTk5.c:177:12: warning: suggest parentheses around assignment used as truth value
grTOGL1.c:1095:9: warning: suggest parentheses around assignment used as truth value
grTOGL1.c:1111:9: warning: suggest parentheses around assignment used as truth value
grTOGL1.c:1542:13: warning: suggest parentheses around assignment used as truth value
grTOGL1.c:1551:13: warning: suggest parentheses around assignment used as truth value
grTOGL5.c:201:12: warning: suggest parentheses around assignment used as truth value
grTCairo1.c:1093:13: warning: suggest parentheses around assignment used as truth value
grTCairo1.c:1109:13: warning: suggest parentheses around assignment used as truth value
grTCairo1.c:1493:21: warning: suggest parentheses around assignment used as truth value
grTCairo1.c:1502:21: warning: suggest parentheses around assignment used as truth value
grTCairo5.c:202:16: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles e3bfe8c59e 42 x warning: suggest parentheses around assignment used as truth value
EFbuild.c:466:9: warning: suggest parentheses around assignment used as truth value
EFbuild.c:662:20: warning: suggest parentheses around assignment used as truth value
EFbuild.c:682:24: warning: suggest parentheses around assignment used as truth value
EFbuild.c:690:24: warning: suggest parentheses around assignment used as truth value
EFbuild.c:1760:12: warning: suggest parentheses around assignment used as truth value
EFbuild.c:1973:9: warning: suggest parentheses around assignment used as truth value
EFbuild.c:2062:12: warning: suggest parentheses around assignment used as truth value
EFbuild.c:2063:13: warning: suggest parentheses around assignment used as truth value
EFbuild.c:2091:12: warning: suggest parentheses around assignment used as truth value
EFbuild.c:2134:12: warning: suggest parentheses around assignment used as truth value
EFbuild.c:2135:13: warning: suggest parentheses around assignment used as truth value
EFread.c:673:12: warning: suggest parentheses around assignment used as truth value
ExtArray.c:693:12: warning: suggest parentheses around assignment used as truth value
ExtArray.c:800:13: warning: suggest parentheses around assignment used as truth value
ExtBasic.c:4569:9: warning: suggest parentheses around assignment used as truth value
ExtBasic.c:4949:13: warning: suggest parentheses around assignment used as truth value
ExtBasic.c:5032:12: warning: suggest parentheses around assignment used as truth value
ExtCell.c:218:13: warning: suggest parentheses around assignment used as truth value
ExtCouple.c:222:12: warning: suggest parentheses around assignment used as truth value
ExtCouple.c:278:12: warning: suggest parentheses around assignment used as truth value
ExtCouple.c:467:9: warning: suggest parentheses around assignment used as truth value
ExtHard.c:379:12: warning: suggest parentheses around assignment used as truth value
ExtHard.c:458:12: warning: suggest parentheses around assignment used as truth value
ExtHier.c:740:16: warning: suggest parentheses around assignment used as truth value
ExtHier.c:831:12: warning: suggest parentheses around assignment used as truth value
ExtHier.c:841:13: warning: suggest parentheses around assignment used as truth value
ExtHier.c:851:17: warning: suggest parentheses around assignment used as truth value
ExtHier.c:865:34: warning: suggest parentheses around assignment used as truth value
ExtLength.c:264:12: warning: suggest parentheses around assignment used as truth value
ExtLength.c:276:12: warning: suggest parentheses around assignment used as truth value
ExtLength.c:878:9: warning: suggest parentheses around assignment used as truth value
ExtMain.c:499:12: warning: suggest parentheses around assignment used as truth value
ExtMain.c:970:12: warning: suggest parentheses around assignment used as truth value
ExtNghbors.c:298:13: warning: suggest parentheses around assignment used as truth value
ExtSubtree.c:683:12: warning: suggest parentheses around assignment used as truth value
ExtTest.c:457:21: warning: suggest parentheses around assignment used as truth value
ExtTest.c:466:21: warning: suggest parentheses around assignment used as truth value
ExtTimes.c:216:12: warning: suggest parentheses around assignment used as truth value
ExtTimes.c:226:12: warning: suggest parentheses around assignment used as truth value
ExtTimes.c:235:12: warning: suggest parentheses around assignment used as truth value
ExtYank.c:236:34: warning: suggest parentheses around assignment used as truth value
ExtYank.c:238:42: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 6cdb9ad167 36 x warning: suggest parentheses around assignment used as truth value
bpMain.c:265:11: warning: suggest parentheses around assignment used as truth value
CmdSubrs.c:413:12: warning: suggest parentheses around assignment used as truth value
CmdSubrs.c:759:13: warning: suggest parentheses around assignment used as truth value
CmdFI.c:1600:12: warning: suggest parentheses around assignment used as truth value
DBcell.c:109:12: warning: suggest parentheses around assignment used as truth value
DBcellname.c:2512:9: warning: suggest parentheses around assignment used as truth value
DBcellsrch.c:95:12: warning: suggest parentheses around assignment used as truth value
DBio.c:3998:9: warning: suggest parentheses around assignment used as truth value
DBlabel2.c:228:9: warning: suggest parentheses around assignment used as truth value
DBWelement.c:195:12: warning: suggest parentheses around assignment used as truth value
DBWelement.c:197:13: warning: suggest parentheses around assignment used as truth value
DBWelement.c:295:12: warning: suggest parentheses around assignment used as truth value
DBWelement.c:297:13: warning: suggest parentheses around assignment used as truth value
DBWelement.c:637:12: warning: suggest parentheses around assignment used as truth value
DBWelement.c:639:13: warning: suggest parentheses around assignment used as truth value
DBWelement.c:679:12: warning: suggest parentheses around assignment used as truth value
DBWelement.c:681:13: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1219:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1368:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1471:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1543:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1676:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1772:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:1919:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:2099:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:2324:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:2713:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:2830:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:2944:17: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3097:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3144:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3181:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3215:9: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3227:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3261:21: warning: suggest parentheses around assignment used as truth value
DRCtech.c:3459:17: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 518b5f45d8 bpEnum.h: warning: suggest parentheses around assignment used as truth value
Removes 1312 warning lines from build output due to inline nature of use.

bplane/bpEnum.h:509:10: warning: suggest parentheses around assignment used as truth value
bplane/bpEnum.h:513:10: warning: suggest parentheses around assignment used as truth value
bplane/bpEnum.h:517:10: warning: suggest parentheses around assignment used as truth value
bplane/bpEnum.h:521:10: warning: suggest parentheses around assignment used as truth value
bbplane/bpEnum.h:525:10: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 21:12:55 -04:00
Darryl L. Miles d94cd72538 37 x warning: array subscript has type 'char'
Compiler is expressing range concern with the warning mitigated by using
unsigned C array offsets.  This also draws attention to the range concern
when reading the code and making changes.

DBundo.c:263:45: warning: array subscript has type 'char'
DBundo.c:279:49: warning: array subscript has type 'char'
DBundo.c:317:52: warning: array subscript has type 'char'
DBundo.c:318:64: warning: array subscript has type 'char'
DBundo.c:324:52: warning: array subscript has type 'char'
DBundo.c:325:64: warning: array subscript has type 'char'
DBundo.c:329:50: warning: array subscript has type 'char'
DBundo.c:330:58: warning: array subscript has type 'char'
DBundo.c:338:52: warning: array subscript has type 'char'
DBundo.c:339:64: warning: array subscript has type 'char'
DBundo.c:345:52: warning: array subscript has type 'char'
DBundo.c:346:64: warning: array subscript has type 'char'
DBundo.c:350:50: warning: array subscript has type 'char'
DBundo.c:351:58: warning: array subscript has type 'char'
DBundo.c:371:52: warning: array subscript has type 'char'
DBundo.c:372:64: warning: array subscript has type 'char'
DBundo.c:378:52: warning: array subscript has type 'char'
DBundo.c:379:64: warning: array subscript has type 'char'
DBundo.c:383:50: warning: array subscript has type 'char'
DBundo.c:384:58: warning: array subscript has type 'char'
DBundo.c:392:52: warning: array subscript has type 'char'
DBundo.c:393:57: warning: array subscript has type 'char'
DBundo.c:399:52: warning: array subscript has type 'char'
DBundo.c:400:57: warning: array subscript has type 'char'
DBundo.c:403:53: warning: array subscript has type 'char'
DBundo.c:407:50: warning: array subscript has type 'char'
DBundo.c:408:58: warning: array subscript has type 'char'
EFbuild.c:1048:32: warning: array subscript has type 'char'
EFbuild.c:1056:32: warning: array subscript has type 'char'
ExtBasic.c:2358:43: warning: array subscript has type 'char'
ExtBasic.c:2493:43: warning: array subscript has type 'char'
ExtBasic.c:2519:43: warning: array subscript has type 'char'
ExtBasic.c:2644:43: warning: array subscript has type 'char'
ExtBasic.c:2678:43: warning: array subscript has type 'char'
ResPrint.c:143:43: warning: array subscript has type 'char'
plotRutils.c:713:34: warning: array subscript has type 'char'
plotRutils.c:786:29: warning: array subscript has type 'char'

GCC14 -Wall cleanup series [-Wchar-subscripts]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 9225fa6cf1 4 x warning: suggest explicit braces to avoid ambiguous 'else'
Give compiler the extra braces it recommends.

DBio.c edited as my original change was caught out by the incorrect
indention of the 'else' keyword and my modification would have caused a
NULL deref.   Exactly the kind of issue this warning is trying to prevent.

CmdTZ.c:417:20: warning: suggest explicit braces to avoid ambiguous 'else'
DBio.c:1422:12: warning: suggest explicit braces to avoid ambiguous 'else'
DBpaint2.c:285:12: warning: suggest explicit braces to avoid ambiguous 'else'
DBpaint2.c:384:12: warning: suggest explicit braces to avoid ambiguous 'else'

GCC14 -Wall cleanup series [-Wdangling-else]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 7dfdf5aa63 CIFrdcl.c: warning: comparison between two arrays
Added pointer casts to hint to compiler the programmer intention
is to compare as pointers to the start of the array (and not be
concerned the programmer is overlooking the contents of the array).

GCC14 -Wall cleanup series [-Warray-compare]
2024-10-09 21:12:55 -04:00
Darryl L. Miles b654647fdc PlowTest.c: warning: enumeration value 'PC_ERROR' not handled in switch
False positive.

Added no-op case statement, but code above looks the case should never
execute due return from function.

GCC14 -Wall cleanup series [-Wswitch]
2024-10-09 21:12:55 -04:00
Darryl L. Miles bd75ddf32c mzMain.c: warning: this 'else' clause does not guard...
Use of macro idiom: if(1) { ... } else
  which has dangling else keyword to allow trailing semicolon at
  use site, is not a good pattern.

Replaced with idiom: do { ... } while(0)
  which should achieve the same purpose but now cause compile
  error when used incorrectly at use site.

GCC14 -Wall cleanup series [-Wmisleading-indentation]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 88d36bfd1e geofast.h: warning: this 'else' clause does not guard...
Use of macro idiom: if(1) { ... } else
  which has dangling else keyword to allow trailing semicolon at
  use site, is not a good pattern.

Replaced with idiom: do { ... } while(0)
  which should achieve the same purpose but now cause compile
  error when used incorrectly at use site.

GCC14 -Wall cleanup series [-Wmisleading-indentation]
2024-10-09 21:12:55 -04:00
Darryl L. Miles e8f9b0af5e CIFgen.c: warning: this 'for' clause does not guard...
return keyword indention corrected
braces added to previous statement to better convey code
 intention of multiline statement

GCC14 -Wall cleanup series [-Wmisleading-indentation]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 0cde303563 ResReadSim.c: warning: this 'if' clause does not guard...
break keyword indention corrected, braces added to better
convey code intention of multiline statement.

GCC14 -Wall cleanup series [-Wmisleading-indentation]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 967b41343b GCC14: warning: missing braces around initializer
GCC14 -Wall cleanup series [-Wmissing-braces]
2024-10-09 21:12:55 -04:00
Darryl L. Miles 3300f45a22 DRCtech.c: warning: use of logical '&&' with constant operand
Looks like logic error hiding behind warning

DRCtech.c:4365:22: warning: use of logical '&&' with constant
 operand [-Wconstant-logical-operand]
DRCtech.c:4365:22: note: remove constant to silence this warning

clang18 default warning cleanup
2024-10-09 20:50:00 -04:00
Darryl L. Miles da2c7b719e DRCsubcell.c: fix: warning: value computed is not used
Looks like a logic bug hidden in the warning.

GCC14 -Wall cleanup series [-Wunused-value]
2024-10-09 20:50:00 -04:00
Darryl L. Miles 3477480ab0 NMbutton.c: fix: warning: statement with no effect
Looks like a logic bug hidden in the warning.

GCC14 -Wall cleanup series [-Wunused-value]
2024-10-09 20:50:00 -04:00
Darryl L. Miles c749d01eb7 rtrStem.c: fix: warning: statement with no effect
Looks like a logic bug hidden in the warning.

GCC14 -Wall cleanup series [-Wunused-value]
2024-10-09 20:50:00 -04:00
Darryl L. Miles cebb1a5277 lefTech.c: fix: default value logic error
Looks like a logic bug, hiding behind this compiler warning

lefTech.c:507:21: warning: suggest parentheses around assignment used as truth value
lefTech.c:509:21: warning: suggest parentheses around assignment used as truth value

GCC14 -Wall cleanup series [-Wparentheses]
2024-10-09 20:50:00 -04:00
Darryl L. Miles 4ea0f6a9b7 DBcellcopy.c: fix warning: self-comparison always evaluates to false
Looks like a straighforward logic bug from a recent (2023) change.

GCC14 -Wall cleanup series [-Wtautological-compare]
2024-10-09 20:50:00 -04:00
Darryl L. Miles 015f03307a appimage/Dockerfile: fix CentOS7 based docker build due to EOL
CentOS7 went EOL on June 30, 2024 this builds out of vault.centos.org
2024-10-09 20:40:28 -04:00
Darryl L. Miles 65a0dc45dc graphics: windowname[] potential buffer overrun warning
GCC14 loud default warnings series
2024-10-09 20:39:12 -04:00
Darryl L. Miles 63256f1a44 DBio.c: resolve warnings and use snprintf()
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 1c326c9141 grouteCrss.c: '%s' directive writing up to 1023 bytes into a region of size 227
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 6a08b31149 defWrite.: '%.10g' directive writing between 1 and 17 bytes into a region of size 12
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 9f88450243 niceabort.c: '%s' directive writing up to 199 bytes into a region of size 177
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 29bd23d40b txOutput.c:408: warning: missing sentinel in function call
GCC false positive, seems pedantic over it being NULL not 0.

GCC14 loud default warnings series [-Wformat=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles bf916d2647 SimRsim.c: directive writing 1 byte into a region of size between 0 and 255
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles b81e04eed4 ResPrint.c: '%s' directive writing 2 bytes into a region of size between 1 and 1000
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 41913fbd78 ExtUnique.c: '_uq' directive writing 3 bytes into a region of size between 1 and 1024
GCC14 loud default warnings series [-Wformat-overflow=]
2024-10-09 20:39:12 -04:00
Darryl L. Miles 66734bbaee ExtHier.c: format '%ld' expects argument of type 'long int', but .. 'dlong'
GCC14 loud default warnings series
2024-10-09 20:39:12 -04:00
Darryl L. Miles b3cb528e46 ExtBasic.c: comparison between pointer and integer
GCC14 loud default warnings series
2024-10-09 20:39:12 -04:00
Darryl L. Miles 1ae4518846 DLONG_PREFIX is %ld on x86_64 LP64
GCC14 loud default warnings fix
2024-10-09 20:39:12 -04:00
Darryl L. Miles 32a7323287 SimSelect.c: type defaults to 'int' in declaration of 'RsimErrorMsg'
GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles 932deeaf2d readline: define _XOPEN_SOURCE at the top of files
It is a requirement to define feature_test_macros(7) as soon as possible
before including any files, otherwise the headers may not allow further
configuration, as reconfiguration maybe denied.  You need to pick the
standard you wish to work with for the compilation unit (the file).

This can be seen with an error for lack of symbol `wcwidth()` from wchar.h

Moving the order slightly fixes the compile failure issue.
See feature_test_macros(7) for more info.

GCC14 --without-tk --without-tcl (without system libreadline-dev)
2024-10-09 20:35:19 -04:00
Darryl L. Miles 54f49829f2 graphics: multiple definition of `various_x11_symbols'
Solution is to make the grX11thread.c and grX11su1[5].c versions
the official location.  Another solution maybe to split them into
their own file grX11common.c that would be shared.

Multiple configurations tested, tested configurations assume X11
is available.  The configuration wording indicates X11 must be
available for all graphics enabled build configurations.

Affected symbols appear to have multiple definitions:
grCursors
grXdpy
grXscrn
pipeRead
pipeWrite
Xhelper
grVisual

GCC14 and linker will not link the final executable due to this.

GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles e5c3e703c3 HashLookOnly(): passing argument 2 of 'HashLookOnly' makes pointer from integer without a cast
Also HashFind()

GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles c90bde4961 DBWelement.c: passing argument 1 of 'TxPrintf' from incompatible pointer type
GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles 23930909b1 database/DBio.c: error: assignment to 'char *' from 'ClientData'
GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles 8994a68e61 DBPropGet(): error: assignment to 'char *' from 'ClientData'
GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Darryl L. Miles 0a4e2a5a27 HashGetValue: warning: comparison between pointer and integer
GCC14 --without-tk --without-tcl
Related issue: https://github.com/RTimothyEdwards/magic/issues/323
2024-10-09 20:35:19 -04:00
Tim Edwards de5c54e20b Added a missing description of the "flatten" property, which is
documented briefly in the "flatten" command reference page, but
no in the "property" command reference page.
2024-10-09 20:34:08 -04:00
Tim Edwards a3b61abe2b Corrected an error in which "extract unique noports" and
"extract unique notopports" both fail to work correctly because
an attempt some time ago to avoid issuing warnings about shorted
port names when using those options was changed in the wrong
line.
2024-10-07 11:48:27 -04:00
Tim Edwards 6162a9f459 Corrected the "bloat-all" function so that it behaves properly on
angled edges.  This is a rare case and so has never come up before,
but can happen especially on transistors with gate or diffusion
with 45 degree chamfers or flanges.  Thanks to Mark Martin for
providing the use case.
2024-10-03 20:37:43 -04:00
Darryl L. Miles 80f051f79d GHA: CI WASM build use --disable-compression
I assume it can't link to libz anyway, you'd need to rebuild libz
for WASM target (or use a the Web API for GZIP).
2024-10-01 21:18:55 -04:00
Darryl L. Miles 7589bdba10 GHA: BUMP actions/upload-artifact@v4 (from v3) 2024-10-01 21:18:55 -04:00
Darryl L. Miles 08affbe032 GHA: BUMP actions/checkout@v4 (from v2) 2024-10-01 21:18:55 -04:00
Darryl L. Miles a467154fec Update appimage.yml (rename job) 2024-10-01 21:18:55 -04:00
Tim Edwards e2c3eb3e20 Corrected the previous commit, which did not fix the problem that
it claimed to fix, but caused an incorrect DRC maxwidth check
instead.  The problem appears to be correctly resolved now.
Also:  Tracked down a recently-introduced minor issue in which
the interactive DRC stops running after issuing "drc check" and
does not resume until another key or mouse even occurs.  This
turned out to be caused by the work on the "logcommands" command,
which should have used "*bypass" before "logcommands suspend"
and "logcommands resume", since the "*bypass" indicates that
the command has no impact on layout and should not interrupt
the DRC checker.
2024-10-01 21:14:12 -04:00
Tim Edwards 3e0ad4ff58 Finally got around to restoring the behavior of the toolbar with
respect to using the 3rd mouse button to hide a layer, and
indicating the layer is hidden by blanking the icon (which works
better with the new scrollable icon list, but got broken by the
same).  Also:  Added a previously missing behavior, which is to
correctly update the icon settings based on using the command
"see" and "see no" with layer aliases (e.g., "allm1").
2024-10-01 16:01:28 -04:00
Tim Edwards dba6f99d93 Updated the revision number to go along with the merge of pull
request #325 from Daryl Miles.  Made a few simple style changes
to conform to (what is vaguely defined as) the overall programming
style for magic (passed down from John Ousterhout).
2024-10-01 12:56:31 -04:00
Darryl L. Miles e119188f23 fix: findUse can return NULL crash
The main cause of the crash was the path for UNDO_CELL_PLACE this was
trigged by performing a number of cell create/move operations (unknown
exactly what sequence).  Then a large number of "undo" operations.

There is an ASSERT in findUse() but that does not seem built into the
release (or debug CFLAGS=-g3) builds.
2024-10-01 12:43:27 -04:00
Darryl L. Miles 3638d382d6 fix: lef write crash (when cells with labels in space pNum==-1)
The issue here is can pNum==-1 which causes a crash.
2024-10-01 12:43:27 -04:00
Darryl L. Miles 18a4dddc2b fix: read of uninitialized data at inChar[0]
This is a defensive fix, might cause unexpected program exit if triggered.
The loop will iterate at least once when nbytes==0, but this value
indicates XLookupString did not fill in any data, so the entire buffer
is undefined.

Using memset() before or inChar[0]=0 after XLookupString did not fix
the issue.  Using inChar[0]=0 immediately before the loop did fix as
well.  But this patch seems to be the best approach.
2024-10-01 12:43:27 -04:00
Darryl L. Miles 1ca23ca0a2 fix: Accessing uninitialized variable
Trigger condition maybe that no labels exist in the project, so the
loop never iterates.
2024-10-01 12:43:27 -04:00
Darryl L. Miles 8e0f34c6f1 debug/hist.c Access .. results in a dereference of a null
Maybe this is only a bug if a call to HistAdd() is made before HistCreate().

SonarCloud
debug/hist.c:147 Access to field 'hi_cum' results in a dereference of a null pointer (loaded from variable 'h')
https://sonarcloud.io/project/issues?open=AZJB17kdNGfDNup0RkzB&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 60fe6427da graphics/grX11su1.c: Dereference of null pointer
Looks like the code below requires w!=NULL to do anything useful.
So when w==NULL we don't continue processing X11 Event.

SonarCloud
graphics/grX11su1.c:895 Dereference of null pointer
https://sonarcloud.io/project/issues?open=AZJB163RNGfDNup0Ri4p&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 01f9f2246b graphics/grX11su1.c: Dereference of null pointer
Looks like the code below requires w!=NULL to do anything useful.
So when w==NULL we don't continue processing X11 Event.

SonarCloud
graphics/grX11su1.c:842 Dereference of null pointer
https://sonarcloud.io/project/issues?open=AZJB163RNGfDNup0Ri4o&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles cb31675174 utils/geometry.c: non-void function does not return a value in all control paths
Had to pick a value to return by default.  This is a probably should never happen ?

SonarCloud
utils/geometry.c:589 non-void function does not return a value in all control paths
https://sonarcloud.io/project/issues?open=AZJB16DGNGfDNup0Rg7u&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles bfd818fbd3 textio/txInput.c non-void function does not return a value
This function is related to libreadline rl_pre_input_hook callback
which is invoked as (not making use of any function return value):

readline.c:    (*rl_pre_input_hook) ();

The general prototype for this function is:

rltypedefs.h:typedef int rl_hook_func_t PARAMS((void));

So the resolution is to provide a known value as the return value, which
resolves the concern.

SonarCloud
textio/txInput.c:550 non-void function does not return a value
https://sonarcloud.io/project/issues?open=AZJB17NwNGfDNup0Rj5G&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles ab747a0f8c grouter/groutePin.c: multiple: non-void function does not return a value
Multiple reports exists in this file

Affected functions:
 GLInitPins() now returns void
 glPinArrayInit() now returns void
 GLLinkPins() now returns void
 glPinArrayLink() now returns void
 GLFixStemPins() now returns void
 glPinArrayFixStems() now returns void

SonarCloud
https://sonarcloud.io/project/issues?open=AZJB17L0NGfDNup0Rj0D&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 8b2efd5d7d gcr/gcrDebug.c Opened stream never closed. Potential resource leak
A false positive in practice, made clearer by using a 2nd variable
with attention drawing name.

SonarCloud
gcr/gcrDebug.c:429 Opened stream never closed. Potential resource leak
https://sonarcloud.io/project/issues?open=AZJB17OzNGfDNup0Rj-t&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 0cea17e801 utils/magic.h pointertype prefer use of 'long' instead of 'int'
It is usual for a pointer to require the largest width, while some
platforms might have an 'int' that is smaller than a pointer width.

This reverses the detection order to find.

Note since C99 there is <stdint.h> with type 'intmax_t' which
serves a similar purpose.

SonarCloud reports a concern with this on many lines where used.
"An integral type is too small to hold a pointer value."
https://sonarcloud.io/project/issues?open=AZJB17ZoNGfDNup0RkY_&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles a0aea2aa2e gcr/gcrDebug.c Add a field width specifier to this "%s" placeholder.
Unbounded local buffer used in fscanf() string extraction call.
Add width to specified to ensure truncation as 24 character instead
of buffer overflow.

SonarCloud https://sonarcloud.io/project/issues?open=AZJB17OzNGfDNup0Rj9x&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 29ee094074 graphics/grOGL1.c Dereference of null pointer
Looks like the code below requires mw!=NULL to do anything useful.
So when mw==NULL we don't continue processing X11 Event.

SonarCloud
graphics/grOGL1.c:563 Dereference of null pointer
https://sonarcloud.io/project/issues?open=AZJB16z6NGfDNup0Riss&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles be258c6557 graphics/grOGL1.c: non-void function does not return a value
Making oglSetProjection() return void, like toglSetProjection()

SonarCloud
graphics/grOGL1.c:408 non-void function does not return a value
https://sonarcloud.io/project/issues?open=AZJB16z6NGfDNup0Riro&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles ae0cdd9fea graphics/grClip.c Branch condition evaluates to a garbage value
This is technically a false positive as grClipPoints() will always
initializes a value to ok1 and ok2 when called.  The function is in
the same compile unit, so probably the compiler can see this as well
and potentially not perform the initiailization begin performed in
this commit.

But to quieten and remove this item from the analysis report
assigning an initialization value.

SonarCloud
graphics/grClip.c:451 Branch condition evaluates to a garbage value
https://sonarcloud.io/project/issues?open=AZJB160MNGfDNup0Rit4&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 10442b6534 graphics/cairo_orig/grTCairo5.c uninitialized local variable
Looks like old code.  Based on cairo_fill() action state this is initialized to
no-op by default.

SonarCloud
graphics/cairo_orig/grTCairo5.c:107 The left operand of '!=' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB16wANGfDNup0RiiZ&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 5e00e3fe1b graphics/cairo_orig/grTCairo3.c uninitialized value
Looks like old code.  Looks like local variable 'j' could be removed.
Initialization lowers the severity of concern in this area.
The 'j' variable is now written but never read.

SonarCloud
graphics/cairo_orig/grTCairo3.c:492
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
https://sonarcloud.io/project/issues?open=AZJB16voNGfDNup0Rig_&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles a9b707460b garouter/gaChannel.c use of unintialized or incorrect variable
This resolution assumes that all records and values of ch->gcr_type are expected
to be one of the 3 cases in the switch.  The bug it on the first iteration it is
possible 'tot' and 'clear' is just not initializaed and on a subsequent iteration
it is possible it ot setup to the previous interation values.

SonarCloud
garouter/gaChannel.c:385:3rd function call argument is an uninitialized value
https://sonarcloud.io/project/issues?open=AZJB17fFNGfDNup0RkoE&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 543bd5a5b8 ext2sim/sim2simp.c ParseAttr does not return a value
SonarCloud
ext2sim/sim2simp.c:43 non-void function 'parseAttr' should return a value
https://sonarcloud.io/project/issues?open=AZJB17kzNGfDNup0RkzS&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 973c9a4d1a database/DBio.c read of variable before initialization
Due to FEOF condition and handling it is possible local variable 'c' is not
initialized before being read and compared.

SonarCloud retails
DBio.c:3049 The left operand of '==' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB16rxNGfDNup0Ribf&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 48853b98a3 calma/CalmaRead.c missing initialization
An FEOF exit path exists in READRH() which causes the output
variable(s) to not be assigned a value, then the code makes
a decision (branch) based on uninitialized data.

SonarCloud detection
CalmaRead.c:359:The left operand of '!=' is a garbage value
https://sonarcloud.io/project/issues?open=AZJB17gSNGfDNup0Rkp5&id=dlmiles_magic
2024-10-01 12:36:13 -04:00
Darryl L. Miles 290887912f ext2spice/ext2hier.c: Wrong type of arguments to formatting function
Applied the same fixes as other commits already merged into file.

Copilot Autofix: Error contact support...

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/38
        https://github.com/dlmiles/magic/security/code-scanning/39
        https://github.com/dlmiles/magic/security/code-scanning/41
2024-10-01 12:36:13 -04:00
Darryl L. Miles 62ebf49758 mzrouter/mzEstimate.c: (intmax_t) %lx Wrong type of arguments to formatting function
Copilot Autofix rejected: TxPrintf("\ntile %p\t\t  (x: %d to %d, y: %d to %d)\n",

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/102
2024-10-01 12:36:13 -04:00
Darryl L. Miles 7509802b3d mzrouter/mzDebug.c: (intmax_t) %lx Wrong type of arguments to formatting function
Copilot Autofix rejected: TxPrintf("tile %p  (x: %d to %d, y: %d to %d)\n"

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/101
2024-10-01 12:36:13 -04:00
Darryl Miles 2c8c60510b plot/plotRutils.c: Multiplication result converted to larger type
Fix code scanning alert no. 56: Multiplication result converted to larger type (#67)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 14a1b21fb6 extract/ExtHier.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 159: Wrong type of arguments to formatting function (#66)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl L. Miles 4dc708aea2 ext2spice/ext2spice.c: Multiplication result converted to larger type
Applying similat fix to others in the file, promote to double ASAP.

Copilot Autofix: Retry and if the problem persists contact support.

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/46
2024-10-01 12:36:13 -04:00
Darryl Miles 98b5f57ea0 ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 48: Multiplication result converted to larger type (#63)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 3becc0e03f ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 47: Multiplication result converted to larger type (#62)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles a6db54c0b7 ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 45: Multiplication result converted to larger type (#61)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 7e04089872 ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 44: Multiplication result converted to larger type (#60)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles cde5418e7d ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 43: Multiplication result converted to larger type (#59)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 9327388ae0 ext2spice/ext2hier.c: Multiplication result converted to larger type
Fix code scanning alert no. 42: Multiplication result converted to larger type (#65)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 147ca7a61f ext2spice/ext2hier.c: Multiplication result converted to larger type
Fix code scanning alert no. 40: Multiplication result converted to larger type (#64)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles fe39d889f0 plot/plotRutils.c: Multiplication result converted to larger type
Fix code scanning alert no. 54: Multiplication result converted to larger type (#56)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 86a6551f9b ext2spice/ext2hier.c: Multiplication result converted to larger type
Fix code scanning alert no. 37: Multiplication result converted to larger type (#58)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 82bec60ccf ext2spice/ext2hier.c: Multiplication result converted to larger type
Fix code scanning alert no. 36: Multiplication result converted to larger type (#57)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 691c27081f drc/DRCcif.c: Multiplication result converted to larger type
Fix code scanning alert no. 34: Multiplication result converted to larger type (#54)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 1fb82e7225 database/DBtiles.c: Multiplication result converted to larger type
Fix code scanning alert no. 30: Multiplication result converted to larger type (#55)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles d8b886aa1d debug/debugFlags.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 67: Wrong type of arguments to formatting function (#45)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 846f2b4cb1 debug/debugFlags.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 68: Wrong type of arguments to formatting function (#46)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 40f96faff8 plot/plotPNM.c: Multiplication result converted to larger type
Fix code scanning alert no. 55: Multiplication result converted to larger type (#47)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 5ffc74d915 lef/defWrite.c: Multiplication result converted to larger type
Fix code scanning alert no. 53: Multiplication result converted to larger type (#48)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 1a351efd56 extract/ExtBasic.c: Multiplication result converted to larger type
Fix code scanning alert no. 52: Multiplication result converted to larger type (#49)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 00086817a4 extract/ExtCouple.c: Multiplication result converted to larger type
Fix code scanning alert no. 51: Multiplication result converted to larger type (#50)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles d6cc790d48 extflat/EFvisit.c: Multiplication result converted to larger type
Fix code scanning alert no. 50: Multiplication result converted to larger type (#51)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 6cae64edc5 drc/DRCbasic.c: Multiplication result converted to larger type
Fix code scanning alert no. 35: Multiplication result converted to larger type (#53)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 5a8cdb68d0 ext2spice/ext2spice.c: Multiplication result converted to larger type
Fix code scanning alert no. 49: Multiplication result converted to larger type (#52)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles f809b2dfac graphics/grTk1.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 98: Wrong type of arguments to formatting function (#44)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 9096946a12 windows/windDebug.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 130: Wrong type of arguments to formatting function (#43)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 3848ec7b4e extract/ExtHier.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 71: Wrong type of arguments to formatting function (#37)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl L. Miles 2703f55449 extract/ExtTest.c: Too few arguments to formatting function
A bit of a guess based on context.

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/58
        https://github.com/dlmiles/magic/security/code-scanning/59
2024-10-01 12:36:13 -04:00
Darryl Miles 4ddd0624cb gcr/gcrDebug.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 97: Wrong type of arguments to formatting function (#41)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl L. Miles fc20977fa5 gcr/gcrDebug.c: (intmax_t) %ld Wrong type of arguments to formatting function
Mutiple items per line.

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/87
2024-10-01 12:36:13 -04:00
Darryl L. Miles aa703a67b7 resis/ResDebug.c: %.2f Wrong type of arguments to formatting function
Applied same fix as other patch for line below;

Copilot Autofix: did not infer the same fix for same vaiable from line next to it.

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/158
2024-10-01 12:36:13 -04:00
Darryl Miles d1dc038cb7 windows/windDisp.c: Redundant null check due to previous dereference
Fix code scanning alert no. 133: Redundant null check due to previous dereference (#40)

* Update windDisp.c

* DLM - AI wanted to guard the '*area' dereference in if() statement, but the code path above has address of '&' operator for the assignment to 'area' so it must always be non-null.  So I rejected this approach and removed the extra null check, replacing it with an assert().

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 499ac84ac0 database/DBio.c: Redundant null check due to previous dereference
Fix code scanning alert no. 132: Redundant null check due to previous dereference (#39)

* Update DBio.c

* AI wanted to move guard 'pathptr != NULL' up to 1953, but it is assigned to guaranteed non-null in every assignment above and only incremented or dereferenced.

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles f976005d2d resis/ResMerge.c: Too few arguments to formatting function
Fix code scanning alert no. 64: Too few arguments to formatting function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 3c90bbbe1f lef/defWrite.c: Call to function with fewer arguments than declared parameters
Fix code scanning alert no. 23: Call to function with fewer arguments than declared parameters (#38)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl L. Miles f69b02b092 sim/SimExtract.c: extEnumTilePerim() Call to function with fewer arguments than declared parameters
This is a complete guess based on function parameter types and the locallity of the 'pNum' value.

This error predates the 2017 Initial Commit git history.

Copilot Autofix rejected: extEnumTilePerim(tile, devptr->exts_deviceSDTypes[i],
   SimTransTerms, (ClientData) &transistor, (ClientData) NULL );

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/26
2024-10-01 12:36:13 -04:00
Darryl Miles fdc81f5eec windows/windDebug.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 129: Wrong type of arguments to formatting function (#24)

* Update windDebug.c

* AI wanted "%p", DLM changed to (intmax_t) "%lx"

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles cf90d50999 grouter/grouteMaze.c: Wrong type of arguments to formatting function
* Fix code scanning alert no. 99: Wrong type of arguments to formatting function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update grouteMaze.c

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 77c1082886 grouter/grouteTest.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 100: Wrong type of arguments to formatting function (#31)

* Update grouteTest.c

* AI suggested just "%p", DLM modified to used intmax_t cast.

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 21924ec151 extract/ExtTech.c: Too few arguments to formatting function
Fix code scanning alert no. 61: Too few arguments to formatting function (#35)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl Miles 66297bd7d0 extract/ExtTech.c: Too few arguments to formatting function
Fix code scanning alert no. 60: Too few arguments to formatting function (#36)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:13 -04:00
Darryl L. Miles 4359aa8d4b commands/CmdWizard.c: %x => (intmax_t) %lx
Wrong type of arguments to formatting function

Looks like SPICE comment, change maintains hex without 0x prefix in portable way.

Copilot Autofix rejected: TxPrintf("%p\n", tp);

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/65
2024-10-01 12:36:13 -04:00
Darryl L. Miles 4f5eb7da2d ext2spice/ext2spice.c: %x => (intmax_t) %lx
Wrong type of arguments to formatting function

Looks like SPICE comment, change maintains hex without 0x prefix in portable way.

Copilot Autofix rejected: TxError("** %s (%p)\n", nsn, node);

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/70
2024-10-01 12:36:12 -04:00
Darryl Miles 0619cf4291 extract/ExtBasic.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 140: Incorrect return-value check for a 'scanf'-like function (#23)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles c16c770d7a extract/ExtBasic.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 138: Incorrect return-value check for a 'scanf'-like function (#22)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 91ec4e4cb8 resis/ResRex.c: Wrong type of arguments to formatting function
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 9f39380b6a resis/ResDebug.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 109: Wrong type of arguments to formatting function (#27)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 6946ea6845 plow/PlowTest.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 106: Wrong type of arguments to formatting function (#30)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 384e59ea98 plow/PlowTest.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 104: Wrong type of arguments to formatting function (#29)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 318993cb7b plow/PlowTest.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 103: Wrong type of arguments to formatting function (#28)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 82aa62e65d database/DBcellsrch.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 66: Wrong type of arguments to formatting function (#33)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl L. Miles e896377ead extflat/EFantenna.c: EFDone() Call to function with fewer arguments than declared parameters
Passing NULL is valid in efFreeNodeList() to not perform callback..

extflat/EFdef.c:
^231a299 (2017-04-25 08:41:48 -0400  97) void
5e3c26c9 (2021-12-13 18:05:53 -0500  98) EFDone(func)
5e3c26c9 (2021-12-13 18:05:53 -0500  99)     int (*func)();

commit 5e3c26c95a (tag: 8.3.241)
Date:   Mon Dec 13 18:05:53 2021 -0500

extflat/EFdef.c:97
void EFDone(int (*func)());

extflat/EFbuild.c:2180
void efFreeNodeList(EFNode *head, int (*func)());

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/16
2024-10-01 12:36:12 -04:00
Darryl L. Miles 4d81a77bf3 extcheck/extcheck.c: EFDone() Call to function with fewer arguments than declared parameters
Passing NULL is valid in efFreeNodeList() to not perform callback..

extflat/EFdef.c:
^231a299 (2017-04-25 08:41:48 -0400  97) void
5e3c26c9 (2021-12-13 18:05:53 -0500  98) EFDone(func)
5e3c26c9 (2021-12-13 18:05:53 -0500  99)     int (*func)();

commit 5e3c26c95a (tag: 8.3.241)
Date:   Mon Dec 13 18:05:53 2021 -0500

extflat/EFdef.c:97
void EFDone(int (*func)());

extflat/EFbuild.c:2180
void efFreeNodeList(EFNode *head, int (*func)());

CodeQL: none (grep found this?)
2024-10-01 12:36:12 -04:00
Darryl L. Miles c8e00ef494 ext2spice/ext2spice.c: EFDone() Call to function with fewer arguments than declared parameters
Passing NULL is valid in efFreeNodeList() to not perform callback..

extflat/EFdef.c:
^231a299 (2017-04-25 08:41:48 -0400  97) void
5e3c26c9 (2021-12-13 18:05:53 -0500  98) EFDone(func)
5e3c26c9 (2021-12-13 18:05:53 -0500  99)     int (*func)();

commit 5e3c26c95a (tag: 8.3.241)
Date:   Mon Dec 13 18:05:53 2021 -0500

extflat/EFdef.c:97
void EFDone(int (*func)());

extflat/EFbuild.c:2180
void efFreeNodeList(EFNode *head, int (*func)());

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/20
        https://github.com/dlmiles/magic/security/code-scanning/21
        https://github.com/dlmiles/magic/security/code-scanning/22
2024-10-01 12:36:12 -04:00
Darryl L. Miles d2ae7f78e8 ext2sim/ext2sim.c: EFDone() Call to function with fewer arguments than declared parameters
Passing NULL is valid in efFreeNodeList() to not perform callback..

extflat/EFdef.c:
^231a299 (2017-04-25 08:41:48 -0400  97) void
5e3c26c9 (2021-12-13 18:05:53 -0500  98) EFDone(func)
5e3c26c9 (2021-12-13 18:05:53 -0500  99)     int (*func)();

commit 5e3c26c95a (tag: 8.3.241)
Date:   Mon Dec 13 18:05:53 2021 -0500

extflat/EFdef.c:97
void EFDone(int (*func)());

extflat/EFbuild.c:2180
void efFreeNodeList(EFNode *head, int (*func)());

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/11
2024-10-01 12:36:12 -04:00
Darryl L. Miles 1360f962a1 calma/CalmaRdcl.c: calmaFindCell() Call to function with fewer arguments than declared parameters
The 'predefined' pointer argument to calmaFindCell() is for an optional return value, so must be
NULL when feature is not used.

Copilot Autofix rejected: newdef = calmaFindCell(newname, someSecondArgument);

calma/CalmaRdcl.c
1c822652 (2020-12-04 16:56:51 -0500 1359)     bool *predefined; /* If this cell was in memory before the GDS
1c822652 (2020-12-04 16:56:51 -0500 1360)                        * file was read, then this flag gets set.
1c822652 (2020-12-04 16:56:51 -0500 1361)                        */

commit 1c82265244 (tag: mpw-one-a, tag: 8.3.92)
Date:   Fri Dec 4 16:56:51 2020 -0500

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/6
        https://github.com/dlmiles/magic/security/code-scanning/5
2024-10-01 12:36:12 -04:00
Darryl L. Miles 7feec63580 cif/CIFgen.c: CmdFindNetProc() Call to function with fewer arguments than declared parameters
The 'isvalid' pointer argument to CmdFindNetProc() is for an optional return value, so must be
NULL when feature is not used.

Copilot Autofix rejected: ttype = CmdFindNetProc(netname, CIFDummyUse, &bbox, FALSE, additional_arg1, additional_arg2);

commands/CmdFI.c
cfb81101 (2022-03-30 13:02:12 -0400 1584)     bool *isvalid;

commit f89d52dbcc (tag: 8.3.253)
Date:   Thu Jan 6 13:29:43 2022 -0500

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/7
2024-10-01 12:36:12 -04:00
Darryl L. Miles ce1e027c55 resis/ResSimple.c: ResGetDevice(): Call to function with fewer arguments than declared parameters
gparams.rg_ttype seems to be the only value of the correct type that has connectivity with the callsite.

Copilot Autofix rejected: ResGetDevice(gparams.rg_devloc, /* second argument */);

resis/ResSimple.c
9aa39f82 (2021-05-25 22:41:52 -0400 1039)           resDevice *res = ResGetDevice(gparams.rg_devloc);

commit 9aa39f820f (tag: 8.3.169)
Date:   Tue May 25 22:41:52 2021 -0400
2024-10-01 12:36:12 -04:00
Darryl L. Miles d297b99953 select/selOps.c: CmdFindNetProc() Call to function with fewer arguments than declared parameters
The 'isvalid' pointer argument to CmdFindNetProc() is for an optional return value, so must be
NULL when feature is not used.

Copilot Autofix rejected: ttype = CmdFindNetProc(lab1, use, &rect, FALSE, additionalArg);

commands/CmdFI.c
cfb81101 (2022-03-30 13:02:12 -0400 1584)     bool *isvalid;

commit f89d52dbcc (tag: 8.3.253)
Date:   Thu Jan 6 13:29:43 2022 -0500

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/25
2024-10-01 12:36:12 -04:00
Darryl L. Miles fff3be2f29 utils/main.c: DefRead() Call to function with fewer arguments than declared parameters
Resolution maintains behaviour closest to original behaviour from a37fc1e2

Copilot Autofix no offered.

related git blame lef/defRead.c:
cfb81101 (2022-03-30 13:02:12 -0400 2388)     bool annotate;
f7df5e7c (2022-06-24 15:22:53 -0400 2389)     bool noblockage;

related commits:

commit cfb81101ec
Date:   Wed Mar 30 13:02:12 2022 -0400

commit f7df5e7c86 (tag: 8.3.315)
Date:   Fri Jun 24 15:22:53 2022 -0400

commit a37fc1e242
Date:   Thu Mar 5 14:29:54 2020 -0500

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/29
2024-10-01 12:36:12 -04:00
Darryl L. Miles 3db35216b9 utils/main.c: LefRead() Call to function with fewer arguments than declared parameters
Looks like -1 is accepted as placeholder, maybe it should be the
temporary->fn (filename mtime?).

Copilot Autofix rejected: LefRead(temporary->fn, FALSE, NULL);

related git blame utils/main.c:
8e80644d (2022-01-22 13:30:11 -0500 2078)     int lefTimestamp;         /* If not -1, use the value pointed to
8e80644d (2022-01-22 13:30:11 -0500 2884)     int lefTimestamp;

related commit:
commit 8e80644dd7
Date:   Sat Jan 22 13:30:11 2022 -0500

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/28
2024-10-01 12:36:12 -04:00
Darryl L. Miles 49f4daa715 utils/main.c: Call to function with fewer arguments than declared parameters
Copilot Autofix rejected: DBFileRecovery(MainFileName);

database/DBio.c looks to take NULL as a value for automatic recovery.

Related commits:
commit 231a299b16 (tag: 8.2.0)
Date:   Tue Apr 25 08:41:48 2017 -0400
    Initial commit at Tue Apr 25 08:41:48 EDT 2017 by tim on stravinsky
2024-10-01 12:36:12 -04:00
Darryl L. Miles f47a173a49 commands/CmdLQ.c: Call to function with fewer arguments than declared parameters
No AI resolution.

The NULL added is cdata which looks to be opaque callback user-defined-pointer,
this is not used in the method printPropertiesFunc() as a possible 3rd argument.

CodeQL: https://github.com/dlmiles/magic/security/code-scanning/157
2024-10-01 12:36:12 -04:00
Darryl Miles 88a1a9b166 utils/undo.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 120: Wrong type of arguments to formatting function (#17)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 9f052c0e4d utils/undo.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 117: Wrong type of arguments to formatting function (#16)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 8f60ed472b textio/txCommands.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 116: Wrong type of arguments to formatting function (#19)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles a307e9d052 textio/txCommands.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 115: Wrong type of arguments to formatting function (#20)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 9295240047 textio/txCommands.c: Wrong type of arguments to formatting function
Fix code scanning alert no. 114: Wrong type of arguments to formatting function (#21)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 573e59da44 database/DBcellname.c: Call to function with fewer arguments than declared parameters
Fix code scanning alert no. 10: Call to function with fewer arguments than declared parameters (#14)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles a5f7cbd597 database/DBcellcopy.c: Call to function with fewer arguments than declared parameters
Fix code scanning alert no. 9: Call to function with fewer arguments than declared parameters (#15)

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles c89455782b cmwind/CMWcmmnds.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 134: Incorrect return-value check for a 'scanf'-like function (#13)

* Create codeql.yml

* Fix code scanning alert no. 134: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 886a0212e8 database/DBtech.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 135: Incorrect return-value check for a 'scanf'-like function (#12)

* Create codeql.yml

* Fix code scanning alert no. 135: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 2a00ab7eb8 extract/ExtTech.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 136: Incorrect return-value check for a 'scanf'-like function (#11)

* Create codeql.yml

* Fix code scanning alert no. 136: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles e66e3b32ad extract/ExtBasic.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 149: Incorrect return-value check for a 'scanf'-like function (#10)

* Create codeql.yml

* Fix code scanning alert no. 149: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 96c7e283c0 gcr/gcrDebug.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 137: Incorrect return-value check for a 'scanf'-like function (#9)

* Create codeql.yml

* Fix code scanning alert no. 137: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 4ca98dc31b graphics/grCMap.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 150: Incorrect return-value check for a 'scanf'-like function (#8)

* Create codeql.yml

* Fix code scanning alert no. 150: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update grCMap.c

* AI suggested '< 1', DLM edited to '<= 0' easier for a human to reason about ?

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 39e76f3f31 graphics/grDStyle.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 151: Incorrect return-value check for a 'scanf'-like function (#7)

* Create codeql.yml

* Fix code scanning alert no. 151: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update grDStyle.c

* AI suggested '< 1', DLM edited to '<= 0' easier for a human to reason about ?

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 64d94ae588 router/rtrCmd.c: Incorrect return-value check for a 'scanf'-like function
Fix code scanning alert no. 156: Incorrect return-value check for a 'scanf'-like function (#6)

* Create codeql.yml

* Fix code scanning alert no. 156: Incorrect return-value check for a 'scanf'-like function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 4374a1918e lef/defWrite.c: Too few arguments to formatting function
Fix code scanning alert no. 63: Too few arguments to formatting function (#3)

* Create codeql.yml

* Fix code scanning alert no. 63: Too few arguments to formatting function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles 51b8161a21 lef/defWrite.c: Too few arguments to formatting function
Fix code scanning alert no. 62: Too few arguments to formatting function (#1)

* Create codeql.yml

* Fix code scanning alert no. 62: Too few arguments to formatting function

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl Miles fed93c200d gcr/gcrShwFlgs.c: Likely overrunning write
Fix code scanning alert no. 2: Likely overrunning write (#5)

* Fix code scanning alert no. 2: Likely overrunning write

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update gcrShwFlgs.c

* AI added snprintf(), DLM increased buffer for enough space for rounded/aligned 64bit %p

---------

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2024-10-01 12:36:12 -04:00
Darryl L. Miles 881115a856 database/DBio.c: Fix MAGIC_WRAPPER #endif to fix CI WASM build
Misplaced #endif causing the build to break when option enabled
error introduced in 3dc5018

Related commits:

commit 68a088943f
Date:   Tue Sep 12 11:12:00 2023 -0400

commit 3dc5018af4 (tag: 8.3.477)
Date:   Fri May 3 21:43:27 2024 -0400
2024-09-30 23:00:00 +01:00
Tim Edwards f3b08ad470 Corrected an error that was introduced in the August 3 commit and
which prevents the "Ctrl-P" key from raising the .params window;
the underlying error is that the original error in the "property"
command was a disagreement about where "argstart" is placed.  The
command was fixed to make the "property" command work correctly.
However, the solution made "argstart" wrong when using the command
"cellname property".  Now both uses are handled correctly.
2024-09-25 21:26:41 -04:00
Tim Edwards 427547c927 Changed the behavior of renaming conflicting cells from
"<name>#<num>" to "<name>__<num>", because the use of "#" is
considered illegal for cell names in GDS.
2024-09-15 17:33:51 -04:00
Tim Edwards 974621ebe7 Corrected a missing pointer to integer cast in code that was
added fairly recently when getting rid of crashes related to
commands operating on non-edit cells.  The lack of a cast was
prevening compilation on systems with more rigorous error
checking.
2024-08-30 01:48:38 -04:00
Tim Edwards 0c36365db8 Revised the file opening routine with respect to the search paths.
Previously, a file path beginning with "/", "./", or "../" would be
searched for verbatim and no searching would be done over paths.
This behavior now occurs for a leading "/" only.  File paths with
"./" or "../" will search for the file with the path verbatim, then
proceed to search for the file with each search path prepended to
the filename as usual.  This solves a problem for reusable, non- PDK
IP blocks, where the IP block may have an abstract view pointing to
a GDS file which is specified as being located at "../gds/<file>".
This file would not be found if the IP block was included into
another project.  Now it can be done if the path to the IP is given
by "addpath".
2024-08-16 17:45:10 -04:00
Tim Edwards f3bfde60f0 Change to ext2spice which should solve the problem of ports no
longer being output in order after flattening a circuit.
2024-08-06 11:17:27 -04:00
Tim Edwards 155f19a6d8 Corrected an issue causing a crash condition when using "extract
unique" on a flattened layout (some labels end up NULL and the
NULL condition needs to be checked).  Also remembered to update
VERSION, which was missed on the last commit.
2024-08-04 11:37:54 -04:00
Tim Edwards b441d668bd Corrected the "property" command parsing, which had a print statement
without an argument, resulting in random things getting printed to
the output when a property name does not exist.
2024-08-03 12:05:41 -04:00
Tim Edwards 81b5ac2079 Added two checks when loading a file to determine if two cells are
the same:  (1) If the inodes of the filename are the same, then the
cells are the same.  This avoids treating symbolic links as
different paths with different files;  (2) If both layouts are in
git repositories and the git repository commit hashes are the same,
then the cells are considered to be the same.  This allows projects
to be cloned into other projects as dependencies and used in
multiple places without magic treating them as different layouts.
2024-06-13 15:39:27 -04:00
Tim Edwards e9db9ecbc9 Another correction that avoids a crash condition when attempting
to do an instance array resizing on an uneditable cell.
2024-05-25 21:15:01 -04:00
Tim Edwards cf5fd867f4 Corrected another error related to read-only views in which magic crashes when
attempting to place a generated cell in the layout, as pointed out by Mark Martin
in github Issue #309.
2024-05-24 12:43:36 -04:00
Tim Edwards 291ba96285 Corrected a bad statement running Tcl_NewListObj() that fails to
assign the result to anything, causing later uses of variable
"lobj" to have an unitialized value and potentially causing a
crash condition.  Thanks to Risto Bell for pointing out the
error.
2024-05-13 21:51:59 -04:00
Tim Edwards e4c28ef3bf Corrected an issue introduced in version 8.3.471 when trying to fix
some of the "select" command syntax;  the code change caused the
"select top cell" command to behave the same as "select cell".
There was no specific code for handling "top", so now there is.
2024-05-12 15:54:40 -04:00
Tim Edwards f0c3ec33d6 Modified the "lef nocheck" command to take the argument "*", meaning
that no nets will be checked for antenna gate and diffusion area,
and no antenna properties will be output to the LEF file.  This can
greatly speed up LEF output file generation for a large design.
Thank you to Tamas Hubai for the code patch.
2024-05-11 20:48:35 -04:00
Tim Edwards 9dec47c9b2 Corrected a fairly long-standing error in which the MASKHINTS_ values
in the .mag file "properties" list are not handled as being in
database units during .mag file reading and writing (although they
do track internally), making them subject to being scaled incorrectly
and change between a read and a write.  Thanks to Sylvain Munaut for
identifying the problem.
2024-05-10 13:05:06 -04:00
Tim Edwards fd2b1eb9ee Added code that when running "extract unique" always prefers to
change a non-port label name instead of a port name whenever it
finds one of each with the same text on different nets.
2024-05-07 16:20:35 -04:00
Tim Edwards ca99d0b76a Altered the behavior of handling labels when a layer under a label
is erased.  In cases where magic would previously unattach the
label from the material and attach it to "space", now magic will
instead adjust the size of the label to stay entirely on the
material.  That avoids a common error of losing label or port
connections when the material is trimmed back.  Thanks to Philipp
Guhring for suggesting this implementation (github issue #305).
2024-05-04 21:12:55 -04:00
Tim Edwards efccdbf341 Made some changes to the extresist code to handle the case where
a transistor's first tile record is a well or substrate type;
normally this is avoided, but if that's the only device terminal
that connects to the node, it will be used.  Also changed the
code to not report a failure when space is found under the
device, when space is allowed as a substrate type.  Instead it
will print a message that the substrate is not being extracted as
a resistive network.  However, note that the correct solution is
to do what the regular "extract" code does, which is to paint the
substrate type in the cell area first, so that there are valid
tile types to use for extracting the substrate network.
2024-05-04 20:16:55 -04:00
Tim Edwards 3dc5018af4 Changed the automatic search for tech files from the "tech" line in
a .mag file to include the original system path.  This restores the
ability to find the tech file for any cell created using the old
SCMOS technologies.  This method is as problematic as is the way
all SCMOS tech files used the same name "scmos".  But at least it
preserves backwards-compatible behavior (behavior prior to 8.3.471).
This commit corrects github issue #306.
2024-05-03 21:43:27 -04:00
Tim Edwards fe9ca3a4ce Corrected the routine that parses MASKHINTS_* in cell properties to
avoid an infinite loop in the case that the mask hint does not have
a number of values that is a multiple of 4.
2024-05-01 13:45:00 -04:00
Tim Edwards 0ae54b500a Added the ability to track the first CellDef to fail to read and
report it after "Failure to read in entire sub-tree".  This will
not report every failing cell (since it quits reading after the
first failure) but will avoid the existing issue of printing
nothing and leaving the user with no feedback as to which cell
was the problem.
2024-04-29 17:43:37 -04:00
Tim Edwards 41e65b5214 Committing a patch to prevent segfaulting during "extresist" when
non-Manhattan geometry is analyzed for resistance extraction.
This patch merely prevents the crash condition.  It does not
solve the root of the problem, which is that split tiles can
belong to two different nets, but the tile can hold extraction
information for at most one of those nets.
2024-04-16 20:51:52 -04:00
Tim Edwards 3a1f4dc816 Removed an "if" statement that was apparently designed to
reduce the amount of redundant painting done by the connectivity
search algorithm, but which was preventing composed types (such
as FET gates) from getting added to a net if one of the composing
types (such as poly) was drawn over the device in an ancestor
cell.  Removing the "if" statement does not appear to have any
significant performance impact, so this change is being adopted.
2024-04-11 15:18:25 -04:00
Tim Edwards 82d64aa4b1 Corrected an issue with passing a Tcl script as a command-line
argument.  For interactive magic in the Tcl/Tk wrapper, the
"-nowindow" option was appended to the command line.  But for
Tcl scripts on the command line, all arguments following the
script name are considered arguments of the script.  So the
"-nowindow" argument has to be inserted at the beginning of
the command line as the first argument after "magic".
2024-04-10 20:51:05 -04:00
Tim Edwards 60049f3702 Modified the "select" command routine to get rid of the very hack
method of messing with the argument count when using qualifiers
like "less" and "more".  Now it keeps a separate count of the
number of non-qualifier arguments.
2024-04-08 17:59:53 -04:00
Tim Edwards 38d890c407 Made a slight modification to the "lef write -hide" routine;
previously, MASTERSLICE layers would not be added to obstruction
layers made by "-hide".  However, an nwell, for example, that
stuck outside of a prBoundary *would* be recorded, which was
inconsistent.  Resolved this by allowing MASTERSLICE layers
in the OBS block, but only for layers that are not a substrate
type.  NOTE:  It may be better to just insist that a MASTERSLICE
layer define an obstruction type in the "lef" section of the
tech file, and treat it like routing obstructions.  Alternatively,
one may question whether special obstruction types are needed at
all, as one could simply define an obstruction as a type without
a port label.
2024-04-08 14:10:46 -04:00
Tim Edwards 71f4dd2f9f Discovered that the non-Euclidean distance checks had not been
completely implemented for the "cifwidth" and "cifspacing" rules,
resulting in those rules being Manhattan distance checks.  Finished
the implementation (duplicating code from DRCbasic.c, with
appropriate scaling to CIF coordinates).
2024-04-06 16:36:31 -04:00
Tim Edwards 8b3524575f Corrected the failure to copy mask hints to the flattened DRC yank
cell.  Otherwise, DRC errors corrected by mask hints will get
flagged.
2024-04-06 15:03:37 -04:00
Tim Edwards 4e5af57f3c Corrected an issue with "instance celldef" when the instance name
contains brackets which are not indicating a cell array.  Also
fixed a related issue with the PDK toolkit code, in which the
gencell routines fail if an instance name contains brackets which
are not indicating a cell array.
2024-04-05 17:47:44 -04:00
Tim Edwards 9800d98dee Corrects "ext2spice hierarchy off" when subcircuits with ports are
present.  Note, however, this fix breaks the use of "ext2spice
subcircuit descend off" because subcircuits are always descended
into.  It's not clear that "subcircuit descend off" worked at all
before, anyway.  That still needs fixing.
2024-04-02 21:55:57 -04:00
Tim Edwards d0f6dab896 Corrected issue from github issue tracker #297, where "Import SPICE"
fails on instances with names containing brackets.
2024-04-01 16:42:10 -04:00
Tim Edwards bfd938b5e2 Correction to the previous bug fix: The layer was correct and
did not need to be changed, but the line below it that depended
on the layer being a contact type was wrong;  the contact had
to be identified independently of the last layer type, which
might not be the contact cut type.
2024-03-20 22:15:41 -04:00
Tim Edwards fede9d5c4d Fixed an error when reading a DEF file using generated vias in a
non-default rule.  The code was first failing to identify the via
cut type from the generated via record, and then it was failing
to return to the non-default rule width after the route exits the
via.  Both issues have been fixed.  Thanks to Sylvain Munaut for
providing a reproducible test case.
2024-03-20 17:19:45 -04:00
Tim Edwards 54773957c9 Corrected an issue with annotating a layout from a LEF file; if
new port labels are created for an existing port, then they must
take the existing port number.  The code was previously causing
collisions between port numbers on different pins.
2024-03-18 16:25:49 -04:00
Tim Edwards cb73ebfab0 Corrected an error in lefWrite where SelectClear() is called
without SelectRootDef being set, which causes SelectClear() to
return without doing anything.  However---question is why
SelectClear() needs SelectRootDef to be non-NULL since it is
clearing the selection, not the selection source.  For now, just
patching the failing case, not trying to mess with the whole
selection mechanism.
2024-03-08 12:28:29 -05:00
Tim Edwards eeeaf49ec7 Corrected an error in defGetType() that incorrectly looks at a
lefLayer's "via" record even when the layer might not be a via,
causing potential issues with uninitialized variables.  Not sure
if this is related to the bug that started this investigation,
but it was the only thing that looked relevant.
2024-03-08 09:33:13 -05:00
Tim Edwards 191bff6c47 Modified the schematic-to-layout script to be better at being
used in a re-entrant manner.  Applied to an existing layout,
it will no longer keep generating new instances and ports over
top existing ones.  Could use improvement by attempting to
retain the location of a device when the instance changes
device type (such as when a device parameter was changed in
the netlist).  However, the current set of changes should
help, whether the re-entrant use is purposeful or accidental.
2024-02-27 15:41:17 -05:00
Tim Edwards 3691b53dde Was given a use case by Carsten Wulff (github issue #289) that
fails in the bplane code for subcell binning.  It is still not
clear why this example causes a failure when the bplane code
has been working for so long.  However, simply checking for the
BT_ARRAY bit at one additional point in the code prevents the
crash condition and appears not to have caused any issue with
the database.
2024-02-19 12:54:51 -05:00
Tim Edwards 814fb6f18d Corrected two separate issues with R-C extraction: (1) There was
a method that failed to work on devices with complex shapes on the
device recognition layer, such as snake-geometry resistors.  (2)
The use of contact type "xpc" in the sky130 tech file as its own
contact residue caused the contact tracing in extresist to fail.
I opted to keep the unorthodox contact description in the tech
file and wrote an extension to a routine in extresist to handle
the case.
2024-02-18 14:04:21 -05:00
Tim Edwards 038f02d2b2 Updated the version to go along with the merge of pull request #288
from Ryan Schmidt, changing regular expression strings in the python
preprocessor to raw string types so that they don't produce warnings
in python 3.12.
2024-01-23 15:34:05 -05:00
Ryan Carsten Schmidt 8a93d6136b
Use raw strings in preproc.py
Avoids "SyntaxWarning: invalid escape sequence" with Python 3.12.
2024-01-23 09:38:23 -06:00
Tim Edwards b08c785c1d One correction to the previous commit to restore the original
behavior when a child coordinate is not specified;  otherwise,
the original code's setting of the child reference point to the
bounding box lower left causes the lower left point to be
used always, which is not how the getcell command is supposed to
function.
2024-01-21 16:29:02 -05:00
Tim Edwards 7f5571768f Corrected a long-standing error, which caused "getcell child <point>"
to place a cell in a meaningless position for any rotation and flip
combination other than zero.  The issue was that the reference point
was not rotated along with the cell.
2024-01-21 15:54:49 -05:00
Tim Edwards 5f6ba3be69 Corrected an error when using the "instance" command with an instance
name.  The instance search routine was not rejecting internal cells,
and so would choose, e.g., a selection cell and reject it because it
was not the edit cell.
2024-01-21 11:00:19 -05:00
Tim Edwards 63109229f4 Corrected an error in the "cifarea" rule that had previously been
fixed for "cifwidth" and "cifspacing", in which the rule distance
is incorrectly multiplied by the expander (in the case of area,
multiplied by the expander squared).
2024-01-14 17:35:39 -05:00
Tim Edwards 6b8239e258 Corrected a recently-discovered error in the "minimum area" DRC rule.
The fractional part of the rule distance (modulus after scaling)
does not fit in the unsigned char variable unless it is first
divided by the scalefactor (also requires multiplying up by the same
amount when scaling the other direction).  The truncation of the
unsigned char value was causing the minimum area value to be off by
a small amount, causing false negatives (no DRC violation is shown
when metal area is slightly smaller than the minimum allowed).
2024-01-14 15:19:39 -05:00
Tim Edwards a816da60f9 Updated the HTML command reference files to refer to magic version 8.3,
since all of the title images still had 8.2, and the title text still
said 7.3 or 7.4, having not been updated for a long time.
2024-01-09 16:37:00 -05:00
Tim Edwards 006c07082b Inadvertently introduced a segfault on exit on the last commit,
while trying to get rid of a compiler warning.  Fixed by this
update.
2024-01-01 15:36:05 -05:00
Tim Edwards 8f9c328150 Got rid of two compiler warnings; one recently introduced, the
other from some time ago.
2023-12-30 15:00:18 -05:00
Tim Edwards 68e537b968 Added a tile unfracture routine at the end of CIFMakeManhattanPath
that resolves issues of excessive tile fracturing during read-in
of GDS (or CIF) polygons and paths that have non-manhattan geometry.
This was particularly noticeable when reading the GF180MCU corner
I/O cell, which ended up being something close to a worst-case
scenario.
2023-12-30 14:10:09 -05:00
Tim Edwards 0cd4a10036 Updated version to go along with the merge of pull request #283
from Vasil Yordanov, which changes the toolbar icon into a
scrollable list with layer names, much better than the former
minimalist array of icons.
2023-12-15 15:58:20 -05:00
Vasil Yordanov affd68aad9 EDIT: wrapper maketoolbar method refactored into a separate script, with changes to the toolbar. Reorder layers functionality added as well 2023-12-15 15:54:05 -05:00
Tim Edwards 943e0d4d8d Updated version to go along with the merge of pull request #282 from
Donn (corrects a pointer incorrectly passed to dbReadOpen() that
should have been a boolean).
2023-12-04 10:33:05 -05:00
Mohamed Gaber 9e6d1d789e More explicit pointer truthiness check
`magic/database/DBio.c::DBOpenOnly` calls `dbReadOpen(CellDef *, bool, bool, int)` with a pointer for the second argument. While technically valid C, newer compilers (Clang 16) have recently frowned upon implicit pointer-to-int conversion, requiring the flag `-Wno-int-conversion` or else an error is raised.

Given that there is one such instance in the codebase, I think fixing it would be the simplest solution.
2023-12-04 17:10:11 +02:00
Tim Edwards 83ed73ac52 One more change to the "extresist" code which prevents extresist
from substituting a regular label for a port during a node merge,
which can cause ports to become orphaned.
2023-11-27 16:18:43 -05:00
Tim Edwards 84af801608 Fixed two independent errors, both of which can cause devices to be
missing from a netlist generated by ext2spice with the "extresist"
option enabled.  The first had to do with some parts of nets being
given alias names for a net, and the second was caused during
"extresist" and would also result in error messages about devices
missing terminals.
2023-11-24 16:51:26 -05:00
Tim Edwards 21336607e0 Added checks for GDS scalefactor (DBU) both when reading GDS in
"gds readonly true" mode and when writing a GDS file in full-dump
mode.  Reading or writing a file with an incompatible DBU is now
prohibited.  This is not a great solution, as it forces the
original file to be rewritten with a different DBU.  Preferably
there should be code to scale the units during a dump, but that
needs to be coded.
2023-11-21 09:44:16 -05:00
Tim Edwards 5352a23577 Updated the SPICE import routine in the toolkit so that it will
correctly handle subcircuits that are used before they are
defined, and will determine whether the imported spice does or
does not contain a top level, and either return to the top level
or any top level cell found in the netlist.
2023-11-15 11:46:22 -05:00
Tim Edwards d09b0e8c51 Corrected an error that can prevent capacitances to substrate from
being output if the substrate node is declared as a port.
2023-11-14 20:10:57 -05:00
Tim Edwards 11080465ad Corrected the Tcl exit hook routine so that it passes on the
client data value as the exit status value (this was not at
all clear from the documentation and required a bit of
experimentation).  The fix allows Tcl scripts to exit magic
with a non-zero status by invoking "exit" in Tcl.
2023-11-11 13:09:59 -05:00
Tim Edwards 7db77d47f1 Yet another fix to the ext2spice code handling output formatting
of SI values, this time to put the precision and the value in the
order that is generally more accepted.  The gcc compiler, at
least, doesn't seem to care which order they are given in.
2023-11-10 12:52:55 -05:00
Tim Edwards 1131085d0f Added "u" as a recognized suffix to dimensions, meaning the same
thing as "micron" or "um", since it is regularly used that way.
2023-11-10 09:45:32 -05:00
Tim Edwards 67d68717ca Corrected a typo in the ext2spice code as pointed out (with
corretion) user cgurleyuk on github.
2023-11-10 08:01:51 -05:00
Tim Edwards 8445f3eb5d Corrected ext2spice to avoid incorrect precision when writing out
values.  The "%.3g" format was changed to "%.*g" with a variable
precision that accounts for the actual precision required by the
manufacturing grid.
2023-11-05 11:00:30 -05:00
Tim Edwards 0894248e0a Updated version to go along with the merge of pull request #278
from user pinu-73 (updates to the MacOS install instructions
with additional information and explanation).
2023-11-02 10:11:10 -04:00
Dikshant 40e6a28ff6 appended macOS install file for XQuartz Display issue. 2023-11-02 18:08:03 +05:30
Tim Edwards df6333bb7b Modified the "makedbh.in" script ("makedbh", after running
configure) so that it does not use python-3.6-style f-strings,
and so is backwardly compatible with any python-3 revision.
2023-10-28 12:14:26 -04:00
Tim Edwards 22ea7a924f Corrected an extraction error that can cause an infinite loop
depending on the order of extraction devices.  Specifically, the
case of a source-drain tied FET was breaking out of a loop when
it should have been breaking out of a double loop.
2023-10-27 14:32:44 -04:00
Tim Edwards 7a9445ec30 Corrected the extraction offset, in which a parameter like "l"
can provide a delta offset such as "l+0.06", indicating that
the extraction model has a length larger than the drawn device.
Previously the value was assumed to be in microns but did not
scale between the .ext file and the SPICE netlist.  Corrected
so that it scales like the other parameter values, being
converted to internal units and tracking the internal grid
scale.
2023-10-24 20:29:04 -04:00
Tim Edwards 610c86a234 When writing a GDS file, there is a statement printed about each
cell being generated.  This statement does not disambiguate the
case where a cell is being ripped verbatim from GDS instead of
being generated from the magic database.  This print statement
has been split into two cases, and where a cell is being ripped
verbatim, the name of the file is indicated.  This provides better
information to the user.
2023-10-24 10:36:57 -04:00
Tim Edwards 98f3b39dc2 Two small tweaks on plot filename behavior: (1) "plot svg" without
a filename causes an error instead of generating a trash filename
or crashing, while (2) "plot pnm" with a filename that has the ".pnm"
extension does not add another ".pnm" extension to the end of it.
2023-10-17 20:01:39 -04:00
Tim Edwards fdcc178bcd After a discussion about "cifinput" rules, realized that there is
no way to implement boolean operators on labels, so any "label"
statement in the section can apply only to one magic layer.  This
is regularly violated in most (all?) techfiles (due mainly to lack
of explanation and guidance).  The addition of the "no-reconnect-
labels" option for cifinput made it worse, as it can cause a label
to be attached to the wrong layer and be stuck that way.  Even
without the option, an attachment to a non-connecting type is a
problem;  DIFF cannot simultaneously have a connection to both
ndiff and pdiff, so it will be one or the other, and the one not
connected can easily get labels moved to other nets.  To avoid
this:  (1) removed the "no-reconnect-labels" option, and (2) made
the automatic label reconnection smarter, as well as splitting it
into two different behaviors based on whether a label is being
created or manipulated from the command line (more or less the
original behavior) vs. being read from GDS or LEF.  The new rules
assume that labels attached to a GDS type will all map to the
same plane in magic.  To avoid excessive error messages from
existing tech files, a warning is issued only if "labels" changes
the plane of the target layer (a realistic solution rather than
the preferred one).  Also:  Fixed an error that causes a crash on
the "wizard" command "*watch" if the cell being observed is
read-only (see github issue #271).
2023-10-17 15:54:38 -04:00
Tim Edwards 5b29870fce Corrected an extraction issue in which an error message about
"unexpected asymmetric device" is printed prematurely, as it
is inside a loop checking over all device entries compatible
with a device type.  Also:  Flagged an issue with the "label"
keyword in the "cifinput" section of a tech file.  The "label"
keyword cannot be used in conjunction with boolean operators.
It can only connect labels on a specific GDS type to one magic
type.  Unfortunately, because this was not flagged before as
an error or warning, the incorrect usage has crept into a lot
of tech files.  This uncovers an underlying issue that labels
must be allowed to automatically reconnect types, which is
undermined by the "no-reconnect-labels" cifinput option.  That
issue will be addressed in an upcoming commit.
2023-10-16 17:29:05 -04:00
Tim Edwards 8798a3256c Corrected an error in which DRCStatus is set outside of an #ifdef
for MAGIC_WRAPPER, which is required.
2023-10-12 15:14:13 -04:00
Tim Edwards eda5f506f3 Made another change to the netlist-to-layout procedure so that it
better supports re-entrant use, especially for the use case where
the import was abandoned before saving, or the generated cells
were not saved (which is easy to do, because the top level cell
is always written out to disk, but the rest of the cells will only
be written when "writeall" is executed).  The new code detects
input cells that did not have any layout file (has flag "not-found"
after loading) and deletes them and their instances so that they
can be regenerated from scratch.
2023-10-06 19:38:53 -04:00
Tim Edwards 9e7c104d29 Corrected a small error in the device generator toolkit that fails
to pick up properties from an existing cell and prints an error
message instead.  This will likely cause non-default properties
of an instance to be lost if the SPICE import is used in a
re-entrant manner (not exactly a common use-case).
2023-10-06 17:51:40 -04:00
Tim Edwards ce6f7840db Backed up the version by one minor revision because I accidentally
upped it twice in one day.
2023-09-29 17:47:03 -04:00
Tim Edwards 2aa7380cb6 Changed the fix from the last commit by solving the problem in a
different way.  Added a routine to remove all layers of a contact
from all planes except the contact's base plane before finding
and processing contacts.  This causes ExtFindRegions() to find
and process only one tile on one plane per contact, so there are
no redundant contact entries.  Also, any overlapping stacked
contacts are resolved, which avoids the very common error of
contacts not being processed at the correct size because they
are being processed per tile for chopped-up areas.
2023-09-29 12:41:54 -04:00
Tim Edwards dacbfc4e1f Found that "extresist" double-counts contacts because no attempt
was made to limit the ExtFindRegions() search to one plane per
contact.  Fixed this simply by doubling the resistance per via
so that the final result is correct.
2023-09-29 10:48:05 -04:00
Tim Edwards b156e79b2c Corrected a toolkit error where the callback to check parameter
bounds should be called whenever an entry is changed and either
the entry window loses focus or the <Enter> key is pressed.
This had ended up disabled when the scrollbar was added to the
dialog window, causing the window hierarchy to change, which
invalidated the regexp used to identify the entry and checkbox
widgets.
2023-09-29 09:38:48 -04:00
Tim Edwards 088bb828ac Corrected an error in the original resistor network simplifying
routine that marks resistors in loops to prevent infinite
recursion, but later incorrectly eliminates those resistors.
Also:  Changed the "tolerance" command to affect only the R-C
time constant tolerance.  Added a "threshold" command option
that limits output of small resistors.  This can help reduce
large networks that are otherwise not reducible by the three
methods of reduction (serial, parallel, and delta-wye), but
does affect output values (slightly).  This will probably need
to be revisited at some point.
2023-09-28 17:15:27 -04:00
Tim Edwards 656b5dbabe Corrected an error in the calculation of the number of contact
cuts per contact area during parasitic resistance extraction.
Previously, the result was divided by the via pitch twice,
resulting in most contact areas being reported as a single
cut.
2023-09-28 12:38:08 -04:00
Tim Edwards 7aa846443a Corrected an issue with the implementation of nondefault rules
in DEF read and write.  The NONDEFAULT LAYER WIREEXT was assumed
to refer to the default wire extension at segments, when instead
it refers to the wire extension only at vias.  The wire
extension at segments is presumably defined by the nondefault
segment (and wire extension at vias remains unimplemented, which
is probably not a big issue because everyone puts the wire
extensions into the via definitions anyway).
2023-09-26 21:26:31 -04:00
Tim Edwards b244d45688 Fixed an error that causes magic to segfault when doing "def write"
on a layout that is caused by either having no .ext file, having
labels attached to space, or possibly both.
2023-09-25 14:18:21 -04:00
Tim Edwards f1e60fe8b1 Found an extreme issue in "extresist" in which the algorithm spent
all of its time running area searches on zero-area rectangles,
which was causing simple extractions to run hours.  Checking for
a zero area rectangle and conditionally skipping the area search
resulted in a massive speed-up in parasitic extraction.
2023-09-23 12:57:03 -04:00
Tim Edwards 68d6632836 Documented the "def write -anal" command option, which had
previously been implemented without being documented.
2023-09-22 16:31:36 -04:00
Tim Edwards 7e5dbd17cd Fixed another issue in which sticky labels on a non-electrical
type (like "comment") show up as nodes in the .ext file, which
they shouldn't.
2023-09-22 16:03:53 -04:00
Tim Edwards 4557dd1639 Modified the "def write" function so that obstruction layers are
output as blockages.  That allows obstruction layers to be placed
in a layout specifically for the purpose of being output as a
blockage.  Otherwise, an obstruction layer is generally considered
non-electrical and will not show up as a node in the extraction
file, so obstruction layers were being missed entirely by "def
write".  Also:  Where "def write" complains about floating labels,
made an exception for labels on non-electrical layers (like
"comment").
2023-09-22 15:51:38 -04:00
Tim Edwards a54a20ee58 Corrected an issue with "drc catchup" that causes it not to work
because commands issued during initialization set the DRC status
in a way that causes DRCContinuous() to return immediately.
Also:  Implemented a slightly different method when automatically
finding the tech file from the input .mag file that loads a
technology .magicrc file if one exists.  If not, just the .tech
file is loaded.  This replaces the method of a previous commit
that loads the technology .tcl script.  The .magicrc file will
include the .tcl script but does other things as well.
2023-09-20 10:27:07 -04:00
Tim Edwards cb25afc5ff Modified the behavior of "gds read" (and by extension "cif read")
so that it does not fail if an edit cell is not loaded, but
simply loads the default unnamed edit cell.  This is somewhat bad
behavior in the case of reading GDS, since if the GDS is a library
and does not have a top level cell that matches the name of the
GDS library, then the edit cell that is loaded when the "gds read"
command is issued remains unchanged, so it didn't need to be there
in the first place.  Fixing this to behave better would require a
bit of additional work.
2023-09-13 16:40:40 -04:00
Tim Edwards 50b1e01cfc Corrected the scrollbar function on the parameterized device
generation dialog window.  The window is now made to fit the
list of parameters when it is made, but can be reduced in size
which allows the scrollbar to function.  Event bindings for the
mouse scrollwheel were added so that it can subsitute for the
scrollbar within the parameter window.
2023-09-13 11:28:07 -04:00
Tim Edwards 93eeb1b703 Documented the "extract halo" command option (which was missed at
the time the option was implemented), and also implemented (and
documented!) a similar command option "extract stepsize" for
reporting or changing the extraction step size.
2023-09-13 10:03:20 -04:00
Tim Edwards dfe3a4defd Added a "Place" button in the cell manager after realizing that
other commands like "Place Instance" and "Library Manager" do not
track cells in the internal database, and so are unable to place
a cell instance that does not have a corresponding file on disk
(e.g., a cell read from GDS or LEF).
2023-09-12 11:52:15 -04:00
Tim Edwards 68a088943f Made an enhancement to the code that automatically tries to figure
out where to find the technology corresponding to a file given on
the command line: (1) Changed the default search location from
/usr/share/pdk to /usr/local/share/pdk, which is the actual default
for open_pdks (can still be overridden by environment variable
PDK_ROOT).  (2) Made the PDK name by itself preferable to the PDK
name plus any extension when searching (e.g., "sky130A" is preferred
over "sky130A_backup").  (3) Check the located directory for any
file <tech_name>.tcl and source it if it exists.  (4) Run any tag
callbacks on the "tech load" command, which rebuilds the tool icons.
2023-09-12 11:12:00 -04:00
Tim Edwards a8cc403e4b Modified "lef write -hide" behavior to fix problems that occur
when a label has no area and magic has to go searching for the
label area.  The resulting behavior is better but is not really
a substitute for adding ports on the proper layers in the proper
locations for routing connections.
2023-09-11 14:34:42 -04:00
Tim Edwards d624b76712 Updated the version to go along with Donn's pull request #266
(fixes some issues around python3 on the Mac, python3 conflicting
with that found by /usr/bin/env, and an issue around "make clean"
attempting to rebuild the Depend files).
2023-08-29 15:50:38 -04:00
Donn 86630fcc02 Allow Python 3 to not be in PATH, Fix `clean` re-building dependencies
* Adds Python 3 to macOS requirements
* Gate include of `DEPEND_FILE` in `rules.mak` on whether the target is `clean` or not (the include isn't pre-processed; it will attempt to build everything in the include otherwise)
* Make `makedbh` a configurable file- the shebang now uses the discovered path for Python3
2023-08-29 22:43:11 +03:00
Tim Edwards 8e25303db4 Corrected what looks like a very long-standing error in the DRC
engine.  Rule checks of triggering rules are not subject to
clipping to the clip area.  However, they *must* be clipped to
the (larger) overall DRC check area, because no layout is valid
outside of that area.  This clipping was missed, allowing
triggering rules to trigger on areas outside the valid layout,
resulting in mysterious false-positive DRC errors.  This has
been fixed.
2023-08-27 14:21:02 -04:00
Donn 02e16b8bce Build Updates
This is a series of updates to make building magic far less of a headache:

* Drop `csh`/`tcsh` dependency and detection from `./configure`.
* Rewrite makedbh in Python.
* Rewrite printmans in POSIX sh.
* Stop deleting Depend before every compile (which causes some files to recompile and thus increases recompile times significantly)
* Add Depend to CLEANS in scripts/defs.mak.in
* Turn POSIX suffix rule in magic/rules.mak to a pattern rule with proper prerequisites
2023-08-25 12:24:14 -04:00
Tim Edwards cb00ede59d Corrected defRead.c so that "read def" will read multiple "+ ROUTED"
(and similar) independent routed segments in the SPECIALNETS section
(which was already working correctly for regular NETS).  This solves
github issue tracker issue #264 from Christian Haufe.
2023-08-25 12:15:58 -04:00
Tim Edwards f4d7646c1e Changed Lookup() to LookupFull() in all the LEF and DEF read routines.
Lookup() is used for command-line parsing in magic and accepts any
unique string that matches a partial keyword.  LEF and DEF do not
allow partial keywords, so only LookupFull() is appropriate to use
for LEF and DEF file parsing.  This fixes issue #263 from Christian
Haufe.
2023-08-25 09:48:24 -04:00
Tim Edwards 71e6bc5dd5 Added an include for <wchar.h> which is needed for readline to avoid
an implicit declaration error.
2023-08-08 13:44:37 -04:00
Tim Edwards 13a7cc32e2 Corrected an issue with the last commit for fixing the "extresist"
command for use with "extract path";  the cellname was being cleared
after generating the filename with the extract path, but was being
used afterward, so it needed to be reverted back to the original
value, not just free'd.  Otherwise "extresist" will fail to produce
any results.
2023-08-07 15:37:04 -04:00
Tim Edwards 22fbb28656 Corrected one major error which will cause magic to fail to find the
".res.ext" file from "extresist" after using "extract do local" (and
probably with "extract path" as well).  Fixed this, and also made
sure that "extresist" writes the ".res.ext" file to the same location
as ".ext" always, so that handling is consistent throughout the
full R-C extraction process, across the use of "extract", "ext2sim",
"extresist", and "ext2spice".
2023-08-06 16:53:07 -04:00
Tim Edwards 952b20d2a2 Corrected an issue where code expected sticky labels to be at the
front of the list during extraction, except that after copying
they're not.  Removed the expectation, although that causes the
entire linked list of labels to be parsed and may cause excessive
run-times in pathological situations.  Keep an eye out for
unintended consequences.
2023-08-01 13:59:46 -04:00
Tim Edwards 96ea4aa2fb Made a minor change to the handling of device nodes in EFBuildDevNode()
to catch cases where a device terminal is connected to the global
substrate node even when the terminal is not specifically a substrate
terminal (e.g., diode cathode or bipolar collector) and  mark them with
the "substrate is port" flag.
2023-07-31 12:11:04 -04:00
Tim Edwards 2aab645308 Discovered an error in region and net selection that can cause
unrelated nets to be captured in the same selection, due to the
use of the label bounding box instead of the label rectangle.
The bounding box is used for display only and should not be used
for connectivity.
2023-07-29 20:36:46 -04:00
Tim Edwards 6b5bd149fc Corrected an issue with "flatten -doinplace" with no cell name
argument, which is supposed to flatten all selected instances.
After flattening, instead of deleting the instance from the
cell, it deleted the instance from the selection, leaving the
one in the cell.
2023-07-28 15:25:42 -04:00
Tim Edwards 89f1c4ee67 Corrected a previous implementation that was supposed to not print
warning messages about ports being electrically connected when
those ports have names that match under rules of case-insensitivity,
and the .ext file is being read for the purpose of generating a
SPICE netlist, which is case-insensitive.  Also:  Corrected a crash
condition when using "extract path <name>" when directory <name>
does not exist.
2023-07-28 09:40:41 -04:00
Tim Edwards d4f8fe04c5 Corrected the variable string "RCS" in tkcon.tcl, which had
become truncated, causing the "About" menu item in the console
to generate an error message.  Since the tkcon.tcl used in my
other software packages like IRSIM was correct, I just pulled
the RCS string from there, and it seems to be okay now.  This
solves github issue #259.
2023-07-25 17:15:11 -04:00
Tim Edwards 0afe4d87d4 Corrected an error introduced by the code added recently for support
of command logging, which caused the "select cell <instance>" command
option to become invalid;  this command option is used by the
parameterized cell generator and makes it impossible to edit the
parameterized cells.
2023-07-21 15:35:58 -04:00
Tim Edwards 90a3cf2d72 Corrected an issue that undermined the "locking disable" command,
and would keep files open (even though they were not marked as
locked) and not close them, causing an open file descriptor overflow
when too many files are read for the same design.
2023-07-20 14:51:05 -04:00
Tim Edwards 36fa9aabd1 Implemented a new command option "gds magscale" to reinterpret the
meaning of the MAG record in GDS files.  Most available GDS
documentation is decidedly vague about what MAG means.  Most
layout tools seem to interpret a MAG of 1 as corresponding to a
text height of 1um.  However, there are a few tools that
interpret it as 1 centimicron, and there's no reason to assume
that any given interpretation is correct.  "gds magscale" allows
the scale to be redefined.
2023-07-19 20:33:01 -04:00
Tim Edwards 8b3bb1ae77 Updated the version to go along with pull request #256 from Proppy. 2023-07-11 16:52:03 -04:00
Johan Euphrosine 7794b1b3cb textio: add missing TxErrorV call 2023-07-12 05:42:55 +09:00
Johan Euphrosine 1bdf173391 textio: add TxErrorV variant 2023-07-12 05:21:20 +09:00
Johan Euphrosine e249e7a0e3 configure: cleanup diff 2023-07-12 05:04:18 +09:00
Johan Euphrosine eb9dcbcd01 calma: fix linux build? 2023-07-12 04:53:07 +09:00
Johan Euphrosine f5793bbefb configure: add asmjs-unknown-emscripten target 2023-07-12 04:44:37 +09:00
Johan Euphrosine a11d2cbaa1 github/workflows: add simple_build_wasm 2023-07-12 01:11:50 +09:00
Johan Euphrosine 96eb275622 quick and dirty emscripten port 2023-07-12 00:31:37 +09:00
Tim Edwards c3ec56725b Corrected a few errors from the previous commit (support for
logging commands without any pointer or screen coordinate
references).
2023-07-08 21:58:12 -04:00
Tim Edwards 7a4a867d6e Extended the "paint" and "erase" commands to accept an option
"pick x y" which acts like "cursor", but operates on a database
coordinate instead of a pointer coordinate.  Made a few other
corrections to the command logging code so that it produces
valid output when the log file is sourced.
2023-07-08 17:34:00 -04:00
Tim Edwards 3890181ebe Completed the small set of command extensions to make sure all
commands that make use of the pointer position have an equivalent
command that operates solely on layout coordinates, or otherwise
avoids needing a pointer position.  Added the command option
"down <instance>" to avoid using the pointer to disambiguate
selections.  Added the command option "select ... at x y" to
do paint or cell selections at a specific coordinate instead of
the pointer position.
2023-07-08 13:59:00 -04:00
Tim Edwards d3b314d877 Corrected an error in the previous commit. Implemented a new form
of the "edit" command that takes an instance name as an argument.
This is the first of a small series of command extensions to
provide the capability to replace any command that is dependent on
the pointer position with an equivalent command that is not, for
the purpose of removing pointer and screen coordinate dependencies
from the log file created by "logcommands".
2023-07-08 12:47:09 -04:00
Tim Edwards 081058a41b Corrected an issue in which ports which have the same name under
the assumption of case insensitivity (e.g., VSS, Vss, and vss)
are kept separate even when writing SPICE netlists, which are
case insensitive.  The code fix both avoids flagging these ports
when running ext2spice, and more importantly, allows the use of
"ext2spice short" without these ports ending up separate in the
output netlist.
2023-07-08 12:14:57 -04:00
Tim Edwards b899a500d5 Added a new method to the extraction which allows parameter limits
to be declared for each device model, so that different models can
be specified for different parameter ranges.  For example, this
will simplify the definition of the high-sheet-rho poly resistors
and the bipolar transistors in sky130 by removing the need for ID
marker layers;  it also allows the correct device model to be
extracted when reading data from GDS that does not contain the
extra (and not foundry-approved) ID markers.
2023-07-06 12:35:47 -04:00
Tim Edwards cc4eef4eb1 Added a (obvious, in retrospect) additional automatic handling of
nets to be avoided for running antenna gate and diffusion area
checks when doing "lef write", which is to check if the pin of
the net is flagged with use "power" or use "ground".  This avoids
the need to use the (recently added) "lef nocheck" option (although
that still exists as an additional way to control which nets do and
do not get checked).
2023-07-05 12:37:56 -04:00
Tim Edwards c8a2d06e08 Finally got around to fixing the "logcommands" command, which has
been broken ever since moving to the Tcl/Tk wrapped version.  Added
some new features that allow background commands from the window
handling (like pointer tracking) to be omitted from the log file
via a suspend/resume function.  Added a header file and a few
commands at the top of the log file that align the log file contents
with the screen and box state at the start of logging.  This makes
a log file which can be "played back" by sourcing it from the magic
console prompt.  Per request from Harald Pretl.
2023-06-28 21:31:24 -04:00
Tim Edwards ca469510d5 Found that extNodeName() prefers the first name in a region's label
list for output, but that the code in ExtRegion.c does not sort a
region's label list to keep ports at the beginning of the list.  So
any net with multiple labels may end up with a non-port label as
the name of the node, which eventually becomes the name of the port.
A quick fix keeps these lists sorted.
2023-06-27 15:35:57 -04:00
Tim Edwards 3ae24e8a8c Extended the method of the previous commit to include the command
option "drc find <text>", to find the next error of a specific
type based on the contents of the DRC error message (e.g.,
"drc find li.1").
2023-06-26 21:17:51 -04:00
Tim Edwards 60a378842f Corrected one array overrun error caused by using the command
"drc printrules".  Implemented a new "drc" command option called
"drc ignore", which can be used to suppress reporting of specific
rules, for both "drc why" and "drc find".  This can help with
finding an error buried among a large number of other errors.
2023-06-26 20:47:37 -04:00
Tim Edwards ca985edbd0 Corrected a typo in the previous commit that causes parameters to
be output twice for scaled devices (such as diodes in the sky130
process).  Above and beyond the typo, though, the implementation
of offsets is not very well thought out and needs to be revised.
For one, the +/- notation can be confused with signs in the
parameter expression;  that is also fixed in this commit.  But
there is currently no way to express both a scale and an offset
for a device parameter.
2023-06-23 08:39:59 -04:00
Tim Edwards 07267dc126 Extended the device parameter notation to include offsets using
'+' and '-' in the same way that '*' is currently used for specifying
a parameter scaling.  The combination of a scale and offset for the
same parameter has not (yet) been implemented.
2023-06-21 20:44:38 -04:00
Tim Edwards 482d7534a2 Reimplemented the "extract do local" option as "extract path <name>"
with "extract do local" now being equivalent to "extract path .".
This allows extraction files to be put in a subdirectory and not
clog up the current working directory.  Also:  Fixed some behavior
around the use of "ext2spice -p <path>" so that it (1) works, and
(2) is compatible with the new "extract path".  Since the ext2spice
and ext2sim commands are effectively independent of the primary
extraction, the "-p" option is needed to correspond to the use of
"extract path".  Hopefully this is seen as only a minor inconvenience.
2023-06-14 13:55:59 -04:00
Tim Edwards 9b131fa96c Corrected an issue that produces potentially incorrect output
from ext2spice due to "equiv" statements in the .ext file.  The
algorithm was not properly keeping the port as the preferred
name of the node, resulting in the non-preferred name being
used instead of the port name in the output.  This would happen
only if there was a label on a net that had a different name than
the port name.  The error became much more prevalent after changing
the extract behavior to make "extract do aliases" default.  Also
fixed a somewhat related minor error in which magic would print an
error message about ports being shorted together on the same kind
of net where both a port and a (different) label were attached to
the net.  Since the non-port label is not a preferred name, then
there should be no warning message.  The warning is only intended
for cases where two (or more) ports are truly shorted together.
2023-06-13 17:14:36 -04:00
Tim Edwards 31b3c0d8b4 Extended the "lef" command to include a new option "lef nocheck"
to create a list of net names to ignore for antenna gate and
diffusion area checks.  This allows the nets not to have to be
selected in their entirity but selected by chunk only.  This
reduces the time to write LEF on a large layout back to approximately
what it was before the change to include the hidden area from "-hide"
in the antenna area checks.  Plus, it greatly reduces the time to
generate LEF for large layouts when not using the "-hide" option.
2023-06-13 11:28:46 -04:00
Tim Edwards 5300f322de Added code to calculate area and perimeter of layers that are not
on the same plane as a device identifier layer.  This (finally!)
allows proper calculation of area and perimeter of diodes and
bipolars, for example.
2023-06-09 15:31:58 -04:00
Tim Edwards 6caab5da37 (1) Corrected an error with extraction in which terminal area and
perimeter are not initialized, and if a terminal perimeter/area
calculation is missed (which is happening on devices with terminals
in planes other than the plane of the identifying type), then the
perimeter/area of a previously handled device will get output.
(2) Corrected an error with "flatten -inplace" in which the command
fails to deal with instance arrays.
2023-06-07 08:06:18 -04:00
Tim Edwards 666c3c2c97 Corrected an issue in which the device merging routine can generate
NaN results for devices which are not FETs (specifically, devices
that are declared using "msubckt" but are not FETs, although there
may have been a related issue with non-FET devices not getting the
correct M count), due to the device having zero measured width or
length.  NOTE:  This may need more investigation.  If a subcircuit
device's method of merging cannot be understood, then such devices
should never extract with "merge aggressive", and should always
merge conservatively if and only if all parameters match.
2023-05-21 12:13:01 -04:00
Tim Edwards c514f5ce0b Apparently forgot to push the last set of changed. Fixes a null
return value in EFbuild.c and adds a couple of sanity checks.
2023-05-18 09:25:37 -04:00
Tim Edwards 44b269e037 Modified the handling of substrate ports so that an existing port
number for a substrate port does not get reassigned, which will
cause port ordering issues.
2023-05-08 09:51:13 -04:00
Tim Edwards 79dc621626 Added a warning message if attempting to extract an empty cell,
so that it is not so mysterious as to why no output was generated.
2023-04-28 09:24:04 -04:00
Tim Edwards c4124b033f Corrected a potential crash condition in extflat which can show up
when reading .ext files with "equiv" statements in them.  The
generation of "equiv" statements was expanded recently, making it
more likely for this issue to show up.  There may be devices in
a file that have a terminal node pointing to the node that gets
removed, and these must be updated to point to the node that
remains after merging.  This requires a full loop over all
devices and so could have a potentially large impact;  but in
general there are not many equiv statements (implying multiple
different labels attached to the same node) and so it is unlikely
that there would be a noticeable performance hit in practice.
2023-04-27 20:47:55 -04:00
Tim Edwards e66b2e1338 Rearranged the "lef write" routine so that the search for antenna
gate and diffusion area on each pin is done before erasing parts
of the cell that are to be hidden by obstruction layers.  That
preserves the antenna information even when "-hide" is used.  This
corrects the issue raised by Kareem Farid in the github issue
tracker #236.
2023-04-26 10:24:13 -04:00
Tim Edwards a33d7b78b5 Corrected an error in search for substrate under a device. If
"space" is considered part of the substrate, then the check for
planes to search should exclude "space" from the type mask
first.  Otherwise, all planes get searched, not just the substrate.
Also:  The same routine can falsely flag a device terminal as
substrate if a split tile is marked as the device's region.  This
was also fixed.
2023-04-24 17:30:40 -04:00
Tim Edwards bf7f1ab39e Updated version with the merge of pull request #235 from Brad Smith. 2023-04-22 14:14:20 -04:00
Brad Smith c8940ab219 Allow for bash in locations other than /bin 2023-04-22 14:13:57 -04:00
Tim Edwards c1f4555ba0 Corrected behavior of "load ... -dereference" to bring back a
previous behavior that had inadvertently been changed.  In recent
versions, "load <absolute_path> -dereference" would incorrectly
apply the dereferencing to <absolute_path> rather than just its
subcells.  Cleaned up the code around DBCellRead() in the process,
so everything is more straightforward (although probably more
could be done in that regard).
2023-04-18 11:01:58 -04:00
Tim Edwards cff2b97678 Changed the default extraction options to include "do aliases" by
default, since not setting it can have unfortunate consequences
for cells that don't declare ports and have multiple conflicting
labels on a node.
2023-04-16 12:18:16 -04:00
Tim Edwards adf9a7703f Added a statement for every file load that prints the file path
of the cell.  This will greatly help in diagnosing issues when
reading cells from multiple locations including cwd, relative
paths, PDK libraries, and the search path.  Also:  Reworked
the timestamp update message so that it prints all at once at
the end of processing, not printing output for every cell
processed as it is being processed.  That prevents output from
the file read routine from getting interleaved with the
timestamp processing output.
2023-04-15 10:44:50 -04:00
Tim Edwards 1d8fcca09b Implemented a change to differentiate between "sticky" labels and
labels that are not connected to their declared layers.  It's the
latter type that need additional processing in ExtSubtree.
Limiting this processing significantly cuts down on processing
time when there are many labels in a layout, as happens with the
"def read -labels" command option.
2023-04-06 12:26:18 -04:00
Tim Edwards 380b9245f3 changed MAXTOKEN in ResReadSim.c from 256 to 1024, having
encountered an issue where a label in a flattened layout
exceeded 256 characters, ended up in the .sim file, and was
truncated when read back during "extresist".  The change to 1024
is a stop-gap measure because ultimately I want to replace the
use of .sim files with .ext files using the routines in extflat/,
which would deprecate everything in ResReadSim.c.
2023-03-25 16:11:46 -04:00
Tim Edwards 8ab5d465e9 Removed an unused variable declaration. 2023-03-25 15:53:32 -04:00
Tim Edwards 7b9809e567 Fixed the "flatten" command so that "-dotoplabels" works as advertised,
and doesn't crash magic.
2023-03-25 15:06:25 -04:00
Tim Edwards fc62a63d41 Corrected errors in the extresist code and in extflat, both of which
can result in negative resistors due to integer overflow.  In all
cases, the target was floating-point and it was only necessary to
recast everything to float first.
2023-03-25 11:01:52 -04:00
Tim Edwards 8fb96db14c Found one additional issue in the extraction that causes incorrect
partitioning of unshielded areas reaching outward from any given
edge, caused by using a boundary value in the 2nd recursion call
that had been modified for the 1st recursion call and so was no
longer valid.
2023-03-24 17:11:27 -04:00
Tim Edwards 30184cb506 Finally tracked down several bugs in the sidewall walking routines
that had been causing negative capacitances to substrate to be
generated for certain complex geometries.
2023-03-24 09:51:22 -04:00
Tim Edwards f0c94d59f3 Minor adjustment to output from esSIvalue() to avoid round-off error
causing the SI suffix not to be the expected one.  Adjusted the
bounds where each SI suffix is used to keep output in the range of
0.1 to 100, although the boundary is very subjective.  Made a
correction to the extresist code to scan through all device records
for a tile type.  However, (1) there are cases being missed, and (2)
this should not be necessary since all device types should be able
to be known exactly from the contents of the .sim file.  Needs more
work.
2023-03-23 15:38:31 -04:00
Tim Edwards 6dd5f4d7e3 Corrected problem caused by adding a scrollbar to the parameters
window in the toolkit, which was to the "tkwait" command, which
waits for a change in state.  What was intended was to wait for
a change in state to visible only;  once visible, the "tkwait"
command should not invoked or else the process will block.
2023-03-22 15:28:00 -04:00
Tim Edwards 58c6a32a6c Applied patch from Donn that converts strcpy() calls in ext2spice
to "safer" strncpy() calls to prevent string buffer overflow.
Also:  Reimplemented the loop in the GDS write routine that counts
ports and then outputs them in order.  It was possible to hang
magic for a long time by giving a port a very, very large index
number.  The new implementation uses qsort() to sort the ports
by index, which is obviously much more efficient for the worst
case (and efficient enough for all normal cases).
2023-03-21 22:04:30 -04:00
Tim Edwards d8f926865d Modified the behavior of cell reading, mainly with respect to
dereferencing, and making the behavior of "load" on the command
line (i.e., loading a cell from a file) the same as the
behavior of loading a cell as a result of expanding an unloaded
instance.  In both cases, if "load -dereference" is used, and
a cell does not exist in any search path but does exist in the
original location, without dereferencing, then the cell will be
loaded from the original location.  Also:  Corrected an error
that has existed since adding the capability to read compressed
files, which causes magic to crash when attempting to run the
"crash recover" command (because that routine was mixing
compressed and regular file stream calls).
2023-03-20 21:00:35 -04:00
Tim Edwards 10448788f9 Found another error causing negative capacitances and fixed it,
but the search continues for another mechanism that continues to
do the same thing.
2023-03-17 21:59:47 -04:00
Tim Edwards ca0cb1322a A couple of corrections to the last commit, where the equation for
computing the amount of fringe shielding was wrong.  This fixes
one of my example cases, but not the other one, so I still need to
pin down a condition that can result in negative capacitance.
2023-03-17 20:47:08 -04:00
Tim Edwards edb05fb3d1 More corrections to the method of calculating fringe capacitance
inside a halo area.  The previous implementation used a linear
accounting of error to determine the amount of shielding, but
since the shielding is nonlinear, this is a poor approximation
and regularly overestimates the shielding and leads to negative
capacitances.  The corrected method makes many more calls to
the atan() function and the performance impact for extraction
will need to be evaluated.
2023-03-17 13:51:33 -04:00
Tim Edwards e9d434597a Corrected issue with the commit of version 8.3.378, which can
cause a crash when extracting some devices like bipolars with
terminals on different plance.
2023-03-15 14:36:15 -04:00
Tim Edwards a2687d4385 Corrected an issue from the last commit, which is that the default
ground node name (which is static) gets put on the node list and
is improperly deallocated.  Corrected by simply allocating the
string for the default substrate node instead of using the static
string.
2023-03-14 12:53:22 -04:00
Tim Edwards a3f5f4db80 Changed the behavior of capacitance value output in ext2spice
and ext2sim to make use of the new esSIvalue() routine, so that
it no longer depends on a preformatted string.  Corrected an
issue where the esSIvalue() routine would output "a" for "atto"
which is not supported by ngspice.
2023-03-13 13:21:34 -04:00
Tim Edwards c077e1acef Removed from the "lef" HTML document some mentions of property names
that aren't actually handled by the "lef write" command.  The three
mentions are "LEFsource", "LEFuse", and "LEFshape", all of which
refer to names of pin properties, not macro properties.  These
mentions were probably left over from early work.
2023-03-13 10:18:17 -04:00
Tim Edwards 913c830dee Corrected the extraction of length and width of devices that are
(truly) missing a terminal (such as a MOSCAP made with a gate
extending into but not crossing a diffusion region).  Added the
most requested GUI feature, which is a vertical scrollbar on the
parameterized device window (could be improved by maximizing
window height without exceeding display height).
2023-03-12 16:57:47 -04:00
Tim Edwards e10901e32b Updated the version to go along with the merge of pull request
222 from Sean Cross.  Corrected a few places where the blanket
conversion "Region"->"ExtRegion" picked up some comment lines
that were unrelated to the structure name.
2023-03-10 11:14:23 -05:00
Sean Cross 1e7da74672 rename Region to ExtRegion
On Macos, Tk includes X11, which has this define:

    #if !defined(MAC_OSX_TK)
    #   include <X11/X.h>
    #endif
    #ifdef MAC_OSX_TK
    #   include <X11/X.h>
    #   define Cursor XCursor
    #   define Region XRegion
    #endif

This causes the keywords `Cursor` and `Region` to be reserved, which
prevents magic from building.

Rename `Region` to `ExtRegion` as suggested by @RTimothyEdwards in
https://github.com/RTimothyEdwards/magic/issues/195#issuecomment-1298870983
and https://github.com/RTimothyEdwards/magic/pull/222#pullrequestreview-1334900670

Signed-off-by: Sean Cross <sean@xobs.io>
2023-03-10 11:07:55 -05:00
Tim Edwards 5e5879c53d Made a simple but important change to "readspice.tcl" to unexpand
the cell being reworked for port numbering.  Otherwise *all*
labels are selected, which can take a very long time depending on
how many labels are in the layout.  Note:  Need a "select area
ports" function, and better yet, rework the whole label database
so that magic no longer has to run compute-intensive routines
like DBEraseLabelsByContent().
2023-03-08 11:14:22 -05:00
Tim Edwards a8c3117020 Implemented and revised the "CIFhier" property to override the
"cif *hier write disable" and "cif *array write disable" commands
for a specific cell def and its descendents.  The revision ensures
that all descendents apply the override.  The "cif write" command
uses a stack instead of recursion, which makes it difficult to
apply the same method.  Currently the method only works for the
"gds write" command, and implementing the feature for "cif write"
is deemed not worth the effort.
2023-03-07 11:16:49 -05:00
Tim Edwards 73398e7e0b Corrected a buffer overrun situation in ExtBasic.c when printing
the "connected other node to. . ." message when terminals of a
device are shorted.  A long enough node name, especially one
created by concatenating hierarchy when flattening a cell, can
easily overrun the short 256-byte string buffer.  Fixed by
changing strcat() to strncat().
2023-03-05 16:39:58 -05:00
Tim Edwards 26da5adf98 Corrected an error in the check for coincident instances. This
check was too aggressive and would delete coincident instances
based on cell def and bounding box only.  If the cells were at
different orientation or mirrored, they would be incorrectly
flagged as coincident.  Instances read from GDS could be
deleted due to this issue.
2023-02-28 16:49:17 -05:00
Tim Edwards 0058000c22 Corrected "ext2spice" to mark nodes on resistors from "extresist"
so that they do not get marked as "FLOATING" nodes when writing out
the parasitic capacitances at the end.
2023-02-28 13:11:32 -05:00
Tim Edwards eb36edf35a Corrected the ext2spice device output for device length, which
somehow acquired a typo which made it write "w=".  Resolves
issue #223 from Mitch Bailey.
2023-02-28 09:34:25 -05:00
Tim Edwards 3da6172706 Modified the "port renumber" command to use (case-insensitive)
natural sort instead of ASCII-based sorting, so that ports that
are numbered arrays will be indexed properly by count.  Also:
Modified the "extresist" handling of substrate to draw the default
substrate type over the entire cell area (less areas of nwell or
other conflicting type).  This allows extresist to extract the
entire substrate as a resistive network.  The result is ugly and
may warrant some aggressive network simplification, but it should
at least be realistic.
2023-02-27 22:22:09 -05:00
Tim Edwards e72f85fd10 Corrected the ext2sim output and extresist to properly handle
2-terminal devices without complaining.  The previous handling
seemed to be technically correct other than spitting out warnings
about missing terminals.
2023-02-24 12:58:46 -05:00
Tim Edwards 7b485efa9b Added code to handle string overflows in property strings. It
might be better to flag a warning, as property strings longer than
the original buffer size of 2048 are probably a bad idea.
2023-02-23 16:44:58 -05:00
Tim Edwards 33d0d53d34 Corrected an error in the extract section setup of the tech file
that allocates and deallocates a single layer mask used by the
tech reader.  Decided to work around the issue just by allocating
it only once and not releasing it---it's just a few bytes.
2023-02-22 17:56:45 -05:00
Tim Edwards be577d4318 Corrected the reading of the "defaultsidewall" statement in the
tech file "extract" section to work correctly when the offset is
negative.  Generally, a negative offset is nonphysical and is just
curve-fitting round-off error, but the existing code was failing
to divide out the factor of 1000 that had been multiplied through
when reading the tech file, resulting in a very wrong offset.
2023-02-22 15:30:50 -05:00
Tim Edwards d4790d2f31 Corrected the "measure" (Tcl scripted) command to fix an error
when internal units no longer match lambda units.  The text
would match the dimension of the cursor box, but the measurement
lines would be drawn assuming a lambda scale, not the internal
scale.
2023-02-20 16:06:18 -05:00
Tim Edwards c7f11d2169 Important update: Reworked the extraction method to properly
isolate the terminal areas of a device (e.g., source and drain)
and calculate their area and perimeter individually for the
device (in addition to the traditional method of calculating
area and perimeter of each resistance class for the entire node).

Also:  Reworked the SPICE syntax output to generate SI values
in the range 1-1000 with the appropriate suffix (e.g., "20u")
instead of defaulting to "u" for lengths and "p" for areas.
This prevents it from producing weird units like "150000u" when
a process definition already includes a scalefactor.

Reworked the "extresist" code to use the device terminal area
and perimeter.  This fixes an error in which "extresist" would
lose these values and "ext2spice" with option "extresist on"
would generate a new netlist output with zero terminal areas
and perimeters.
2023-02-16 11:59:13 -05:00
Tim Edwards 87702ac98a Reworked the previous commit in a way that makes more sense, as
the problem only occurs when handling the legacy "fet" device.
2023-02-13 13:41:58 -05:00
Tim Edwards 5fcd4441c1 Corrected the "extresist" command behavior to ensure that
transistor records match between the ".ext" file and the ".res.ext"
file for the number of terminals per device.  Previously, the first
device type for the layer type was always being used, and if it had
fewer terminals (e.g., a MOScap), then one terminal would go missing
in the output.
2023-02-13 10:57:43 -05:00
Tim Edwards adda4092d6 Updated version to go along with the merge of pull request #217 from
Anton Blanchard.
2023-02-02 09:18:22 -05:00
Anton Blanchard c495b618b2 Remove cast of pointer to struct and back again. 2023-02-02 15:34:52 +11:00
Tim Edwards 1a3caee376 (1) Added a check for unclosed boundaries when reading GDS.
This is diagnostic only and does not change the read-in
    behavior.
(2) ext2spice:  Corrected an error that had been introduced
    into version 8.3.171 that accidentally marks all devices
    as visited which causes all source/drain areas and
    perimeters to be output as zero.
(3) extract:  Sweeping changes to handling of fringe
    capacitance.  Removed the (recently added) "fringeshieldhalo"
    parameter from the tech file.  Reworked the fringe
    capacitance models based on results from the "capiche"
    project (github/RTimothyEdwards/capiche).  Fringe shielding
    is now done by clipping fringe at the boundary of a
    shielding shape, rather than trying to calculate the
    amount of shielding (as the "capiche" project proved this
    to be equivalent).  Values for partial fringing are modeled
    by atan(x), which like the sidewall (1/x) curve, extends to
    infinity and values are limited by the halo but do not
    otherwise depend on the halo.  Because of this, the halo can
    be made variable and controlled by the user for deciding on
    the tradeoff between accuracy and run time.  A new command
    option "extract halo" was added to allow this control over
    the halo distance.
2023-01-27 11:47:37 -05:00
Tim Edwards 8d08cb2f2f One small revision to the last commit, to make the command option
"gds polygon subcells true" the same as "gds polygon subcells
temporary" instead of "gds polygon subcells keep".  This works
well for gf180mcu in open_pdks to keep the existing behavior
but won't break the GDS input on an older version of magic.
2023-01-17 20:23:11 -05:00
Tim Edwards be59d787a1 Modified the "gds subcell polygon" command option to split into
three types:  "none", "temporary", and "keep" (instead of "true"
or "false").  "none" now reverts back to the original behavior,
because it was found that saving polygons in subcells prevents
them from participating in boolean operations.  The "keep"
option is the original option (polygons kept in subcells), and
"temporary" is the one recently introduced (which puts polygons
in subcells and then flattens them).  This restores the original
method while retaining the recently implemented method.  However,
a proper solution needs to be found that deals with the problem
of boolean operators.
2023-01-17 20:14:38 -05:00
Tim Edwards 05ad386500 Updated the version to go along with the merge of pull request
213 from Anton Blanchard (1. Don't cast pointer to struct and back
again in DBDiagonalProc(), 2.  Fix compiler warning in
drcMaskSpacing(), 3. Fix a few issues in leaDBSearchForTech(),
4. Remove spurious ";" from PlotPS()).
2023-01-16 22:11:15 -05:00
Anton Blanchard f181d97315 Remove spurious ; from PlotPS() 2023-01-16 16:00:56 +11:00
Anton Blanchard c89b0c1ff3 Fix a few issues in leaDBSearchForTech()
Always call closedir() after a successful opendir(), and always return
a value from function.
2023-01-16 15:56:02 +11:00
Anton Blanchard e4e115b23e Fix compiler warning in drcMaskSpacing()
why should be an int.
2023-01-16 11:02:58 +11:00
Anton Blanchard eedc0c89a1 Don't cast pointer to struct and back again in DBDiagonalProc() 2023-01-16 11:00:47 +11:00
Tim Edwards f06f3b47db Added an experimental option for the cifoutput tech file section to
force magic to scale down the internal grid to the minimum
manufacturing grid size specified in the cifoutput section, upon
reading the techfile.
2023-01-13 17:21:37 -05:00
Tim Edwards ff608b51f1 Updated version to go along with pull requests #208 from
Alessandro de Laurenzis, and pull requests #209 and #210
from Anton Blanchard.
2023-01-08 13:11:06 -05:00
Anton Blanchard 954418d6d8 Fix clang unsequenced modification warning 2023-01-08 13:10:28 -05:00
Anton Blanchard c276110daa Use offsetof()
Magic has an open coded version of offsetof() which clang complains
about, because it takes the offset of a null pointer. Use offsetof()
instead.
2023-01-08 13:09:00 -05:00
Alessandro De Laurenzis a4e65afae9 Add PlowShowTime prototype when NO_RUSAGE isn't defined
While there, change function's type from (implicit) int to void.
2023-01-08 13:06:12 -05:00
Tim Edwards 6d99e5326e Added a command option "setlabel box" to modify the attachment box
of a label from the command line.  Also fixed a long-standing
irritation that "setlabel" would change the properties of a label
in the edit cell but not in the selection itself, which would
cause the label to be drawn both with the original properties
in the selection and the new properties in the edit cell.  Now
both views will track the same changes.
2023-01-04 14:08:39 -05:00
Tim Edwards 6cefbd13f1 Expanded the method for "flatten in place" to include the more
natural flattening from a selection.  That is, instead of
specifying "flatten -doinplace <cell>", you can select some
number of instances and just do "flatten -doinplace".
2022-12-22 14:53:24 -05:00
Tim Edwards 83e17706fe Added handling of mask-hints properties to the flatten-in-place
method to ensure that mask hint geometry is retained when a
cell instance is flattened into the parent cell.
2022-12-22 11:27:37 -05:00
Tim Edwards 70908a8ab5 One more correction related to the "verbose" level of the "load"
command, without which the previous commit does nothing.
2022-12-21 21:23:51 -05:00
Tim Edwards 7d0d07db38 Changed the default behavior of the "load" command to print
verbose messages (got changed in a recent commit to a quieter
output which doesn't provide much feedback about what's going
on during a lengthy load).
2022-12-21 21:15:33 -05:00
Tim Edwards 0bbb558b94 Reworked the "port" and "noport" label type designations in the
tech file to correct the underlying problem with the SkyWater
sky130 process in which a different layer/purpose pair is used
for TEXTTYPE and DATATYPE for the same layer.  Previously, all
output from magic writes the same pair for both when writing a
port label.  The new method preserves existing syntax, although
there are some differences based on what order the "port"
statement appears relative to other types for the same layer.
2022-12-21 17:49:43 -05:00
Tim Edwards be40825e9a Corrected the "flatten in place" command to force a redraw after
flattening, since the appearance of the layout will change even
though there are no physical changes.  Finally got around to
debugging and correcting the input mask-hints, which can
preserve vendor GDS by marking areas where the vendor GDS differs
from magic's automatically generated output (the method was
almost correct and only needed an input scale factor change).
2022-12-19 16:05:38 -05:00
Tim Edwards 583aaa1007 Added code to avoid making a call to get a default layer width on
an invalid type.  This prevents magic from generating unneeded
error messages about default layer widths on GDS read-in.
2022-12-19 11:52:38 -05:00
Tim Edwards 3d1cf5aa2e Updated the documenation on the "load" command to include the
"-silent" option and the redefinition of "-quiet".
2022-12-19 11:25:09 -05:00
Tim Edwards 23b8d08f86 Modified the "load" command so that "-quiet" is promoted to
"-silent", and "-quiet" now produces relatively little output
except for important warnings and errors.
2022-12-19 11:20:50 -05:00
Tim Edwards a0f502501e Corrected the method of "flatten in place" from the previous
commit to prevent port labels from being copied up from the
flattened cell into the parent, and prefixing the instance
name to text in the instance top level so that there will be
no port or label collisions in the parent cell after flattening
the child cell in place.  Also:  Changed "extract dolabelcheck"
to be the default setting.
2022-12-16 12:03:38 -05:00
Tim Edwards 3b396d65f0 Reverted the toolkit change from the last commit after realizing
that the feature for implementing callbacks on a selection list
was already implemented via the add_dependency procedure.
Modified the GDS read to remove cell instances that are placed
directly on top of one another in the same cell.  Modified the
GDS read to make a better selection of a default font size for
text that specifies a font but not a size, using the minimum
width for the layer the text is placed on.  Modified the GDS
read to remove text with empty-string placeholders (created when
a pin layer is read but no text exists to go along with it, due
to GDS not having a specific way to make pins, such that pins
have to be split between one record for geometry and another
for text).
2022-12-15 12:25:23 -05:00
Tim Edwards 677cd8ab5e Implemented simple drain and source length calculations as device
parameters l1 and l2.  Provides a way to pass the source or drain
length as a parameter for, for example, an extended FET drain
implemented as a resistor abutting the FET gate.  Could potentially
be used as a way to determine source/drain area and perimeter
without resorting to measurements of a shared node.
2022-12-14 21:40:24 -05:00
Tim Edwards edecd81046 Modified the toolkit add_selection procedure to take an extra
optional argument that is a callback function, so that the act
of selecting something from the drop-down menu can cause things
to happen such as changing the GUI window contents for the item
selected.
2022-12-14 17:38:19 -05:00
Tim Edwards e5813f51fa Added a new option "-doinplace" for the "flatten" command. This
should have been done a long time ago!  Allows an instance to be
flattened in place inside a cell def, which otherwise requires
a complicated set of commands to do.  Also:  Modified the polygon
handling routine from the previous commit so that it correctly
removes the polygon cell defs after flattening them into the
parent cell.
2022-12-14 12:44:30 -05:00
Tim Edwards 13a1bfcc2e Discovered that reading in polygons as subcells and then flattening
can be much, much faster than reading in polygons directly into a
cell from GDS.  Modified the handling of polygons so that they are
*always* read into subcells.  If the "polygon subcell flatten true"
option is not enabled, then the subcells are flattened at the end
of reading the cell, and the polygon cells are deleted.  This method
avoids most of the cases in which "polygon subcell flatten true"
has ever needed to be set.
2022-12-13 21:58:30 -05:00
Tim Edwards 53682af668 Added a new special device model name "Short" which enables the
use of a resistor type as a FET extended drain, allowing the
FET drain node to short across to the other side of the resistor
so that the resistor is absorbed into the FET device.  Used with
the GF180MCU process to describe the salicide-block ESD FET types.
2022-12-13 16:02:49 -05:00
Tim Edwards 86b4ac3e4c Modified the "lef read -annotate" method so that pins are checked
for compatible layout over the area of the pin rectangle in the
entire hierarchy of the cell, not just in the top level.  This
corrects issues where pins are placed in the top level cell with
no metal underneath.  It is written in such a way that it will
work regardless of whether paint is split across the hierarchy,
or the label spans different types (such as crossing a contact).
2022-12-12 14:49:42 -05:00
Tim Edwards 11ddd559b2 Fixed an error with LEF read where duplicate macros are encountered
in the input.  The name of one was being modified but was being
right-justified into the string, resulting in a name starting with
many space characters.  Also:  Fixed an issue with extresist where
a label that ends up with an empty string can become a node with
an empty string name in the .res.ext file output.
2022-12-09 17:31:47 -05:00
Tim Edwards 02bbb1064e Corrected an error in "extresist" that can output an incorrect
number of terminals for devices that don't have the usual gate/
source/drain terminals (e.g., diodes, resistors, capacitors) when
writing the devices with re-mapped terminals into the .res.ext
file.  Also:  Changed the size of the word containing the name
refcount for "equiv" statements, since an accidental shorting
of pins can cause a large number of "equiv" statements in a .ext
file, causing an overrun of the previously 1-byte refcount (this
probably does not make the structure any longer, since it likely
has to fit to a word boundary).
2022-12-06 21:55:01 -05:00
Tim Edwards fb091fa03f Revised the string array for labels during output of a .mag file
from 256 to 2048.  The latter matches the maximum array used for
DEF file labels, although allocation is probably preferable.
2022-11-30 20:25:58 -05:00
Tim Edwards 256a47d7b9 Added a method for a property named OBS_BBOX to specify a minimum
area to be marked as an obstruction when writing a LEF file with
the "-hide" option.
2022-11-30 16:29:37 -05:00
Tim Edwards e5e1e04146 Made a variant of the "directional surround" rule to be able to
implement a GF DRC rule.  This variant allows for a difference
between the minimum allowed surround on one side and the amount
that must be extended on the adjacent side.
2022-11-30 15:33:21 -05:00
Tim Edwards f222004d65 Fixed an error in "lef read" that fails to apply an annotated
pin on a compatible area due to an incorrect type mask.  (Also
note that this routine only works (after correction) for RECT
statements, but there should be a similar check for POLYGON
statements.)
2022-11-29 17:02:36 -05:00
Tim Edwards 01f2ce37b8 Modified the "dereference" behavior so that it does not produce
warnings when rereferencing a layout file as intended.
2022-11-22 11:05:55 -05:00
Tim Edwards 71dffb2fd2 Implemented a method to handle empty subcells that exist because a
library has been read in with the "gds readonly true" option set
because the cell contains information on where in the GDS the
cell is located, but the cell is empty because it was flattened
into the magic view and all of its contents were erased.  This can
cause issues with LVS if magic generates an empty cell into the
netlist and the LVS tool tries to compare the cells by name.  Also,
this prevents unnecessary .ext files and unnecessary merges to the
substrate of such cells (since all cells have an implied substrate).
2022-11-21 17:13:33 -05:00
Tim Edwards 0f05bb1356 Corrected the LEF technology setup, where LEF layers (routes and
contacts) take default values from the DRC section.  Since both
are in lambda, but the DRC section uses a two-part integer and
modulus representation, if default values are taken before
scaling, the LEF layers may get rounded values.  This has been
solved by marking values with -1 to indicate that they require
defaults, and then set those defaults (from scaled DRC rules)
after scaling all other tech values.
2022-11-20 15:15:04 -05:00
Tim Edwards 18fc328289 Revised the last commit slightly to put the PIN entry as the first
entry of a set of net connections in a DEF file, instead of the
last entry.
2022-11-20 13:32:40 -05:00
Tim Edwards 44af9aaf9f Added pin connection to the list of NET connections in a DEF file
when doing "def write", which was missing.
2022-11-20 13:30:19 -05:00
Tim Edwards 65ef9a1ad3 Final (I hope!) corrections to the "def write" command. 2022-11-19 22:02:44 -05:00
Tim Edwards 6369c44821 One correction to the last commit, to avoid missing output of
port nets in "def write".
2022-11-18 22:28:20 -05:00
Tim Edwards 16da74a2f9 Implemented a method in EFBuildNode() to capture nodes which are
redundant (same name, different net).  Previously, the method was
to keep the first such node and ignore all others except to add
their resistance and capacitance to the original node.  This
prevented routines like "def write" from enumerating all nets
unless they had unique names.  The new method keeps the additional
records including the node location where they can be found by
EFNodeVisit(), but flags them with EF_UNIQUE_NODE so that routines
like ext2spice or ext2sim can choose to ignore them.  This implies
that this method could be used to reimplement "extract unique"
within "ext2spice" or "ext2sim" without altering label text.  This
has not yet been implemented.
2022-11-18 21:44:06 -05:00
Tim Edwards fe89170f5a Small correction to defWrite to cancel a non-default rule when a
wire with default width is encountered.
2022-11-18 21:00:23 -05:00
Tim Edwards f066844761 Substantially revised the "def write" and "def read" routines.
Both were corrected with respect to the definition of non-default
(taper) rules.  "def write" was additionally modified to avoid
redundantly processing tiles where tile areas were merged together
to form a complete wire.  There is plenty of room for optimization,
but the output appears to be matching the layout.  Also:  Revised
the definition of "(not) visible layers" to include labels attached
to those layers, so that turning off visibility of any layer will
also hide all labels attached to that layer.
2022-11-17 20:24:39 -05:00
Tim Edwards 2519d0a4d8 Corrected an issue with readline that breaks the non-Tcl/Tk flow
due to a missing function prototype.  Modified the GDS output
flow to always output instance IDs as a property, not just in the
non-default case.  The property has been used for many years and
appears to be accepted by all tools reading GDS, so there is no
downside to always generating this output.  This has the upside
that default instance names don't get scrambled by going from
magic to GDS and back to magic.
2022-11-11 11:20:34 -05:00
Tim Edwards 05056d2f1f Left in the new code supporting the "calma contact true" option
for the squares-grid operator and for GDS compression.  But I
reverted the "calma contact" option to be false by default, because
the method does not exactly match the output when not using cell
instance arrays, and so may produce unexpected results.  Will
need a different implementation that uses the same code to generate
the same (effective) layout.
2022-11-10 14:46:26 -05:00
Tim Edwards e37a4f418a Based on output from a large contact array for a pad, modified the
default behavior of magic to make use of the "gds contacts true"
option to output contacts as arrays of subcells instead of
individual boundary entries, as the former is much more efficient
than the latter.  Set the option to be true by default, and set
the "gds flatglob" option to have one entry "$$*$$" corresponding
to the contact subcells created by the "gds contacts" option, so
that GDS reads and writes as it did previously (but using a
different method).  Expanded the method to include "squares-grid"
and "slots" operators (the latter should produce much more
efficient fill pattern arrays).  Implemented for both compressed
and uncompressed GDS.  Tested in all variations.
2022-11-10 14:08:58 -05:00
Tim Edwards 70e15b1d33 Corrected the "def write" output with respect to the "-units"
option.  This is important as the default units of 1nm are not
necessarily able to be converted to integer values if the
minimum manufacturing grid is an odd number of nanometers.
2022-11-09 17:38:09 -05:00
Tim Edwards 31ba6eeba3 Corrected an error introduced with the last push which changes
wire direction on vias during DEF write without changing the
"orient" value, causing Y values to get copied into X positions
in the output.
2022-11-09 15:14:53 -05:00
Tim Edwards f4c5ec3a78 Fixed the DEF write routine, which had an error in identifying
"slivers";  the error tended to produce artifacts (extra metal)
around contacts.  Fixed an issue that caused the DEF write routine
to open the same file twice instead of a new file for the second
part of the DEF data, and then potentially hit a runaway condition
when trying to merge the two files together.
2022-11-09 11:15:06 -05:00
Tim Edwards 2059d6fbb1 Corrected an error in "def write" that starts output on the wrong
layer when the first part of the route is a contact (starts on the
via top instead of the via bottom).
2022-11-08 09:59:43 -05:00
Tim Edwards a9aafebfc4 Corrected the antenna checking routines, which were incorrect with
respect to calculations around diode-connected diffusion regions.
The diffusion area calculation needed to be fixed to avoid double-
counting contacts, and the value for the ratioDiffA coefficient
needed to be scaled, since it is multiplied by the diffusion area
and therefore has dimensioned units of (1/area^2) and should be
treated like all other dimensioned units in magic.
2022-11-06 11:50:05 -05:00
794 changed files with 33542 additions and 16894 deletions

View File

@ -1,28 +0,0 @@
on:
push:
tags:
- "*"
name: CI
jobs:
build_appimage:
name: Build AppImage
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v2
- 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}}

289
.github/workflows/canary-matrix.yml vendored Normal file
View File

@ -0,0 +1,289 @@
name: CI-canary-matrix
on:
push:
tags:
- "*"
workflow_dispatch:
jobs:
canary:
strategy:
max-parallel: 3
matrix:
os: [ubuntu-24.04, ubuntu-22.04]
# Configure Options
# 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, 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-22.04
tc: gcc-13
- os: ubuntu-22.04
tc: gcc-14
- os: ubuntu-22.04
tc: clang-17
- 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-11
- os: ubuntu-24.04
tc: clang-14
- os: ubuntu-24.04
tc: clang-15
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Matrix Check
env:
MATRIX_OS: ${{ matrix.os }}
MATRIX_PKGS: ${{ matrix.pkgs }}
MATRIX_TC: ${{ matrix.tc }}
run: |
# This takes the macros params ENV and processes into options list
if [ "${MATRIX_PKGS}" = "none" ]
then
pkgs=""
cfgs=""
else
pkgs="kcnrzCLUX"
cfgs=""
fi
# 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 # 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
pkgs=$(echo -n "$pkgs" | sed -e 's#c##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tk"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#k##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gc"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#C##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gl"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#L##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gu"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#U##'); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gx"; then
pkgs=$(echo -n "$pkgs" | sed -e 's#X##'); fi
_package_list=()
echo -n $pkgs | grep -q "z" && _package_list+=(zlib1g-dev)
echo -n $pkgs | grep -q "n" && _package_list+=(libncurses-dev)
echo -n $pkgs | grep -q "r" && _package_list+=(libreadline-dev)
echo -n $pkgs | grep -q "c" && _package_list+=(tcl-dev)
echo -n $pkgs | grep -q "k" && _package_list+=(tk-dev)
echo -n $pkgs | grep -q "C" && _package_list+=(libcairo-dev)
echo -n $pkgs | grep -q "L" && _package_list+=(libgl-dev)
echo -n $pkgs | grep -q "U" && _package_list+=(libglu1-mesa-dev)
echo -n $pkgs | grep -q "X" && _package_list+=(libx11-dev)
echo "PACKAGE_LIST=${_package_list[*]}" >> $GITHUB_ENV
#
_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
_configure_args+=(--without-tcl); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_tk"; then
_configure_args+=(--without-tk); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gc"; then
_configure_args+=(--without-cairo); fi
if echo -n "$MATRIX_PKGS" | grep -q "^no.*_gl"; then
_configure_args+=(--without-opengl); fi
echo "CONFIGURE_ARGS=${_configure_args[*]}" >> $GITHUB_ENV
- name: Setup Toolchain
env:
MATRIX_TC: ${{ matrix.tc }}
run: |
# decode settings
BUILD_GCC_VERSION=$( echo -n "$MATRIX_TC" | grep -i "^gcc" | sed -e 's#^gcc\-\?##i')
BUILD_CLANG_VERSION=$(echo -n "$MATRIX_TC" | grep -i "^clang" | sed -e 's#^clang\-\?##i')
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
if [ -n "$BUILD_GCC_VERSION" ]
then
GCCV=$BUILD_GCC_VERSION
# https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
sudo apt-get install gcc-${GCCV} g++-${GCCV} cpp-${GCCV}
gcc-${GCCV} -v
g++-${GCCV} -v
cpp-${GCCV} -v < /dev/null
ls -l /usr/bin/g++ /usr/bin/g++-[0-9]* /usr/bin/gcc /usr/bin/gcc-[0-9]* /usr/bin/cpp-* /usr/bin/*-gnu-cpp* || true
update-alternatives --list gcc || true
update-alternatives --list g++ || true
update-alternatives --list cpp || true
update-alternatives --query gcc || true
update-alternatives --query g++ || true
update-alternatives --query cpp || true
ls -l /usr/bin/g++ /usr/bin/g++-[0-9]* /usr/bin/gcc /usr/bin/gcc-[0-9]* /usr/bin/cpp-* /usr/bin/*-gnu-cpp* || true
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCCV} 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCCV} 50
sudo update-alternatives --install "/usr/bin/$(uname -m)-linux-gnu-cpp" cpp "/usr/bin/$(uname -m)-linux-gnu-cpp-${GCCV}" 50
ls -l /usr/bin/g++ /usr/bin/g++-[0-9]* /usr/bin/gcc /usr/bin/gcc-[0-9]* /usr/bin/cpp-* /usr/bin/*-gnu-cpp* || true
update-alternatives --list gcc || true
update-alternatives --list g++ || true
update-alternatives --list cpp || true
hash -r
gcc -v
elif [ -n "$BUILD_CLANG_VERSION" ]
then
CLANGV=$BUILD_CLANG_VERSION
# https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
sudo apt-get install clang-${CLANGV} clang++-${CLANGV} #clang-cpp-${CLANGV}
clang-${CLANGV} -v
clang++-${CLANGV} -v
clang-cpp-${CLANGV} -v < /dev/null
ls -l /usr/bin/clang++ /usr/bin/clang++-[0-9]* /usr/bin/clang /usr/bin/clang-[0-9]* /usr/bin/clang-cpp-* /usr/bin/clang-cpp* || true
update-alternatives --list clang || true
update-alternatives --list clang++ || true
update-alternatives --list clang-cpp || true
update-alternatives --query clang || true
update-alternatives --query clang++ || true
update-alternatives --query clang-cpp || true
ls -l /usr/bin/clang++ /usr/bin/clang++-[0-9]* /usr/bin/clang /usr/bin/clang-[0-9]* /usr/bin/clang-cpp-* /usr/bin/clang-cpp* || true
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${CLANGV} 50
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANGV} 50
sudo update-alternatives --install "/usr/bin/clang-cpp" clang-cpp "/usr/bin/clang-cpp-${CLANGV}" 50
ls -l /usr/bin/clang++ /usr/bin/clang++-[0-9]* /usr/bin/clang /usr/bin/clang-[0-9]* /usr/bin/clang-cpp-* /usr/bin/clang-cpp* || true
update-alternatives --list clang || true
update-alternatives --list clang++ || true
update-alternatives --list clang-cpp || true
hash -r
clang -v
fi
- name: Get Dependencies
run: |
if [ -n "$PACKAGE_LIST" ]
then
sudo apt-get install -y ${PACKAGE_LIST}
fi
- name: Build
run: |
if [ -n "$BUILD_CLANG_VERSION" ]
then
export CC="clang-${BUILD_CLANG_VERSION}"
export CXX="clang++-${BUILD_CLANG_VERSION}"
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
# Add -Wall for CI loggings
sed -e 's# -Werror=# -Wall -Werror=#' -i defs.mak
# Non security/reliability related warnings
#sed -e 's# -Werror=# -Wno-unused-variable -Werror=#' -i defs.mak
#sed -e 's# -Werror=# -Wno-unused-local-typedefs -Werror=#' -i defs.mak
#sed -e 's# -Werror=# -Wno-unused-label -Werror=#' -i defs.mak
#sed -e 's# -Werror=# -Wno-unused-but-set-variable -Werror=#' -i defs.mak
make database/database.h
make -j$(nproc) 2>&1 | tee MAKE.LOG
- name: Summary
env:
MATRIX_OS: ${{ matrix.os }}
MATRIX_PKGS: ${{ matrix.pkgs }}
run: |
set +e
grep "error:" MAKE.LOG > MAKE_error.LOG
grep "warning:" MAKE.LOG > MAKE_warning.LOG
# Less important warnings relating to codesmell more than security (filter out of headline)
grep -v "Wunused-variable" MAKE_warning.LOG |
grep -v "Wunused-local-typedefs" |
grep -v "Wunused-label" |
grep -v "Wunused-but-set-variable" > MAKE_warning_filtered.LOG
ls -l
wc -l *.LOG
error_count=$( grep -c "error:" MAKE_error.LOG)
filtered_warning_count=$(grep -c "warning:" MAKE_warning_filtered.LOG)
title="### $(cat VERSION) ${MATRIX_OS} ${MATRIX_TC} ${MATRIX_PKGS} :: "
if [ "$error_count" -gt 0 ]
then
title="$title $error_count error(s)"
fi
if [ "$filtered_warning_count" -gt 0 ]
then
title="$title $filtered_warning_count warning(s)"
fi
(
total_error_count=$( wc -l MAKE_error.LOG | cut -d' ' -f1)
total_warning_count=$(wc -l MAKE_warning.LOG | cut -d' ' -f1)
echo "$title"
echo ""
echo "PACKAGE_LIST=$PACKAGE_LIST"
echo "CONFIGURE_ARGS=$CONFIGURE_ARGS"
echo ""
if [ "$BUILD_CLANG_VERSION" ]
then
"clang-${BUILD_CLANG_VERSION}" --version | head -n1
if ! update-alternatives --list clang
then
update-alternatives --list "clang-${BUILD_CLANG_VERSION}"
fi
else
gcc --version | head -n1
if ! update-alternatives --list gcc
then
update-alternatives --list "gcc-${BUILD_GCC_VERSION}"
fi
fi
echo ""
echo "total ${total_error_count} error(s) ${total_warning_count} warning(s) :"
echo "|Count|Warning Group (-j build log inaccuracies)|"
echo "|--:|:--|"
# due to -j build the log lines might get corrupted, so missing/incorrect/bogus entries might be seen
# so we add extra: egrep "\[\-W.*\]" (to try to remove that)
sed -e 's#.*\(\[\-W\)#\1#' -e 's#\(\]\).*$#\1#' MAKE_warning.LOG | egrep "\[\-W.*\]" | sort | uniq -c | sort -n | tr -s ' ' | tr ' ' '|' | awk '{print $0"|"}'
echo ""
sed -e '0,/Configuration Summary/d' -e '/\---/,//d' CONFIGURE.LOG | egrep "^.*:"
echo ""
grep DCAD_DIR MAKE.LOG | tail -n1
) >> $GITHUB_STEP_SUMMARY

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

475
.github/workflows/main-macos.yml vendored Normal file
View File

@ -0,0 +1,475 @@
# This is a basic workflow to help you get started with Actions
name: CI-macos
# 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_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
uses: actions/checkout@v4
- name: Get Dependencies
shell: bash # default shell has unwanted broken pipe indication
run: |
brew install --cask xquartz
PACKAGE_LIST="xquartz"
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"
if [ -n "$PACKAGE_LIST" ]
then
brew install $PACKAGE_LIST
fi
PACKAGE_LIST="$PACKAGE_LIST $_package_list"
echo "PACKAGE_LIST=$PACKAGE_LIST" >> $GITHUB_ENV
echo "UNAME_M=$(uname -m)" >> $GITHUB_ENV
set +e
set +o pipefail # macosx this is on by default (turn it off)
(
echo "### $(uname -s) $(uname -m) $(uname -r)"
echo ""
set +e
set +o pipefail # macosx this is on by default (turn it off)
export HOMEBREW_NO_COLOR=true
export HOMEBREW_NO_EMOKI=true
# output to $TMPFILE first, then head, instead of using pipeline directly
# this removes unwanted GHA SIGPIPE error/warning indicators from GHA logs
# brew maybe a nodejs command which has a known issue in this area on macosx
TMPFILE=/tmp/shell0$$.tmp
brew info xquartz > $TMPFILE && head -n1 $TMPFILE
brew info cairo > $TMPFILE && head -n1 $TMPFILE
brew info libglu > $TMPFILE && head -n1 $TMPFILE
brew info freeglut > $TMPFILE && head -n1 $TMPFILE
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 ""
xcodebuild -version
echo ""
xcodebuild -showsdks | grep macOS
) >> $GITHUB_STEP_SUMMARY
- name: Search
run: |
set +e
( # designed to speed up this process in a single scan
echo "#!/bin/sh"
echo "echo \$*"
echo "ls -ld -- \$*"
echo "shasum -a 1 \$* </dev/null"
echo "echo \"\""
echo "exit 0"
) > search.sh
echo "=== search.sh"
cat search.sh
chmod a+x search.sh
find /opt /usr $HOME \( -iname "libX11.*dylib" -or -iname "Xlib.h" -or -iname "libtcl*dylib" -or -iname "tcl.h" \) -exec ./search.sh {} \; 2>/dev/null
#
# Example symbols that were found missing from the tcl-tk X11 implementation
#find /opt /usr $HOME -iname "x*.h" -exec grep -Hn "XCreateGC" {} \; 2>/dev/null || true
#find /opt /usr $HOME -iname "x*.h" -exec grep -Hn "XGetVisualInfo" {} \; 2>/dev/null || true
#for i in /usr/X11/include/X11/Xlib.h /opt/X11/include/X11/Xlib.h /usr/local/include/X11/Xlib.h;
#do
# echo "====== $i"
# head -n 50 "$i"
# echo "==="
# tail -n 50 "$i"
# echo "======"
#done
# Different GHA platforms have different layouts (x86_64/arm64)
echo "=== /opt"
ls -l /opt
if [ -d /opt/homebrew ]
then
echo "=== /opt/homebrew"
ls -l /opt/homebrew
fi
echo "=== /usr/local/opt"
ls -l /usr/local/opt
echo "=== /usr/local/opt/runner"
ls -l /usr/local/opt/runner
echo "Done"
- name: Build
run: |
export PATH="/opt/X11/bin:$PATH"
./scripts/configure_mac 2>&1 | tee CONFIGURE.LOG
config_log=""
if [ -f scripts/config.log ]
then
config_log="scripts/config.log"
elif [ -f build-magic/config.log ]
then
config_log="build-magic/config.log"
fi
if [ -n "$config_log" ]
then
CONFIGURE_ARGS=$(head -n 10 $config_log | egrep "./configure" | sed -e 's#^ *\$ ##' -e 's#./configure ##')
echo "CONFIGURE_ARGS=$CONFIGURE_ARGS" >> $GITHUB_ENV
fi
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="
make database/database.h
make -j$(sysctl -n hw.ncpu) 2>&1 | tee MAKE.LOG
- name: Install
run: |
sudo make install
- name: Kick The Tyres
run: |
set +e
echo "=== ls -l"
ls -l
find . -type f \( -name "*.dylib" -or -name "magic" -or -name "magicexec" -or -name "magicdnull" \)
echo "=== find /usr/local/bin"
find /usr/local/bin -mtime 0
echo "=== find /usr/local/share"
find /usr/local/share -mtime 0
echo "=== find /usr/local/lib/magic"
find /usr/local/lib/magic -mtime 0
echo "=== otool -L magic/tclmagic.dylib"
otool -L magic/tclmagic.dylib
echo "=== otool -L tcltk/magicexec"
otool -L tcltk/magicexec
echo "=== otool -L tcltk/magicdnull"
otool -L tcltk/magicdnull
set +o pipefail # macosx this is on by default (turn it off)
echo "=== magic --version"
magic --version
echo "=== magic -d help -noconsole"
magic -d help -noconsole
echo "=== magic -d null -noconsole -nowindow -T scmos"
echo "version ; quit" | magic -d null -noconsole -nowindow -T scmos
echo "=== magic -d null -noconsole -T scmos"
echo "version ; quit" | magic -d null -noconsole -T scmos
- name: Summary
if: always()
run: |
set +e
ls -l
touch MAKE.LOG # just in case it did not even build
grep "error:" MAKE.LOG > MAKE_error.LOG
grep "warning:" MAKE.LOG > MAKE_warning.LOG
# Less important warnings relating to codesmell more than security (filter out of headline)
grep -v "Wunused-variable" MAKE_warning.LOG |
grep -v "Wunused-local-typedefs" |
grep -v "Wunused-label" |
grep -v "Wunused-but-set-variable" > MAKE_warning_filtered.LOG
wc -l *.LOG
error_count=$( grep -c "error:" MAKE_error.LOG)
filtered_warning_count=$(grep -c "warning:" MAKE_warning_filtered.LOG)
title="### $(cat VERSION) ${MATRIX_OS} ${MATRIX_TC} ${MATRIX_PKGS} :: "
if [ "$error_count" -gt 0 ]
then
title="$title $error_count error(s)"
fi
if [ "$filtered_warning_count" -gt 0 ]
then
title="$title $filtered_warning_count warning(s)"
fi
(
total_error_count=$( wc -l MAKE_error.LOG | cut -d' ' -f1)
total_warning_count=$(wc -l MAKE_warning.LOG | cut -d' ' -f1)
echo "---"
echo "$title"
echo ""
[ -f scripts/config.log ] && grep "./configure" scripts/config.log | head -n1
echo ""
echo "PACKAGE_LIST=$PACKAGE_LIST"
echo "CONFIGURE_ARGS=$CONFIGURE_ARGS"
echo ""
if [ -s MAKE.LOG ]
then
echo "total ${total_error_count} error(s) ${total_warning_count} warning(s) :"
echo "|Count|Warning Group (-j build log inaccuracies)|"
echo "|--:|:--|"
# due to -j build the log lines might get corrupted, so missing/incorrect/bogus entries might be seen
# so we add extra: egrep "\[\-W.*\]" (to try to remove that)
sed -e 's#.*\(\[\-W\)#\1#' -e 's#\(\]\).*$#\1#' MAKE_warning.LOG | egrep "\[\-W.*\]" | sort | uniq -c | sort -n | tr -s ' ' | tr ' ' '|' | awk '{print $0"|"}'
echo ""
fi
grep -A100 "Configuration Summary" CONFIGURE.LOG | grep -v "Configuration Summary" | egrep "^.*:" | sed -e '/\---/,//d'
echo ""
grep DCAD_DIR MAKE.LOG | tail -n1
) >> $GITHUB_STEP_SUMMARY
- name: Prepare archive
run: |
mkdir -p dist
make install "DESTDIR=$(pwd)/dist"
# Diagnostic details about this build
mkdir -p dist/BUILD-INFO
set +e
cp */config.log dist/BUILD-INFO/
cp *.mak dist/BUILD-INFO/
cp *.LOG dist/BUILD-INFO/
- name: Upload archive magic-macos15
uses: actions/upload-artifact@v4
with:
name: magic-macos15
path: |
${{ github.workspace }}/dist
simple_build_macos:
runs-on: macos-latest
timeout-minutes: 30 # arm64 seems SSD based (faster)
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get Dependencies
shell: bash # default shell has unwanted broken pipe indication
run: |
brew install --cask xquartz
PACKAGE_LIST="xquartz"
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"
if [ -n "$PACKAGE_LIST" ]
then
brew install $PACKAGE_LIST
fi
PACKAGE_LIST="$PACKAGE_LIST $_package_list"
echo "PACKAGE_LIST=$PACKAGE_LIST" >> $GITHUB_ENV
echo "UNAME_M=$(uname -m)" >> $GITHUB_ENV
set +e
set +o pipefail # macosx this is on by default (turn it off)
(
echo "### $(uname -s) $(uname -m) $(uname -r)"
echo ""
set +e
set +o pipefail # macosx this is on by default (turn it off)
export HOMEBREW_NO_COLOR=true
export HOMEBREW_NO_EMOKI=true
# output to $TMPFILE first, then head, instead of using pipeline directly
# this removes unwanted GHA SIGPIPE error/warning indicators from GHA logs
# brew maybe a nodejs command which has a known issue in this area on macosx
TMPFILE=/tmp/shell0$$.tmp
brew info xquartz > $TMPFILE && head -n1 $TMPFILE
brew info cairo > $TMPFILE && head -n1 $TMPFILE
brew info libglu > $TMPFILE && head -n1 $TMPFILE
brew info freeglut > $TMPFILE && head -n1 $TMPFILE
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 ""
xcodebuild -version
echo ""
xcodebuild -showsdks | grep macOS
) >> $GITHUB_STEP_SUMMARY
- name: Search
run: |
set +e
( # designed to speed up this process in a single scan
echo "#!/bin/sh"
echo "echo \$*"
echo "ls -ld -- \$*"
echo "shasum -a 1 \$* </dev/null"
echo "echo \"\""
echo "exit 0"
) > search.sh
echo "=== search.sh"
cat search.sh
chmod a+x search.sh
find /opt /usr $HOME \( -iname "libX11.*dylib" -or -iname "Xlib.h" -or -iname "libtcl*dylib" -or -iname "tcl.h" \) -exec ./search.sh {} \; 2>/dev/null
#
# Example symbols that were found missing from the tcl-tk X11 implementation
#find /opt /usr $HOME -iname "x*.h" -exec grep -Hn "XCreateGC" {} \; 2>/dev/null || true
#find /opt /usr $HOME -iname "x*.h" -exec grep -Hn "XGetVisualInfo" {} \; 2>/dev/null || true
#for i in /usr/X11/include/X11/Xlib.h /opt/X11/include/X11/Xlib.h /usr/local/include/X11/Xlib.h;
#do
# echo "====== $i"
# head -n 50 "$i"
# echo "==="
# tail -n 50 "$i"
# echo "======"
#done
# Different GHA platforms have different layouts (x86_64/arm64)
echo "=== /opt"
ls -l /opt
if [ -d /opt/homebrew ]
then
echo "=== /opt/homebrew"
ls -l /opt/homebrew
fi
echo "=== /usr/local/opt"
ls -l /usr/local/opt
echo "=== /usr/local/opt/runner"
ls -l /usr/local/opt/runner
echo "Done"
- name: Build
run: |
export PATH="/opt/X11/bin:$PATH"
./scripts/configure_mac 2>&1 | tee CONFIGURE.LOG
config_log=""
if [ -f scripts/config.log ]
then
config_log="scripts/config.log"
elif [ -f build-magic/config.log ]
then
config_log="build-magic/config.log"
fi
if [ -n "$config_log" ]
then
CONFIGURE_ARGS=$(head -n 10 $config_log | egrep "./configure" | sed -e 's#^ *\$ ##' -e 's#./configure ##')
echo "CONFIGURE_ARGS=$CONFIGURE_ARGS" >> $GITHUB_ENV
fi
echo "===== defs.mak ====="
cat defs.mak
echo "===== defs.mak ====="
make database/database.h
make -j$(sysctl -n hw.ncpu) 2>&1 | tee MAKE.LOG
- name: Install
run: |
sudo make install
- name: Kick The Tyres
run: |
set +e
echo "=== ls -l"
ls -l
find . -type f \( -name "*.dylib" -or -name "magic" -or -name "magicexec" -or -name "magicdnull" \)
echo "=== find /usr/local/bin"
find /usr/local/bin -mtime 0
echo "=== find /usr/local/share"
find /usr/local/share -mtime 0
echo "=== find /usr/local/lib/magic"
find /usr/local/lib/magic -mtime 0
echo "=== otool -L magic/tclmagic.dylib"
otool -L magic/tclmagic.dylib
echo "=== otool -L tcltk/magicexec"
otool -L tcltk/magicexec
echo "=== otool -L tcltk/magicdnull"
otool -L tcltk/magicdnull
set +o pipefail # macosx this is on by default (turn it off)
echo "=== magic --version"
magic --version
echo "=== magic -d help -noconsole"
magic -d help -noconsole
echo "=== magic -d null -noconsole -nowindow -T scmos"
echo "version ; quit" | magic -d null -noconsole -nowindow -T scmos
echo "=== magic -d null -noconsole -T scmos"
echo "version ; quit" | magic -d null -noconsole -T scmos
- name: Summary
if: always()
run: |
set +e
ls -l
touch MAKE.LOG # just in case it did not even build
grep "error:" MAKE.LOG > MAKE_error.LOG
grep "warning:" MAKE.LOG > MAKE_warning.LOG
# Less important warnings relating to codesmell more than security (filter out of headline)
grep -v "Wunused-variable" MAKE_warning.LOG |
grep -v "Wunused-local-typedefs" |
grep -v "Wunused-label" |
grep -v "Wunused-but-set-variable" > MAKE_warning_filtered.LOG
wc -l *.LOG
error_count=$( grep -c "error:" MAKE_error.LOG)
filtered_warning_count=$(grep -c "warning:" MAKE_warning_filtered.LOG)
title="### $(cat VERSION) ${MATRIX_OS} ${MATRIX_TC} ${MATRIX_PKGS} :: "
if [ "$error_count" -gt 0 ]
then
title="$title $error_count error(s)"
fi
if [ "$filtered_warning_count" -gt 0 ]
then
title="$title $filtered_warning_count warning(s)"
fi
(
total_error_count=$( wc -l MAKE_error.LOG | cut -d' ' -f1)
total_warning_count=$(wc -l MAKE_warning.LOG | cut -d' ' -f1)
echo "---"
echo "$title"
echo ""
[ -f scripts/config.log ] && grep "./configure" scripts/config.log | head -n1
echo ""
echo "PACKAGE_LIST=$PACKAGE_LIST"
echo "CONFIGURE_ARGS=$CONFIGURE_ARGS"
echo ""
if [ -s MAKE.LOG ]
then
echo "total ${total_error_count} error(s) ${total_warning_count} warning(s) :"
echo "|Count|Warning Group (-j build log inaccuracies)|"
echo "|--:|:--|"
# due to -j build the log lines might get corrupted, so missing/incorrect/bogus entries might be seen
# so we add extra: egrep "\[\-W.*\]" (to try to remove that)
sed -e 's#.*\(\[\-W\)#\1#' -e 's#\(\]\).*$#\1#' MAKE_warning.LOG | egrep "\[\-W.*\]" | sort | uniq -c | sort -n | tr -s ' ' | tr ' ' '|' | awk '{print $0"|"}'
echo ""
fi
grep -A100 "Configuration Summary" CONFIGURE.LOG | grep -v "Configuration Summary" | egrep "^.*:" | sed -e '/\---/,//d'
echo ""
grep DCAD_DIR MAKE.LOG | tail -n1
) >> $GITHUB_STEP_SUMMARY
- name: Prepare archive
run: |
mkdir -p dist
make install "DESTDIR=$(pwd)/dist"
# Diagnostic details about this build
mkdir -p dist/BUILD-INFO
set +e
cp */config.log dist/BUILD-INFO/
cp *.mak dist/BUILD-INFO/
cp *.LOG dist/BUILD-INFO/
- name: Upload archive magic-macos
uses: actions/upload-artifact@v4
with:
name: magic-macos
path: |
${{ github.workspace }}/dist

View File

@ -17,35 +17,45 @@ jobs:
steps:
- name: Pulling the docker image
run: docker pull vezzal/vezzal:v1
- name: Start the container with the docker image
run: docker run -id --name test_magic vezzal/vezzal:v1 bash | exit
- 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@v2
- uses: actions/checkout@v4
- name: Get Dependencies
run: |
sudo apt-get install -y tcl-dev tk-dev libcairo-dev csh
sudo apt-get install -y tcl-dev tk-dev libcairo-dev
- name: Build
run: |
./configure
make database/database.h
make -j$(nproc)
# simple_build_mac:
# runs-on: macos-11
# steps:
# - uses: actions/checkout@v2
# - name: Get Dependencies
# run: |
# brew install --cask xquartz
# brew install cairo tcl-tk tcsh
# - name: Build
# run: |
# export PATH="/opt/X11/bin:$PATH"
# ./scripts/configure_mac
# make database/database.h
# make -j$(sysctl -n hw.ncpu)
simple_build_wasm:
runs-on: ubuntu-22.04
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
path: |
${{ github.workspace }}/magic/magic.wasm

2
.gitignore vendored
View File

@ -14,7 +14,6 @@ database/database.h
install.log
magic/proto.magicrc
make.log
readline/readline
scmos/gdsquery.tech
scmos/minimum.tech
scmos/scmos-sub.tech
@ -32,3 +31,4 @@ magic/tclmagic.dylib
tcltk/magicdnull.dSYM/
tcltk/magicexec.dSYM/
reconfigure.sh
pfx/

View File

@ -47,6 +47,12 @@ Autoconf Capsule Summary:
Disable threaded X11 and OpenGL graphics.
Normally enabled.
--disable-compression
Disable reading and writing of compressed
(gzipped) GDS files and reading of compressed
.mag files. Normally enabled, if the zlib
development package is installed.
Notes to Magic maintainers:
--------------------------

View File

@ -3,9 +3,10 @@
Get [Homebrew](https://brew.sh).
```sh
brew install cairo tcl-tk tcsh
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 which was selected.
make database/database.h
make -j$(sysctl -n hw.ncpu)
make install # may need sudo depending on your setup
@ -22,6 +23,7 @@ We are following the instructions from xschem (https://github.com/StefanSchipper
We are using not `opt` but `opt2` so that this Tcl does not interfere with `tcl-tk` from HomeBrew.
Extract the Tcl sources and then go to the unix folder and execute the following commands::
```
./configure --prefix=/usr/local/opt2/tcl-tk
make
@ -32,6 +34,13 @@ make install
* Download Tk from https://prdownloads.sourceforge.net/tcl/tk8.6.10-src.tar.gz
Extract Tk source and then go to the unix folder:
NOTE: before running 'make' inspect the Makefile and ensure the LIB_RUNTIME_DIR is set as follows. Make the correction if not:
```
LIB_RUNTIME_DIR = $(libdir)
```
```
./configure --prefix=/usr/local/opt2/tcl-tk \
--with-tcl=/usr/local/opt2/tcl-tk/lib --with-x \
@ -53,3 +62,18 @@ CFLAGS=-Wno-error=implicit-function-declaration
make
make install
```
## If facing issue with layout window not opening / XQuartz:
Make sure that the output of the following command is ```:0```.
```
echo $DISPLAY
```
if the above command doesn't display ```:0``` then add the following line in ```.zshrc```.
```
export PATH="/opt/X11/bin:$PATH"
```
Close & reopen terminal to load the path. Then set display manually to ```0``` by using the following command.
```
export DISPLAY=:0
```
Now ```echo DISPLAY``` should give ```:0``` as output.

104
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,25 +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
${RM} */Depend
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)
@ -96,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
@ -106,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 \
@ -134,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.335
8.3.591

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 |

68
appimage/7/Dockerfile Normal file
View File

@ -0,0 +1,68 @@
FROM centos/python-38-centos7:20210726-fad62e9
USER root
# CentOS7 went EOL on June 30, 2024 this builds out of vault.centos.org
RUN 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
# 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
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 \
--without-opengl \
&& 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/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,44 +0,0 @@
FROM centos/python-38-centos7:20210726-fad62e9
USER root
# Build Dependencies
RUN yum install -y cairo-devel freeglut-devel gcc make tcsh
# Tcl/Tk
WORKDIR /tcl
RUN curl -L https://prdownloads.sourceforge.net/tcl/tcl8.6.12-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 . \
&& 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 \
--without-opengl \
&& make clean \
&& make database/database.h \
&& make -j$(nproc) \
&& make install
WORKDIR /
RUN tar -czf /prefix.tar.gz -C ./prefix .
CMD ["/bin/bash"]

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;
@ -567,6 +567,9 @@ BinArray *bpBinArrayBuild(Rect bbox,
int numBins;
int count;
/* Added by Tim, 2/19/2024 */
/* This line is not supposed to be needed? */
if ((!subbin) && ((pointertype)elements & BT_ARRAY)) return NULL;
if(BPD) DumpRect("#### bpBinArrayBuild, TOP 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

@ -50,9 +50,9 @@
*/
void BPEnumInit(BPEnum *bpe, /* enum to initialize */
BPlane *bp,
Rect *area, /* search area */
const Rect *area, /* search area */
int match,
char *id) /* for debugging */
const char *id) /* for debugging */
{
bool inside = FALSE;
bpe->bpe_plane = bp;

View File

@ -25,8 +25,8 @@
//
// ************************************************************************
#ifndef _BPENUM_H
#define _BPENUM_H
#ifndef _MAGIC__BPLANE__BPENUM_H
#define _MAGIC__BPLANE__BPENUM_H
/* bpEnum.h --
*
@ -305,7 +305,7 @@ bpEnumNextBin(BPEnum *bpe, bool inside)
{
BPStack *bps = bpe->bpe_top;
#ifdef PARANOID
#ifdef BPARANOID
ASSERT(bps,"bpEnumNextBin");
ASSERT(!bpe->bpe_nextElement,"bpEnumNextBin");
#endif
@ -506,23 +506,23 @@ static __inline__ void *BPEnumNext(BPEnum *bpe)
switch (bpe->bpe_top->bps_state)
{
case BPS_BINS:
if(e=bpEnumNextBINS(bpe, 0)) return e;
if((e=bpEnumNextBINS(bpe, 0))) return e;
break;
case BPS_BINS_INSIDE:
if(e=bpEnumNextBINS(bpe, 1)) return e;
if((e=bpEnumNextBINS(bpe, 1))) return e;
break;
case BPS_INBOX:
if(e=bpEnumNextINBOX(bpe, 0)) return e;
if((e=bpEnumNextINBOX(bpe, 0))) return e;
break;
case BPS_INBOX_INSIDE:
if(e=bpEnumNextINBOX(bpe, 1)) return e;
if((e=bpEnumNextINBOX(bpe, 1))) return e;
break;
case BPS_HASH:
if(e=bpEnumNextHASH(bpe)) return e;
if((e=bpEnumNextHASH(bpe))) return e;
break;
case BPS_DONE:
@ -534,4 +534,4 @@ static __inline__ void *BPEnumNext(BPEnum *bpe)
}
}
#endif /* _BPENUM_H */
#endif /* _MAGIC__BPLANE__BPENUM_H */

View File

@ -37,6 +37,7 @@
*/
#include <stdio.h>
#include <stddef.h>
#include "utils/utils.h"
#include "utils/malloc.h"
#include "database/database.h"
@ -68,8 +69,8 @@ BPlane *BPNew(void)
/* HASH TABLE */
new->bp_hashTable = IHashInit(4, /* initial buckets */
OFFSET(Element, e_rect), /* key */
OFFSET(Element, e_hashLink),
offsetof(Element, e_rect), /* key */
offsetof(Element, e_hashLink),
IHash4WordKeyHash,
IHash4WordKeyEq);
@ -127,7 +128,7 @@ void BPAdd(BPlane *bp, void *element)
"BPAdd, attempted during active enumerations");
/* element rect must be canonical! */
#ifdef PARANOID
#ifdef BPARANOID
ASSERT(GeoIsCanonicalRect(r),"BPAdd, rect must be canonical.");
#endif
@ -261,7 +262,7 @@ Rect BPBBox(BPlane *bp)
e = BPEnumNext(&bpe);
bp->bp_bbox = e->e_rect;
while(e = BPEnumNext(&bpe))
while((e = BPEnumNext(&bpe)))
{
GeoIncludeRectInBBox(&e->e_rect, &bp->bp_bbox);
}

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 --
@ -106,7 +106,7 @@ static __inline__ bool bpBinType(BinArray *ba, int i)
static __inline__ Element *bpBinList(BinArray *ba, int i)
{
#ifdef PARANOID
#ifdef BPARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif
return (Element *) ba->ba_bins[i];
@ -114,7 +114,7 @@ static __inline__ Element *bpBinList(BinArray *ba, int i)
static __inline__ Element **bpBinListHead(BinArray *ba, int i)
{
#ifdef PARANOID
#ifdef BPARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif
return (Element **) &ba->ba_bins[i];
@ -122,7 +122,7 @@ static __inline__ Element **bpBinListHead(BinArray *ba, int i)
static __inline__ BinArray *bpSubArray(BinArray *ba, int i)
{
#ifdef PARANOID
#ifdef BPARANOID
ASSERT(bpBinType(ba,i)==BT_ARRAY,"bpSubArray");
#endif
return (BinArray *) ((pointertype) ba->ba_bins[i] & ~BT_TYPE_MASK);
@ -182,7 +182,7 @@ typedef struct bpenum
BPlane *bpe_plane; /* plane being searched */
Rect bpe_srchArea; /* area being searched */
int bpe_match; /* match criteria */
char *bpe_id; /* for debug */
const char *bpe_id; /* for debug */
int bpe_subBinMinX;
int bpe_subBinMinY; /* consider subbinning
* for bins bigger than this.
@ -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 --
@ -160,17 +160,6 @@
*
*/
/* offset of a structure member (used to gen offsets for ihash stuff) */
#if _MSC_VER
/* Microsoft compile complains about size of (void*), so must use (char*) */
/* Could use (char*) in UNIX version too. */
#define OFFSET(structure,member) \
( ((char *) &(((structure *) 0))->member) - ((char *) 0) )
#else
#define OFFSET(structure,member) \
( ((void *) &(((structure *) 0))->member) - ((void *) 0) )
#endif
/* data-structures opaque to clients */
#include "bplane/bpOpaque.h"
@ -196,9 +185,9 @@ extern void BPEnumInit(BPEnum *bpe, /* this procedure initializes this
* enumeration.
*/
BPlane *bp, /* bplane to search */
Rect *area, /* area to search */
const Rect *area, /* area to search */
int match, /* see below */
char *id); /* for debugging */
const char *id); /* for debugging */
/* match values */
/* enum all elements in the bplane (area arg must be null) */
@ -243,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

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdcl.c,v 1.5 2010/06/25 13:59:24 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdcl.c,v 1.5 2010/06/25 13:59:24 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -56,11 +56,12 @@ bool CalmaRewound = FALSE;
TileTypeBitMask *CalmaMaskHints = NULL;
extern HashTable calmaDefInitHash;
extern int CalmaPolygonCount;
/* forward declarations */
int calmaElementSref();
bool calmaParseElement();
void calmaUniqueCell();
int calmaElementSref(char *filename);
bool calmaParseElement(char *filename, int *pnsrefs, int *pnpaths);
void calmaUniqueCell(char *sname);
/* Structure used when flattening the GDS hierarchy on read-in */
@ -95,8 +96,8 @@ typedef struct {
*/
OFFTYPE
calmaSetPosition(sname)
char *sname;
calmaSetPosition(
char *sname)
{
OFFTYPE originalPos = 0, currentPos = 0;
int nbytes, rtype;
@ -187,7 +188,7 @@ calmaSetPosition(sname)
*/
void
calmaNextCell()
calmaNextCell(void)
{
int nbytes, rtype;
@ -239,12 +240,14 @@ calmaNextCell()
*/
Plane **
calmaExact()
calmaExact(void)
{
int pNum;
Plane *newplane;
Plane **parray;
int gdsCopyPaintFunc(); /* Forward reference */
/* Forward reference */
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
@ -274,7 +277,56 @@ calmaExact()
return parray;
}
/*
* ----------------------------------------------------------------------------
*
* calmaFlattenPolygonFunc --
*
* Polygons have been dropped into subcells by default for
* efficiency in reading. If the "subcell polygons" option
* has not been selected, then flatten these cells into the
* layout and delete the cells. This seems inefficient but
* in fact can be much faster than reading the polygons
* directly into the cell from GDS.
*
* Return value:
* Return 0 to keep the search going
*
* Side effects:
* Polygons are copied from use->cu_def to parent.
* use->cu_def is deleted.
*
* ----------------------------------------------------------------------------
*/
int
calmaFlattenPolygonFunc(
CellUse *use,
CellDef *parent)
{
int i;
CellUse dummy;
SearchContext scx;
HashEntry *he;
if (use->cu_def == NULL || use->cu_def->cd_name == NULL) return 0;
if (strncmp(use->cu_def->cd_name, "polygon", 7)) return 0;
dummy.cu_transform = GeoIdentityTransform;
dummy.cu_id = NULL;
dummy.cu_def = parent;
scx.scx_use = use;
scx.scx_area = use->cu_bbox;
scx.scx_trans = GeoIdentityTransform;
DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, 0, &dummy);
DBDeleteCellNoModify(use);
HashRemove(&CifCellTable, use->cu_def->cd_name);
/* There should only be one use, so it can just be cleared */
use->cu_def->cd_parents = (CellUse *)NULL;
DBCellDeleteDef(use->cu_def);
return 0; /* Keep the search going */
}
/*
* ----------------------------------------------------------------------------
@ -297,22 +349,26 @@ calmaExact()
*/
bool
calmaParseStructure(filename)
char *filename; /* Name of the GDS file read */
calmaParseStructure(
char *filename) /* Name of the GDS file read */
{
static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
int nbytes, rtype, nsrefs, osrefs, npaths;
static const int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
int nbytes = -1, rtype = 0, nsrefs, osrefs, npaths;
char *strname = NULL;
HashEntry *he;
int timestampval = 0;
int suffix;
int mfactor;
int locPolygonCount;
OFFTYPE filepos;
bool was_called;
bool was_called = FALSE;
bool was_initialized;
bool predefined;
bool do_flatten;
CellDef *def;
Label *lab;
locPolygonCount = CalmaPolygonCount;
/* Make sure this is a structure; if not, let the caller know we're done */
PEEKRH(nbytes, rtype);
@ -333,6 +389,15 @@ calmaParseStructure(filename)
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 */
@ -342,6 +407,7 @@ calmaParseStructure(filename)
if (!CalmaPostOrder && !CalmaRewound)
{
cifReadCellDef = def;
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
strname);
CalmaReadError("Ignoring duplicate definition\n");
@ -353,6 +419,7 @@ calmaParseStructure(filename)
{
char *newname;
cifReadCellDef = def;
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
strname);
newname = (char *)mallocMagic(strlen(strname) + 20);
@ -547,8 +614,21 @@ calmaParseStructure(filename)
CIFPaintCurrent(FILE_CALMA);
}
DBAdjustLabelsNew(cifReadCellDef, &TiPlaneRect,
(cifCurReadStyle->crs_flags & CRF_NO_RECONNECT_LABELS) ? 1 : 0);
/* Check for empty string labels that are caused by pin geometry that
* did not get any corresponding text type, and remove them.
*/
DBEraseLabelsByContent(cifReadCellDef, NULL, -1, "");
if ((CalmaSubcellPolygons == CALMA_POLYGON_TEMP) &&
(locPolygonCount < CalmaPolygonCount))
DBCellEnum(cifReadCellDef, calmaFlattenPolygonFunc, (ClientData)cifReadCellDef);
/* Because the "label" statement can only match one GDS layer to one magic
* layer, then all labels are subject to adjustment to attach them to
* something meaningful in the layout. The "no-reconnect-labels" option
* is not useful and has been deprecated.
*/
DBAdjustLabelsNew(cifReadCellDef, &TiPlaneRect);
DBReComputeBbox(cifReadCellDef);
/* Don't bother to register with DRC if we're going to delete the */
@ -608,11 +688,12 @@ syntaxerror:
*/
bool
calmaParseElement(filename, pnsrefs, pnpaths)
char *filename;
int *pnsrefs, *pnpaths;
calmaParseElement(
char *filename,
int *pnsrefs,
int *pnpaths)
{
static int node[] = { CALMA_ELFLAGS, CALMA_PLEX, CALMA_LAYER,
static const int node[] = { CALMA_ELFLAGS, CALMA_PLEX, CALMA_LAYER,
CALMA_NODETYPE, CALMA_XY, -1 };
int nbytes, rtype, madeinst;
@ -670,9 +751,10 @@ calmaParseElement(filename, pnsrefs, pnpaths)
*/
int
calmaEnumFunc(tile, plane)
Tile *tile;
int *plane;
calmaEnumFunc(
Tile *tile,
TileType dinfo,
int *plane)
{
return 1;
}
@ -697,24 +779,26 @@ calmaEnumFunc(tile, plane)
*/
int
calmaElementSref(filename)
char *filename;
calmaElementSref(
char *filename)
{
int nbytes, rtype, cols, rows, nref, n, i, savescale;
int xlo, ylo, xhi, yhi, xsep, ysep;
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(); /* Forward reference */
int gdsHasUses(); /* 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);
@ -730,7 +814,38 @@ calmaElementSref(filename)
*/
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
@ -764,6 +879,7 @@ calmaElementSref(filename)
FSEEK(calmaInputFile, originalFilePos, SEEK_SET);
cifReadCellDef = calmaLookCell(currentSname);
def = calmaLookCell(sname);
def->cd_flags |= CDPRELOADED;
cifCurReadPlanes = savePlanes;
calmaLayerHash = OrigCalmaLayerHash;
if (crsMultiplier != cifCurReadStyle->crs_multiplier)
@ -1038,7 +1154,14 @@ calmaElementSref(filename)
if (isArray)
DBMakeArray(use, &GeoIdentityTransform, xlo, ylo, xhi, yhi, xsep, ysep);
DBSetTrans(use, &trans);
DBPlaceCell(use, cifReadCellDef);
if (DBCellFindDup(use, cifReadCellDef) != NULL)
{
DBCellDeleteUse(use);
CalmaReadError("Warning: cell \"%s\" placed on top of"
" itself. Ignoring the extra one.\n", def->cd_name);
}
else
DBPlaceCell(use, cifReadCellDef);
break; // No need to do 2nd loop
}
@ -1105,8 +1228,17 @@ calmaElementSref(filename)
if (isArray)
DBMakeArray(use, &GeoIdentityTransform, xlo, ylo, xhi, yhi, xsep, ysep);
DBSetTrans(use, &trans);
DBPlaceCell(use, cifReadCellDef);
madeinst = TRUE;
if (DBCellFindDup(use, cifReadCellDef) != NULL)
{
DBCellDeleteUse(use);
CalmaReadError("Warning: cell \"%s\" placed on top of"
" itself. Ignoring the extra one.\n", def->cd_name);
}
else
{
DBPlaceCell(use, cifReadCellDef);
madeinst = TRUE;
}
}
else
{
@ -1123,8 +1255,17 @@ calmaElementSref(filename)
if (isArray)
DBMakeArray(use, &GeoIdentityTransform, xlo, ylo, xhi, yhi, xsep, ysep);
DBSetTrans(use, &trans);
DBPlaceCell(use, cifReadCellDef);
madeinst = TRUE;
if (DBCellFindDup(use, cifReadCellDef) != NULL)
{
DBCellDeleteUse(use);
CalmaReadError("Warning: cell \"%s\" placed on top of"
" itself. Ignoring the extra one.\n", def->cd_name);
}
else
{
DBPlaceCell(use, cifReadCellDef);
madeinst = TRUE;
}
}
}
@ -1140,9 +1281,9 @@ calmaElementSref(filename)
/* Callback function for determining if a cell has at least one subcell */
int
gdsHasUses(use, clientdata)
CellUse *use;
ClientData clientdata;
gdsHasUses(
CellUse *use,
ClientData clientdata)
{
return 1;
}
@ -1150,29 +1291,30 @@ gdsHasUses(use, clientdata)
/* Callback function for copying paint from one CIF cell into another */
int
gdsCopyPaintFunc(tile, gdsCopyRec)
Tile *tile;
GDSCopyRec *gdsCopyRec;
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;
@ -1197,8 +1339,8 @@ gdsCopyPaintFunc(tile, gdsCopyRec)
*/
void
calmaUniqueCell(sname)
char *sname;
calmaUniqueCell(
char *sname)
{
HashEntry *h;
CellDef *def, *testdef;
@ -1257,14 +1399,14 @@ calmaUniqueCell(sname)
*/
CellDef *
calmaFindCell(name, was_called, predefined)
char *name; /* Name of desired cell */
bool *was_called; /* If this cell is in the hash table, then it
calmaFindCell(
const char *name, /* Name of desired cell */
bool *was_called, /* If this cell is in the hash table, then it
* was instanced before it was defined. We
* need to know this so as to avoid flattening
* the cell if requested.
*/
bool *predefined; /* If this cell was in memory before the GDS
bool *predefined) /* If this cell was in memory before the GDS
* file was read, then this flag gets set.
*/
@ -1286,20 +1428,26 @@ calmaFindCell(name, was_called, predefined)
* if the cell is used in a parent before being defined
* then it will cause a core dump.
*/
DBReComputeBbox(def);
DBReComputeBbox(def);
if (was_called) *was_called = FALSE;
}
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);
if (was_called) *was_called = FALSE;
}
else
{
@ -1338,8 +1486,8 @@ calmaFindCell(name, was_called, predefined)
*/
CellDef *
calmaLookCell(name)
char *name; /* Name of desired cell */
calmaLookCell(
char *name) /* Name of desired cell */
{
HashEntry *h;

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -50,8 +50,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "calma/calma.h"
/* Forward declarations */
bool calmaReadR8();
bool calmaSkipBytes();
bool calmaReadR8(double *pd);
bool calmaSkipBytes(int nbytes);
/*
@ -73,9 +73,9 @@ bool calmaSkipBytes();
*/
bool
calmaReadTransform(ptrans, name)
Transform *ptrans; /* Fill in this transform */
char *name; /* Name of subcell (for errors) */
calmaReadTransform(
Transform *ptrans, /* Fill in this transform */
char *name) /* Name of subcell (for errors) */
{
int nbytes, rtype, flags, angle;
double dangle;
@ -205,9 +205,9 @@ calmaReadTransform(ptrans, name)
*/
bool
calmaReadI2Record(type, pvalue)
int type; /* Type of record expected */
int *pvalue; /* Store value here */
calmaReadI2Record(
int type, /* Type of record expected */
int *pvalue) /* Store value here */
{
int nbytes, rtype, n;
@ -250,9 +250,9 @@ eof:
*/
bool
calmaReadI4Record(type, pvalue)
int type; /* Type of record expected */
int *pvalue; /* Store value here */
calmaReadI4Record(
int type, /* Type of record expected */
int *pvalue) /* Store value here */
{
int nbytes, rtype, n;
@ -298,9 +298,9 @@ eof:
*/
bool
calmaReadStampRecord(type, stampptr)
int type;
int *stampptr;
calmaReadStampRecord(
int type,
int *stampptr)
{
int nbytes, rtype;
struct tm gds_timestamp;
@ -371,9 +371,9 @@ eof:
*/
bool
calmaReadStringRecord(type, str)
int type;
char **str;
calmaReadStringRecord(
int type,
char **str)
{
int nbytes, rtype;
@ -389,7 +389,7 @@ calmaReadStringRecord(type, str)
nbytes -= CALMAHEADERLENGTH;
*str = (char *) mallocMagic(nbytes + 1);
if (FREAD(*str, sizeof (char), nbytes, calmaInputFile) != nbytes)
if (magicFREAD(*str, sizeof (char), nbytes, calmaInputFile) != nbytes)
goto eof;
*(*str + nbytes) = '\0';
@ -420,21 +420,21 @@ eof:
*/
bool
calmaReadR8(pd)
double *pd; /* Store result in *pd */
calmaReadR8(
double *pd) /* Store result in *pd */
{
int i, exponent;
unsigned char dchars[8];
double mantissa, d;
bool isneg;
if (FREAD((char *) dchars, sizeof (char), sizeof dchars,
if (magicFREAD((char *) dchars, sizeof (char), sizeof dchars,
calmaInputFile) != sizeof dchars)
return (FALSE);
/* Extract the sign and exponent */
exponent = dchars[0];
if (isneg = (exponent & 0x80))
if ((isneg = (exponent & 0x80)))
exponent &= ~0x80;
exponent -= 64;
@ -489,10 +489,10 @@ calmaReadR8(pd)
*/
void
calmaSkipSet(skipwhat)
int *skipwhat;
calmaSkipSet(
const int *skipwhat)
{
int *skipp;
const int *skipp;
int nbytes, rtype;
for (;;)
@ -533,8 +533,8 @@ skipit:
*/
bool
calmaSkipExact(type)
int type;
calmaSkipExact(
int type)
{
int nbytes, rtype;
@ -579,8 +579,8 @@ eof:
*/
bool
calmaSkipTo(what)
int what;
calmaSkipTo(
int what)
{
int nbytes, rtype;
@ -615,8 +615,8 @@ calmaSkipTo(what)
*/
bool
calmaSkipBytes(nbytes)
int nbytes; /* Skip this many bytes */
calmaSkipBytes(
int nbytes) /* Skip this many bytes */
{
while (nbytes-- > 0)
if (FGETC(calmaInputFile) < 0)

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdpt.c,v 1.7 2010/08/25 17:33:54 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdpt.c,v 1.7 2010/08/25 17:33:54 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -57,8 +57,8 @@ extern int CalmaPolygonCount;
extern int CalmaPathCount;
extern HashTable calmaDefInitHash;
extern void calmaLayerError();
bool calmaReadPath();
extern void calmaLayerError(char *mesg, int layer, int dt);
CIFPath *calmaReadPath(int iscale);
/*
* ----------------------------------------------------------------------------
@ -82,8 +82,9 @@ bool calmaReadPath();
*/
void
calmaInputRescale(n, d)
int n, d;
calmaInputRescale(
int n,
int d)
{
HashEntry *h;
HashSearch hs;
@ -135,9 +136,9 @@ calmaInputRescale(n, d)
*/
void
calmaReadPoint(p, iscale)
Point *p;
int iscale;
calmaReadPoint(
Point *p,
int iscale)
{
int rescale;
@ -205,14 +206,14 @@ calmaReadPoint(p, iscale)
*/
void
calmaElementBoundary()
calmaElementBoundary(void)
{
int dt, layer, ciftype;
CIFPath *pathheadp;
LinkedRect *rp;
Plane *plane;
CellUse *use;
CellDef *savedef, *newdef = NULL;
CellDef *savedef = NULL, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -236,7 +237,8 @@ calmaElementBoundary()
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");
@ -247,23 +249,27 @@ calmaElementBoundary()
/* so we need to set it again. */
if (ciftype >= 0) plane = cifCurReadPlanes[ciftype];
/* Convert the polygon to rectangles. */
/* Save non-Manhattan polygons in their own subcells. */
/* NOTE: CALMA_POLYGON_TEMP and CALMA_POLYGON_KEEP read in polygons much
* faster, but that interferes with boolean processing. This method
* needs to be reworked.
*/
if (CalmaSubcellPolygons && (calmaNonManhattan > 0))
if ((CalmaSubcellPolygons != CALMA_POLYGON_NONE) && (calmaNonManhattan > 0))
{
/* Place the polygon in its own subcell */
char newname[] = "polygonXXXXX";
char newname[20];
HashEntry *he;
savedef = cifReadCellDef;
/* Make up name for cell */
sprintf(newname + 7, "%05d", ++CalmaPolygonCount);
snprintf(newname, sizeof(newname), "polygon%05d", ++CalmaPolygonCount);
he = HashFind(&calmaDefInitHash, newname);
if (!HashGetValue(he))
{
newdef = calmaFindCell(newname, NULL);
newdef = calmaFindCell(newname, NULL, NULL);
cifReadCellDef = newdef;
DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef);
@ -277,7 +283,9 @@ calmaElementBoundary()
}
}
rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
/* Convert the polygon to rectangles. */
rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL, TRUE);
CIFFreePath(pathheadp);
/* If the input layer is designated for ports by a "label" */
@ -319,18 +327,47 @@ calmaElementBoundary()
if (lab == NULL)
{
/* There was no label in the area. Create a placeholder label */
DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 0, 0);
lab = DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 0, 0);
}
if ((cifCurReadStyle->crs_labelSticky[ciftype] == LABEL_TYPE_PORT)
&& ((lab->lab_flags & PORT_DIR_MASK) == 0))
{
/* Label was read previously as a text type, but the pin layer
* causes it to be recast as a port, or corresponding label has
* not yet been seen.
*/
int i, idx;
Label *sl;
/* Order ports as encountered. */
i = -1;
for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next)
{
idx = sl->lab_port;
if (idx > i) i = idx;
if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, lab->lab_text))
{
i = idx - 1;
break;
}
}
i++;
lab->lab_port = i;
lab->lab_flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH |
PORT_DIR_EAST | PORT_DIR_WEST;
}
}
}
/* 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)
{
@ -373,7 +410,7 @@ calmaElementBoundary()
*/
void
calmaElementBox()
calmaElementBox(void)
{
int nbytes, rtype, npoints, savescale;
int dt, layer, ciftype;
@ -468,9 +505,9 @@ calmaElementBox()
*/
void
calmaElementPath()
calmaElementPath(void)
{
int nbytes, rtype, extend1, extend2;
int nbytes = -1, rtype = 0, extend1, extend2;
int layer, dt, width, pathtype, ciftype, savescale;
int xmin, ymin, xmax, ymax, temp;
CIFPath *pathheadp, *pathp, *previousp;
@ -478,7 +515,7 @@ calmaElementPath()
Plane *plane;
int first,last;
CellUse *use;
CellDef *savedef, *newdef = NULL;
CellDef *savedef = NULL, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -561,7 +598,8 @@ calmaElementPath()
/* Read the points in the path */
savescale = calmaReadScale1;
if (!calmaReadPath(&pathheadp, 2))
pathheadp = calmaReadPath(2);
if (pathheadp == NULL)
{
CalmaReadError("Improper path; ignored.\n");
return;
@ -629,18 +667,18 @@ calmaElementPath()
if (CalmaSubcellPaths)
{
/* Place the path in its own subcell */
char newname[] = "pathXXXXX";
char newname[16];
HashEntry *he;
savedef = cifReadCellDef;
/* Make up name for cell */
sprintf(newname + 4, "%05d", ++CalmaPathCount);
snprintf(newname, sizeof(newname), "path%05d", ++CalmaPathCount);
he = HashFind(&calmaDefInitHash, newname);
if (!HashGetValue(he))
{
newdef = calmaFindCell(newname, NULL);
newdef = calmaFindCell(newname, NULL, NULL);
cifReadCellDef = newdef;
DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef);
@ -696,16 +734,16 @@ calmaElementPath()
*/
void
calmaElementText()
calmaElementText(void)
{
static int ignore[] = { CALMA_PATHTYPE, CALMA_WIDTH, -1 };
static const int ignore[] = { CALMA_PATHTYPE, CALMA_WIDTH, -1 };
char *textbody = NULL;
int nbytes, rtype;
int nbytes = -1, rtype = 0;
int layer, textt, cifnum, textpres;
TileType type;
Rect r;
double dval;
int size, angle, font, pos;
int size, micron, angle, font, pos, portnum, idx;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore);
@ -727,10 +765,29 @@ calmaElementText()
font = -1;
angle = 0;
portnum = 0;
/* Default size is 1um */
size = (int)((1000 * cifCurReadStyle->crs_multiplier)
/* Use the minimum width of the layer on which the text is placed
* as the default text size, or 1um, whichever is smaller. Account
* for the 8/10 difference encoded in the rendered font height.
*/
size = 0;
if (type > 0)
{
size = DRCGetDefaultLayerWidth(type);
if (size > 0)
{
size *= (calmaReadScale2 * cifCurReadStyle->crs_multiplier * 8);
size /= (calmaReadScale1 * cifCurReadStyle->crs_scaleFactor * 10);
}
}
/* Default or maximum size is 1um */
micron = (int)((800 * cifCurReadStyle->crs_multiplier)
/ cifCurReadStyle->crs_scaleFactor);
if ((size == 0) || (size > micron))
size = micron;
/* Default position is bottom-right (but what the spec calls "top-left"!) */
pos = GEO_SOUTHEAST;
@ -820,8 +877,11 @@ calmaElementText()
else
/* Assume that MAG is the label size in microns */
/* "size" is the label size in 10 * (database units) */
size = (int)((dval * 1000 * cifCurReadStyle->crs_multiplier)
/ cifCurReadStyle->crs_scaleFactor);
/* The "calma magscale" option can be used to */
/* reinterpret the size for any specific GDS file. */
size = (int)(0.5 + ((dval * 1000 * CalmaMagScale
* cifCurReadStyle->crs_multiplier)
/ cifCurReadStyle->crs_scaleFactor));
}
else
UNREADRH(nbytes, rtype);
@ -947,8 +1007,6 @@ calmaElementText()
flags = 0;
else if (cifnum >= 0 && (cifCurReadStyle->crs_labelSticky[cifnum] != LABEL_TYPE_NONE))
flags = LABEL_STICKY;
else if (cifCurReadStyle->crs_flags & CRF_NO_RECONNECT_LABELS)
flags = LABEL_STICKY;
else
flags = 0;
@ -970,6 +1028,26 @@ calmaElementText()
sl->lab_next = lab->lab_next;
if (cifReadCellDef->cd_lastLabel == lab)
cifReadCellDef->cd_lastLabel = sl;
/* Port number from the placeholder is ignored; find
* a new valid port number for the new label name.
*/
i = -1;
for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next)
{
idx = sl->lab_port;
if (idx > i) i = idx;
if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, textbody))
{
i = idx - 1;
break;
}
}
i++;
portnum = i;
flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH |
PORT_DIR_EAST | PORT_DIR_WEST;
freeMagic((char *)lab);
break;
}
@ -978,16 +1056,14 @@ calmaElementText()
}
if (font < 0)
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, 0);
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, portnum);
else
lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle,
&GeoOrigin, pos, textbody, type, flags, 0);
&GeoOrigin, pos, textbody, type, flags, portnum);
if ((lab != NULL) && (cifnum >= 0) &&
(cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT))
{
int idx;
/* No port information can be encoded in the GDS file, so */
/* assume defaults, and assume that the port order is the */
/* order in which labels arrive in the GDS stream. If */
@ -1026,26 +1102,24 @@ calmaElementText()
* 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
calmaReadPath(pathheadpp, iscale)
CIFPath **pathheadpp;
int iscale;
CIFPath *
calmaReadPath(
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;
@ -1054,12 +1128,12 @@ calmaReadPath(pathheadpp, iscale)
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) */
@ -1070,7 +1144,7 @@ calmaReadPath(pathheadpp, iscale)
calmaReadPoint(&path.cifp_point, iscale);
if (savescale != calmaReadScale1)
{
CIFPath *phead = *pathheadpp;
CIFPath *phead = pathheadp;
int newscale = calmaReadScale1 / savescale;
while (phead != NULL)
{
@ -1085,8 +1159,8 @@ calmaReadPath(pathheadpp, iscale)
}
if (FEOF(calmaInputFile))
{
CIFFreePath(*pathheadpp);
return (FALSE);
CIFFreePath(pathheadp);
return (NULL);
}
if (iscale != 0)
@ -1094,7 +1168,7 @@ calmaReadPath(pathheadpp, iscale)
newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath)));
*newpathp = path;
if (*pathheadpp)
if (pathheadp)
{
/*
* Check that this segment is Manhattan. If not, remember the
@ -1115,11 +1189,11 @@ calmaReadPath(pathheadpp, iscale)
}
pathtailp->cifp_next = newpathp;
}
else *pathheadpp = newpathp;
else pathheadp = newpathp;
pathtailp = newpathp;
}
}
return (*pathheadpp != NULL);
return (pathheadp);
}
/*
@ -1144,10 +1218,10 @@ calmaReadPath(pathheadpp, iscale)
*/
void
calmaLayerError(mesg, layer, dt)
char *mesg;
int layer;
int dt;
calmaLayerError(
char *mesg,
int layer,
int dt)
{
CalmaLayerType clt;
HashEntry *he;

View File

@ -17,9 +17,10 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRead.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRead.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@ -27,6 +28,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <netinet/in.h>
/*
* C99 compat
* Mind: tcltk/tclmagic.h must be included prior to all the other headers
*/
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "tiles/tile.h"
@ -55,9 +62,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Globals for Calma reading */
FILETYPE calmaInputFile = NULL; /* Read from this stream */
FILE *calmaErrorFile = NULL; /* Write error output here */
bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons
* in their own subcells.
*/
unsigned char CalmaSubcellPolygons = CALMA_POLYGON_NONE;
/* Read non-Manhattan polygons as-is */
int CalmaPolygonCount;
bool CalmaSubcellPaths = FALSE; /* Put paths in their own subcells. */
int CalmaPathCount;
@ -76,6 +82,12 @@ bool CalmaReadOnly = FALSE; /* Set files to read-only and
* retain file position information
* so cells can be written verbatim.
*/
float CalmaMagScale = 1.0; /* Scale by which to interpret the MAG
* record in GDS text records. The
* default is to treat the value as
* the text height in microns. This
* value reinterprets the scale.
*/
bool CalmaNoDRCCheck = FALSE; /* If TRUE, don't mark cells as needing
* a DRC check; they will be assumed
* DRC clean.
@ -99,10 +111,8 @@ bool CalmaUnique = FALSE; /* If TRUE, then if a cell exists in
*/
extern bool CalmaDoLibrary; /* Also used by GDS write */
extern void calmaUnexpected();
extern int calmaWriteInitFunc();
bool calmaParseUnits();
extern void calmaUnexpected(int wanted, int got);
extern int calmaWriteInitFunc(CellDef *def);
/*
* Scaling.
@ -137,7 +147,7 @@ HashTable calmaLayerHash;
HashTable calmaDefInitHash;
/* Common stuff to ignore */
int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
const int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
/*
* ----------------------------------------------------------------------------
@ -157,18 +167,18 @@ int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
*/
void
CalmaReadFile(file, filename)
FILETYPE file; /* File from which to read Calma */
char *filename; /* The real name of the file read */
CalmaReadFile(
FILETYPE file, /* File from which to read Calma */
char *filename) /* The real name of the file read */
{
int k, version;
char *libname = NULL, *libnameptr;
char *libname = NULL, *libnameptr = NULL;
MagWindow *mw;
static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
CALMA_LIBSECUR, -1 };
static const int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
static const int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
CALMA_LIBSECUR, -1 };
if (EditCellUse == (CellUse *)NULL)
{
@ -289,7 +299,7 @@ done:
windCheckOnlyWindow(&mw, DBWclientID);
if (mw != NULL)
{
if (calmaLookCell(libnameptr, NULL) != (CellDef *)NULL)
if (calmaLookCell(libnameptr) != (CellDef *)NULL)
DBWloadWindow(mw, libnameptr, 0);
}
freeMagic(libname);
@ -299,7 +309,11 @@ done:
HashKill(&calmaDefInitHash);
UndoEnable();
if (calmaErrorFile != NULL) fclose(calmaErrorFile);
if (calmaErrorFile != NULL)
{
fclose(calmaErrorFile);
calmaErrorFile = NULL;
}
}
/*
@ -333,12 +347,13 @@ done:
*/
bool
calmaParseUnits()
calmaParseUnits(void)
{
int nbytes, rtype;
int nbytes, rtype = 0;
double metersPerDBUnit;
double userUnitsPerDBUnit;
double cuPerDBUnit;
bool compatible;
READRH(nbytes, rtype);
#ifdef lint
@ -357,6 +372,39 @@ calmaParseUnits()
/* Read meters per database unit */
if (!calmaReadR8(&metersPerDBUnit)) return (FALSE);
/* Important! When CalmaReadOnly is TRUE, then this file will have its
* contents output verbatim. But if the database units don't match,
* then it will get output at the wrong scale. Setting a magnification
* factor on the instance when generating output might (?) work. For
* now, prohibiting a GDS read in read-only mode when the database units
* don't match. This forces the user either to reconsider the read-only
* status or to rewrite the GDS at a compatible scalefactor.
*/
compatible = TRUE;
if (CalmaReadOnly == TRUE)
{
if (CIFCurStyle->cs_flags & CWF_ANGSTROMS)
{
if ((int)(0.5 + metersPerDBUnit * 1e12) != 100)
{
CalmaReadError("Incompatible scale factor of %g, must be 1e-10.\n",
metersPerDBUnit);
TxError("Cannot read this file in read-only mode.\n");
return FALSE;
}
}
else
{
if ((int)(0.5 + metersPerDBUnit * 1e11) != 100)
{
CalmaReadError("Incompatible scale factor of %g, must be 1e-9.\n",
metersPerDBUnit);
TxError("Cannot read this file in read-only mode.\n");
return FALSE;
}
}
}
#ifdef notdef
TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit);
TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit);
@ -411,11 +459,9 @@ calmaParseUnits()
*/
void
/*VARARGS1*/
CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
char *format;
char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10;
CalmaReadError(const char *format, ...)
{
va_list args;
OFFTYPE filepos;
calmaTotalErrors++;
@ -433,15 +479,18 @@ CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
cifReadCellDef->cd_name);
fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"d): ",
(dlong)filepos);
fprintf(calmaErrorFile, format, a1, a2, a3, a4, a5, a6, a7,
a8, a9, a10);
va_start(args, format);
Vfprintf(calmaErrorFile, format, args);
va_end(args);
}
}
else
{
TxError("Error while reading cell \"%s\" ", cifReadCellDef->cd_name);
TxError("(byte position %"DLONG_PREFIX"d): ", (dlong)filepos);
TxError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
va_start(args, format);
TxErrorV(format, args);
va_end(args);
}
}
else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT))
@ -467,9 +516,9 @@ CalmaReadError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
*/
void
calmaUnexpected(wanted, got)
int wanted; /* Type of record we wanted */
int got; /* Type of record we got */
calmaUnexpected(
int wanted, /* Type of record we wanted */
int got) /* Type of record we got */
{
CalmaReadError("Unexpected record type in input: \n");
@ -509,12 +558,12 @@ calmaUnexpected(wanted, got)
* ----------------------------------------------------------------------------
*/
char *
calmaRecordName(rtype)
int rtype;
const char *
calmaRecordName(
int rtype)
{
static char numeric[10];
static char *calmaRecordNames[] =
static const char * const calmaRecordNames[] =
{
"HEADER", "BGNLIB", "LIBNAME", "UNITS",
"ENDLIB", "BGNSTR", "STRNAME", "ENDSTR",
@ -559,8 +608,28 @@ calmaRecordName(rtype)
*/
void
CalmaTechInit()
CalmaTechInit(void)
{
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
ASSERT(sizeof(TwoByteInt)==2, "definition in calmaInt.h");
/* 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 */
/* "*_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, "*_CDNS_*");
*(CalmaFlattenUsesByName + 1) = NULL;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/calma/CalmaWrite.c,v 1.8 2010/12/22 16:29:06 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/calma/CalmaWrite.c,v 1.8 2010/12/22 16:29:06 tim Exp $";
#endif /* not lint */
#ifdef HAVE_ZLIB
@ -34,13 +34,19 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
#include <stdint.h>
#include <stdlib.h> /* for random() */
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <sys/types.h>
#include <arpa/inet.h> /* for htons() */
#ifdef SYSV
#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"
@ -48,6 +54,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
#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"
@ -60,6 +67,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
#include "utils/styles.h"
#include "textio/textio.h"
#include "calma/calmaInt.h"
#include "extract/extractInt.h" /* for LabelList */
#include "utils/main.h" /* for Path and CellLibPath */
#include "utils/stack.h"
@ -88,32 +96,31 @@ extern int calmaPaintLayerNumber;
extern int calmaPaintLayerType;
/* External functions from CalmaWrite.c */
extern int calmaWriteInitFunc();
extern int calmaWriteMarkFunc();
/* Forward declarations */
extern int calmaWritePaintFuncZ();
extern int calmaMergePaintFuncZ();
extern int calmaWriteUseFuncZ();
extern int calmaPaintLabelFuncZ();
extern void calmaWriteContactsZ();
extern void calmaOutFuncZ();
extern void calmaOutStructNameZ();
extern void calmaWriteLabelFuncZ();
extern void calmaOutHeaderZ();
extern void calmaOutDateZ();
extern void calmaOutStringRecordZ();
extern void calmaOut8Z();
extern void calmaOutR8Z();
extern int calmaWriteInitFunc(CellDef *def);
/* Structure used by calmaWritePaintFuncZ() and others */
typedef struct {
gzFile f; /* Compressed file stream for output */
Rect *area; /* Clipping area, in GDS coordinates */
const Rect *area; /* Clipping area, in GDS coordinates */
int type; /* Layer index */
} calmaOutputStructZ;
/* Forward declarations */
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, 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);
extern void calmaWriteLabelFuncZ(Label *lab, int ltype, int type, gzFile f);
extern void calmaOutHeaderZ(CellDef *rootDef, gzFile f);
extern void calmaOutDateZ(time_t t, gzFile f);
extern void calmaOutStringRecordZ(int type, char *str, gzFile f);
extern void calmaOut8Z(const char *str, gzFile f);
extern void calmaOutR8Z(double d, gzFile f);
/*--------------------------------------------------------------*/
/* Structures used by the tile merging algorithm */
/*--------------------------------------------------------------*/
@ -122,28 +129,12 @@ typedef struct {
#define GDS_UNPROCESSED CLIENTDEFAULT
#define GDS_PROCESSED 1
#define PUSHTILE(tp) \
if ((tp)->ti_client == (ClientData) GDS_UNPROCESSED) { \
(tp)->ti_client = (ClientData) GDS_PENDING; \
#define PUSHTILEZ(tp) \
if (TiGetClient(tp) == GDS_UNPROCESSED) { \
TiSetClientINT(tp, GDS_PENDING); \
STACKPUSH((ClientData) (tp), SegStack); \
}
#define LB_EXTERNAL 0 /* Polygon external edge */
#define LB_INTERNAL 1 /* Polygon internal edge */
#define LB_INIT 2 /* Data not yet valid */
typedef struct LB1 {
char lb_type; /* Boundary Type (external or internal) */
Point lb_start; /* Start point */
struct LB1 *lb_next; /* Next point record */
} LinkedBoundary;
typedef struct BT1 {
LinkedBoundary *bt_first; /* Polygon list */
int bt_points; /* Number of points in this list */
struct BT1 *bt_next; /* Next polygon record */
} BoundaryTop;
/* -------------------------------------------------------------------- */
/*
@ -195,7 +186,7 @@ typedef struct BT1 {
(void) gzputc(f, u.u_c[3]); \
}
static char calmaMapTableStrict[] =
static const char calmaMapTableStrict[] =
{
0, 0, 0, 0, 0, 0, 0, 0, /* NUL - BEL */
0, 0, 0, 0, 0, 0, 0, 0, /* BS - SI */
@ -215,7 +206,7 @@ static char calmaMapTableStrict[] =
'x', 'y', 'z', '_', '_', '_', '_', 0, /* x - DEL */
};
static char calmaMapTablePermissive[] =
static const char calmaMapTablePermissive[] =
{
0, 0, 0, 0, 0, 0, 0, 0, /* NUL - BEL */
0, 0, 0, 0, 0, 0, 0, 0, /* BS - SI */
@ -270,12 +261,13 @@ static char calmaMapTablePermissive[] =
*/
bool
CalmaWriteZ(rootDef, f)
CellDef *rootDef; /* Pointer to CellDef to be written */
gzFile f; /* Open compressed output file */
CalmaWriteZ(
CellDef *rootDef, /* Pointer to CellDef to be written */
gzFile f) /* Open compressed output file */
{
int oldCount = DBWFeedbackCount, problems, nerr;
bool good;
CellDef *err_def;
CellUse dummy;
HashEntry *he;
HashSearch hs;
@ -301,9 +293,11 @@ CalmaWriteZ(rootDef, f)
*/
dummy.cu_def = rootDef;
if (DBCellReadArea(&dummy, &rootDef->cd_bbox, !CalmaAllowUndefined))
err_def = DBCellReadArea(&dummy, &rootDef->cd_bbox, !CalmaAllowUndefined);
if (err_def != NULL)
{
TxError("Failure to read entire subtree of the cell.\n");
TxError("Failed on cell %s.\n", err_def->cd_name);
return FALSE;
}
@ -365,7 +359,7 @@ CalmaWriteZ(rootDef, f)
good = (nerr == 0) ? TRUE : FALSE;
/* See if any problems occurred */
if (problems = (DBWFeedbackCount - oldCount))
if ((problems = (DBWFeedbackCount - oldCount)))
TxPrintf("%d problems occurred. See feedback entries.\n", problems);
/*
@ -395,13 +389,13 @@ CalmaWriteZ(rootDef, f)
*/
bool
calmaDumpStructureZ(def, outf, calmaDefHash, filename)
CellDef *def;
gzFile outf;
HashTable *calmaDefHash;
char *filename;
calmaDumpStructureZ(
CellDef *def,
gzFile outf,
HashTable *calmaDefHash,
char *filename)
{
int nbytes, rtype;
int nbytes = -1, rtype = 0;
char *strname = NULL, *newnameptr;
HashEntry *he, *he2;
CellDef *edef;
@ -665,11 +659,11 @@ syntaxerror:
*/
void
calmaFullDumpZ(def, fi, outf, filename)
CellDef *def;
gzFile fi;
gzFile outf;
char *filename;
calmaFullDumpZ(
CellDef *def,
gzFile fi,
gzFile outf,
char *filename)
{
int version, rval;
char *libname = NULL, *testlib, uniqlibname[4];
@ -679,10 +673,10 @@ calmaFullDumpZ(def, fi, outf, filename)
HashSearch hs;
HashEntry *he, *he2;
static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
static const int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
CALMA_STYPTABLE, CALMA_GENERATIONS, CALMA_UNITS, -1 };
static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
static const int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
CALMA_LIBSECUR, -1 };
HashInit(&calmaDefHash, 32, 0);
@ -697,10 +691,14 @@ calmaFullDumpZ(def, fi, outf, filename)
calmaSkipSet(skipBeforeLib);
if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done;
// NOTE: CALMA_UNITS needs to be parsed to determine if units in
// the input file are compatible with units being used in the output
// CALMA_UNITS needs to be parsed to determine if units in the
// input file are compatible with units being used in the output
// file.
calmaSkipSet(hdrSkip);
if (calmaParseUnits() == FALSE)
{
TxError("Error: Library %s has incompatible database units!\n", libname);
return;
}
// Record the GDS library so it will not be processed again.
he = HashFind(&calmaLibHash, filename);
@ -809,42 +807,40 @@ done:
*/
int
calmaProcessUseZ(use, outf)
CellUse *use; /* Process use->cu_def */
gzFile outf; /* Stream file */
calmaProcessUseZ(
CellUse *use, /* Process use->cu_def */
gzFile outf) /* Stream file */
{
return (calmaProcessDefZ(use->cu_def, outf, FALSE));
}
int
calmaProcessDefZ(def, outf, do_library)
CellDef *def; /* Output this def's children, then the def itself */
gzFile outf; /* Stream file */
bool do_library; /* If TRUE, output only children of def, but not def */
calmaProcessDefZ(
CellDef *def, /* Output this def's children, then the def itself */
gzFile outf, /* Stream file */
bool do_library) /* If TRUE, output only children of def, but not def */
{
char *filename;
int polyidx;
bool isReadOnly, oldStyle, hasContent, isAbstract, hasGDSEnd;
bool isReadOnly, oldStyle, hasContent, isAbstract, hasGDSEnd, needHier;
bool hierWrite, arrayWrite;
HashEntry *he;
/* Skip if already output */
if ((int) def->cd_client > 0)
if ((int) CD2INT(def->cd_client) > 0)
return (0);
/* Assign it a (negative) number if it doesn't have one yet */
if ((int) def->cd_client == 0)
def->cd_client = (ClientData) calmaCellNum--;
if ((int) CD2INT(def->cd_client) == 0)
def->cd_client = INT2CD(calmaCellNum--);
/* Mark this cell */
def->cd_client = (ClientData) (- (int) def->cd_client);
def->cd_client = INT2CD(- (int) CD2INT(def->cd_client));
/* Read the cell in if it is not already available. */
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(def, TRUE, TRUE, NULL))
return (0);
}
/*
* Flag an error if attempting to write the default (UNNAMED) cell
@ -873,6 +869,7 @@ calmaProcessDefZ(def, outf, do_library)
DBPropGet(def, "LEFview", &isAbstract);
DBPropGet(def, "GDS_START", &hasContent);
DBPropGet(def, "GDS_END", &hasGDSEnd);
DBPropGet(def, "CIFhier", &needHier);
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
/* When used with "calma addendum true", don't output the read-only */
@ -902,8 +899,29 @@ calmaProcessDefZ(def, outf, do_library)
* as they are expected to be in the referenced GDS file.
*/
if (!hasContent || hasGDSEnd)
if (DBCellEnum(def, calmaProcessUseZ, (ClientData) outf) != 0)
{
int result;
if (needHier)
{
hierWrite = CIFHierWriteDisable;
arrayWrite = CIFArrayWriteDisable;
CIFHierWriteDisable = FALSE;
CIFArrayWriteDisable = FALSE;
}
result = DBCellEnum(def, calmaProcessUseZ, (ClientData) outf);
if (needHier)
{
CIFHierWriteDisable = hierWrite;
CIFArrayWriteDisable = arrayWrite;
}
if (result != 0)
return 1;
}
/* Give some feedback to the user */
TxPrintf(" Generating output for cell %s\n", def->cd_name);
@ -921,6 +939,11 @@ calmaProcessDefZ(def, outf, do_library)
/* searched to find the .mag file that indicated this GDS file. */
fi = PaZOpen(filename, "r", "", Path, CellLibPath, &retfilename);
/* Check if file may have been compressed */
if (fi == NULL)
fi = PaZOpen(filename, "r", ".gz", Path, CellLibPath, &retfilename);
if (fi == NULL)
{
/* This is a rare error, but if the subcell is inside */
@ -1026,6 +1049,7 @@ calmaProcessDefZ(def, outf, do_library)
" Using magic's internal definition\n");
isReadOnly = FALSE;
}
freeMagic(buffer);
if (cellend < cellstart) /* Sanity check */
{
@ -1106,8 +1130,25 @@ calmaProcessDefZ(def, outf, do_library)
/* Output this cell definition from the Magic database */
if (!isReadOnly)
if (!do_library)
{
if (needHier)
{
hierWrite = CIFHierWriteDisable;
arrayWrite = CIFArrayWriteDisable;
CIFHierWriteDisable = FALSE;
CIFArrayWriteDisable = FALSE;
}
calmaOutFuncZ(def, outf, &TiPlaneRect);
if (needHier)
{
CIFHierWriteDisable = hierWrite;
CIFArrayWriteDisable = arrayWrite;
}
}
return 0;
}
@ -1131,10 +1172,10 @@ calmaProcessDefZ(def, outf, do_library)
*/
void
calmaOutFuncZ(def, f, cliprect)
CellDef *def; /* Pointer to cell def to be written */
gzFile f; /* Open output file */
Rect *cliprect; /* Area to clip to (used for contact cells),
calmaOutFuncZ(
CellDef *def, /* Pointer to cell def to be written */
gzFile f, /* Open output file */
const Rect *cliprect)/* Area to clip to (used for contact cells),
* in CIF/GDS coordinates.
*/
{
@ -1144,6 +1185,9 @@ calmaOutFuncZ(def, f, cliprect)
int type;
int dbunits;
calmaOutputStructZ cos;
bool propfound;
char *propvalue;
extern int compport(const void *one, const void *two); /* Forward declaration */
cos.f = f;
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
@ -1200,13 +1244,27 @@ calmaOutFuncZ(def, f, cliprect)
/* Output all the tiles associated with this cell; skip temporary layers */
GEO_EXPAND(&def->cd_bbox, CIFCurStyle->cs_radius, &bigArea);
/* Include any fixed bounding box as part of the area to process, */
/* in case the fixed bounding box is larger than the geometry. */
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
if (propfound)
{
Rect bbox;
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) == 4)
GeoInclude(&bbox, &bigArea);
}
CIFErrorDef = def;
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
(ClientData)f);
if (!CIFHierWriteDisable)
CIFGenSubcells(def, &bigArea, CIFPlanes);
CIFGenSubcells(def, &bigArea, CIFPlanes);
if (!CIFArrayWriteDisable)
CIFGenArrays(def, &bigArea, CIFPlanes);
CIFGenArrays(def, &bigArea, CIFPlanes);
for (type = 0; type < CIFCurStyle->cs_nLayers; type++)
{
@ -1234,33 +1292,57 @@ calmaOutFuncZ(def, f, cliprect)
if (CalmaDoLabels)
{
int i, maxport = -1;
int i, ltype, numports = 0;
LabelList *ll = NULL, *newll;
for (lab = def->cd_labels; lab; lab = lab->lab_next)
{
type = CIFCurStyle->cs_labelLayer[lab->lab_type];
if ((type >= 0) && (lab->lab_flags & PORT_DIR_MASK) == 0)
if ((lab->lab_flags & PORT_DIR_MASK) == 0)
{
calmaWriteLabelFuncZ(lab, type, f);
ltype = CIFCurStyle->cs_labelLayer[lab->lab_type];
type = ltype;
calmaWriteLabelFuncZ(lab, ltype, type, f);
}
else
{
if ((int)lab->lab_port > maxport)
maxport = (int)lab->lab_port;
newll = (LabelList *)mallocMagic(sizeof(LabelList));
newll->ll_label = lab;
newll->ll_attr = (unsigned int)lab->lab_port;
newll->ll_next = ll;
ll = newll;
numports++;
}
}
if (maxport >= 0)
for (i = 0; i <= maxport; i++)
for (lab = def->cd_labels; lab; lab = lab->lab_next)
{
type = CIFCurStyle->cs_portLayer[lab->lab_type];
if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) &&
(lab->lab_port == i))
{
calmaWriteLabelFuncZ(lab, type, f);
/* break; */ /* Do not limit to unique labels! */
}
}
if (newll != NULL)
{
/* Turn linked list into an array, then run qsort on it */
/* to sort by port number. */
PortLabel *pllist = (PortLabel *)mallocMagic(numports * sizeof(PortLabel));
i = 0;
while (ll != NULL)
{
pllist[i].pl_label = ll->ll_label;
pllist[i].pl_port = (unsigned int)ll->ll_attr;
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, ll);
ll = ll->ll_next;
freeMagic1_end(&mm1);
i++;
}
qsort(pllist, numports, sizeof(PortLabel), compport);
for (i = 0; i < numports; i++)
{
lab = pllist[i].pl_label;
ltype = CIFCurStyle->cs_portText[lab->lab_type];
type = CIFCurStyle->cs_portLayer[lab->lab_type];
if (type >= 0)
calmaWriteLabelFuncZ(lab, ltype, type, f);
}
freeMagic(pllist);
}
}
/* End of structure */
@ -1287,9 +1369,9 @@ calmaOutFuncZ(def, f, cliprect)
*/
int
calmaWriteUseFuncZ(use, f)
CellUse *use;
gzFile f;
calmaWriteUseFuncZ(
CellUse *use,
gzFile f)
{
/*
* r90, r180, and r270 are Calma 8-byte real representations
@ -1297,10 +1379,10 @@ calmaWriteUseFuncZ(use, f)
* only 4 possible values, it is faster to have them pre-computed
* than to format with calmaOutR8Z().
*/
static unsigned char r90[] = { 0x42, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static unsigned char r180[] = { 0x42, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static unsigned char r270[] = { 0x43, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned char *whichangle;
static const unsigned char r90[] = { 0x42, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char r180[] = { 0x42, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const unsigned char r270[] = { 0x43, 0x10, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00 };
const unsigned char *whichangle;
int x, y, topx, topy, rows, cols, xxlate, yxlate, hdrsize;
int rectype, stransflags;
Transform *t;
@ -1374,7 +1456,7 @@ calmaWriteUseFuncZ(use, f)
if (whichangle)
{
calmaOutRHZ(12, CALMA_ANGLE, CALMA_R8, f);
calmaOut8Z(whichangle, f);
calmaOut8Z((char *)whichangle, f);
}
/* Translation */
@ -1411,7 +1493,7 @@ calmaWriteUseFuncZ(use, f)
if (whichangle)
{
calmaOutRHZ(12, CALMA_ANGLE, CALMA_R8, f);
calmaOut8Z(whichangle, f);
calmaOut8Z((char *)whichangle, f);
}
/* If array, number of columns and rows in the array */
@ -1457,13 +1539,11 @@ calmaWriteUseFuncZ(use, f)
/* By NP */
/* Property attributes/value pairs. */
/* Add a CellUse ID property, if the CellUse has a non-default name */
/* (Modified 11/11/2022: Do this always, not just the non-default case) */
if (!calmaIsUseNameDefault(use->cu_def->cd_name, use->cu_id))
{
calmaOutRHZ(6, CALMA_PROPATTR, CALMA_I2, f);
calmaOutI2Z(CALMA_PROP_USENAME_STD, f);
calmaOutStringRecordZ(CALMA_PROPVALUE, use->cu_id, f);
}
calmaOutRHZ(6, CALMA_PROPATTR, CALMA_I2, f);
calmaOutI2Z(CALMA_PROP_USENAME_STD, f);
calmaOutStringRecordZ(CALMA_PROPVALUE, use->cu_id, f);
/* Add an array limits property, if the CellUse is an array and */
/* limits of the array (xlo, ylo) are not zero (the default). */
@ -1504,16 +1584,16 @@ calmaWriteUseFuncZ(use, f)
*/
void
calmaOutStructNameZ(type, def, f)
int type;
CellDef *def;
gzFile f;
calmaOutStructNameZ(
int type,
CellDef *def,
gzFile f)
{
char *defname;
unsigned char c;
char *cp;
int calmanum;
char *table;
const char *table;
if (CIFCurStyle->cs_flags & CWF_PERMISSIVE_LABELS)
{
@ -1523,7 +1603,7 @@ calmaOutStructNameZ(type, def, f)
}
/* Is the def name a legal Calma name? */
for (cp = def->cd_name; c = (unsigned char) *cp; cp++)
for (cp = def->cd_name; (c = (unsigned char) *cp); cp++)
{
if ((c > 127) || (table[c] == 0))
goto bad;
@ -1544,7 +1624,7 @@ calmaOutStructNameZ(type, def, f)
{
/* Bad name: use XXXXXcalmaNum */
bad:
calmanum = (int) def->cd_client;
calmanum = (int) CD2INT(def->cd_client);
if (calmanum < 0) calmanum = -calmanum;
defname = (char *)mallocMagic(32);
(void) sprintf(defname, "XXXXX%d", calmanum);
@ -1559,7 +1639,7 @@ bad:
/*
* ----------------------------------------------------------------------------
*
* CalmaGenerateArray --
* CalmaGenerateArrayZ --
*
* This routine
*
@ -1573,14 +1653,16 @@ bad:
*/
bool
CalmaGenerateArrayZ(f, type, llx, lly, pitch, cols, rows)
gzFile f; /* GDS output file */
TileType type; /* Magic tile type of contact */
int llx, lly; /* Lower-left hand coordinate of the array
CalmaGenerateArrayZ(
gzFile f, /* GDS output file */
TileType type, /* Magic tile type of contact */
int llx,
int lly, /* Lower-left hand coordinate of the array
* (centered on contact cut)
*/
int pitch; /* Pitch of the array elements */
int cols, rows; /* Number of array elements in X and Y */
int pitch, /* Pitch of the array elements */
int cols,
int rows) /* Number of array elements in X and Y */
{
CellDef *child; /* Cell definition of the contact cell */
int xxlate, yxlate;
@ -1641,8 +1723,8 @@ CalmaGenerateArrayZ(f, type, llx, lly, pitch, cols, rows)
*/
void
calmaWriteContactsZ(f)
gzFile f;
calmaWriteContactsZ(
gzFile f)
{
TileType type;
TileTypeBitMask tMask, *rMask;
@ -1681,7 +1763,7 @@ calmaWriteContactsZ(f)
/* Get clip bounds, so that residue surround is */
/* minimum. Note that these values are in CIF/GDS */
/* units, and the clipping rectangle passed to */
/* calmaOutFunc is also in CIF/GDS units. */
/* calmaOutFuncZ is also in CIF/GDS units. */
halfsize = CIFGetContactSize(type, NULL, NULL, NULL) >> 1;
@ -1724,9 +1806,9 @@ calmaWriteContactsZ(f)
*/
void
calmaProcessBoundaryZ(blist, cos)
BoundaryTop *blist;
calmaOutputStructZ *cos;
calmaProcessBoundaryZ(
BoundaryTop *blist,
calmaOutputStructZ *cos)
{
gzFile f = cos->f;
LinkedBoundary *listtop, *lbref, *lbstop, *lbfree;
@ -1762,8 +1844,11 @@ calmaProcessBoundaryZ(blist, cos)
calmaOutI4Z(lbref->lb_start.p_y * calmaPaintScale, f);
chkcount++;
}
calmaOutI4Z(listtop->lb_start.p_x * calmaPaintScale, f);
calmaOutI4Z(listtop->lb_start.p_y * calmaPaintScale, f);
if (listtop != NULL)
{
calmaOutI4Z(listtop->lb_start.p_x * calmaPaintScale, f);
calmaOutI4Z(listtop->lb_start.p_y * calmaPaintScale, f);
}
if (chkcount != bounds->bt_points)
TxError("Points recorded=%d; Points written=%d\n",
@ -1774,19 +1859,27 @@ calmaProcessBoundaryZ(blist, cos)
/* 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);
}
}
/*
@ -1804,12 +1897,13 @@ calmaProcessBoundaryZ(blist, cos)
*/
int
calmaMergePaintFuncZ(tile, cos)
Tile *tile; /* Tile to be written out. */
calmaOutputStructZ *cos; /* Information needed by algorithm */
calmaMergePaintFuncZ(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information (unused) */
calmaOutputStructZ *cos) /* Information needed by algorithm */
{
gzFile f = cos->f;
Rect *clipArea = cos->area;
const Rect *clipArea = cos->area;
Tile *t, *tp;
TileType ttype;
int i, llx, lly, urx, ury, intedges, num_points, split_type;
@ -1821,26 +1915,25 @@ calmaMergePaintFuncZ(tile, cos)
BoundaryTop *bounds = NULL;
/* Quick check for tiles that have already been processed */
if (tile->ti_client == (ClientData)GDS_PROCESSED) return 0;
if (TiGetClientINT(tile) == GDS_PROCESSED) return 0;
if (SegStack == (Stack *)NULL)
SegStack = StackNew(64);
PUSHTILE(tile);
PUSHTILEZ(tile);
while (!StackEmpty(SegStack))
{
t = (Tile *) STACKPOP(SegStack);
if (t->ti_client != (ClientData)GDS_PENDING) continue;
t->ti_client = (ClientData)GDS_PROCESSED;
if (TiGetClientINT(t) != GDS_PENDING) continue;
TiSetClientINT(t, GDS_PROCESSED);
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;
@ -1852,8 +1945,10 @@ calmaMergePaintFuncZ(tile, cos)
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
@ -1994,7 +2089,7 @@ calmaMergePaintFuncZ(tile, cos)
intedges += calmaAddSegment(&lb, is_ext,
MIN(RIGHT(t), RIGHT(tp)), TOP(t),
MAX(LEFT(t), LEFT(tp)), TOP(t));
if (!is_ext) PUSHTILE(tp);
if (!is_ext) PUSHTILEZ(tp);
}
if (split_type == 0x3)
@ -2014,7 +2109,7 @@ left_search:
intedges += calmaAddSegment(&lb, is_ext,
LEFT(t), MIN(TOP(t), TOP(tp)),
LEFT(t), MAX(BOTTOM(t), BOTTOM(tp)));
if (!is_ext) PUSHTILE(tp);
if (!is_ext) PUSHTILEZ(tp);
}
if (split_type == 0x0)
@ -2034,7 +2129,7 @@ bottom_search:
intedges += calmaAddSegment(&lb, is_ext,
MAX(LEFT(t), LEFT(tp)), BOTTOM(t),
MIN(RIGHT(t), RIGHT(tp)), BOTTOM(t));
if (!is_ext) PUSHTILE(tp);
if (!is_ext) PUSHTILEZ(tp);
}
if (split_type == 0x1)
@ -2053,7 +2148,7 @@ right_search:
intedges += calmaAddSegment(&lb, is_ext,
RIGHT(t), MAX(BOTTOM(t), BOTTOM(tp)),
RIGHT(t), MIN(TOP(t), TOP(tp)));
if (!is_ext) PUSHTILE(tp);
if (!is_ext) PUSHTILEZ(tp);
}
/* If tile is isolated, process it now and we're done */
@ -2061,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 */
@ -2072,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))
@ -2127,12 +2226,13 @@ done_searches:
*/
int
calmaWritePaintFuncZ(tile, cos)
Tile *tile; /* Tile to be written out. */
calmaOutputStructZ *cos; /* File for output and clipping area */
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;
Rect *clipArea = cos->area;
const Rect *clipArea = cos->area;
Rect r, r2;
TiToRect(tile, &r);
@ -2164,7 +2264,7 @@ calmaWritePaintFuncZ(tile, cos)
/* 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);
@ -2232,18 +2332,21 @@ calmaWritePaintFuncZ(tile, cos)
*/
void
calmaWriteLabelFuncZ(lab, type, f)
Label *lab; /* Label to output */
int type; /* CIF layer number, or -1 if not attached to a layer */
gzFile f; /* Stream file */
calmaWriteLabelFuncZ(
Label *lab, /* Label to output */
int ltype, /* CIF layer number to use for TEXT record */
int type, /* CIF layer number to use for BOUNDARY record,
* or -1 if not attached to a layer
*/
gzFile f) /* Stream file */
{
Point p;
int calmanum, calmatype;
if (type < 0)
if (ltype < 0)
return;
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
calmanum = CIFCurStyle->cs_layers[ltype]->cl_calmanum;
if (!CalmaIsValidLayer(calmanum))
return;
@ -2252,7 +2355,7 @@ calmaWriteLabelFuncZ(lab, type, f)
calmaOutRHZ(6, CALMA_LAYER, CALMA_I2, f);
calmaOutI2Z(calmanum, f);
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
calmatype = CIFCurStyle->cs_layers[ltype]->cl_calmatype;
calmaOutRHZ(6, CALMA_TEXTTYPE, CALMA_I2, f);
calmaOutI2Z(calmatype, f);
@ -2334,6 +2437,15 @@ calmaWriteLabelFuncZ(lab, type, f)
/* and the label rectangle is not degenerate, then output the label */
/* rectangle as a boundary with the label's layer:purpose pair. */
if (type < 0)
return;
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
if (!CalmaIsValidLayer(calmanum))
return;
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
/* Note that the check for whether the CIF_LABEL_NOPORT flag has */
/* been set is done outside of this routine. */
@ -2391,12 +2503,13 @@ calmaWriteLabelFuncZ(lab, type, f)
*/
int
calmaPaintLabelFuncZ(tile, cos)
Tile *tile; /* Tile contains area for label. */
calmaOutputStructZ *cos; /* File for output and clipping area */
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;
Rect *clipArea = cos->area;
const Rect *clipArea = cos->area;
Rect r, r2;
Point p;
int len;
@ -2452,9 +2565,9 @@ calmaPaintLabelFuncZ(tile, cos)
*/
void
calmaOutHeaderZ(rootDef, f)
CellDef *rootDef;
gzFile f;
calmaOutHeaderZ(
CellDef *rootDef,
gzFile f)
{
static double useru = 0.001;
static double mum = 1.0e-9;
@ -2513,9 +2626,9 @@ calmaOutHeaderZ(rootDef, f)
*/
void
calmaOutDateZ(t, f)
time_t t; /* Time (UNIX format) to be output */
gzFile f; /* Stream file */
calmaOutDateZ(
time_t t, /* Time (UNIX format) to be output */
gzFile f) /* Stream file */
{
struct tm *datep = localtime(&t);
@ -2548,14 +2661,15 @@ calmaOutDateZ(t, f)
*/
void
calmaOutStringRecordZ(type, str, f)
int type; /* Type of this record (data type is ASCII string) */
char *str; /* String to be output */
gzFile f; /* Compressed stream file */
calmaOutStringRecordZ(
int type, /* Type of this record (data type is ASCII string) */
char *str, /* String to be output */
gzFile f) /* Compressed stream file */
{
int len;
unsigned char c;
char *table, *locstr, *origstr = NULL;
const char *table;
char *locstr, *origstr = NULL;
char *locstrprv;
if(CIFCurStyle->cs_flags & CWF_PERMISSIVE_LABELS)
@ -2649,9 +2763,9 @@ calmaOutStringRecordZ(type, str, f)
*/
void
calmaOutR8Z(d, f)
double d; /* Double value to write to output */
gzFile f; /* Stream file */
calmaOutR8Z(
double d, /* Double value to write to output */
gzFile f) /* Stream file */
{
int c, i, sign, expon;
@ -2724,9 +2838,9 @@ calmaOutR8Z(d, f)
*/
void
calmaOut8Z(str, f)
char *str; /* 8-byte string to be output */
gzFile f; /* Compressed stream file */
calmaOut8Z(
const char *str, /* 8-byte string to be output */
gzFile f) /* Compressed stream file */
{
int i;

View File

@ -19,13 +19,13 @@
* 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"
/* Externally visible variables */
extern bool CalmaSubcellPolygons;
extern unsigned char CalmaSubcellPolygons;
extern bool CalmaSubcellPaths;
extern bool CalmaDoLabels;
extern bool CalmaDoLibrary;
@ -39,6 +39,8 @@ extern bool CalmaMergeTiles;
extern bool CalmaFlattenArrays;
extern bool CalmaNoDRCCheck;
extern bool CalmaFlattenUses;
extern int CalmaFlattenLimit;
extern float CalmaMagScale;
extern char **CalmaFlattenUsesByName;
extern bool CalmaReadOnly;
extern bool CalmaContactArrays;
@ -49,43 +51,50 @@ extern bool CalmaPostOrder;
extern bool CalmaAllowUndefined;
extern bool CalmaAllowAbstract;
/* Definitions used by the return value for CalmaSubcellPolygons */
/* CALMA_POLYGON_NONE: Process polygons immediately */
/* CALMA_POLYGON_TEMP: Create temporary polygon subcells */
/* CALMA_POLYGON_KEEP: Keep polygons in subcells */
#define CALMA_POLYGON_NONE 0
#define CALMA_POLYGON_TEMP 1
#define CALMA_POLYGON_KEEP 2
/* Externally-visible procedures: */
extern bool CalmaWrite();
extern void CalmaReadFile();
extern void CalmaTechInit();
extern bool CalmaGenerateArray();
extern void CalmaReadError();
extern bool CalmaWrite(CellDef *rootDef, FILE *f);
extern void CalmaReadFile(FILETYPE file, char *filename);
extern void CalmaTechInit(void);
extern bool CalmaGenerateArray(FILE *f, TileType type, int llx, int lly, int pitch, int cols, int rows);
extern void CalmaReadError(const char *format, ...) ATTR_FORMAT_PRINTF_1;
/* C99 compat */
extern void CalmaReadError();
extern int calmaAddSegment();
extern void calmaDelContacts();
extern void calmaElementBoundary();
extern void calmaElementBox();
extern void calmaElementPath();
extern void calmaElementText();
extern bool calmaIsUseNameDefault();
extern bool calmaParseStructure();
extern int calmaProcessDef();
extern int calmaProcessDefZ();
extern bool calmaReadI2Record();
extern bool calmaReadI4Record();
extern void calmaReadPoint();
extern bool calmaReadR8();
extern bool calmaReadStampRecord();
extern bool calmaReadStringRecord();
extern bool calmaReadStringRecord();
extern bool calmaReadTransform();
extern bool calmaSkipBytes();
extern bool calmaSkipExact();
extern bool calmaSkipTo();
extern void calmaUnexpected();
extern void calmaMergeSegments();
extern void calmaRemoveDegenerate();
extern void calmaRemoveColinear();
extern void calmaDelContacts(void);
extern void calmaElementBoundary(void);
extern void calmaElementBox(void);
extern void calmaElementPath(void);
extern void calmaElementText(void);
extern bool calmaIsUseNameDefault(char *defName, char *useName);
extern bool calmaParseStructure(char *filename);
extern int calmaProcessDef(CellDef *def, FILE *outf, bool do_library);
#ifdef HAVE_ZLIB
extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library);
#endif
extern bool calmaReadI2Record(int type, int *pvalue);
extern bool calmaReadI4Record(int type, int *pvalue);
extern void calmaReadPoint(Point *p, int iscale);
extern bool calmaReadR8(double *pd);
extern bool calmaReadStampRecord(int type, int *stampptr);
extern bool calmaReadStringRecord(int type, char **str);
extern bool calmaReadStringRecord(int type, char **str);
extern bool calmaReadTransform(Transform *ptrans, char *name);
extern bool calmaSkipBytes(int nbytes);
extern bool calmaSkipExact(int type);
extern bool calmaSkipTo(int what);
extern void calmaUnexpected(int wanted, int got);
#ifdef HAVE_ZLIB
extern bool CalmaWriteZ();
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"
@ -131,8 +131,11 @@ typedef struct
/* Length of record header */
#define CALMAHEADERLENGTH 4
/* Label types */
typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CELLID } labelType;
/* Label types
* The intention is all the values can be stored/converted with unsigned char type,
* C23 allows us to be explicit with the type but C99 does not, so a comment for now.
*/
typedef enum /* : unsigned char */ { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CELLID } labelType;
/* ------------------------- Input macros ----------------------------- */
@ -216,19 +219,52 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
UNREADRH(nb, rt); \
}
/* Structure used for sorting ports by number */
typedef struct portlabel
{
Label *pl_label;
unsigned int pl_port;
} PortLabel;
/* Other commonly used globals */
extern HashTable calmaLayerHash;
extern int calmaElementIgnore[];
extern CellDef *calmaFindCell();
extern const int calmaElementIgnore[];
extern CellDef *calmaFindCell(const char *name, bool *was_called, bool *predefined);
/* (Added by Nishit, 8/18/2004--8/24/2004) */
extern CellDef *calmaLookCell();
extern void calmaWriteContact();
extern CellDef *calmaGetContactCell();
extern CellDef *calmaLookCell(char *name);
extern void calmaWriteContacts(FILE *f);
extern CellDef *calmaGetContactCell(TileType type, bool lookOnly);
extern bool calmaIsContactCell;
extern char *calmaRecordName();
extern void calmaSkipSet();
extern const char *calmaRecordName(int rtype);
extern void calmaSkipSet(const int *skipwhat);
extern bool calmaParseUnits(void);
extern int compport(const void *one, const void *two);
#define LB_EXTERNAL 0 /* Polygon external edge */
#define LB_INTERNAL 1 /* Polygon internal edge */
#define LB_INIT 2 /* Data not yet valid */
typedef struct LB1 {
char lb_type; /* Boundary Type (external or internal) */
Point lb_start; /* Start point */
struct LB1 *lb_next; /* Next point record */
} LinkedBoundary;
typedef struct BT1 {
LinkedBoundary *bt_first; /* Polygon list */
int bt_points; /* Number of points in this list */
struct BT1 *bt_next; /* Next polygon record */
} BoundaryTop;
extern int calmaAddSegment(LinkedBoundary **lbptr, bool poly_edge, int p1x, int p1y, int p2x, int p2y);
extern void calmaMergeSegments(LinkedBoundary *edge, BoundaryTop **blist, int num_points);
extern void calmaRemoveDegenerate(BoundaryTop *blist);
extern void calmaRemoveColinear(BoundaryTop *blist);
/* ------------------- Imports from CIF reading ----------------------- */
@ -238,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

@ -22,7 +22,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFhier.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFhier.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -107,7 +107,7 @@ static CIFLayer *CurCifLayer;
*/
void
CIFInitCells()
CIFInitCells(void)
{
int i;
@ -172,7 +172,7 @@ CIFInitCells()
*/
void
cifHierCleanup()
cifHierCleanup(void)
{
int i;
@ -232,10 +232,10 @@ typedef struct _maskHintsData
/* DEPRECATED */
int
cifMaskHints(name, value, targetDef)
char *name;
char *value;
CellDef *targetDef;
cifMaskHints(
char *name,
char *value,
CellDef *targetDef)
{
char *propvalue, *newval;
bool propfound;
@ -277,15 +277,15 @@ cifMaskHints(name, value, targetDef)
*/
int
cifFlatMaskHints(name, value, mhd)
char *name;
char *value;
MaskHintsData *mhd;
cifFlatMaskHints(
char *name,
char *value,
MaskHintsData *mhd)
{
Rect r, newr;
char *vptr, *newval, *lastval, *propvalue;
bool propfound;
int lastlen;
int lastlen, numvals;
if (!strncmp(name, "MASKHINTS_", 10))
{
@ -293,8 +293,9 @@ cifFlatMaskHints(name, value, mhd)
vptr = value;
while (*vptr != '\0')
{
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
numvals = sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop);
if (numvals == 4)
{
/* Transform rectangle to top level coordinates */
GeoTransRect(mhd->mh_trans, &r, &newr);
@ -320,6 +321,12 @@ cifFlatMaskHints(name, value, mhd)
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
}
else
{
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
name + 10, numvals);
break;
}
}
/* Check if name exists already in the flattened cell */
@ -354,9 +361,9 @@ cifFlatMaskHints(name, value, mhd)
*/
void
CIFCopyMaskHints(scx, targetDef)
SearchContext *scx;
CellDef *targetDef;
CIFCopyMaskHints(
SearchContext *scx,
CellDef *targetDef)
{
MaskHintsData mhd;
@ -385,9 +392,9 @@ CIFCopyMaskHints(scx, targetDef)
*/
int
cifHierCopyMaskHints(scx, clientData)
SearchContext *scx;
ClientData clientData;
cifHierCopyMaskHints(
SearchContext *scx,
ClientData clientData)
{
MaskHintsData mhd;
@ -424,17 +431,18 @@ cifHierCopyMaskHints(scx, clientData)
*/
int
cifHierCopyFunc(tile, cxp)
Tile *tile; /* Pointer to tile to copy. */
TreeContext *cxp; /* Describes context of search, including
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. */
@ -450,8 +458,8 @@ cifHierCopyFunc(tile, cxp)
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);
}
@ -466,7 +474,7 @@ cifHierCopyFunc(tile, cxp)
{
if (DBPaintOnPlane(type, pNum))
{
DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect,
DBNMPaintPlane(def->cd_planes[pNum], newdinfo, &targetRect,
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
}
}
@ -493,8 +501,8 @@ cifHierCopyFunc(tile, cxp)
*/
int
cifHierCellFunc(scx)
SearchContext *scx; /* Describes cell and area in cell. */
cifHierCellFunc(
SearchContext *scx) /* Describes cell and area in cell. */
{
SearchContext newscx;
Rect rootArea;
@ -553,11 +561,13 @@ cifHierCellFunc(scx)
*/
int
cifHierErrorFunc(tile, checkArea)
Tile *tile; /* Tile that covers area it shouldn't. */
Rect *checkArea; /* Intersection of this and tile is error. */
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);
@ -565,8 +575,8 @@ cifHierErrorFunc(tile, checkArea)
* 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);
@ -595,9 +605,10 @@ cifHierErrorFunc(tile, checkArea)
*/
int
cifHierCheckFunc(tile, plane)
Tile *tile; /* Tile containing CIF. */
Plane *plane; /* Plane to check against and modify. */
cifHierCheckFunc(
Tile *tile, /* Tile containing CIF. */
TileType dinfo, /* Split tile information */
Plane *plane) /* Plane to check against and modify. */
{
Rect area;
@ -605,10 +616,10 @@ cifHierCheckFunc(tile, plane)
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
@ -642,16 +653,17 @@ cifHierCheckFunc(tile, plane)
*/
int
cifHierTempCheckFunc(tile, plane)
Tile *tile; /* Tile containing CIF. */
Plane *plane; /* Plane to check against and modify. */
cifHierTempCheckFunc(
Tile *tile, /* Tile containing CIF. */
TileType dinfo, /* Information about split tiles */
Plane *plane) /* Plane to check against and modify. */
{
Rect area;
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);
@ -677,18 +689,19 @@ cifHierTempCheckFunc(tile, plane)
*/
int
cifHierPaintFunc(tile, plane)
Tile *tile;
Plane *plane; /* Plane in which to paint CIF over tile's
cifHierPaintFunc(
Tile *tile,
TileType dinfo, /* Information about split tiles */
Plane *plane) /* Plane in which to paint CIF over tile's
* area.
*/
{
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);
@ -718,8 +731,8 @@ cifHierPaintFunc(tile, plane)
*/
void
cifCheckAndErase(style)
CIFStyle *style; /* Describes how to make CIF. */
cifCheckAndErase(
CIFStyle *style) /* Describes how to make CIF. */
{
int i;
@ -759,10 +772,10 @@ cifCheckAndErase(style)
*/
void
CIFGenSubcells(def, area, output)
CellDef *def; /* Parent cell for which CIF is computed. */
Rect *area; /* All CIF in this area is interesting. */
Plane **output; /* Array of pointers to planes into which
CIFGenSubcells(
CellDef *def, /* Parent cell for which CIF is computed. */
Rect *area, /* All CIF in this area is interesting. */
Plane **output) /* Array of pointers to planes into which
* the CIF output will be OR'ed (real CIF
* only).
*/
@ -927,13 +940,14 @@ CIFGenSubcells(def, area, output)
*/
int
cifHierElementFuncLow(use, transform, x, y, checkArea)
CellUse *use; /* CellUse being array-checked. */
Transform *transform; /* Transform from this instance to
cifHierElementFuncLow(
CellUse *use, /* CellUse being array-checked. */
Transform *transform, /* Transform from this instance to
* the parent.
*/
int x, y; /* Indices of this instance. */
Rect *checkArea; /* Area (in parent coords) to be
int x,
int y, /* Indices of this instance. */
Rect *checkArea) /* Area (in parent coords) to be
* CIF-generated.
*/
{
@ -950,13 +964,14 @@ cifHierElementFuncLow(use, transform, x, y, checkArea)
*/
int
cifHierElementFuncHigh(use, transform, x, y, checkArea)
CellUse *use; /* CellUse being array-checked. */
Transform *transform; /* Transform from this instance to
cifHierElementFuncHigh(
CellUse *use, /* CellUse being array-checked. */
Transform *transform, /* Transform from this instance to
* the parent.
*/
int x, y; /* Indices of this instance. */
Rect *checkArea; /* Area (in parent coords) to be
int x,
int y, /* Indices of this instance. */
Rect *checkArea) /* Area (in parent coords) to be
* CIF-generated.
*/
{
@ -991,13 +1006,14 @@ cifHierElementFuncHigh(use, transform, x, y, checkArea)
/* ARGSUSED */
int
cifHierElementFunc(use, transform, x, y, checkArea)
CellUse *use; /* CellUse being array-checked. */
Transform *transform; /* Transform from this instance to
cifHierElementFunc(
CellUse *use, /* CellUse being array-checked. */
Transform *transform, /* Transform from this instance to
* the parent.
*/
int x, y; /* Indices of this instance. */
Rect *checkArea; /* Area (in parent coords) to be
int x,
int y, /* Indices of this instance. */
Rect *checkArea) /* Area (in parent coords) to be
* CIF-generated.
*/
{
@ -1055,9 +1071,10 @@ cifHierElementFunc(use, transform, x, y, checkArea)
*/
int
cifGrowSliver(tile, area)
Tile *tile;
Rect *area;
cifGrowSliver(
Tile *tile,
TileType dinfo, /* Split tile information, needs to be handled */
Rect *area)
{
int height, width, expand_up, expand_side;
@ -1116,23 +1133,25 @@ cifGrowSliver(tile, area)
*/
int
cifHierPaintArrayFunc(tile)
Tile *tile;
cifHierPaintArrayFunc(
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;
}
@ -1187,9 +1206,9 @@ cifHierPaintArrayFunc(tile)
*/
int
cifHierArrayFunc(scx, output)
SearchContext *scx; /* Information about the search. */
Plane **output; /* Array of planes to hold results. */
cifHierArrayFunc(
SearchContext *scx, /* Information about the search. */
Plane **output) /* Array of planes to hold results. */
{
Rect childArea, parentArea, A, B, C, D, expandedArea;
CellUse *use;
@ -1533,10 +1552,10 @@ cifHierArrayFunc(scx, output)
*/
void
CIFGenArrays(def, area, output)
CellDef *def; /* Parent cell for which CIF is computed. */
Rect *area; /* All CIF in this area is interesting. */
Plane **output; /* Array of pointers to planes into which
CIFGenArrays(
CellDef *def, /* Parent cell for which CIF is computed. */
Rect *area, /* All CIF in this area is interesting. */
Plane **output) /* Array of pointers to planes into which
* the CIF output will be OR'ed (real CIF
* only, temp layers won't appear). If
* output is NULL, then CIF is stored in

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"
@ -134,12 +134,14 @@ typedef struct cifop
* box coordinates into CIF layer geometry.
* CIFOP_NET - Added 11/3/08---pull an entire electrical net into
* the CIF layer, selectively picking layers.
* CIFOP_MAXRECT - Reduce all areas to the largest internal fitting
* CIFOP_MAXRECT - Reduce all disjoint regions to the largest internal fitting
* rectangle.
* CIFOP_INTERACT - Select all disjoint regions which overlap a given set of types
* CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer,
* which will be painted into parent cells instead of the
* current cell. This replaces the "fault" method.
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated
* CIFOP_MANHATTAN - Added 3/27/25---remove or fill nonmanhattan areas
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
@ -163,12 +165,17 @@ typedef struct cifop
#define CIFOP_BOUNDARY 16
#define CIFOP_NET 17
#define CIFOP_MAXRECT 18
#define CIFOP_COPYUP 19
#define CIFOP_CLOSE 20
#define CIFOP_BRIDGE 21
#define CIFOP_BRIDGELIM 22
#define CIFOP_MASKHINTS 23
#define CIFOP_INTERACT 19
#define CIFOP_COPYUP 20
#define CIFOP_CLOSE 21
#define CIFOP_MANHATTAN 22
#define CIFOP_BRIDGE 23
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
#define CIFOP_INT_TOUCHING 0x2 /* Include both touching and overlapping */
/* Added by Tim 10/21/2004 */
/* The following structure is used to pass information on how to draw
@ -294,9 +301,12 @@ typedef struct cifstyle
* layer.
*/
int cs_portLayer[TT_MAXTYPES];
/* Similar to cs_labelLayer, to distinguish
* between output types used for "normal"
* text and those used specifically for ports.
/* Similar to cs_labelLayer, to use as
* a type for geometry attached to port labels.
*/
int cs_portText[TT_MAXTYPES];
/* Similar to cs_labelLayer, to use as
* a text type for port labels
*/
CIFLayer *cs_layers[MAXCIFLAYERS];
/* Describes how to generate each layer.*/
@ -312,40 +322,38 @@ typedef struct cifstyle
#define CWF_SEE_NO_VENDOR 0x10 /* Hide magic's GDS from vendor cells */
#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */
#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */
#define CWF_MINIMUM_GRID 0x80 /* Force minimum grid scaling */
/* procedures */
extern bool CIFNameToMask();
extern void CIFGenSubcells();
extern void CIFGenArrays();
extern void CIFGen();
extern void CIFClearPlanes();
extern Plane *CIFGenLayer();
extern void CIFInitCells();
extern int cifHierCopyFunc();
extern int cifHierCopyMaskHints();
extern void CIFLoadStyle();
extern void CIFCopyMaskHints();
extern bool CIFNameToMask(char *name, TileTypeBitMask *result, TileTypeBitMask *depend);
extern void CIFGenSubcells(CellDef *def, Rect *area, Plane **output);
extern void CIFGenArrays(CellDef *def, Rect *area, Plane **output);
extern void CIFGen(CellDef *cellDef, CellDef *origDef, const Rect *area, Plane **planes, TileTypeBitMask *layers,
bool replace, bool genAllPlanes, bool hier, ClientData clientdata);
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, TileType dinfo, TreeContext *cxp);
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
extern void CIFLoadStyle(char *stylename);
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
/* C99 compat */
extern void CIFCoverageLayer();
extern bool CIFWriteFlat();
extern void CIFScalePlanes();
extern void CIFInputRescale();
extern int CIFCalmaLayerToCifLayer();
extern int CIFScaleCoord();
extern void CIFPropRecordPath();
extern void CIFPaintWirePath();
extern void CIFMakeManhattanPath();
extern int cifGrowSliver();
extern int cifHierElementFunc();
extern int cifSquareFunc();
extern int cifSquareGridFunc();
extern int cifSlotFunc();
extern int CIFParseScale();
extern int cifParseCalmaNums();
extern int CIFEdgeDirection();
extern bool CIFReadTechLimitScale();
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
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, 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);
extern int cifSlotFunc(Rect *area, CIFOp *op, int *numY, int *numX, Rect *cut, bool vertical);
extern int CIFParseScale(char *true_scale, int *expander);
extern int cifParseCalmaNums(char *str, int *numArray, int numNums);
extern bool CIFReadTechLimitScale(int ns, int ds);
/* Shared variables and structures: */
@ -359,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,
@ -373,13 +384,13 @@ extern int CIFHierRects;
/* Tables used for painting and erasing CIF. */
extern PaintResultType CIFPaintTable[], CIFEraseTable[];
extern const PaintResultType CIFPaintTable[], CIFEraseTable[];
/* Procedures and variables for reporting errors. */
extern int CIFErrorLayer;
extern CellDef *CIFErrorDef;
extern void CIFError();
extern void CIFError(Rect *area, char *message);
/* The following determines the tile type used to hold the CIF
* information on its paint plane.
@ -388,4 +399,4 @@ extern void CIFError();
#define CIF_SOLIDTYPE 1
extern TileTypeBitMask CIFSolidBits;
#endif /* _CIFINT_H */
#endif /* _MAGIC__CIF__CIFINT_H */

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFmain.c,v 1.3 2009/01/15 15:44:34 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFmain.c,v 1.3 2009/01/15 15:44:34 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -95,7 +95,7 @@ global int CIFErrorLayer; /* Index of CIF layer associated with errors.*/
*/
void
CIFPrintStats()
CIFPrintStats(void)
{
TxPrintf("CIF statistics (recent/total):\n");
cifTotalTileOps += CIFTileOps;
@ -136,8 +136,8 @@ CIFPrintStats()
*/
float
CIFGetOutputScale(convert)
int convert;
CIFGetOutputScale(
int convert)
{
if (CIFCurStyle == NULL) return 1.0;
@ -159,8 +159,8 @@ CIFGetOutputScale(convert)
*/
float
CIFGetScale(convert)
int convert;
CIFGetScale(
int convert)
{
if (CIFCurStyle == NULL) return 1.0;
@ -185,10 +185,10 @@ CIFGetScale(convert)
*/
void
CIFPrintStyle(dolist, doforall, docurrent)
bool dolist; /* Return as a list if true */
bool doforall; /* Print all known styles if true */
bool docurrent; /* Print current style if true */
CIFPrintStyle(
bool dolist, /* Return as a list if true */
bool doforall, /* Print all known styles if true */
bool docurrent) /* Print current style if true */
{
CIFKeep *style;
@ -254,8 +254,8 @@ CIFPrintStyle(dolist, doforall, docurrent)
*/
void
CIFSetStyle(name)
char *name; /* Name of the new style. If NULL, just
CIFSetStyle(
char *name) /* Name of the new style. If NULL, just
* print out the valid styles.
*/
{
@ -320,10 +320,10 @@ CIFSetStyle(name)
*/
bool
CIFNameToMask(name, result, depend)
char *name;
TileTypeBitMask *result;
TileTypeBitMask *depend;
CIFNameToMask(
char *name,
TileTypeBitMask *result,
TileTypeBitMask *depend)
{
int i, j;
CIFOp *op;
@ -414,11 +414,11 @@ CIFNameToMask(name, result, depend)
*/
void
CIFError(area, message)
Rect *area; /* Place in CIFErrorDef where there was a
CIFError(
Rect *area, /* Place in CIFErrorDef where there was a
* problem in generating CIFErrorLayer.
*/
char *message; /* Short note about what went wrong. */
char *message) /* Short note about what went wrong. */
{
char msg[200];
@ -452,7 +452,7 @@ CIFError(area, message)
*/
int
CIFOutputScaleFactor()
CIFOutputScaleFactor(void)
{
if (CIFCurStyle == NULL) return 1;
return CIFCurStyle->cs_scaleFactor;

View File

@ -19,7 +19,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdcl.c,v 1.5 2010/08/25 17:33:55 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdcl.c,v 1.5 2010/08/25 17:33:55 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -126,8 +126,8 @@ char *cifSubcellId = NULL;
*/
void
CIFReadCellInit(ptrkeys)
int ptrkeys;
CIFReadCellInit(
int ptrkeys)
{
int i;
@ -162,8 +162,8 @@ CIFReadCellInit(ptrkeys)
*/
bool
cifForgetCell(cifNum)
int cifNum;
cifForgetCell(
int cifNum)
{
HashEntry *h;
@ -196,8 +196,8 @@ cifForgetCell(cifNum)
*/
void
cifUniqueCell(cifNum)
int cifNum;
cifUniqueCell(
int cifNum)
{
HashEntry *h;
CellDef *def, *testdef;
@ -256,8 +256,8 @@ cifUniqueCell(cifNum)
*/
CellDef *
cifFindCell(cifNum)
int cifNum; /* The CIF number of the desired cell. */
cifFindCell(
int cifNum) /* The CIF number of the desired cell. */
{
HashEntry *h;
CellDef *def, *testdef;
@ -299,10 +299,10 @@ cifFindCell(cifNum)
*/
void
CIFScalePlanes(scalen, scaled, planearray)
int scalen;
int scaled;
Plane **planearray;
CIFScalePlanes(
int scalen,
int scaled,
Plane **planearray)
{
int pNum;
Plane *newplane;
@ -348,8 +348,9 @@ CIFScalePlanes(scalen, scaled, planearray)
*/
void
CIFInputRescale(n, d)
int n, d;
CIFInputRescale(
int n,
int d)
{
CIFReadStyle *istyle = cifCurReadStyle;
CIFReadLayer *cl;
@ -389,7 +390,7 @@ CIFInputRescale(n, d)
CIFScalePlanes(n, d, cifCurReadPlanes);
if (cifCurReadPlanes != cifEditCellPlanes)
CIFScalePlanes(n, d, cifEditCellPlanes);
if (cifEditCellPlanes != cifSubcellPlanes && cifCurReadPlanes != cifSubcellPlanes)
if ((const Plane*)cifEditCellPlanes != (const Plane*)cifSubcellPlanes && cifCurReadPlanes != cifSubcellPlanes)
CIFScalePlanes(n, d, cifSubcellPlanes);
CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n",
@ -417,7 +418,7 @@ CIFInputRescale(n, d)
*/
bool
CIFParseStart()
CIFParseStart(void)
{
int number;
@ -502,9 +503,10 @@ CIFParseStart()
* ----------------------------------------------------------------------------
*/
int cifCheckPaintFunc(tile, clientData)
Tile *tile;
ClientData clientData;
int cifCheckPaintFunc(
Tile *tile,
TileType dinfo,
ClientData clientData)
{
return 1;
}
@ -512,29 +514,30 @@ int cifCheckPaintFunc(tile, clientData)
/* Callback function for copying paint from one CIF cell into another */
int
cifCopyPaintFunc(tile, cifCopyRec)
Tile *tile;
CIFCopyRec *cifCopyRec;
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;
@ -558,9 +561,10 @@ cifCopyPaintFunc(tile, cifCopyRec)
*/
int
cifMaskHintFunc(tile, lrecp)
Tile *tile;
LinkedRect **lrecp;
cifMaskHintFunc(
Tile *tile,
TileType dinfo, /* Unused, do not support non-manhattan hints */
LinkedRect **lrecp)
{
Rect r;
LinkedRect *newlr;
@ -593,11 +597,12 @@ cifMaskHintFunc(tile, lrecp)
*/
int
CIFPaintCurrent(filetype)
bool filetype;
CIFPaintCurrent(
int filetype)
{
extern int cifMakeBoundaryFunc(); /* Forward declaration. */
extern int cifPaintCurrentFunc(); /* 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;
@ -696,7 +701,7 @@ CIFPaintCurrent(filetype)
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMakeBoundaryFunc, (ClientData)filetype);
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
}
/* Swap planes */
@ -708,7 +713,7 @@ CIFPaintCurrent(filetype)
{
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifPaintCurrentFunc,
(ClientData)type);
INT2CD(type));
}
/* Recycle the plane, which was dynamically allocated. */
@ -759,7 +764,8 @@ CIFPaintCurrent(filetype)
}
/* Multiply input planes to the same scale as the generated output */
CIFScalePlanes(CIFCurStyle->cs_scaleFactor, 1, cifCurReadPlanes);
CIFScalePlanes(CIFCurStyle->cs_scaleFactor, cifCurReadStyle->crs_scaleFactor,
cifCurReadPlanes);
/* Generate the output for these layers from the cell contents */
CIFClearPlanes(CIFPlanes);
@ -849,9 +855,11 @@ CIFPaintCurrent(filetype)
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.
*/
@ -885,9 +893,10 @@ CIFPaintCurrent(filetype)
/* Use CIF layer geometry to define a fixed bounding box for the current cell */
int
cifMakeBoundaryFunc(tile, clientdata)
Tile *tile; /* Tile of CIF information. */
ClientData clientdata; /* Pass the file type (CIF or CALMA) */
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. */
/* If there are multiple rectangles defined with the boundary */
@ -896,7 +905,7 @@ cifMakeBoundaryFunc(tile, clientdata)
Rect area;
char propertyvalue[128], *storedvalue;
int savescale;
bool filetype = (bool)clientdata;
int filetype = (int)CD2INT(clientdata);
TiToRect(tile, &area);
area.r_xtop = CIFScaleCoord(area.r_xtop, COORD_EXACT);
@ -964,9 +973,10 @@ cifMakeBoundaryFunc(tile, clientdata)
/* Paint CIF layer geometry into the current cell def as magic layer "type" */
int
cifPaintCurrentFunc(tile, type)
Tile *tile; /* Tile of CIF information. */
TileType type; /* Magic type to be painted. */
cifPaintCurrentFunc(
Tile *tile, /* Tile of CIF information. */
TileType dinfo, /* Split tile information */
TileType type) /* Magic type to be painted. */
{
Rect area;
int pNum;
@ -1015,7 +1025,7 @@ cifPaintCurrentFunc(tile, type)
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);
}
@ -1041,7 +1051,7 @@ cifPaintCurrentFunc(tile, type)
*/
bool
CIFParseFinish()
CIFParseFinish(void)
{
if (!cifSubcellBeingRead)
{
@ -1096,7 +1106,7 @@ CIFParseFinish()
*/
bool
CIFParseDelete()
CIFParseDelete(void)
{
int number;
@ -1138,7 +1148,7 @@ CIFParseDelete()
*/
char *
cifParseName()
cifParseName(void)
{
char ch;
char *bufferp;
@ -1180,7 +1190,7 @@ cifParseName()
*/
bool
cifParseUser9()
cifParseUser9(void)
{
char *name;
@ -1212,7 +1222,7 @@ cifParseUser9()
*/
bool
CIFParseCall()
CIFParseCall(void)
{
int called;
Transform transform;
@ -1279,7 +1289,7 @@ CIFParseCall()
*/
bool
cifParseUser91()
cifParseUser91(void)
{
if (cifSubcellId != NULL)
{
@ -1310,7 +1320,7 @@ cifParseUser91()
*/
bool
cifParseUser94()
cifParseUser94(void)
{
Rect rectangle;
char *name = NULL;
@ -1400,7 +1410,7 @@ cifParseUser94()
*/
bool
cifParseUser95()
cifParseUser95(void)
{
/* Modified by BIM 1/8/2018 */
Rect rectangle;
@ -1560,7 +1570,7 @@ cifParseUser95()
* ----------------------------------------------------------------------------
*/
bool
CIFParseUser()
CIFParseUser(void)
{
char ch;
@ -1612,8 +1622,8 @@ CIFParseUser()
*/
void
CIFReadCellCleanup(filetype)
bool filetype;
CIFReadCellCleanup(
int filetype)
{
HashEntry *h;
HashSearch hs;
@ -1656,7 +1666,7 @@ CIFReadCellCleanup(filetype)
def->cd_flags &= ~CDPROCESSEDGDS;
if ((filetype == FILE_CIF && CIFNoDRCCheck == FALSE) ||
(filetype == 1 && CalmaNoDRCCheck == FALSE))
(filetype == FILE_CALMA && CalmaNoDRCCheck == FALSE))
DRCCheckThis(def, TT_CHECKPAINT, &def->cd_bbox);
DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits);
DBCellSetModified(def, TRUE);

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpoly.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpoly.c,v 1.3 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -29,6 +29,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h"
#include "cif/CIFint.h"
#include "cif/CIFread.h"
#include "calma/calma.h"
#include "utils/malloc.h"
#define HEDGE 0 /* Horizontal edge */
@ -54,10 +55,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
int
cifLowX(a, b)
CIFPath **a, **b;
cifLowX(
const void *aa,
const void *bb)
{
Point *p, *q;
const CIFPath **a = (const CIFPath **)aa;
const CIFPath **b = (const CIFPath **)bb;
const Point *p, *q;
p = &(*a)->cifp_point;
q = &(*b)->cifp_point;
@ -87,9 +92,12 @@ cifLowX(a, b)
*/
int
cifLowY(a, b)
Point **a, **b;
cifLowY(
const void *aa,
const void *bb)
{
const Point **a = (const Point **)aa;
const Point **b = (const Point **)bb;
if ((*a)->p_y < (*b)->p_y)
return (-1);
if ((*a)->p_y > (*b)->p_y)
@ -118,10 +126,10 @@ cifLowY(a, b)
*/
bool
cifOrient(edges, nedges, dir)
CIFPath *edges[]; /* Array of edges to be categorized. */
int dir[]; /* Array to hold directions. */
int nedges; /* Size of arrays. */
cifOrient(
CIFPath *edges[], /* Array of edges to be categorized. */
int nedges, /* Size of arrays. */
int dir[]) /* Array to hold directions. */
{
Point *p, *q;
int n;
@ -178,10 +186,11 @@ cifOrient(edges, nedges, dir)
*/
bool
cifCross(edge, dir, ybot, ytop)
CIFPath *edge; /* Pointer to first of 2 path points in edge */
int dir; /* Direction of edge */
int ybot, ytop; /* Range of interest */
cifCross(
CIFPath *edge, /* Pointer to first of 2 path points in edge */
int dir, /* Direction of edge */
int ybot,
int ytop) /* Range of interest */
{
int ebot, etop;
@ -222,11 +231,12 @@ cifCross(edge, dir, ybot, ytop)
*/
LinkedRect *
CIFPolyToRects(path, plane, resultTbl, ui)
CIFPath *path; /* Path describing a polygon. */
Plane *plane; /* Plane to draw on */
PaintResultType *resultTbl;
PaintUndoInfo *ui;
CIFPolyToRects(
CIFPath *path, /* Path describing a polygon. */
Plane *plane, /* Plane to draw on */
const PaintResultType *resultTbl,
PaintUndoInfo *ui,
bool isCalma) /* TRUE for Calma, FALSE for CIF */
{
int npts = 0, n, *dir, curr, wrapno;
int xbot, xtop, ybot, ytop;
@ -240,6 +250,9 @@ CIFPolyToRects(path, plane, resultTbl, ui)
if ((tail->cifp_x != path->cifp_x) || (tail->cifp_y != path->cifp_y))
{
if (isCalma)
CalmaReadError("Boundary is not closed.\n" );
p = (CIFPath *) mallocMagic ((unsigned) sizeof (CIFPath));
p->cifp_x = path->cifp_x;
p->cifp_y = path->cifp_y;

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpt.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdpt.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -65,7 +65,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
bool
CIFParseBox()
CIFParseBox(void)
{
Point center;
Point direction;
@ -176,7 +176,7 @@ CIFParseBox()
*/
bool
CIFParseFlash()
CIFParseFlash(void)
{
int diameter;
int savescale;
@ -236,13 +236,13 @@ CIFParseFlash()
*/
void
CIFPropRecordPath(def, pathheadp, iswire, propname)
CellDef *def;
CIFPath *pathheadp;
bool iswire;
char *propname;
CIFPropRecordPath(
CellDef *def,
CIFPath *pathheadp,
bool iswire,
char *propname)
{
extern float CIFGetOutputScale();
extern float CIFGetOutputScale(int convert);
CIFPath *pathp;
char *pathstr, *sptr;
int components;
@ -316,13 +316,13 @@ CIFPropRecordPath(def, pathheadp, iswire, propname)
*/
void
CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui)
CIFPath *pathheadp;
int width;
bool endcap;
Plane *plane;
PaintResultType *ptable;
PaintUndoInfo *ui;
CIFPaintWirePath(
CIFPath *pathheadp,
int width,
bool endcap,
Plane *plane,
const PaintResultType *ptable,
PaintUndoInfo *ui)
{
CIFPath *pathp, *previousp, *nextp, *polypath;
CIFPath *returnpath, *newpath, *savepath;
@ -338,18 +338,20 @@ CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui)
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(pathheadp, width, endcap, plane, ptable, ui)
/* 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(pathheadp, width, endcap, plane, ptable, ui)
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;
}
@ -481,14 +485,16 @@ CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui)
/* Slow draw for non-Manhattan paths: */
/* Break the area up into triangles and rectangles */
rectp = CIFPolyToRects(polypath, plane, ptable, ui);
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
@ -562,13 +568,13 @@ CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui)
*/
LinkedRect *
PaintPolygon(pointlist, number, plane, ptable, ui, keep)
Point *pointlist; /* Array of Point structures */
int number; /* total number of points */
Plane *plane; /* Plane structure to paint into */
PaintResultType *ptable; /* Paint result table */
PaintUndoInfo *ui; /* Undo record */
bool keep; /* Return list of rects if true */
PaintPolygon(
Point *pointlist, /* Array of Point structures */
int number, /* total number of points */
Plane *plane, /* Plane structure to paint into */
PaintResultType *ptable, /* Paint result table */
PaintUndoInfo *ui, /* Undo record */
bool keep) /* Return list of rects if true */
{
LinkedRect *rectp, *rectlist;
CIFPath *newpath, *cifpath = (CIFPath *)NULL;
@ -583,14 +589,16 @@ PaintPolygon(pointlist, number, plane, ptable, ui, keep)
cifpath = newpath;
}
rectlist = CIFPolyToRects(cifpath, plane, ptable, ui);
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;
}
@ -617,14 +625,14 @@ PaintPolygon(pointlist, number, plane, ptable, ui, keep)
*/
void
PaintWireList(pointlist, number, width, endcap, plane, ptable, ui)
Point *pointlist; /* Array of Point structures */
int number; /* total number of points */
int width; /* Route width of path */
bool endcap; /* Whether or not to add 1/2 width endcaps */
Plane *plane; /* Plane structure to paint into */
PaintResultType *ptable; /* Paint result table */
PaintUndoInfo *ui; /* Undo record */
PaintWireList(
Point *pointlist, /* Array of Point structures */
int number, /* total number of points */
int width, /* Route width of path */
bool endcap, /* Whether or not to add 1/2 width endcaps */
Plane *plane, /* Plane structure to paint into */
PaintResultType *ptable, /* Paint result table */
PaintUndoInfo *ui) /* Undo record */
{
CIFPath *newpath, *cifpath = (CIFPath *)NULL;
int i;
@ -661,7 +669,7 @@ PaintWireList(pointlist, number, width, endcap, plane, ptable, ui)
*/
bool
CIFParseWire()
CIFParseWire(void)
{
int width;
CIFPath *pathheadp, *polypath;
@ -687,7 +695,8 @@ CIFParseWire()
width /= cifReadScale2;
savescale = cifReadScale1;
if (!CIFParsePath(&pathheadp, 2))
pathheadp = CIFParsePath(2);
if (pathheadp == NULL)
{
CIFReadError("wire, but improper path; ignored.\n");
CIFSkipToSemi();
@ -721,7 +730,7 @@ CIFParseWire()
*/
bool
CIFParseLayer()
CIFParseLayer(void)
{
#define MAXCHARS 4
char name[MAXCHARS+1];
@ -784,7 +793,7 @@ CIFParseLayer()
*/
bool
CIFParsePoly()
CIFParsePoly(void)
{
CIFPath *pathheadp;
LinkedRect *rectp;
@ -797,7 +806,8 @@ CIFParsePoly()
CIFSkipToSemi();
return FALSE;
}
if (!CIFParsePath(&pathheadp, 1))
pathheadp = CIFParsePath(1);
if (pathheadp == NULL)
{
CIFReadError("polygon, but improper path; ignored.\n");
CIFSkipToSemi();
@ -807,7 +817,7 @@ CIFParsePoly()
/* Convert the polygon to rectangles. */
rectp = CIFPolyToRects(pathheadp, cifReadPlane, CIFPaintTable,
(PaintUndoInfo *)NULL);
(PaintUndoInfo *)NULL, FALSE);
CIFFreePath(pathheadp);
if (rectp == NULL)
{
@ -817,11 +827,13 @@ CIFParsePoly()
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

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdtech.c,v 1.4 2010/09/15 15:45:30 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdtech.c,v 1.4 2010/09/15 15:45:30 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -62,8 +62,8 @@ CIFReadLayer *cifCurReadLayer; /* Current layer being processed. */
CIFOp *cifCurReadOp; /* Last geometric operation seen. */
/* Forward declarations */
void cifReadStyleInit();
void CIFReadLoadStyle();
void cifReadStyleInit(void);
void CIFReadLoadStyle(char *stylename);
/*
* ----------------------------------------------------------------------------
@ -90,8 +90,9 @@ void CIFReadLoadStyle();
*/
bool
CIFReadTechLimitScale(ns, ds)
int ns, ds;
CIFReadTechLimitScale(
int ns,
int ds)
{
int gridup, scaledown;
int scale, limit, mult;
@ -131,9 +132,9 @@ CIFReadTechLimitScale(ns, ds)
*/
int
CIFReadNameToType(name, newOK)
char *name; /* Name of a CIF layer. */
bool newOK; /* TRUE means OK to create a new layer if this
CIFReadNameToType(
char *name, /* Name of a CIF layer. */
bool newOK) /* TRUE means OK to create a new layer if this
* name is one we haven't seen before.
*/
{
@ -196,34 +197,34 @@ CIFReadNameToType(name, newOK)
*/
int
CIFCalmaLayerToCifLayer(layer, datatype, calmaStyle)
int layer; /* Calma layer number */
int datatype; /* Calma datatype */
CIFReadStyle *calmaStyle;
CIFCalmaLayerToCifLayer(
int layer, /* Calma layer number */
int datatype, /* Calma datatype */
CIFReadStyle *calmaStyle)
{
CalmaLayerType clt;
HashEntry *he;
clt.clt_layer = layer;
clt.clt_type = datatype;
if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)))
return ((spointertype) HashGetValue(he));
/* Try wildcarding the datatype */
clt.clt_type = -1;
if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)))
return ((spointertype) HashGetValue(he));
/* Try wildcarding the layer */
clt.clt_layer = -1;
clt.clt_type = datatype;
if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)))
return ((spointertype) HashGetValue(he));
/* Try wildcarding them both, for a default value */
clt.clt_layer = -1;
clt.clt_type = -1;
if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt)))
return ((spointertype) HashGetValue(he));
/* No luck */
@ -251,10 +252,10 @@ CIFCalmaLayerToCifLayer(layer, datatype, calmaStyle)
*/
void
CIFParseReadLayers(string, mask, newok)
char *string; /* Comma-separated list of CIF layers. */
TileTypeBitMask *mask; /* Where to store bit mask. */
bool newok; /* If TRUE, create new layers if they don't exist */
CIFParseReadLayers(
char *string, /* Comma-separated list of CIF layers. */
TileTypeBitMask *mask, /* Where to store bit mask. */
bool newok) /* If TRUE, create new layers if they don't exist */
{
int i;
char *p;
@ -313,7 +314,7 @@ CIFParseReadLayers(string, mask, newok)
*/
void
cifNewReadStyle()
cifNewReadStyle(void)
{
int i;
CIFOp *op;
@ -328,8 +329,10 @@ cifNewReadStyle()
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);
}
}
@ -353,7 +356,7 @@ cifNewReadStyle()
*/
void
cifReadStyleInit()
cifReadStyleInit(void)
{
int i;
@ -395,7 +398,7 @@ cifReadStyleInit()
*/
void
CIFReadTechInit()
CIFReadTechInit(void)
{
CIFReadKeep *style;
@ -407,11 +410,13 @@ CIFReadTechInit()
/* 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;
}
@ -433,7 +438,7 @@ CIFReadTechInit()
*/
void
CIFReadTechStyleInit()
CIFReadTechStyleInit(void)
{
cifNReadLayers = 0;
cifCurReadLayer = NULL;
@ -460,10 +465,10 @@ CIFReadTechStyleInit()
*/
/* ARGSUSED */
bool
CIFReadTechLine(sectionName, argc, argv)
char *sectionName; /* Name of this section ("cifinput"). */
int argc; /* Number of fields on line. */
char *argv[]; /* Values of fields. */
CIFReadTechLine(
char *sectionName, /* Name of this section ("cifinput"). */
int argc, /* Number of fields on line. */
char *argv[]) /* Values of fields. */
{
CIFOp *newOp = NULL;
CIFReadKeep *newStyle, *p;
@ -872,10 +877,33 @@ CIFReadTechLine(sectionName, argc, argv)
goto wrongNumArgs;
}
CIFParseReadLayers(argv[1], &mask, TRUE);
for (i=0; i<MAXCIFRLAYERS; i+=1)
for (i = 0; i < MAXCIFRLAYERS; i++)
{
if (TTMaskHasType(&mask,i))
if (TTMaskHasType(&mask, i))
{
/* Only one magic type can be assigned to a GDS layer, so
* multiple assignments should be flagged as errors. BUT,
* this is a common historic error. Since reattachments
* should be handled rationally (by code added 10/17/2023
* to DBlabel.c), there is no urgent need to flag an issue
* unless the new layer does not exist on the same plane
* as the old one.
*/
if (cifCurReadStyle->crs_labelLayer[i] != TT_SPACE)
{
int p1, p2;
p1 = DBPlane(cifCurReadLayer->crl_magicType);
p2 = DBPlane(cifCurReadStyle->crs_labelLayer[i]);
if (!DBTypeOnPlane(cifCurReadLayer->crl_magicType, p2) &&
!DBTypeOnPlane(cifCurReadStyle->crs_labelLayer[i], p1))
TechError("Labels on layer \"%s\" attached to \"%s\" "
"supersedes prior attachment to \"%s\".\n",
cifReadLayers[i],
DBTypeLongNameTbl[cifCurReadLayer->crl_magicType],
DBTypeLongNameTbl[cifCurReadStyle->crs_labelLayer[i]]);
}
cifCurReadStyle->crs_labelLayer[i]
= cifCurReadLayer->crl_magicType;
if (argc == 3)
@ -899,8 +927,8 @@ CIFReadTechLine(sectionName, argc, argv)
if (argc != 2) goto wrongNumArgs;
CIFParseReadLayers(argv[1], &mask, TRUE);
/* trash the value in crs_labelLayer so that any labels on this
layer get junked, also. dcs 4/11/90
*/
* layer get junked, also. dcs 4/11/90
*/
for (i=0; i < cifNReadLayers; i++)
{
if (TTMaskHasType(&mask,i))
@ -916,14 +944,15 @@ CIFReadTechLine(sectionName, argc, argv)
/* miscellaneous cif-reading boolean options */
if(strcmp(argv[0], "options") == 0) {
if (strcmp(argv[0], "options") == 0) {
int i;
if (argc < 2) goto wrongNumArgs;
for(i = 1; i < argc; i++) {
if(strcmp(argv[i], "ignore-unknown-layer-labels") == 0)
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "ignore-unknown-layer-labels") == 0)
cifCurReadStyle->crs_flags |= CRF_IGNORE_UNKNOWNLAYER_LABELS;
if(strcmp(argv[i], "no-reconnect-labels") == 0)
cifCurReadStyle->crs_flags |= CRF_NO_RECONNECT_LABELS;
/* Allow "no-reconnect-labels", although it has been deprecated */
else if (strcmp(argv[i], "no-reconnect-labels") != 0)
TechError("Unknown cifinput option \"%s\".\n", argv[i]);
}
return TRUE;
}
@ -1027,7 +1056,7 @@ CIFReadTechLine(sectionName, argc, argv)
*/
void
CIFReadTechFinal()
CIFReadTechFinal(void)
{
/* Reduce the scale by the multiplier, as much as possible while */
/* keeping all CIF input ops in integer units. */
@ -1071,8 +1100,8 @@ CIFReadTechFinal()
* ----------------------------------------------------------------------------
*/
void
CIFReadLoadStyle(stylename)
char *stylename;
CIFReadLoadStyle(
char *stylename)
{
SectionID invcifr;
@ -1114,8 +1143,8 @@ CIFReadLoadStyle(stylename)
*/
int
CIFReadGetGrowSize(type)
TileType type;
CIFReadGetGrowSize(
TileType type)
{
CIFReadStyle *istyle = cifCurReadStyle;
CIFOp *op;
@ -1169,8 +1198,8 @@ CIFReadGetGrowSize(type)
*/
float
CIFGetInputScale(convert)
int convert;
CIFGetInputScale(
int convert)
{
/* Avoid divide-by-0 error if there is no cif input style */
/* in the tech file. */
@ -1202,10 +1231,10 @@ CIFGetInputScale(convert)
*/
void
CIFPrintReadStyle(dolist, doforall, docurrent)
bool dolist; /* Return as a list if true */
bool doforall; /* Return list of all styles if true */
bool docurrent; /* Return current style if true */
CIFPrintReadStyle(
bool dolist, /* Return as a list if true */
bool doforall, /* Return list of all styles if true */
bool docurrent) /* Return current style if true */
{
CIFReadKeep *style;
@ -1273,8 +1302,8 @@ CIFPrintReadStyle(dolist, doforall, docurrent)
*/
void
CIFSetReadStyle(name)
char *name; /* Name of the new style. If NULL,
CIFSetReadStyle(
char *name) /* Name of the new style. If NULL,
* just print the name of the current
* style.
*/
@ -1334,10 +1363,10 @@ CIFSetReadStyle(name)
*/
int
cifParseCalmaNums(str, numArray, numNums)
char *str; /* String to parse */
int *numArray; /* Array to fill in */
int numNums; /* Maximum number of entries in numArray */
cifParseCalmaNums(
char *str, /* String to parse */
int *numArray, /* Array to fill in */
int numNums) /* Maximum number of entries in numArray */
{
int numFilled, num;
@ -1397,9 +1426,10 @@ cifParseCalmaNums(str, numArray, numNums)
*/
int
CIFTechInputScale(n, d, opt)
int n, d;
bool opt;
CIFTechInputScale(
int n,
int d,
bool opt)
{
CIFReadStyle *istyle = cifCurReadStyle;
CIFReadLayer *cl;

View File

@ -19,7 +19,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdutils.c,v 1.4 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFrdutils.c,v 1.4 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -129,7 +129,7 @@ Plane *cifReadPlane; /* Plane into which to paint material
/* VARARGS1 */
void
CIFReadError(char *format, ...)
CIFReadError(const char *format, ...)
{
va_list args;
@ -140,7 +140,7 @@ CIFReadError(char *format, ...)
if (cifLineNumber > 0)
TxError("Error at line %d of CIF file: ", cifLineNumber);
else
TxError("CIF file read error: ", cifLineNumber);
TxError("CIF file read error: ");
va_start(args, format);
Vfprintf(stderr, format, args);
va_end(args);
@ -153,7 +153,7 @@ CIFReadError(char *format, ...)
void
CIFReadWarning(char *format, ...)
CIFReadWarning(const char *format, ...)
{
va_list args;
@ -205,9 +205,9 @@ CIFReadWarning(char *format, ...)
*/
int
CIFScaleCoord(cifCoord, snap_type)
int cifCoord; /* A coordinate in CIF units. */
int snap_type; /* How to deal with fractional results */
CIFScaleCoord(
int cifCoord, /* A coordinate in CIF units. */
int snap_type) /* How to deal with fractional results */
{
int result, scale, remain, denom;
int mult, mfactor;
@ -276,8 +276,10 @@ CIFScaleCoord(cifCoord, snap_type)
PlowAfterTech();
ExtTechScale(1, denom);
WireTechScale(1, denom);
#ifdef ROUTE_MODULE
MZAfterTech();
IRAfterTech();
#endif
#ifdef LEF_MODULE
LefTechScale(1, denom);
#endif
@ -343,8 +345,8 @@ CIFScaleCoord(cifCoord, snap_type)
*/
bool
cifIsBlank(ch)
int ch;
cifIsBlank(
int ch)
{
if ( isdigit(ch) || isupper(ch)
@ -376,7 +378,7 @@ cifIsBlank(ch)
*/
void
CIFSkipBlanks()
CIFSkipBlanks(void)
{
while (cifIsBlank(PEEK())) {
@ -405,7 +407,7 @@ CIFSkipBlanks()
*/
void
CIFSkipSep()
CIFSkipSep(void)
{
int ch;
@ -435,7 +437,7 @@ CIFSkipSep()
*/
void
CIFSkipToSemi()
CIFSkipToSemi(void)
{
int ch;
@ -464,7 +466,7 @@ CIFSkipToSemi()
*/
void
CIFSkipSemi()
CIFSkipSemi(void)
{
CIFSkipBlanks();
@ -495,8 +497,8 @@ CIFSkipSemi()
*/
bool
CIFParseSInteger(valuep)
int *valuep;
CIFParseSInteger(
int *valuep)
{
bool is_signed;
char buffer[ BUFSIZ ];
@ -540,8 +542,8 @@ CIFParseSInteger(valuep)
*/
bool
CIFParseInteger(valuep)
int *valuep;
CIFParseInteger(
int *valuep)
{
if (!CIFParseSInteger(valuep))
@ -581,9 +583,9 @@ CIFParseInteger(valuep)
*/
bool
CIFParsePoint(pointp, iscale)
Point *pointp;
int iscale;
CIFParsePoint(
Point *pointp,
int iscale)
{
int rescale;
@ -649,12 +651,11 @@ CIFParsePoint(pointp, iscale)
* 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(pointp, iscale)
* ----------------------------------------------------------------------------
*/
bool
CIFParsePath(pathheadpp, iscale)
CIFPath **pathheadpp;
int iscale;
CIFPath *
CIFParsePath(
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(pathheadpp, iscale)
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(pathheadpp, iscale)
}
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(pathheadpp, iscale)
}
pathtailp->cifp_next = newpathp;
}
else *pathheadpp = newpathp;
else pathheadp = newpathp;
pathtailp = newpathp;
}
return (*pathheadpp != NULL);
return pathheadp;
}
/*
@ -744,9 +744,9 @@ CIFParsePath(pathheadpp, iscale)
*/
bool
test_insideness(start, tpoint)
CIFPath *start;
Point *tpoint;
test_insideness(
CIFPath *start,
Point *tpoint)
{
Rect tmprect, irect;
@ -782,10 +782,11 @@ test_insideness(start, tpoint)
*/
bool
seg_intersect(tstart, bf, bs, respt)
CIFPath *tstart;
Point *bf, *bs;
Point *respt;
seg_intersect(
CIFPath *tstart,
Point *bf,
Point *bs,
Point *respt)
{
int afx = tstart->cifp_x;
int afy = tstart->cifp_y;
@ -848,9 +849,10 @@ seg_intersect(tstart, bf, bs, respt)
*/
bool
path_intersect(pathHead, start, respt)
CIFPath *pathHead, *start;
Point *respt;
path_intersect(
CIFPath *pathHead,
CIFPath *start,
Point *respt)
{
CIFPath *path, *segcrossed, *new;
Point tmppt;
@ -953,8 +955,8 @@ path_intersect(pathHead, start, respt)
*/
bool
is_clockwise(pathHead)
CIFPath *pathHead;
is_clockwise(
CIFPath *pathHead)
{
CIFPath *path, *midx = NULL, *last;
Point *p1, *p2, *p3;
@ -1047,11 +1049,11 @@ is_clockwise(pathHead)
*/
void
CIFMakeManhattanPath(pathHead, plane, resultTbl, ui)
CIFPath *pathHead;
Plane *plane;
PaintResultType *resultTbl;
PaintUndoInfo *ui;
CIFMakeManhattanPath(
CIFPath *pathHead,
Plane *plane,
const PaintResultType *resultTbl,
PaintUndoInfo *ui)
{
CIFPath *new, *new2, *next, *path;
int xinit, xdiff, xincr, xlast, x;
@ -1154,7 +1156,11 @@ CIFMakeManhattanPath(pathHead, plane, resultTbl, ui)
/* Final check---ensure that rectangle is not degenerate */
if (plane && (tr.r_xtop - tr.r_xbot > 0) && (tr.r_ytop - tr.r_ybot > 0))
{
DBNMPaintPlane(plane, type, &tr, resultTbl, ui);
GEO_EXPAND(&tr, 1, &tr);
DBMergeNMTiles(plane, &tr, ui);
}
}
}
@ -1181,8 +1187,9 @@ CIFMakeManhattanPath(pathHead, plane, resultTbl, ui)
*/
int
CIFEdgeDirection(first, last)
CIFPath *first, *last; /* Edge to be categorized. */
CIFEdgeDirection(
CIFPath *first,
CIFPath *last) /* Edge to be categorized. */
{
if (first->cifp_x < last->cifp_x)
@ -1229,8 +1236,8 @@ CIFEdgeDirection(first, last)
*/
void
CIFCleanPath(pathHead)
CIFPath *pathHead;
CIFCleanPath(
CIFPath *pathHead)
{
CIFPath *next, *path, *prev, *last;
int dir1, dir2;
@ -1249,7 +1256,7 @@ CIFCleanPath(pathHead)
if (!path) return;
}
while (next = path->cifp_next)
while ((next = path->cifp_next))
{
if ((dir2 = CIFEdgeDirection(path, next)) == CIF_ZERO)
{
@ -1328,14 +1335,16 @@ path_inc:
*/
void
CIFFreePath(path)
CIFPath *path; /* Path to be freed. */
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);
}
/*
@ -1357,7 +1366,7 @@ CIFFreePath(path)
*/
void
cifCommandError()
cifCommandError(void)
{
CIFReadError("unknown command `%c'; ignored.\n" , PEEK());
CIFSkipToSemi();
@ -1382,7 +1391,7 @@ cifCommandError()
*/
bool
cifParseEnd()
cifParseEnd(void)
{
TAKE();
CIFSkipBlanks();
@ -1411,7 +1420,7 @@ cifParseEnd()
*/
bool
cifParseComment()
cifParseComment(void)
{
int opens;
int ch;
@ -1462,9 +1471,9 @@ cifParseComment()
* ----------------------------------------------------------------------------
*/
Transform *
CIFDirectionToTrans(point)
Point *point; /* Direction vector from origin. */
const Transform *
CIFDirectionToTrans(
const Point *point) /* Direction vector from origin. */
{
if ((point->p_x != 0) && (point->p_y == 0))
{
@ -1503,8 +1512,8 @@ CIFDirectionToTrans(point)
*/
bool
CIFParseTransform(transformp)
Transform *transformp;
CIFParseTransform(
Transform *transformp)
{
char ch;
Point point;
@ -1597,8 +1606,8 @@ CIFParseTransform(transformp)
*/
void
CIFReadFile(file)
FILE *file; /* File from which to read CIF. */
CIFReadFile(
FILE *file) /* File from which to read CIF. */
{
/* We will use 1-word CIF numbers as keys in this hash table */
CIFReadCellInit(1);

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"
@ -104,8 +104,10 @@ typedef struct cifrstyle
/* Gives the Magic layer to use for labels
* on each possible CIF layer.
*/
bool crs_labelSticky[MAXCIFRLAYERS];
/* Marker if label layer makes sticky labels */
/* enum labelType */ unsigned char crs_labelSticky[MAXCIFRLAYERS];
/* Marker if label layer makes sticky labels
* enum labelType LABEL_TYPE_xxxxxx
*/
CIFReadLayer *crs_layers[MAXCIFRLAYERS];
HashTable cifCalmaToCif; /* Table mapping from Calma layer numbers to
* CIF layers
@ -115,7 +117,6 @@ typedef struct cifrstyle
/* option bitmasks used in crs_flags */
#define CRF_IGNORE_UNKNOWNLAYER_LABELS 1
#define CRF_NO_RECONNECT_LABELS 2
/* Methods to deal with fractional results of conversion from CIF to magic */
/* units (see routine CIFScaleCoord() for details). */
@ -153,22 +154,45 @@ typedef struct cifpath
/* Procedures */
extern bool CIFParseBox(), CIFParseWire(), CIFParsePoly();
extern bool CIFParseFlash(), CIFParseLayer(), CIFParseStart();
extern bool CIFParseFinish(), CIFParseDelete(), CIFParseUser();
extern bool CIFParseCall(), CIFParseTransform(), CIFParseInteger();
extern bool CIFParsePath(), CIFParsePoint(), CIFParseSInteger();
extern void CIFSkipToSemi(), CIFSkipSep(), CIFSkipBlanks();
extern void CIFFreePath(), CIFCleanPath();
extern void CIFReadCellInit(), CIFReadCellCleanup();
extern LinkedRect *CIFPolyToRects();
extern Transform *CIFDirectionToTrans();
extern int CIFReadNameToType();
extern bool CIFParseBox(void);
extern bool CIFParseWire(void);
extern bool CIFParsePoly(void);
extern bool CIFParseFlash(void);
extern bool CIFParseLayer(void);
extern bool CIFParseStart(void);
extern bool CIFParseFinish(void);
extern bool CIFParseDelete(void);
extern bool CIFParseUser(void);
extern bool CIFParseCall(void);
extern bool CIFParseTransform(Transform *transformp);
extern bool CIFParseInteger(int *valuep);
extern CIFPath *CIFParsePath(int iscale);
extern bool CIFParsePoint(Point *pointp, int iscale);
extern bool CIFParseSInteger(int *valuep);
extern void CIFSkipToSemi(void);
extern void CIFSkipSep(void);
extern void CIFSkipBlanks(void);
extern void CIFFreePath(CIFPath *path);
extern void CIFCleanPath(CIFPath *pathHead);
extern void CIFReadCellInit(int ptrkeys);
extern void CIFReadCellCleanup(int filetype);
extern LinkedRect *CIFPolyToRects(CIFPath *path, Plane *plane, const PaintResultType *resultTbl,
PaintUndoInfo *ui, bool isCalma);
extern const Transform *CIFDirectionToTrans(const Point *point);
extern int CIFReadNameToType(char *name, bool newOK);
extern int CIFCalmaLayerToCifLayer(int layer, int datatype, CIFReadStyle *calmaStyle);
extern void CIFPropRecordPath(CellDef *def, CIFPath *pathheadp, bool iswire, char *propname);
extern void CIFPaintWirePath(CIFPath *pathheadp, int width, bool endcap, Plane *plane,
const PaintResultType *ptable, PaintUndoInfo *ui);
extern void CIFMakeManhattanPath(CIFPath *pathHead, Plane *plane, const PaintResultType *resultTbl, PaintUndoInfo *ui);
extern int CIFEdgeDirection(CIFPath *first, CIFPath *last);
/* Variable argument procedures require complete prototype */
extern void CIFReadError(char *format, ...);
extern void CIFReadWarning(char *format, ...);
extern void CIFReadError(const char *format, ...) ATTR_FORMAT_PRINTF_1;
extern void CIFReadWarning(const char *format, ...) ATTR_FORMAT_PRINTF_1;
/* Variables shared by the CIF-reading modules, see CIFreadutils.c
* for more details:
@ -197,4 +221,4 @@ extern int cifParseLaChar;
? (cifParseLaAvail = FALSE, cifParseLaChar) \
: (cifParseLaChar = getc(cifInputFile)))
#endif /* _CIFREAD_H */
#endif /* _MAGIC__CIF__CIFREAD_H */

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFsee.c,v 1.5 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFsee.c,v 1.5 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -76,9 +76,10 @@ typedef struct {
*/
int
cifPaintDBFunc(tile, pld)
Tile *tile; /* Tile of CIF information. */
PaintLayerData *pld;
cifPaintDBFunc(
Tile *tile, /* Tile of CIF information. */
TileType dinfo,
PaintLayerData *pld)
{
Rect area;
int pNum;
@ -106,7 +107,7 @@ cifPaintDBFunc(tile, pld)
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);
}
@ -132,14 +133,14 @@ cifPaintDBFunc(tile, pld)
*/
void
CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef)
CellDef *rootDef; /* Cell for which to generate CIF. Must be
CIFPaintLayer(
CellDef *rootDef, /* Cell for which to generate CIF. Must be
* the rootDef of a window.
*/
Rect *area; /* Area in which to generate CIF. */
char *cifLayer; /* CIF layer to highlight on the screen. */
int magicLayer; /* Magic layer to paint with the result */
CellDef *paintDef; /* CellDef to paint into (may be NULL) */
Rect *area, /* Area in which to generate CIF. */
char *cifLayer, /* CIF layer to highlight on the screen. */
int magicLayer, /* Magic layer to paint with the result */
CellDef *paintDef) /* CellDef to paint into (may be NULL) */
{
int oldCount, i;
char msg[100];
@ -217,9 +218,10 @@ CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef)
*/
int
cifSeeFunc(tile, sld)
Tile *tile; /* Tile to be entered as feedback. */
SeeLayerData *sld; /* Layer and explanation for the feedback. */
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(tile, sld)
(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;
}
@ -258,12 +260,12 @@ cifSeeFunc(tile, sld)
*/
void
CIFSeeLayer(rootDef, area, layer)
CellDef *rootDef; /* Cell for which to generate CIF. Must be
CIFSeeLayer(
CellDef *rootDef, /* Cell for which to generate CIF. Must be
* the rootDef of a window.
*/
Rect *area; /* Area in which to generate CIF. */
char *layer; /* CIF layer to highlight on the screen. */
Rect *area, /* Area in which to generate CIF. */
char *layer) /* CIF layer to highlight on the screen. */
{
int oldCount, i;
char msg[100];
@ -348,14 +350,14 @@ CIFSeeLayer(rootDef, area, layer)
*/
void
CIFSeeHierLayer(rootDef, area, layer, arrays, subcells)
CellDef *rootDef; /* Def in which to compute CIF. Must be
CIFSeeHierLayer(
CellDef *rootDef, /* Def in which to compute CIF. Must be
* the root definition of a window.
*/
Rect *area; /* Area in which to generate CIF. */
char *layer; /* CIF layer to be highlighted. */
bool arrays; /* TRUE means show array interactions. */
bool subcells; /* TRUE means show subcell interactions. */
Rect *area, /* Area in which to generate CIF. */
char *layer, /* CIF layer to be highlighted. */
bool arrays, /* TRUE means show array interactions. */
bool subcells) /* TRUE means show subcell interactions. */
{
int i, oldCount;
SeeLayerData sld;
@ -426,11 +428,11 @@ typedef struct {
} coverstats;
void
CIFCoverageLayer(rootDef, area, layer, dolist)
CellDef *rootDef; /* Def in which to compute CIF coverage */
Rect *area; /* Area in which to compute coverage */
char *layer; /* CIF layer for coverage computation. */
bool dolist; /* If TRUE, report only the value, in decimal */
CIFCoverageLayer(
CellDef *rootDef, /* Def in which to compute CIF coverage */
Rect *area, /* Area in which to compute coverage */
char *layer, /* CIF layer for coverage computation. */
bool dolist) /* If TRUE, report only the value, in decimal */
{
coverstats cstats;
int i, scale;
@ -438,9 +440,11 @@ CIFCoverageLayer(rootDef, area, layer, dolist)
SearchContext scx;
TileTypeBitMask mask, depend;
float fcover;
int cifCoverageFunc();
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;
@ -510,9 +514,10 @@ CIFCoverageLayer(rootDef, area, layer, dolist)
}
int
cifCoverageFunc(tile, arg)
Tile *tile;
ClientData *arg;
cifCoverageFunc(
Tile *tile,
TileType dinfo, /* (unused) */
ClientData *arg)
{
coverstats *cstats = (coverstats *)arg;
Rect r;

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFtech.c,v 1.7 2010/10/20 20:34:19 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFtech.c,v 1.7 2010/10/20 20:34:19 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -64,8 +64,8 @@ TileTypeBitMask CIFSolidBits;
/* Forward Declarations */
void cifTechStyleInit();
bool cifCheckCalmaNum();
void cifTechStyleInit(void);
bool cifCheckCalmaNum(char *str);
/*
* ----------------------------------------------------------------------------
@ -85,7 +85,7 @@ bool cifCheckCalmaNum();
*/
void
cifTechFreeStyle()
cifTechFreeStyle(void)
{
int i;
CIFOp *op;
@ -100,6 +100,7 @@ cifTechFreeStyle()
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)
@ -110,6 +111,8 @@ cifTechFreeStyle()
case CIFOP_BBOX:
case CIFOP_MAXRECT:
case CIFOP_BOUNDARY:
case CIFOP_INTERACT:
case CIFOP_MANHATTAN:
/* These options use co_client to hold a single */
/* integer value, so it is not allocated. */
break;
@ -118,8 +121,9 @@ cifTechFreeStyle()
break;
}
}
freeMagic((char *)op);
freeMagic1(&mm1, (char *)op);
}
freeMagic1_end(&mm1);
freeMagic((char *)layer);
}
}
@ -148,7 +152,7 @@ cifTechFreeStyle()
*/
void
cifTechNewStyle()
cifTechNewStyle(void)
{
cifTechFreeStyle();
cifTechStyleInit();
@ -165,7 +169,7 @@ cifTechNewStyle()
*/
void
cifTechStyleInit()
cifTechStyleInit(void)
{
int i;
@ -188,6 +192,7 @@ cifTechStyleInit()
{
CIFCurStyle->cs_labelLayer[i] = -1;
CIFCurStyle->cs_portLayer[i] = -1;
CIFCurStyle->cs_portText[i] = -1;
}
for (i = 0; i < MAXCIFLAYERS; i++)
CIFCurStyle->cs_layers[i] = NULL;
@ -215,23 +220,23 @@ cifTechStyleInit()
*/
void
cifParseLayers(string, style, paintMask, cifMask, spaceOK)
char *string; /* List of layers. */
CIFStyle *style; /* Gives CIF style for parsing string.*/
TileTypeBitMask *paintMask; /* Place to store mask of paint layers. If
cifParseLayers(
char *string, /* List of layers. */
CIFStyle *style, /* Gives CIF style for parsing string.*/
TileTypeBitMask *paintMask, /* Place to store mask of paint layers. If
* NULL, then only CIF layer names are
* considered.
*/
TileTypeBitMask *cifMask; /* Place to store mask of CIF layers. If
TileTypeBitMask *cifMask, /* Place to store mask of CIF layers. If
* NULL, then only paint layer names are
* considered.
*/
int spaceOK; /* are space layers permissible in this cif
int spaceOK) /* are space layers permissible in this cif
layer?
*/
{
TileTypeBitMask curCifMask, curPaintMask;
char curLayer[40], *p, *cp;
char curLayer[512], *p, *cp;
TileType paintType;
int i;
bool allResidues;
@ -243,6 +248,10 @@ cifParseLayers(string, style, paintMask, cifMask, spaceOK)
{
p = curLayer;
if (*string == '(')
while ((*string != ')') && (*string != 0))
*p++ = *string++;
if (*string == '*')
{
allResidues = TRUE;
@ -260,7 +269,22 @@ cifParseLayers(string, style, paintMask, cifMask, spaceOK)
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;
@ -296,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");
@ -356,7 +380,7 @@ okpaint:
*/
void
CIFTechInit()
CIFTechInit(void)
{
CIFKeep *style;
@ -366,11 +390,13 @@ CIFTechInit()
/* 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;
}
@ -392,7 +418,7 @@ CIFTechInit()
*/
void
CIFTechStyleInit()
CIFTechStyleInit(void)
{
CalmaTechInit();
@ -433,8 +459,9 @@ CIFTechStyleInit()
*/
bool
CIFTechLimitScale(ns, ds)
int ns, ds;
CIFTechLimitScale(
int ns,
int ds)
{
int gridup, scaledown;
int scale, limit, expand;
@ -473,9 +500,9 @@ CIFTechLimitScale(ns, ds)
*/
int
CIFParseScale(true_scale, expander)
char *true_scale;
int *expander;
CIFParseScale(
char *true_scale,
int *expander)
{
char *decimal;
short places;
@ -524,10 +551,10 @@ CIFParseScale(true_scale, expander)
*/
bool
CIFTechLine(sectionName, argc, argv)
char *sectionName; /* The name of this section. */
int argc; /* Number of fields on line. */
char *argv[]; /* Values of fields. */
CIFTechLine(
char *sectionName, /* The name of this section. */
int argc, /* Number of fields on line. */
char *argv[]) /* Values of fields. */
{
TileTypeBitMask mask, tempMask, cifMask, bloatLayers;
int i, j, l, distance;
@ -790,7 +817,7 @@ CIFTechLine(sectionName, argc, argv)
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;
@ -871,7 +898,7 @@ CIFTechLine(sectionName, argc, argv)
if (strcmp(argv[0], "labels") == 0)
{
bool portOnly = FALSE, noPort = FALSE;
bool portOnly = FALSE, noPort = FALSE, textOnly = FALSE;
if (cifCurLayer == NULL)
{
@ -886,6 +913,8 @@ CIFTechLine(sectionName, argc, argv)
portOnly = TRUE;
else if (!strncmp(argv[2], "noport", 6))
noPort = TRUE;
else if (!strncmp(argv[2], "text", 6))
textOnly = TRUE;
else
{
TechError("Unknown option %s for labels statement.\n", argv[2]);
@ -898,10 +927,28 @@ CIFTechLine(sectionName, argc, argv)
{
if (TTMaskHasType(&mask, i))
{
if (portOnly != TRUE)
CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1;
if (noPort != TRUE)
if (portOnly == TRUE)
{
/* With "port", use layer for port geometry.
* If the port text type has not been set, set it to
* this layer.
*/
CIFCurStyle->cs_portLayer[i] = CIFCurStyle->cs_nLayers-1;
if (CIFCurStyle->cs_portText[i] == -1)
CIFCurStyle->cs_portText[i] = CIFCurStyle->cs_nLayers-1;
}
else
{
/* For "noport" or no argument, the label text and data
* are set to this layer. If no argument, then set the
* port text type to this type. If a later "port" statement
* applies to the same layer, then the data type will be
* separate from the text type.
*/
CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1;
if (noPort == FALSE)
CIFCurStyle->cs_portText[i] = CIFCurStyle->cs_nLayers-1;
}
}
}
cifGotLabels = TRUE;
@ -997,6 +1044,8 @@ CIFTechLine(sectionName, argc, argv)
{
if (strcmp(argv[i], "calma-permissive-labels") == 0)
CIFCurStyle->cs_flags |= CWF_PERMISSIVE_LABELS;
else if (strcmp(argv[i], "set-minimum-grid") == 0)
CIFCurStyle->cs_flags |= CWF_MINIMUM_GRID;
else if (strcmp(argv[i], "grow-euclidean") == 0)
CIFCurStyle->cs_flags |= CWF_GROW_EUCLIDEAN;
else if (strcmp(argv[i], "see-no-vendor") == 0)
@ -1066,10 +1115,29 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "close") == 0)
newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "orthogonal") == 0)
newOp->co_opcode = CIFOP_MANHATTAN;
else if (strcmp(argv[0], "bridge") == 0)
newOp->co_opcode = CIFOP_BRIDGE;
else if (strcmp(argv[0], "bridge-lim") == 0)
newOp->co_opcode = CIFOP_BRIDGELIM;
else if (strcmp(argv[0], "overlapping") == 0)
newOp->co_opcode = CIFOP_INTERACT;
else if (strcmp(argv[0], "nonoverlapping") == 0)
{
newOp->co_opcode = CIFOP_INTERACT;
newOp->co_client = (ClientData)CIFOP_INT_NOT;
}
else if (strcmp(argv[0], "interacting") == 0)
{
newOp->co_opcode = CIFOP_INTERACT;
newOp->co_client = (ClientData)CIFOP_INT_TOUCHING;
}
else if (strcmp(argv[0], "noninteracting") == 0)
{
newOp->co_opcode = CIFOP_INTERACT;
newOp->co_client = (ClientData)(CIFOP_INT_TOUCHING | CIFOP_INT_NOT);
}
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1081,6 +1149,7 @@ CIFTechLine(sectionName, argc, argv)
case CIFOP_AND:
case CIFOP_ANDNOT:
case CIFOP_OR:
case CIFOP_INTERACT:
if (argc != 2) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask,FALSE);
@ -1090,7 +1159,6 @@ CIFTechLine(sectionName, argc, argv)
case CIFOP_GROWMIN:
case CIFOP_GROW_G:
case CIFOP_SHRINK:
case CIFOP_CLOSE:
if (argc != 2) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
@ -1100,6 +1168,26 @@ CIFTechLine(sectionName, argc, argv)
}
break;
case CIFOP_CLOSE:
/* "close" is like "grow" and "shrink" except that it can have
* no argument, in which case any closed shape of any size
* will be closed (useful for finding enclosed areas).
*/
if (argc == 1)
newOp->co_distance = 0;
else if (argc != 2)
goto wrongNumArgs;
else
{
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
{
TechError("Grow/shrink distance must be greater than zero.\n");
goto errorReturn;
}
}
break;
case CIFOP_BRIDGE:
if (argc != 3) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
@ -1140,7 +1228,7 @@ CIFTechLine(sectionName, argc, argv)
break;
case CIFOP_BLOATALL:
if (argc != 3) goto wrongNumArgs;
if (argc != 3 && argc != 4) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask, FALSE);
bloats = (BloatData *)mallocMagic(sizeof(BloatData));
@ -1156,6 +1244,21 @@ CIFTechLine(sectionName, argc, argv)
if (!TTMaskIsZero(&mask) && !TTMaskIsZero(&cifMask))
TechError("Can't mix CIF and magic layers in bloat statement.\n");
if (argc == 4)
{
/* 12/23/2024: Allow an additional argument, which is a
* maximum halo distance to bloat (i.e., clip mask)
*/
newOp->co_distance = atoi(argv[3]);
if (newOp->co_distance <= 0)
{
TechError("Bloat distance must be greater than zero.\n");
goto errorReturn;
}
}
else
newOp->co_distance = 0;
/* 10/15/2019: Lifting restriction that the types that */
/* trigger the bloating must be in the same plane as the */
/* types that are bloated into. */
@ -1276,6 +1379,19 @@ bloatCheck:
goto wrongNumArgs;
break;
case CIFOP_MANHATTAN:
if (argc == 2)
{
if (!strcmp(argv[1], "fill"))
newOp->co_client = (ClientData)1;
else if (strcmp(argv[1], "remove"))
TechError("Orthogonal takes only one optional argument "
"\"fill\" or \"remove\" (default).\n");
}
else if (argc != 1)
goto wrongNumArgs;
break;
case CIFOP_BBOX:
if (argc == 2)
{
@ -1502,8 +1618,8 @@ bloatCheck:
*/
bool
cifCheckCalmaNum(str)
char *str;
cifCheckCalmaNum(
char *str)
{
int n = atoi(str);
@ -1539,9 +1655,9 @@ cifCheckCalmaNum(str)
*/
void
cifComputeRadii(layer, des)
CIFLayer *layer; /* Layer for which to compute distances. */
CIFStyle *des; /* CIF style (used to find temp layer
cifComputeRadii(
CIFLayer *layer, /* Layer for which to compute distances. */
CIFStyle *des) /* CIF style (used to find temp layer
* distances.
*/
{
@ -1586,6 +1702,7 @@ cifComputeRadii(layer, des)
case CIFOP_AND:
case CIFOP_ANDNOT:
case CIFOP_OR:
case CIFOP_INTERACT:
case CIFOP_MASKHINTS:
break;
@ -1647,8 +1764,8 @@ cifComputeRadii(layer, des)
*/
void
cifComputeHalo(style)
CIFStyle *style;
cifComputeHalo(
CIFStyle *style)
{
int maxGrow, maxShrink, i;
@ -1664,7 +1781,8 @@ cifComputeHalo(style)
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",
@ -1717,7 +1835,7 @@ cifComputeHalo(style)
*/
void
CIFTechFinal()
CIFTechFinal(void)
{
CIFStyle *style = CIFCurStyle;
CIFOp *op;
@ -1866,7 +1984,7 @@ CIFTechFinal()
}
}
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
/* of the SquaresData pointer from a following operator */
/* of the SquaresData pointer from a following operator. */
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* uses it for a string. */
@ -1879,6 +1997,7 @@ CIFTechFinal()
case CIFOP_MASKHINTS:
case CIFOP_BOUNDARY:
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
break;
case CIFOP_BRIDGELIM:
@ -1977,6 +2096,7 @@ CIFTechFinal()
case CIFOP_AND:
case CIFOP_ANDNOT:
case CIFOP_INTERACT:
case CIFOP_SHRINK:
case CIFOP_CLOSE:
case CIFOP_BRIDGELIM:
@ -2049,7 +2169,8 @@ CIFTechFinal()
for (op = style->cs_layers[i]->cl_ops; (op != NULL) &&
(op->co_opcode == CIFOP_OR) &&
(TTMaskIsZero(&op->co_cifMask)); op = op->co_next);
if (op && (op->co_opcode == CIFOP_SQUARES) && (op->co_next == NULL))
if (op && ((op->co_opcode == CIFOP_SQUARES) ||
(op->co_opcode == CIFOP_SQUARES_G)) && (op->co_next == NULL))
{
clientdata = op->co_client;
for (op = style->cs_layers[i]->cl_ops; op->co_opcode == CIFOP_OR;
@ -2100,8 +2221,8 @@ CIFTechFinal()
*/
void
CIFLoadStyle(stylename)
char *stylename;
CIFLoadStyle(
char *stylename)
{
SectionID invcif;
@ -2149,11 +2270,11 @@ CIFLoadStyle(stylename)
*/
int
CIFGetContactSize(type, edge, spacing, border)
TileType type;
int *edge;
int *border;
int *spacing;
CIFGetContactSize(
TileType type,
int *edge,
int *spacing,
int *border)
{
CIFStyle *style = CIFCurStyle;
CIFOp *op, *sop;
@ -2246,8 +2367,9 @@ CIFGetContactSize(type, edge, spacing, border)
*/
void
CIFTechOutputScale(n, d)
int n, d;
CIFTechOutputScale(
int n,
int d)
{
int i, j, lgcf, lexpand;
CIFStyle *ostyle = CIFCurStyle;
@ -2410,7 +2532,9 @@ CIFTechOutputScale(n, d)
case CIFOP_BOUNDARY:
case CIFOP_MASKHINTS:
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_INTERACT:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFwrite.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFwrite.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdlib.h>
@ -44,15 +44,15 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "textio/textio.h"
/* Forward declarations */
extern int cifWriteInitFunc();
extern int cifWriteMarkFunc();
extern int cifWritePaintFunc();
extern int cifWriteLabelFunc();
extern int cifWriteUseFunc();
extern void cifOutPreamble();
extern void cifOut();
extern void cifOutFunc();
extern int GrClipTriangle();
extern int cifWriteInitFunc(CellDef *def);
extern int cifWriteMarkFunc(CellUse *use);
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);
extern void cifOutFunc(CellDef *def, FILE *f);
extern void GrClipTriangle(Rect *r, Rect *c, int clipped, TileType dinfo, Point *points, int *np);
/* Current cell number in CIF numbering scheme */
@ -118,12 +118,13 @@ bool CIFArrayWriteDisable = FALSE;
*/
bool
CIFWrite(rootDef, f)
CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f; /* Open output file */
CIFWrite(
CellDef *rootDef, /* Pointer to CellDef to be written */
FILE *f) /* Open output file */
{
bool good;
int oldCount = DBWFeedbackCount;
CellDef *err_def;
CellUse dummy;
/*
@ -133,9 +134,11 @@ CIFWrite(rootDef, f)
*/
dummy.cu_def = rootDef;
if (DBCellReadArea(&dummy, &rootDef->cd_bbox, TRUE))
err_def = DBCellReadArea(&dummy, &rootDef->cd_bbox, TRUE);
if (err_def != NULL)
{
TxError("Failure to read in entire subtree of the cell.\n");
TxError("Failed on cell %s.\n", err_def->cd_name);
return (FALSE);
}
DBFixMismatch();
@ -164,8 +167,8 @@ CIFWrite(rootDef, f)
cifOutPreamble(f, rootDef);
cifOut(f);
StackFree(cifStack);
if ((int) rootDef->cd_client < 0)
rootDef->cd_client = (ClientData) (- (int) rootDef->cd_client);
if ((int) CD2INT(rootDef->cd_client) < 0)
rootDef->cd_client = INT2CD(- (int) CD2INT(rootDef->cd_client));
/* See if any problems occurred. */
@ -179,7 +182,7 @@ CIFWrite(rootDef, f)
* Now we are almost done.
* Just output a call on the root cell
*/
fprintf(f, "C %d;\nEnd\n", (int) rootDef->cd_client);
fprintf(f, "C %d;\nEnd\n", (int) CD2INT(rootDef->cd_client));
good = !ferror(f);
return (good);
}
@ -202,8 +205,8 @@ CIFWrite(rootDef, f)
*/
int
cifWriteInitFunc(def)
CellDef *def;
cifWriteInitFunc(
CellDef *def)
{
def->cd_client = (ClientData) 0;
return (0);
@ -226,11 +229,11 @@ cifWriteInitFunc(def)
*/
int
cifWriteMarkFunc(use)
CellUse *use;
cifWriteMarkFunc(
CellUse *use)
{
if (use->cu_def->cd_client != (ClientData) 0) return 0;
use->cu_def->cd_client = (ClientData) cifCellNum;
use->cu_def->cd_client = INT2CD(cifCellNum);
cifCellNum -= 1;
StackPush((ClientData) use->cu_def, cifStack);
return (0);
@ -252,9 +255,9 @@ cifWriteMarkFunc(use)
*/
void
cifOutPreamble(outf, cell)
FILE *outf;
CellDef *cell;
cifOutPreamble(
FILE *outf,
CellDef *cell)
{
extern char *MagicVersion;
extern char *MagicCompileTime;
@ -301,25 +304,24 @@ cifOutPreamble(outf, cell)
*/
void
cifOut(outf)
FILE *outf;
cifOut(
FILE *outf)
{
CellDef *def;
bool needHier;
while (!StackEmpty(cifStack))
{
def = (CellDef *) StackPop(cifStack);
if ((int) def->cd_client >= 0) continue; /* Already output */
if ((int) CD2INT(def->cd_client) >= 0) continue; /* Already output */
if (SigInterruptPending) continue;
def->cd_client = (ClientData) (- (int) def->cd_client);
def->cd_client = INT2CD(- (int) CD2INT(def->cd_client));
/* Read the cell in if it is not already available. */
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) continue;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
continue;
/* Add any subcells to the stack. This must be done before
* outputting CIF to make sure that the subcells all have
@ -351,16 +353,16 @@ cifOut(outf)
*/
void
cifOutFunc(def, f)
CellDef *def; /* Pointer to cell def to be written */
FILE *f; /* Open output file */
cifOutFunc(
CellDef *def, /* Pointer to cell def to be written */
FILE *f) /* Open output file */
{
Rect bigArea;
Label *lab;
int type;
CIFLayer *layer;
fprintf(f, "DS %d %d %d;\n", (int) def->cd_client,
fprintf(f, "DS %d %d %d;\n", (int) CD2INT(def->cd_client),
CIFCurStyle->cs_reducer, 2 * CIFCurStyle->cs_expander);
if (def->cd_name != (char *) NULL)
@ -385,10 +387,12 @@ cifOutFunc(def, f)
CIFErrorDef = def;
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
(ClientData)NULL);
if (!CIFHierWriteDisable)
CIFGenSubcells(def, &bigArea, CIFPlanes);
CIFGenSubcells(def, &bigArea, CIFPlanes);
if (!CIFArrayWriteDisable)
CIFGenArrays(def, &bigArea, CIFPlanes);
CIFGenArrays(def, &bigArea, CIFPlanes);
for (type = 0; type < CIFCurStyle->cs_nLayers; type++)
{
layer = CIFCurStyle->cs_layers[type];
@ -480,16 +484,16 @@ cifOutFunc(def, f)
*/
int
cifWriteUseFunc(use, f)
CellUse *use;
FILE *f;
cifWriteUseFunc(
CellUse *use,
FILE *f)
{
int x, y, topx, topy;
int realx, realy;
Transform *t;
int cifnum;
cifnum = (int) use->cu_def->cd_client;
cifnum = (int) CD2INT(use->cu_def->cd_client);
if (cifnum < 0) cifnum = (-cifnum);
topx = use->cu_xhi - use->cu_xlo;
if (topx < 0) topx = -topx;
@ -578,9 +582,10 @@ cifWriteUseFunc(use, f)
*/
int
cifWriteLabelFunc(tile, f)
Tile *tile; /* Tile to be written out. */
FILE *f; /* File in which to write. */
cifWriteLabelFunc(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information (unused) */
FILE *f) /* File in which to write. */
{
Rect r;
int type;
@ -637,9 +642,10 @@ cifWriteLabelFunc(tile, f)
*/
int
cifWritePaintFunc(tile, f)
Tile *tile; /* Tile to be written out. */
FILE *f; /* File in which to write. */
cifWritePaintFunc(
Tile *tile, /* Tile to be written out. */
TileType dinfo, /* Split tile information */
FILE *f) /* File in which to write. */
{
Rect r;
@ -658,7 +664,7 @@ cifWritePaintFunc(tile, f)
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 */
@ -718,9 +724,9 @@ cifWritePaintFunc(tile, f)
*/
bool
CIFWriteFlat(rootDef, f)
CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f; /* Open output file */
CIFWriteFlat(
CellDef *rootDef, /* Pointer to CellDef to be written */
FILE *f) /* Open output file */
{
bool good;
int oldCount = DBWFeedbackCount;
@ -769,7 +775,7 @@ CIFWriteFlat(rootDef, f)
* Just output a call on the root cell
*/
fprintf(f, "C %d;\nEnd\n", (int) CIFComponentDef->cd_client);
fprintf(f, "C %d;\nEnd\n", (int) CD2INT(CIFComponentDef->cd_client));
DBCellClearDef(CIFComponentDef);
good = !ferror(f);

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"
@ -51,47 +51,48 @@ extern bool CIFUnfracture;
/* Procedures that parse the cif sections of a technology file. */
extern void CIFTechStyleInit();
extern void CIFTechInit();
extern bool CIFTechLine();
extern void CIFTechFinal();
extern void CIFTechOutputScale();
extern int CIFTechInputScale();
extern bool CIFTechLimitScale();
extern void CIFReadTechStyleInit();
extern void CIFReadTechInit();
extern bool CIFReadTechLine();
extern void CIFReadTechFinal();
extern void CIFParseReadLayers();
extern void CIFTechStyleInit(void);
extern void CIFTechInit(void);
extern bool CIFTechLine(char *sectionName, int argc, char *argv[]);
extern void CIFTechFinal(void);
extern void CIFTechOutputScale(int n, int d);
extern int CIFTechInputScale(int n, int d, bool opt);
extern bool CIFTechLimitScale(int ns, int ds);
extern void CIFReadTechStyleInit(void);
extern void CIFReadTechInit(void);
extern bool CIFReadTechLine(char *sectionName, int argc, char *argv[]);
extern void CIFReadTechFinal(void);
extern void CIFParseReadLayers(char *string, TileTypeBitMask *mask, bool newok);
/* Externally-visible procedures: */
extern float CIFGetOutputScale();
extern float CIFGetScale();
extern float CIFGetInputScale();
extern int CIFGetDefaultContactSize();
extern float CIFGetOutputScale(int convert);
extern float CIFGetScale(int convert);
extern float CIFGetInputScale(int convert);
extern int CIFPaintCurrent();
extern void CIFSeeLayer();
extern void CIFPaintLayer();
extern void CIFSeeHierLayer();
extern void CIFPrintStats();
extern int CIFPaintCurrent(int filetype);
extern void CIFSeeLayer(CellDef *rootDef, Rect *area, char *layer);
extern void CIFPaintLayer(CellDef *rootDef, Rect *area, char *cifLayer, int magicLayer, CellDef *paintDef);
extern void CIFSeeHierLayer(CellDef *rootDef, Rect *area, char *layer, int arrays, int subcells);
extern void CIFPrintStats(void);
extern bool CIFWrite();
extern void CIFReadFile();
extern bool CIFWrite(CellDef *rootDef, FILE *f);
extern void CIFReadFile(FILE *file);
extern void CIFSetStyle();
extern void CIFSetReadStyle();
extern void CIFSetStyle(char *name);
extern void CIFSetReadStyle(char *name);
extern void CIFPrintStyle();
extern void CIFPrintReadStyle();
extern void CIFPrintStyle(bool dolist, bool doforall, bool docurrent);
extern void CIFPrintReadStyle(bool dolist, bool doforall, bool docurrent);
extern int CIFOutputScaleFactor();
extern int CIFOutputScaleFactor(void);
extern void PaintWireList();
extern LinkedRect *PaintPolygon();
extern void PaintWireList(Point *pointlist, int number, int width, int endcap, Plane *plane,
PaintResultType *ptable, PaintUndoInfo *ui);
extern LinkedRect *PaintPolygon(Point *pointlist, int number, Plane *plane, PaintResultType *ptable,
PaintUndoInfo *ui, int keep);
/* C99 compat */
extern int CIFGetContactSize();
extern int CIFGetContactSize(TileType type, int *edge, int *spacing, int *border);
#endif /* _CIF_H */
#endif /* _MAGIC__CIF__CIF_H */

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWcmmnds.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWcmmnds.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -43,10 +43,11 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Forward declarations: */
extern void cmwButtonUp(), cmwButtonDown();
extern void cbUpdate();
extern void RGBxHSV();
extern void HSVxRGB();
extern void cmwButtonUp(MagWindow *w, Point *p, int button);
extern void cmwButtonDown(MagWindow *w, Point *p, int button);
extern void cbUpdate(MagWindow *w, int code, double x, int replace);
extern bool RGBxHSV(double r, double g, double b, double *h, double *s, double *v);
extern void HSVxRGB(double h, double s, double v, double *r, double *g, double *b);
/* If a button is pressed over the top box in the window, which
* displays the current color, we must save the window in which
@ -84,9 +85,9 @@ bool cmwModified = FALSE;
*/
void
CMWcommand(w, cmd)
MagWindow *w;
TxCommand *cmd;
CMWcommand(
MagWindow *w,
TxCommand *cmd)
{
switch (cmd->tx_button)
{
@ -137,13 +138,13 @@ CMWcommand(w, cmd)
*/
void
cmwButtonDown(w, p, button)
MagWindow *w; /* Window where the button was pressed. */
Point *p;
int button;
cmwButtonDown(
MagWindow *w, /* Window where the button was pressed. */
Point *p,
int button)
{
ColorBar *cb;
ColorPump *cp;
const ColorBar *cb;
const ColorPump *cp;
Point surfacePoint;
int x;
double dx;
@ -224,14 +225,14 @@ cmwButtonDown(w, p, button)
*/
void
cmwButtonUp(w, p, button)
MagWindow *w; /* Window where the button was released */
Point *p; /* Point where button was released, in window coords.*/
int button; /* Button that was released. */
cmwButtonUp(
MagWindow *w, /* Window where the button was released */
Point *p, /* Point where button was released, in window coords.*/
int button) /* Button that was released. */
{
CMWclientRec *crec;
int r, g, b, color, oldR, oldG, oldB;
extern int cmwRedisplayFunc();
extern int cmwRedisplayFunc(MagWindow *w, int color);
/* If the button wasn't depressed over the top box in the window
* (the one displaying the current color), then we ignore the
@ -296,12 +297,12 @@ cmwButtonUp(w, p, button)
*/
void
cmwPushbutton(w, cmd)
MagWindow *w;
TxCommand *cmd;
cmwPushbutton(
MagWindow *w,
TxCommand *cmd)
{
int button;
static char *cmwButton[] = {"left", "middle", "right", NULL};
static const char * const cmwButton[] = {"left", "middle", "right", NULL};
if (cmd->tx_argc != 2)
{
@ -355,9 +356,9 @@ cmwPushbutton(w, cmd)
*/
void
cmwColor(w, cmd)
MagWindow *w;
TxCommand *cmd;
cmwColor(
MagWindow *w,
TxCommand *cmd)
{
int color, r, g, b;
CMWclientRec *crec;
@ -372,7 +373,7 @@ cmwColor(w, cmd)
}
else if (cmd->tx_argc == 2)
{
if (sscanf(cmd->tx_argv[1], "%i", &color) == 0)
if (sscanf(cmd->tx_argv[1], "%i", &color) != 1)
{
/* Invalid color---allow keywords "next" and "last" */
crec = (CMWclientRec *) w->w_clientData;
@ -450,9 +451,9 @@ cmwColor(w, cmd)
*/
void
cmwSave(w, cmd)
MagWindow *w;
TxCommand *cmd;
cmwSave(
MagWindow *w,
TxCommand *cmd)
{
bool ok;
if ((cmd->tx_argc != 1) && (cmd->tx_argc != 4))
@ -495,9 +496,9 @@ cmwSave(w, cmd)
*/
void
cmwLoad(w, cmd)
MagWindow *w;
TxCommand *cmd;
cmwLoad(
MagWindow *w,
TxCommand *cmd)
{
if ((cmd->tx_argc != 1) && (cmd->tx_argc != 4))
{
@ -537,18 +538,18 @@ cmwLoad(w, cmd)
*/
void
cbUpdate(w, code, x, replace)
MagWindow *w; /* Window whose color is to be changed. */
int code; /* Indicates which color component to change. */
double x; /* Gives increment or new value for color. */
int replace; /* TRUE means replace component with x, FALSE
cbUpdate(
MagWindow *w, /* Window whose color is to be changed. */
int code, /* Indicates which color component to change. */
double x, /* Gives increment or new value for color. */
int replace) /* TRUE means replace component with x, FALSE
* means increment component by x.
*/
{
CMWclientRec *cr = (CMWclientRec *) w->w_clientData;
double values[6];
int r, g, b, nr, ng, nb;
extern int cmwRedisplayFunc();
extern int cmwRedisplayFunc(MagWindow *w, int color);
/* Get current color map values */
(void) GrGetColor(cr->cmw_color, &r, &g, &b);
@ -591,14 +592,14 @@ cbUpdate(w, code, x, replace)
}
int
cmwRedisplayFunc(w, color)
MagWindow *w; /* Window that may have to be redisplayed. */
int color; /* If this color is in window, redisplay the
cmwRedisplayFunc(
MagWindow *w, /* Window that may have to be redisplayed. */
int color) /* If this color is in window, redisplay the
* color bars in the window.
*/
{
ColorBar *cb;
ColorPump *cp;
const ColorBar *cb;
const ColorPump *cp;
Rect screenR;
CMWclientRec *cr = (CMWclientRec *) w->w_clientData;
@ -644,11 +645,11 @@ cmwRedisplayFunc(w, color)
*/
bool
CMWCheckWritten()
CMWCheckWritten(void)
{
bool indx;
char *prompt;
static char *(yesno[]) = {"no", "yes", NULL};
static const char * const yesno[] = {"no", "yes", NULL};
if (!cmwModified) return TRUE;
prompt = TxPrintString("The color map has been modified.\n"

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWmain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWmain.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -44,12 +44,12 @@ global WindClient CMWclientID;
/* Forward and external declarations */
extern void cmwColor();
extern void cmwSave();
extern void cmwLoad();
extern void cmwPushbutton();
extern void RGBxHSV();
extern void CMWundoInit();
extern void cmwColor(MagWindow *w, TxCommand *cmd);
extern void cmwSave(MagWindow *w, TxCommand *cmd);
extern void cmwLoad(MagWindow *w, TxCommand *cmd);
extern void cmwPushbutton(MagWindow *w, TxCommand *cmd);
extern bool RGBxHSV(double r, double g, double b, double *h, double *s, double *v);
extern void CMWundoInit(void);
/* -------------------------------------------------------------------- */
@ -89,47 +89,47 @@ extern void CMWundoInit();
* which pump is hit and which mouse button is used to hit it.
*/
ColorBar colorBars[] =
const ColorBar colorBars[] =
{
"Red", CB_RED, STYLE_RED, {2000, 8000, 10000, 9000},
{2000, 9500, 10000, 10500},
"Green", CB_GREEN, STYLE_GREEN, {2000, 5000, 10000, 6000},
{2000, 6500, 10000, 7500},
"Blue", CB_BLUE, STYLE_BLUE, {2000, 2000, 10000, 3000},
{2000, 3500, 10000, 4500},
"Hue", CB_HUE, STYLE_YELLOW, {14000, 8000, 22000, 9000},
{14000, 9500, 22000, 10500},
"Saturation", CB_SAT, STYLE_GRAY, {14000, 5000, 22000, 6000},
{14000, 6500, 22000, 7500},
"Value", CB_VALUE, STYLE_BROWN1, {14000, 2000, 22000, 3000},
{14000, 3500, 22000, 4500},
0
{"Red", CB_RED, STYLE_RED, {{ 2000, 8000}, {10000, 9000}},
{{ 2000, 9500}, {10000, 10500}}},
{"Green", CB_GREEN, STYLE_GREEN, {{ 2000, 5000}, {10000, 6000}},
{{ 2000, 6500}, {10000, 7500}}},
{"Blue", CB_BLUE, STYLE_BLUE, {{ 2000, 2000}, {10000, 3000}},
{{ 2000, 3500}, {10000, 4500}}},
{"Hue", CB_HUE, STYLE_YELLOW, {{14000, 8000}, {22000, 9000}},
{{14000, 9500}, {22000, 10500}}},
{"Saturation", CB_SAT, STYLE_GRAY, {{14000, 5000}, {22000, 6000}},
{{14000, 6500}, {22000, 7500}}},
{"Value", CB_VALUE, STYLE_BROWN1, {{14000, 2000}, {22000, 3000}},
{{14000, 3500}, {22000, 4500}}},
{0}
};
ColorPump colorPumps[] =
const ColorPump colorPumps[] =
{
CB_RED, -.0078, {500, 8000, 1500, 9000},
CB_RED, .0078, {10500, 8000, 11500, 9000},
CB_GREEN, -.0078, {500, 5000, 1500, 6000},
CB_GREEN, .0078, {10500, 5000, 11500, 6000},
CB_BLUE, -.0078, {500, 2000, 1500, 3000},
CB_BLUE, .0078, {10500, 2000, 11500, 3000},
CB_HUE, -.01, {12500, 8000, 13500, 9000},
CB_HUE, .01, {22500, 8000, 23500, 9000},
CB_SAT, -.01, {12500, 5000, 13500, 6000},
CB_SAT, .01, {22500, 5000, 23500, 6000},
CB_VALUE, -.01, {12500, 2000, 13500, 3000},
CB_VALUE, .01, {22500, 2000, 23500, 3000},
-1
{CB_RED, -.0078, {{ 500, 8000}, { 1500, 9000}}},
{CB_RED, .0078, {{10500, 8000}, {11500, 9000}}},
{CB_GREEN, -.0078, {{ 500, 5000}, { 1500, 6000}}},
{CB_GREEN, .0078, {{10500, 5000}, {11500, 6000}}},
{CB_BLUE, -.0078, {{ 500, 2000}, { 1500, 3000}}},
{CB_BLUE, .0078, {{10500, 2000}, {11500, 3000}}},
{CB_HUE, -.01, {{12500, 8000}, {13500, 9000}}},
{CB_HUE, .01, {{22500, 8000}, {23500, 9000}}},
{CB_SAT, -.01, {{12500, 5000}, {13500, 6000}}},
{CB_SAT, .01, {{22500, 5000}, {23500, 6000}}},
{CB_VALUE, -.01, {{12500, 2000}, {13500, 3000}}},
{CB_VALUE, .01, {{22500, 2000}, {23500, 3000}}},
{-1}
};
Rect cmwCurrentColorArea = {{6000, 12000}, {18000, 15000}};
Rect cmwCurrentColorTextBox = {{6000, 15500}, {18000, 16500}};
char *cmwCurrentColorText = "Color Being Edited";
const Rect cmwCurrentColorArea = {{6000, 12000}, {18000, 15000}};
const Rect cmwCurrentColorTextBox = {{6000, 15500}, {18000, 16500}};
const char * const cmwCurrentColorText = "Color Being Edited";
/* Bounding rectangle for entire window */
Rect colorWindowRect = {{0, 1500}, {24000, 17000}};
const Rect colorWindowRect = {{0, 1500}, {24000, 17000}};
/*
* ----------------------------------------------------------------------------
@ -149,13 +149,13 @@ Rect colorWindowRect = {{0, 1500}, {24000, 17000}};
*/
bool
CMWcreate(window, argc, argv)
MagWindow *window;
int argc;
char *argv[];
CMWcreate(
MagWindow *window,
int argc,
char *argv[])
{
CMWclientRec *crec;
int color;
unsigned int color;
crec = (CMWclientRec *) mallocMagic(sizeof(CMWclientRec));
window->w_clientData = (ClientData) crec;
@ -189,8 +189,8 @@ CMWcreate(window, argc, argv)
*/
bool
CMWdelete(window)
MagWindow *window;
CMWdelete(
MagWindow *window)
{
CMWclientRec *cr;
@ -218,10 +218,10 @@ CMWdelete(window)
*/
void
CMWreposition(window, newScreenArea, final)
MagWindow *window;
Rect *newScreenArea;
bool final;
CMWreposition(
MagWindow *window,
Rect *newScreenArea,
bool final)
{
if (final)
WindMove(window, &colorWindowRect);
@ -244,14 +244,14 @@ CMWreposition(window, newScreenArea, final)
*/
void
CMWredisplay(w, rootArea, clipArea)
MagWindow *w; /* The window containing the area. */
Rect *rootArea; /* Redisplay area in surface coordinates. */
Rect *clipArea; /* An area on the screen to clip to. */
CMWredisplay(
MagWindow *w, /* The window containing the area. */
Rect *rootArea, /* Redisplay area in surface coordinates. */
Rect *clipArea) /* An area on the screen to clip to. */
{
CMWclientRec *cr;
ColorBar *cb;
ColorPump *cp;
const ColorBar *cb;
const ColorPump *cp;
Rect rect, screenR;
Point screenP;
double values[6], x;
@ -372,9 +372,9 @@ CMWredisplay(w, rootArea, clipArea)
*/
void
CMWloadWindow(w, color)
MagWindow *w; /* Identifies window to which color is to be bound */
int color; /* New color to be bound to this window. */
CMWloadWindow(
MagWindow *w, /* Identifies window to which color is to be bound */
int color) /* New color to be bound to this window. */
{
CMWclientRec *cr = (CMWclientRec *) w->w_clientData;
char caption[40];
@ -407,7 +407,7 @@ CMWloadWindow(w, color)
*/
void
CMWinit()
CMWinit(void)
{
CMWclientID = WindAddClient("color", CMWcreate, CMWdelete,
CMWredisplay, CMWcommand,

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWrgbhsv.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWrgbhsv.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -45,9 +45,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
bool
RGBxHSV( r, g, b, h, s, v)
double r, g, b;
double *h, *s, *v;
RGBxHSV(
double r,
double g,
double b,
double *h,
double *s,
double *v)
{
double max, delta;
double mr,mg,mb;
@ -90,10 +94,14 @@ RGBxHSV( r, g, b, h, s, v)
#define SETRGB(rr,gg,bb) *r=rr;*g=gg;*b=bb
void
HSVxRGB( h,s,v,r,g,b)
double h,s,v;
double *r,*g,*b;
{
HSVxRGB(
double h,
double s,
double v,
double *r,
double *g,
double *b)
{
double f,m,n,k;
int i;
double vs,vsf;
@ -125,9 +133,13 @@ double *r,*g,*b;
*/
bool
RGBxHSL( r, g, b, h, s, l )
double r, g, b;
double *h, *s, *l;
RGBxHSL(
double r,
double g,
double b,
double *h,
double *s,
double *l)
{
double min, max;
double delta, mr, mg, mb;
@ -184,9 +196,13 @@ RGBxHSL( r, g, b, h, s, l )
*/
void
HSLxRGB( h, s, l, r, g, b )
double h, s, l;
double *r, *g, *b;
HSLxRGB(
double h,
double s,
double l,
double *r,
double *g,
double *b)
{
double min;
double v;
@ -235,9 +251,11 @@ HSLxRGB( h, s, l, r, g, b )
*/
void
Correct_chromaticity(x, y, wx, wy)
double *x,*y;
double wx,wy;
Correct_chromaticity(
double *x,
double *y,
double wx,
double wy)
{
double oldx,oldy;
double slope;
@ -261,9 +279,13 @@ Correct_chromaticity(x, y, wx, wy)
*/
void
xyz_to_mrgb(x, y, z, mr, mg, mb)
double x, y, z;
double *mr, *mg, *mb;
xyz_to_mrgb(
double x,
double y,
double z,
double *mr,
double *mg,
double *mb)
{
*mr = 2.4513*x - 1.2249*y - 0.3237*z;
*mg = -1.4746*x + 2.5052*y + 0.0596*z;
@ -281,8 +303,10 @@ xyz_to_mrgb(x, y, z, mr, mg, mb)
*/
void
Make_mRGB_Nice(mR,mG,mB)
double *mR,*mG,*mB;
Make_mRGB_Nice(
double *mR,
double *mG,
double *mB)
{
double min,max;
double mr, mg, mb;

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWundo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cmwind/CMWundo.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -35,12 +35,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
UndoType cmwUndoClientID;
/*
* Functions to play events forward/backward.
*/
void cmwUndoForw(), cmwUndoBack();
void cmwUndoStart(), cmwUndoDone();
/*
* A single undo event for the
* color map module.
@ -58,6 +52,14 @@ void cmwUndoStart(), cmwUndoDone();
*/
bool cmwColorsChanged[256];
/*
* Functions to play events forward/backward.
*/
void cmwUndoForw(colorUE *up);
void cmwUndoBack(colorUE *up);
void cmwUndoStart(void);
void cmwUndoDone(void);
/*
* ----------------------------------------------------------------------------
*
@ -77,7 +79,7 @@ bool cmwColorsChanged[256];
*/
void
CMWundoInit()
CMWundoInit(void)
{
cmwUndoClientID = UndoAddClient(cmwUndoStart, cmwUndoDone, NULL, NULL,
cmwUndoForw, cmwUndoBack, "color map");
@ -102,16 +104,16 @@ CMWundoInit()
*/
void
cmwUndoForw(up)
colorUE *up;
cmwUndoForw(
colorUE *up)
{
(void) GrPutColor(up->cue_color, up->new_r, up->new_g, up->new_b);
cmwColorsChanged[up->cue_color] = TRUE;
}
void
cmwUndoBack(up)
colorUE *up;
cmwUndoBack(
colorUE *up)
{
(void) GrPutColor(up->cue_color, up->old_r, up->old_g, up->old_b);
cmwColorsChanged[up->cue_color] = TRUE;
@ -134,10 +136,14 @@ cmwUndoBack(up)
*/
void
cmwUndoColor(color, oldr, oldg, oldb, newr, newg, newb)
int color;
int oldr, oldg, oldb;
int newr, newg, newb;
cmwUndoColor(
int color,
int oldr,
int oldg,
int oldb,
int newr,
int newg,
int newb)
{
colorUE *up;
@ -171,7 +177,7 @@ cmwUndoColor(color, oldr, oldg, oldb, newr, newg, newb)
*/
void
cmwUndoStart()
cmwUndoStart(void)
{
int i;
@ -198,13 +204,13 @@ cmwUndoStart()
*/
void
cmwUndoDone()
cmwUndoDone(void)
{
int i;
extern int cmwRedisplayFunc();
extern int cmwRedisplayFunc(MagWindow *w, int color);
for (i = 0; i < 256; i++)
if (cmwColorsChanged[i])
(void) WindSearch(CMWclientID, (ClientData) NULL, (Rect *) NULL,
cmwRedisplayFunc, (ClientData) i);
cmwRedisplayFunc, INT2CD(i));
}

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"
@ -69,16 +69,16 @@ typedef struct
extern void CMWloadWindow(MagWindow *, int);
extern void CMWcommand(MagWindow *, TxCommand *);
extern Rect colorWindowRect;
extern const Rect colorWindowRect;
extern WindClient CMWclientID;
extern ColorBar colorBars[];
extern ColorPump colorPumps[];
extern Rect cmwCurrentColorArea;
extern const ColorBar colorBars[];
extern const ColorPump colorPumps[];
extern const Rect cmwCurrentColorArea;
extern void cmwUndoColor(int, int, int, int, int, int, int);
extern bool CMWCheckWritten(void);
/* C99 compat */
extern void CMWinit();
extern void CMWinit(void);
#endif /* _CMWIND_H */
#endif /* _MAGIC__CMWIND__CMWIND_H */

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdAB.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdAB.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -50,7 +50,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* CmdAddPath --
*
* Implement the "addpath" command: append to the global cell search path.
* (Usage superceded by extended "path" command; retained for compatibility)
* (Usage superseded by extended "path" command; retained for compatibility)
*
* Usage:
* addpath path
@ -70,9 +70,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/*ARGSUSED*/
void
CmdAddPath( w, cmd )
MagWindow *w;
TxCommand *cmd;
CmdAddPath(
MagWindow *w,
TxCommand *cmd)
{
if (cmd->tx_argc != 2) {
TxError("Usage: %s appended_search_path\n", cmd->tx_argv[0]);
@ -81,6 +81,70 @@ CmdAddPath( w, cmd )
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 */
@ -130,11 +194,11 @@ typedef struct LA1
#define ARRAY_DEFAULT 6
void
CmdArray(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdArray(
MagWindow *w,
TxCommand *cmd)
{
static char *cmdArrayOption[] = {
static const char * const cmdArrayOption[] = {
"count [[xlo] xhi [ylo] yhi] array subcells",
"width [value] set or return array x-spacing",
"height [value] set or return array y-spacing",
@ -144,7 +208,7 @@ CmdArray(w, cmd)
NULL
};
char **msg;
const char * const *msg;
int option, locargc, argstart;
bool doList = FALSE;
ArrayInfo a;
@ -156,7 +220,7 @@ CmdArray(w, cmd)
Tcl_Obj *tobj;
#endif
extern int selGetArrayFunc();
extern int selGetArrayFunc(CellUse *selUse, CellUse *use, Transform *trans, LinkedArray **arg);
locargc = cmd->tx_argc;
argstart = 1;
@ -466,11 +530,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;
}
@ -480,11 +548,11 @@ freelist:
*/
int
selGetArrayFunc(selUse, use, trans, arg)
CellUse *selUse;
CellUse *use;
Transform *trans;
LinkedArray **arg;
selGetArrayFunc(
CellUse *selUse,
CellUse *use,
Transform *trans,
LinkedArray **arg)
{
/* Check "use" for array information and pass this to arrayInfo */
@ -593,11 +661,11 @@ selGetArrayFunc(selUse, use, trans, arg)
#define BOX_DEFAULT 13
void
CmdBox(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdBox(
MagWindow *w,
TxCommand *cmd)
{
static char *cmdBoxOption[] = {
static const char * const cmdBoxOption[] = {
"width [value] set or return box width",
"height [value] set or return box height",
"size [width height] set or return box size",
@ -626,7 +694,7 @@ CmdBox(w, cmd)
bool needBox = TRUE; /* require that box be defined */
bool refEdit = FALSE; /* referenced to edit cell coordinates */
bool cursorRef = FALSE; /* reference position is the cursor */
char **msg;
const char * const *msg;
argc = cmd->tx_argc;
if (argc > 7) goto badusage;
@ -797,6 +865,13 @@ CmdBox(w, cmd)
ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
break;
}
/* Recast command as "box values" for logging purposes */
ToolGetBox(&rootBoxDef, &rootBox);
sprintf(cmd->tx_argstring, "box values %di %di %di %di",
rootBox.r_xbot, rootBox.r_ybot,
rootBox.r_xtop, rootBox.r_ytop);
TxRebuildCommand(cmd);
return;
}
else if (DBWSnapToGrid != DBW_SNAP_USER)
@ -1148,7 +1223,7 @@ CmdBox(w, cmd)
boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
if (area > 0)
TxPrintf(" %-10lld", area);
TxPrintf(" %-10"DLONG_PREFIX"d", area);
TxPrintf("\n");
break;

View File

@ -48,9 +48,9 @@
*/
void
CmdAutoExtToSim(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdAutoExtToSim(
MagWindow *w,
TxCommand *cmd)
{
int result;
@ -83,9 +83,9 @@ CmdAutoExtToSim(w, cmd)
*/
void
CmdAutoExtToSpice(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdAutoExtToSpice(
MagWindow *w,
TxCommand *cmd)
{
int result;
@ -119,9 +119,9 @@ CmdAutoExtToSpice(w, cmd)
*/
void
CmdAutoRoute(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdAutoRoute(
MagWindow *w,
TxCommand *cmd)
{
int result;
@ -154,9 +154,9 @@ CmdAutoRoute(w, cmd)
*/
void
CmdAutoPlot(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdAutoPlot(
MagWindow *w,
TxCommand *cmd)
{
int result;
@ -189,9 +189,9 @@ CmdAutoPlot(w, cmd)
*/
void
CmdAutoLef(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdAutoLef(
MagWindow *w,
TxCommand *cmd)
{
int result;

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdE.c,v 1.4 2010/06/17 14:38:33 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdE.c,v 1.4 2010/06/17 14:38:33 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -42,6 +42,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "drc/drc.h"
#include "textio/txcommands.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "select/select.h"
/* C99 compat */
@ -55,10 +56,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*
* Implement the "edit" command.
* Use the cell that is currently selected as the edit cell. If more than
* one cell is selected, use the point to choose between them.
* one cell is selected, use the point to choose between them. If the
* optional argument "<instname>" is provided, then edit the specified
* instance (if it exists in the current layout window).
*
* Usage:
* edit
* edit [<instname>]
*
* Results:
* None.
@ -76,18 +79,29 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
static bool cmdFoundNewEdit;
void
CmdEdit(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdEdit(
MagWindow *w,
TxCommand *cmd)
{
Rect area, pointArea;
CellUse *usave;
CellUse *usave, *use = NULL;
CellDef *csave;
int cmdEditRedisplayFunc(); /* Forward declaration. */
int cmdEditEnumFunc(); /* Forward declaration. */
int cmdEditRedisplayFunc(MagWindow *w, Rect *area); /* Forward declaration. */
int cmdEditEnumFunc(CellUse *selUse, CellUse *use, Transform *transform, Rect *area); /* Forward declaration. */
bool noCurrentUse = FALSE;
if (cmd->tx_argc > 1)
if ((w != NULL) && (cmd->tx_argc == 2))
{
CellUse *rootUse;
SearchContext scx;
rootUse = (CellUse *)w->w_surfaceID;
bzero(&scx, sizeof(SearchContext));
DBTreeFindUse(cmd->tx_argv[1], rootUse, &scx);
use = scx.scx_use;
}
if ((use == NULL) && (cmd->tx_argc > 1))
{
TxError("Usage: edit\nMaybe you want the \"load\" command\n");
return;
@ -120,10 +134,18 @@ CmdEdit(w, cmd)
cmdFoundNewEdit = FALSE;
csave = EditRootDef;
usave = EditCellUse;
EditCellUse = NULL;
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
cmdEditEnumFunc, (ClientData) &pointArea);
if (use == NULL)
{
EditCellUse = NULL;
SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
cmdEditEnumFunc, (ClientData) &pointArea);
}
else
{
EditCellUse = use;
cmdFoundNewEdit = TRUE;
}
if (EditCellUse == (CellUse *)NULL)
{
@ -133,11 +155,7 @@ CmdEdit(w, cmd)
return;
}
else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE))
{
bool dereference = (EditCellUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, dereference, NULL);
}
DBCellRead(EditCellUse->cu_def, TRUE, TRUE, NULL);
if (EditCellUse->cu_def->cd_flags & CDNOEDIT)
{
@ -161,6 +179,14 @@ CmdEdit(w, cmd)
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
(void) WindSearch(DBWclientID, (ClientData) NULL,
(Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area);
if ((cmd->tx_argc == 1) && cmdFoundNewEdit)
{
/* Recast the command with the instance name for logging */
sprintf(cmd->tx_argstring, "edit %s", EditCellUse->cu_id);
TxRebuildCommand(cmd);
}
}
/* Search function to handle redisplays for CmdEdit: it checks to
@ -171,11 +197,11 @@ CmdEdit(w, cmd)
*/
int
cmdEditRedisplayFunc(w, area)
MagWindow *w; /* Window containing edit cell. */
Rect *area; /* Area to be redisplayed. */
cmdEditRedisplayFunc(
MagWindow *w, /* Window containing edit cell. */
Rect *area) /* Area to be redisplayed. */
{
static Rect origin = {-1, -1, 1, 1};
static const Rect origin = {{-1, -1}, {1, 1}};
Rect tmp;
DBWclientRec *crec = (DBWclientRec *) w->w_clientData;
@ -200,13 +226,13 @@ cmdEditRedisplayFunc(w, area)
*/
int
cmdEditEnumFunc(selUse, use, transform, area)
CellUse *selUse; /* Use from selection (not used). */
CellUse *use; /* Use from layout that corresponds to
cmdEditEnumFunc(
CellUse *selUse, /* Use from selection (not used). */
CellUse *use, /* Use from layout that corresponds to
* selUse (could be an array!).
*/
Transform *transform; /* Transform from use->cu_def to root coords. */
Rect *area; /* We're looking for a use containing this
Transform *transform, /* Transform from use->cu_def to root coords. */
Rect *area) /* We're looking for a use containing this
* area, in root coords.
*/
{
@ -279,20 +305,20 @@ cmdEditEnumFunc(selUse, use, transform, area)
#define OPTION_FLAGS 3
void
CmdElement(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdElement(
MagWindow *w,
TxCommand *cmd)
{
int option, type;
char **msg;
const char * const *msg;
Rect area;
int style;
CellDef *def;
CellUse *use;
bool getopt;
static char *cmdElementOption[] = {
static const char * const cmdElementOption[] = {
"add create a new element",
"delete delete an existing element",
"configure configure or query an existing element",
@ -302,14 +328,14 @@ CmdElement(w, cmd)
NULL
};
static char *cmdElementType[] = {
static const char * const cmdElementType[] = {
"line name style x1 y1 x2 y2",
"rectangle name style llx lly urx ury",
"text name style cx cy label",
NULL
};
static char *cmdConfigureType[] = {
static const char * const cmdConfigureType[] = {
"text get (or) replace <string>",
"style get (or) add <style> (or) remove <style>",
"position get (or) <point> (or) <rect>",
@ -580,7 +606,7 @@ badusage:
* EditCellUse->cu_def.
*
* Usage:
* erase [layers | cursor]
* erase [layers | cursor | pick x y]
*
* Results:
* None.
@ -601,25 +627,34 @@ static CellUse *cmdEraseCells[MAXCELLS];
static int cmdEraseCount;
void
CmdErase(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdErase(
MagWindow *w,
TxCommand *cmd)
{
Rect editRect, areaReturn;
TileTypeBitMask mask, errorLayersForErasure, activeLayersForErasure;
extern int cmdEraseCellsFunc();
extern int cmdEraseCellsFunc(SearchContext *scx, ClientData cdarg);
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL) return;
if ((cmd->tx_argc == 4) && !strcmp(cmd->tx_argv[1], "pick"))
{
Point editPoint, rootPoint;
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint);
CmdPaintEraseButton(w, &rootPoint, FALSE, FALSE);
return;
}
if (cmd->tx_argc > 2)
{
TxError("Usage: %s [<layers> | cursor]\n", cmd->tx_argv[0]);
TxError("Usage: %s [<layers> | cursor | pick x y]\n", cmd->tx_argv[0]);
return;
}
if (!ToolGetEditBox(&editRect)) return;
if (EditCellUse == NULL)
{
TxError("No cell def being edited!\n");
@ -636,7 +671,16 @@ CmdErase(w, cmd)
(void) CmdParseLayers("*,label", &mask);
else if (!strncmp(cmd->tx_argv[1], "cursor", 6))
{
CmdPaintEraseButton(w, &cmd->tx_p, FALSE);
Point editPoint, rootPoint;
CmdPaintEraseButton(w, &cmd->tx_p, FALSE, TRUE);
/* Recast the command as "erase pick x y" for logging purposes */
CmdGetRootPoint(&rootPoint, (Rect *)NULL);
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
sprintf(cmd->tx_argstring, "erase pick %di %di", editPoint.p_x,
editPoint.p_y);
TxRebuildCommand(cmd);
return;
}
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
@ -715,9 +759,9 @@ CmdErase(w, cmd)
}
int
cmdEraseCellsFunc(scx, cdarg)
SearchContext *scx; /* Indicates cell found. */
ClientData cdarg; /* Not used. */
cmdEraseCellsFunc(
SearchContext *scx, /* Indicates cell found. */
ClientData cdarg) /* Not used. */
{
/* All this procedure does is to remember cells that are
* found, up to MAXCELLS of them.
@ -753,15 +797,15 @@ ClientData cdarg; /* Not used. */
*/
void
CmdExpand(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdExpand(
MagWindow *w,
TxCommand *cmd)
{
int windowMask, boxMask, d;
Rect rootRect;
CellUse *rootBoxUse;
CellDef *rootBoxDef;
int cmdExpandFunc(); /* Forward reference. */
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
&& (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
@ -825,9 +869,9 @@ CmdExpand(w, cmd)
*/
int
cmdExpandFunc(use, windowMask)
CellUse *use; /* Use that was just expanded. */
int windowMask; /* Window where it was expanded. */
cmdExpandFunc(
CellUse *use, /* Use that was just expanded. */
int windowMask) /* Window where it was expanded. */
{
if (use->cu_parent == NULL) return 0;
DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask,
@ -860,14 +904,17 @@ cmdExpandFunc(use, windowMask)
#define EXTALL 0
#define EXTCELL 1
#define EXTDO 2
#define EXTHELP 3
#define EXTLENGTH 4
#define EXTNO 5
#define EXTPARENTS 6
#define EXTSHOWPARENTS 7
#define EXTSTYLE 8
#define EXTUNIQUE 9
#define EXTWARN 10
#define EXTHALO 3
#define EXTHELP 4
#define EXTLENGTH 5
#define EXTNO 6
#define EXTPARENTS 7
#define EXTPATH 8
#define EXTSHOWPARENTS 9
#define EXTSTEPSIZE 10
#define EXTSTYLE 11
#define EXTUNIQUE 12
#define EXTWARN 13
#define WARNALL 0
#define WARNDUP 1
@ -894,12 +941,14 @@ cmdExpandFunc(use, windowMask)
#define UNIQNOTOPPORTS 3
void
CmdExtract(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdExtract(
MagWindow *w,
TxCommand *cmd)
{
char **msg, *namep, *arg;
const char * const *msg;
char *namep, *arg;
int option, warn, len, n, all;
int dist;
bool no;
CellUse *selectedUse;
CellDef *selectedDef;
@ -909,7 +958,7 @@ CmdExtract(w, cmd)
int argc = cmd->tx_argc;
char **argv = cmd->tx_argv;
static char *cmdExtWarn[] =
static const char * const cmdExtWarn[] =
{
"all enable all warnings",
"dup warn when different nodes have the same name",
@ -917,7 +966,7 @@ CmdExtract(w, cmd)
"labels warn when subcell nodes are unlabelled",
NULL
};
static char *cmdExtOption[] =
static const char * const cmdExtOption[] =
{
"adjust compensate R and C hierarchically",
"all all options",
@ -930,7 +979,7 @@ CmdExtract(w, cmd)
"aliases output all net name aliases",
NULL
};
static char *cmdExtLength[] =
static const char * const cmdExtLength[] =
{
"clear clear the driver and receiver tables",
"driver termName(s) identify a driving (output) terminal",
@ -940,7 +989,7 @@ CmdExtract(w, cmd)
/* These must match definitions EXT_UNIQ_* in extract/extract.h: */
static char *cmdExtUniq[] =
static const char * const cmdExtUniq[] =
{
"all extract matching labels as unique nodes",
"# extract tagged labels as unique nodes",
@ -948,16 +997,19 @@ CmdExtract(w, cmd)
"notopports ignore top-level ports when making labels unique",
NULL
};
static char *cmdExtCmd[] =
static const char * const cmdExtCmd[] =
{
"all extract root cell and all its children",
"cell name extract selected cell into file \"name\"",
"do [option] enable extractor option",
"halo [value] print or set the sidewall halo distance",
"help print this help information",
"length [option] control pathlength extraction information",
"no [option] disable extractor option",
"parents extract selected cell and all its parents",
"path [path] if set, extract into the indicated path",
"showparents show all parents of selected cell",
"stepsize [value] print or set the extraction step size",
"style [stylename] set current extraction parameter style",
"unique [option] generate unique names when different nodes\n\
have the same name",
@ -1060,6 +1112,66 @@ CmdExtract(w, cmd)
ExtractOneCell(selectedUse->cu_def, namep, FALSE);
return;
case EXTHALO:
if (ExtCurStyle == NULL)
{
TxError("No extraction style set.\n");
return;
}
else if (argc == 2)
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
#endif
return;
}
else if (argc != 3) goto wrongNumArgs;
/* argv[2] is a halo distance */
dist = cmdParseCoord(w, argv[2], TRUE, TRUE);
if (dist < 0)
{
TxError("Bad halo distance. Halo must be non-negative.");
return;
}
else
ExtCurStyle->exts_sideCoupleHalo = dist;
break;
case EXTSTEPSIZE:
if (ExtCurStyle == NULL)
{
TxError("No extraction style set.\n");
return;
}
else if (argc == 2)
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *tobj;
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
Tcl_SetObjResult(magicinterp, tobj);
#else
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
#endif
return;
}
else if (argc != 3) goto wrongNumArgs;
/* argv[2] is a step size */
dist = cmdParseCoord(w, argv[2], TRUE, TRUE);
if (dist <= 0)
{
TxError("Bad step size. Step size must be strictly positive.");
return;
}
else
ExtCurStyle->exts_stepSize = dist;
break;
case EXTPARENTS:
selectedUse = CmdGetSelectedCell((Transform *) NULL);
if (selectedUse == NULL)
@ -1083,6 +1195,13 @@ CmdExtract(w, cmd)
ExtShowParents(selectedUse);
return;
case EXTPATH:
if (argc == 2)
ExtPrintPath(dolist);
else
ExtSetPath(argv[2]);
return;
case EXTSTYLE:
if (argc == 2)
ExtPrintStyle(dolist, doforall, !doforall);
@ -1158,7 +1277,6 @@ CmdExtract(w, cmd)
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
TxPrintf("%s local\n", OPTSET(EXT_DOLOCAL));
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
@ -1188,10 +1306,19 @@ CmdExtract(w, cmd)
case DOCAPACITANCE: option = EXT_DOCAPACITANCE; break;
case DOCOUPLING: option = EXT_DOCOUPLING; break;
case DOLENGTH: option = EXT_DOLENGTH; break;
case DOLOCAL: option = EXT_DOLOCAL; break;
case DORESISTANCE: option = EXT_DORESISTANCE; break;
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
case DOALIASES: option = EXT_DOALIASES; break;
case DOLOCAL:
/* "extract do local" and "extract no local" are kept for
* backwards compatibility, but now effectively implement
* "extract path ." and "extract path none", respectively.
*/
if (no)
StrDup(&ExtLocalPath, NULL);
else
StrDup(&ExtLocalPath, ".");
return;
}
if (no) ExtOptions &= ~option;
else ExtOptions |= option;

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdFI.c,v 1.4 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdFI.c,v 1.4 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -100,17 +100,19 @@ struct cmdFPArg
*/
int
feedPolyFunc(tile, arg)
Tile *tile;
struct cmdFPArg *arg;
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;
}
@ -146,11 +148,11 @@ feedPolyFunc(tile, arg)
#define WHY 6
void
CmdFeedback(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdFeedback(
MagWindow *w,
TxCommand *cmd)
{
static char *cmdFeedbackOptions[] =
static const char * const cmdFeedbackOptions[] =
{
"add text [style] [points...] create new feedback area over box",
"clear [substring] clear all or selected feedback info",
@ -161,11 +163,11 @@ CmdFeedback(w, cmd)
"why print all feedback messages under box",
NULL
};
static char *cmdFeedbackStyleNames[] =
static const char * const cmdFeedbackStyleNames[] =
{
"dotted", "medium", "outline", "pale", "solid", NULL
};
static int cmdFeedbackStyles[] =
static const int cmdFeedbackStyles[] =
{
STYLE_DOTTEDHIGHLIGHTS, STYLE_MEDIUMHIGHLIGHTS,
STYLE_OUTLINEHIGHLIGHTS, STYLE_PALEHIGHLIGHTS,
@ -176,7 +178,8 @@ CmdFeedback(w, cmd)
*/
int option, i, style, pstart;
Rect box, r;
char *text, **msg;
char *text;
const char * const *msg;
CellDef *rootDef;
HashTable table;
HashEntry *h;
@ -505,14 +508,16 @@ Rect cmdFillRootBox; /* Root coords of box. */
struct cmdFillArea *cmdFillList; /* List of areas to fill. */
void
CmdFill(w, cmd)
MagWindow *w; /* Window in which command was invoked. */
TxCommand *cmd; /* Describes the command that was invoked. */
CmdFill(
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();
/* Forward declaration */
extern int cmdFillFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
{
@ -580,13 +585,15 @@ CmdFill(w, cmd)
/* 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);
@ -600,12 +607,17 @@ CmdFill(w, cmd)
* 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, cxp)
Tile *tile; /* Tile to fill with. */
TreeContext *cxp; /* Describes state of search. */
cmdFillFunc(
Tile *tile, /* Tile to fill with. */
TileType dinfo, /* Split tile information (unused) */
TreeContext *cxp) /* Describes state of search. */
{
Rect r1, r2;
struct cmdFillArea *cfa;
@ -658,9 +670,9 @@ cmdFillFunc(tile, cxp)
*/
void
CmdFindBox(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdFindBox(
MagWindow *w,
TxCommand *cmd)
{
CellDef *boxDef;
Rect box;
@ -751,11 +763,12 @@ typedef struct _labsearchrec
} LabSearchRec;
int cmdFindLabelFunc(rect, name, label, cdarg)
Rect *rect;
char *name;
Label *label;
LabSearchRec *cdarg;
int
cmdFindLabelFunc(
Rect *rect,
char *name,
Label *label,
LabSearchRec *cdarg)
{
if (cdarg->lsr_occur == 0)
{
@ -790,9 +803,9 @@ int cmdFindLabelFunc(rect, name, label, cdarg)
*/
void
CmdFindLabel(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdFindLabel(
MagWindow *w,
TxCommand *cmd)
{
CellDef *boxDef;
CellUse *labUse;
@ -801,7 +814,7 @@ CmdFindLabel(w, cmd)
int found, occur, plainargs;
bool doglob = FALSE; /* csh-style glob matching (see utils/match.c) */
LabSearchRec lsr;
int dbListLabels(); /* forward declaration */
int dbListLabels(SearchContext *scx, Label *label, TerminalPath *tpath, ClientData cdarg); /* forward declaration */
plainargs = cmd->tx_argc;
if ((plainargs > 2) && !strncmp(cmd->tx_argv[1], "-glob", 5))
@ -839,7 +852,7 @@ CmdFindLabel(w, cmd)
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;
@ -889,11 +902,11 @@ usage:
*/
int
dbListLabels(scx, label, tpath, cdarg)
SearchContext *scx;
Label *label; /* Pointer to label structure */
TerminalPath *tpath; /* Full pathname of terminal */
ClientData cdarg; /* (unused) */
dbListLabels(
SearchContext *scx,
Label *label, /* Pointer to label structure */
TerminalPath *tpath, /* Full pathname of terminal */
ClientData cdarg) /* (unused) */
{
char *n = tpath->tp_next;
char c = *n;
@ -934,15 +947,16 @@ dbListLabels(scx, label, tpath, cdarg)
*/
void
CmdFlush(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdFlush(
MagWindow *w,
TxCommand *cmd)
{
CellDef *def;
int action;
static char *actionNames[] = { "no", "yes", 0 };
static const char * const actionNames[] = { "no", "yes", 0 };
char *prompt;
bool dereference = FALSE;
bool noprompt = FALSE; /* no interactive confirm when changed */
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "-deref", 6))
{
@ -950,9 +964,15 @@ CmdFlush(w, cmd)
cmd->tx_argc--;
}
if (!strcmp(cmd->tx_argv[cmd->tx_argc - 1], "-noprompt"))
{
noprompt = TRUE;
cmd->tx_argc--;
}
if (cmd->tx_argc > 2)
{
TxError("Usage: flush [cellname] [dereference]\n");
TxError("Usage: flush [cellname] [-noprompt] [-dereference]\n");
return;
}
@ -973,7 +993,9 @@ CmdFlush(w, cmd)
}
}
if (def->cd_flags & (CDMODIFIED|CDSTAMPSCHANGED|CDBOXESCHANGED))
bool has_changes = (def->cd_flags & (CDMODIFIED|CDSTAMPSCHANGED|CDBOXESCHANGED)) != 0;
if (!noprompt && has_changes)
{
prompt = TxPrintString("Really throw away all changes made"
" to cell %s? ", def->cd_name);
@ -984,7 +1006,7 @@ CmdFlush(w, cmd)
cmdFlushCell(def, dereference);
SelectClear();
TxPrintf("[Flushed]\n");
TxPrintf("[Flushed%s]\n", has_changes ? " Modifications were Discarded" : "");
}
@ -1015,9 +1037,9 @@ CmdFlush(w, cmd)
*/
void
CmdGetcell(w, cmd)
MagWindow *w; /* Window in which command was invoked. */
TxCommand *cmd; /* Describes command arguments. */
CmdGetcell(
MagWindow *w, /* Window in which command was invoked. */
TxCommand *cmd) /* Describes command arguments. */
{
CellUse dummy, *newUse;
Transform editTrans;
@ -1100,9 +1122,9 @@ CmdGetcell(w, cmd)
*/
void
CmdGetnode(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdGetnode(
MagWindow *w,
TxCommand *cmd)
{
#define TBLSIZE 50
#define STRINGS 0
@ -1197,7 +1219,7 @@ CmdGetnode(w, cmd)
TxError("Put the cursor in a layout window\n");
return;
}
if( is_fast == TRUE )
if (is_fast == TRUE)
{
SimRecomputeSel = TRUE;
SimGetsnode();
@ -1205,7 +1227,8 @@ CmdGetnode(w, cmd)
else
SimGetnode();
if (SimGetnodeAlias) { /* "erase" the hash table */
if (SimGetnodeAlias) /* "erase" the hash table */
{
HashKill(&SimGNAliasTbl);
HashInit(&SimGNAliasTbl, 120, STRINGS);
}
@ -1251,15 +1274,15 @@ badusage:
#define GRID_WHAT 7
void
CmdGrid(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdGrid(
MagWindow *w,
TxCommand *cmd)
{
int option, locargc;
int xSpacing, ySpacing, xOrig, yOrig, multiple;
DBWclientRec *crec;
char *boxvalues;
static char *cmdGridOptions[] =
static const char * const cmdGridOptions[] =
{
"box [values] report the box representing the user grid",
"help print this message",
@ -1419,9 +1442,9 @@ CmdGrid(w, cmd)
#ifdef USE_READLINE
void
CmdHistory(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdHistory(
MagWindow *w,
TxCommand *cmd)
{
int i;
HIST_ENTRY *he;
@ -1500,11 +1523,11 @@ CmdHistory(w, cmd)
*/
void
CmdIdentify(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdIdentify(
MagWindow *w,
TxCommand *cmd)
{
extern int cmdIdFunc(); /* Forward reference. */
extern int cmdIdFunc(CellUse *selUse, CellUse *use, Transform *transform, char *newId); /* Forward reference. */
if (cmd->tx_argc != 2)
{
@ -1529,13 +1552,13 @@ CmdIdentify(w, cmd)
/* ARGSUSED */
int
cmdIdFunc(selUse, use, transform, newId)
CellUse *selUse; /* Use from selection cell. */
CellUse *use; /* Use from layout that corresponds to
cmdIdFunc(
CellUse *selUse, /* Use from selection cell. */
CellUse *use, /* Use from layout that corresponds to
* selUse.
*/
Transform *transform; /* Not used. */
char *newId; /* New id for cell use. */
Transform *transform, /* Not used. */
char *newId) /* New id for cell use. */
{
if (EditCellUse == NULL)
{
@ -1576,12 +1599,12 @@ cmdIdFunc(selUse, use, transform, newId)
}
TileType
CmdFindNetProc(nodename, use, rect, warn_not_found, isvalid)
char *nodename;
CellUse *use;
Rect *rect;
bool warn_not_found;
bool *isvalid;
CmdFindNetProc(
char *nodename,
CellUse *use,
Rect *rect,
bool warn_not_found,
bool *isvalid)
{
char *s,*s2;
SearchContext scx, scx2;
@ -1591,13 +1614,13 @@ CmdFindNetProc(nodename, use, rect, warn_not_found, isvalid)
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;
s = nodename;
trans = GeoIdentityTransform;
while (s2 = strchr(s, '/'))
while ((s2 = strchr(s, '/')))
{
*s2 = '\0';
DBTreeFindUse(s, scx.scx_use, &scx2);
@ -1629,6 +1652,7 @@ CmdFindNetProc(nodename, use, rect, warn_not_found, isvalid)
if ((xstr = strchr(s, '_')) != NULL)
{
char *hashpos;
bool isNeg = FALSE;
/* The characters up to the leading '_' should match one of the */
@ -1672,6 +1696,17 @@ CmdFindNetProc(nodename, use, rect, warn_not_found, isvalid)
}
}
}
/* 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;
}
}
@ -1694,17 +1729,23 @@ checklocal:
if (locvalid == TRUE)
{
int findTile();
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
{
@ -1768,11 +1809,11 @@ checklocal:
*/
void
CmdGoto(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdGoto(
MagWindow *w,
TxCommand *cmd)
{
char *s, *nodename = cmd->tx_argv[1];
char *nodename = cmd->tx_argv[1];
Rect rect;
CellUse *use;
int locargc;
@ -1813,9 +1854,9 @@ CmdGoto(w, cmd)
/* 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
}
@ -1826,22 +1867,33 @@ CmdGoto(w, cmd)
*/
int
findTile(tile, rtype)
Tile *tile;
TileType *rtype;
findTile(
Tile *tile,
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 */
}
@ -1851,13 +1903,13 @@ findTile(tile, rtype)
*/
void
FlatCopyAllLabels(scx, mask, xMask, targetUse)
SearchContext *scx;
TileTypeBitMask *mask;
int xMask;
CellUse *targetUse;
FlatCopyAllLabels(
SearchContext *scx,
TileTypeBitMask *mask,
int xMask,
CellUse *targetUse)
{
int flatCopyAllLabels();
int flatCopyAllLabels(SearchContext *scx, Label *lab, TerminalPath *tpath, CellUse *targetUse);
char pathstring[FLATTERMSIZE];
TerminalPath tpath;
@ -1870,18 +1922,17 @@ FlatCopyAllLabels(scx, mask, xMask, targetUse)
}
int
flatCopyAllLabels(scx, lab, tpath, targetUse)
SearchContext *scx;
Label *lab;
TerminalPath *tpath;
CellUse *targetUse;
flatCopyAllLabels(
SearchContext *scx,
Label *lab,
TerminalPath *tpath,
CellUse *targetUse)
{
Rect labTargetRect;
int targetPos;
unsigned short flags = 0;
unsigned int port = 0;
CellDef *def;
char labelname[1024];
char *n, *f, c;
/* Ignore null labels */
@ -1954,52 +2005,52 @@ flatCopyAllLabels(scx, lab, tpath, targetUse)
*/
void
CmdFlatten(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdFlatten(
MagWindow *w,
TxCommand *cmd)
{
int rval, xMask;
bool dolabels, dobox, toplabels, invert, doports;
int i, xMask, optargs;
bool dolabels, dobox, toplabels, invert, doports, doinplace;
char *destname;
CellDef *newdef;
CellUse *newuse;
SearchContext scx;
CellUse *flatDestUse;
destname = cmd->tx_argv[cmd->tx_argc - 1];
destname = NULL;
xMask = CU_DESCEND_ALL;
dolabels = TRUE;
toplabels = FALSE;
dobox = FALSE;
doports = TRUE;
doinplace = FALSE;
optargs = cmd->tx_argc - 1;
rval = 0;
if (cmd->tx_argc > 2)
if (optargs > 0)
{
int i;
for (i = 1; i < (cmd->tx_argc - 1); i++)
for (i = 1; i < (optargs + 1); i++)
{
if (!strncmp(cmd->tx_argv[i], "-no", 3))
if ((cmd->tx_argv[i][0] == '-') && (strlen(cmd->tx_argv[i]) > 3))
{
invert = TRUE;
}
else if (!strncmp(cmd->tx_argv[i], "-do", 3))
{
invert = FALSE;
}
else
{
rval = -1;
break;
}
if (!strncmp(cmd->tx_argv[i] + 1, "no", 2))
invert = TRUE;
else if (!strncmp(cmd->tx_argv[i] + 1, "do", 2))
invert = FALSE;
else
{
TxError("Bad flatten option \"%s\"; must start with \"-no\" or \"-do\"\n",
cmd->tx_argv[i]);
return;
}
if (strlen(cmd->tx_argv[i]) > 3)
{
switch(cmd->tx_argv[i][3])
{
case 'b':
dobox = (invert) ? FALSE : TRUE;
break;
case 'i':
doinplace = (invert) ? FALSE : TRUE;
break;
case 'l':
dolabels = (invert) ? FALSE : TRUE;
break;
@ -2020,20 +2071,65 @@ CmdFlatten(w, cmd)
break;
default:
TxError("options are: -nolabels, -nosubcircuits, -noports, "
"-novendor, -dotoplabels, -doproperty, -dobox\n");
"-novendor, -dotoplabels, -doproperty, -dobox, "
"-doinplace\n");
break;
}
}
else
destname = cmd->tx_argv[i];
}
}
else if (cmd->tx_argc != 2)
rval = -1;
if (rval != 0)
/* Flatten-in-place */
if (doinplace)
{
if (destname != NULL) /* instance name was given in "destname" */
{
HashEntry *he;
CellUse *use;
if (EditCellUse == NULL)
{
TxError("The current cell is not editable.\n");
return;
}
he = HashLookOnly(&EditCellUse->cu_def->cd_idHash, destname);
if (he == NULL)
{
TxError("No cell use %s found in edit cell.\n", destname);
return;
}
use = (CellUse *)HashGetValue(he);
UndoDisable();
DBFlattenInPlace(use, EditCellUse, xMask, dolabels, toplabels, TRUE);
UndoEnable();
}
else
{
/* Instances to flatten are taken from SelectDef */
UndoDisable();
scx.scx_use = SelectUse;
scx.scx_area = SelectUse->cu_bbox;
scx.scx_trans = SelectUse->cu_transform;
DBCellFlattenAllCells(&scx, EditCellUse, xMask, dolabels, toplabels);
/* Instances in SelectDef need to be removed. The 2nd */
/* argument TRUE causes the selection to be deleted. */
SelectDeleteUses("flattened", TRUE);
UndoEnable();
}
return;
}
if (destname == NULL)
{
TxError("usage: flatten [-<option>...] destcell\n");
return;
}
/* create the new def */
newdef = DBCellLookDef(destname);
if ((newdef != NULL) && (dobox == FALSE))
@ -2081,15 +2177,17 @@ CmdFlatten(w, cmd)
UndoDisable();
DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, xMask, flatDestUse);
if (dolabels)
FlatCopyAllLabels(&scx, &DBAllTypeBits, xMask, flatDestUse);
else if (toplabels)
DBFlatCopyMaskHints(&scx, xMask, flatDestUse);
if (toplabels)
{
int savemask = scx.scx_use->cu_expandMask;
scx.scx_use->cu_expandMask = CU_DESCEND_SPECIAL;
DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, flatDestUse);
DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, flatDestUse,
NULL);
scx.scx_use->cu_expandMask = savemask;
}
else if (dolabels)
FlatCopyAllLabels(&scx, &DBAllTypeBits, xMask, flatDestUse);
if (xMask != CU_DESCEND_ALL)
DBCellCopyAllCells(&scx, xMask, flatDestUse, (Rect *)NULL);

View File

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdLQ.c,v 1.9 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdLQ.c,v 1.9 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -51,7 +51,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Forward declarations */
void CmdPaintEraseButton();
void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
/* See the SetLabel command */
@ -84,18 +84,18 @@ extern bool FileLocking;
*/
void
CmdLabelProc(text, font, size, rotate, offx, offy, pos, sticky, type)
char *text; /* Text for label. */
int font; /* Known font to use, or -1 for X11 fonts */
int size; /* Fixed size of font (invalid with X11 fonts) */
int rotate; /* Rotation (invalid with X11 fonts) */
int offx; /* Position offset X (invalid with X11 fonts) */
int offy; /* Position offset Y (invalid with X11 fonts) */
int pos; /* Justification of text relative to text. -1
CmdLabelProc(
char *text, /* Text for label. */
int font, /* Known font to use, or -1 for X11 fonts */
int size, /* Fixed size of font (invalid with X11 fonts) */
int rotate, /* Rotation (invalid with X11 fonts) */
int offx, /* Position offset X (invalid with X11 fonts) */
int offy, /* Position offset Y (invalid with X11 fonts) */
int pos, /* Justification of text relative to text. -1
* means "pick a nice one for me."
*/
bool sticky; /* 1 if label should not be moved off chosen layer */
TileType type; /* Type of material label is to be attached
bool sticky, /* 1 if label should not be moved off chosen layer */
TileType type) /* Type of material label is to be attached
* to. -1 means "pick a reasonable layer".
*/
{
@ -182,9 +182,9 @@ CmdLabelProc(text, font, size, rotate, offx, offy, pos, sticky, type)
void
CmdLabel(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdLabel(
MagWindow *w,
TxCommand *cmd)
{
TileType type = (TileType)(-1);
int pos = -1, font = -1, size = 0, rotate = 0, offx = 0, offy = 0;
@ -347,7 +347,8 @@ CmdLabel(w, cmd)
#define LOAD_DEREFERENCE 1
#define LOAD_FORCE 2
#define LOAD_QUIET 3
#define LOAD_FAIL 4
#define LOAD_SILENT 4
#define LOAD_FAIL 5
/*
* ----------------------------------------------------------------------------
@ -387,9 +388,9 @@ CmdLabel(w, cmd)
*/
void
CmdLoad(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdLoad(
MagWindow *w,
TxCommand *cmd)
{
int n = 1;
int d = 1;
@ -398,21 +399,22 @@ CmdLoad(w, cmd)
bool ignoreTech = FALSE;
bool noWindow = FALSE;
bool dereference = FALSE;
bool beQuiet = FALSE;
char verbose = DB_VERBOSE_ALL;
bool failNotFound = FALSE;
bool saveVerbose;
unsigned char saveVerbose;
unsigned char flags;
int keepGoing(); /* forward declaration */
extern bool DBVerbose; /* from DBio.c */
int keepGoing(CellUse *use, ClientData clientdata); /* forward declaration */
extern unsigned char DBVerbose; /* from DBio.c */
saveVerbose = DBVerbose;
static char *cmdLoadOption[] =
static const char * const cmdLoadOption[] =
{
"-nowindow load file but do not display in the layout window",
"-dereference use search paths and ignore embedded cell paths in file",
"-force load file even if tech in header does not match",
"-quiet no alert if file does not exist",
"-quiet only errors printed",
"-silent no alert if file does not exist",
"-fail if file does not exist, do not create a new cell",
NULL
};
@ -432,7 +434,10 @@ CmdLoad(w, cmd)
ignoreTech = TRUE;
break;
case LOAD_QUIET:
beQuiet = TRUE;
verbose = DB_VERBOSE_ERR;
break;
case LOAD_SILENT:
verbose = DB_VERBOSE_NONE;
break;
case LOAD_FAIL:
failNotFound = TRUE;
@ -490,12 +495,12 @@ CmdLoad(w, cmd)
*(cmd->tx_argv[1] + strlen(cmd->tx_argv[1]) - 1) = '\0';
}
#endif
DBVerbose = !beQuiet;
DBVerbose = verbose;
flags = 0;
if (ignoreTech) flags |= DBW_LOAD_IGNORE_TECH;
if (dereference) flags |= DBW_LOAD_DEREFERENCE;
if (failNotFound) flags |= DBW_LOAD_FAIL;
if (beQuiet) flags |= DBW_LOAD_QUIET;
if (verbose < DB_VERBOSE_WARN) flags |= DBW_LOAD_QUIET;
DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1], flags);
DBVerbose = saveVerbose;
@ -533,7 +538,7 @@ CmdLoad(w, cmd)
}
else
{
DBVerbose = !beQuiet;
DBVerbose = verbose;
DBWloadWindow(w, (char *) NULL, DBW_LOAD_IGNORE_TECH);
DBVerbose = saveVerbose;
}
@ -545,9 +550,9 @@ CmdLoad(w, cmd)
*/
int
keepGoing(use, clientdata)
CellUse *use;
ClientData clientdata;
keepGoing(
CellUse *use,
ClientData clientdata)
{
return 0; /* keep the search going */
}
@ -589,13 +594,13 @@ keepGoing(use, clientdata)
*/
void
CmdLocking(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdLocking(
MagWindow *w,
TxCommand *cmd)
{
int option;
static char *cmdLockingYesNo[] = { "disable", "no", "false", "off", "0",
static const char * const cmdLockingYesNo[] = { "disable", "no", "false", "off", "0",
"enable", "yes", "true", "on", "1", 0 };
if (cmd->tx_argc <= 1)
@ -663,9 +668,9 @@ CmdLocking(w, cmd)
*/
void
CmdMove(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdMove(
MagWindow *w,
TxCommand *cmd)
{
Transform t;
Rect rootBox, newBox;
@ -780,7 +785,7 @@ CmdMove(w, cmd)
* box exists.
* If no selection exists, but the box does, then move the box
* anyway (hace 10/8/97)
* The above method is superceded by "box move <dir> <dist>"
* The above method is superseded by "box move <dir> <dist>"
* but is retained for backward compatibility.
*/
@ -810,6 +815,14 @@ CmdMove(w, cmd)
return;
}
/* Recast the command as "move to x y" so that it no longer
* depends on the pointer position, for command logging.
*/
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
sprintf(cmd->tx_argstring, "move to %di %di\n", editPoint.p_x,
editPoint.p_y);
TxRebuildCommand(cmd);
moveToPoint:
if (!ToolGetBox(&rootDef, &rootBox) || (rootDef != SelectRootDef))
{
@ -866,7 +879,7 @@ moveToPoint:
* Paint the specified layers underneath the box in EditCellUse->cu_def.
*
* Usage:
* paint <layers> | cursor
* paint <layers> | cursor | pick x y
*
* Results:
* None.
@ -878,9 +891,9 @@ moveToPoint:
*/
void
CmdPaint(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdPaint(
MagWindow *w,
TxCommand *cmd)
{
Rect editRect;
TileTypeBitMask mask;
@ -892,15 +905,34 @@ CmdPaint(w, cmd)
return;
}
if ((cmd->tx_argc == 4) && !strcmp(cmd->tx_argv[1], "pick"))
{
Point editPoint, rootPoint;
editPoint.p_x = cmdParseCoord(w, cmd->tx_argv[2], FALSE, TRUE);
editPoint.p_y = cmdParseCoord(w, cmd->tx_argv[3], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &editPoint, &rootPoint);
CmdPaintEraseButton(w, &rootPoint, TRUE, FALSE);
return;
}
if (cmd->tx_argc != 2)
{
TxError("Usage: %s <layers> | cursor\n", cmd->tx_argv[0]);
TxError("Usage: %s <layers> | cursor | pick x y\n", cmd->tx_argv[0]);
return;
}
if (!strncmp(cmd->tx_argv[1], "cursor", 6))
{
CmdPaintEraseButton(w, &cmd->tx_p, TRUE);
Point editPoint, rootPoint;
CmdPaintEraseButton(w, &cmd->tx_p, TRUE, TRUE);
/* Recast the command as "paint pick x y" for logging purposes */
CmdGetRootPoint(&rootPoint, (Rect *)NULL);
GeoTransPoint(&RootToEditTransform, &rootPoint, &editPoint);
sprintf(cmd->tx_argstring, "paint pick %di %di", editPoint.p_x,
editPoint.p_y);
TxRebuildCommand(cmd);
return;
}
else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
@ -952,10 +984,11 @@ CmdPaint(w, cmd)
*/
void
CmdPaintEraseButton(w, butPoint, isPaint)
MagWindow *w;
Point *butPoint; /* Screen location at which button was raised */
bool isPaint; /* True for paint, False for erase. */
CmdPaintEraseButton(
MagWindow *w,
Point *refPoint, /* Screen location at which button was raised */
bool isPaint, /* True for paint, False for erase. */
bool isScreen) /* True for screen coordinates, False for root */
{
Rect rootRect, editRect, areaReturn;
TileTypeBitMask mask;
@ -969,7 +1002,15 @@ CmdPaintEraseButton(w, butPoint, isPaint)
}
crec = (DBWclientRec *) w->w_clientData;
WindPointToSurface(w, butPoint, (Point *) NULL, &rootRect);
if (isScreen)
WindPointToSurface(w, refPoint, (Point *) NULL, &rootRect);
else
{
rootRect.r_ll.p_x = refPoint->p_x;
rootRect.r_ll.p_y = refPoint->p_y;
rootRect.r_ur.p_x = refPoint->p_x + 1;
rootRect.r_ur.p_y = refPoint->p_y + 1;
}
DBSeeTypesAll(((CellUse *)w->w_surfaceID), &rootRect,
crec->dbw_bitmask, &mask);
@ -1005,7 +1046,7 @@ CmdPaintEraseButton(w, butPoint, isPaint)
else
{
DBEraseValid(EditCellUse->cu_def, &editRect, &mask, 0);
DBEraseLabel(EditCellUse->cu_def, &editRect, &mask);
DBEraseLabel(EditCellUse->cu_def, &editRect, &mask, NULL);
}
SelectClear();
DBAdjustLabels(EditCellUse->cu_def, &editRect);
@ -1044,14 +1085,14 @@ CmdPaintEraseButton(w, butPoint, isPaint)
#define PATHHELP 3
void
CmdPath(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdPath(
MagWindow *w,
TxCommand *cmd)
{
char **pathptr;
char *srcptr;
int option;
static char *cmdPathOption[] =
static const char * const cmdPathOption[] =
{
"search [[+]path] set [append to] search path",
"cell [[+]path] set [append to] cell path",
@ -1169,9 +1210,9 @@ usage:
*/
void
CmdPolygon(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdPolygon(
MagWindow *w,
TxCommand *cmd)
{
TileType type;
int points, i, j, pNum;
@ -1242,11 +1283,11 @@ CmdPolygon(w, cmd)
/*----------------------------------------------------------------------*/
int
cmdPortLabelFunc1(scx, label, tpath, cdata)
SearchContext *scx;
Label *label;
TerminalPath *tpath;
ClientData cdata;
cmdPortLabelFunc1(
SearchContext *scx,
Label *label,
TerminalPath *tpath,
ClientData cdata)
{
Label **rlab = (Label **)cdata;
@ -1264,11 +1305,11 @@ cmdPortLabelFunc1(scx, label, tpath, cdata)
}
int
cmdPortLabelFunc2(scx, label, tpath, cdata)
SearchContext *scx;
Label *label;
TerminalPath *tpath;
ClientData cdata;
cmdPortLabelFunc2(
SearchContext *scx,
Label *label,
TerminalPath *tpath,
ClientData cdata)
{
Label **rlab = (Label **)cdata;
@ -1297,11 +1338,11 @@ cmdPortLabelFunc2(scx, label, tpath, cdata)
/*----------------------------------------------------------------------*/
Label *
portFindLabel(editDef, port, unique, nonEdit)
CellDef *editDef;
bool unique;
bool port; // If TRUE, only look for labels that are ports
bool *nonEdit; // TRUE if label is not in the edit cell
portFindLabel(
CellDef *editDef,
bool port, // If TRUE, only look for labels that are ports
bool unique,
bool *nonEdit) // TRUE if label is not in the edit cell
{
int found, wrongkind;
Label *lab, *sl;
@ -1400,11 +1441,18 @@ portFindLabel(editDef, port, unique, nonEdit)
*/
int
complabel(const void *one, const void *two)
complabel(
const void *one,
const void *two)
{
/* Natural sort order routine from DBcellname.c
* replaces strcasecmp().
*/
int strcmpbynum(const char *s1, const char *s2);
Label *l1 = *((Label **)one);
Label *l2 = *((Label **)two);
return strcasecmp(l1->lab_text, l2->lab_text);
return strcmpbynum(l1->lab_text, l2->lab_text);
}
/*
@ -1470,11 +1518,11 @@ complabel(const void *one, const void *two)
#define PORT_HELP 15
void
CmdPort(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdPort(
MagWindow *w,
TxCommand *cmd)
{
char **msg;
const char * const *msg;
int argstart;
int i, refidx, idx, pos, type, option, argc;
unsigned int dirmask;
@ -1484,7 +1532,7 @@ CmdPort(w, cmd)
Rect editBox, tmpArea;
CellDef *editDef;
static char *cmdPortOption[] =
static const char * const cmdPortOption[] =
{
"class [type] get [set] port class type",
"use [type] get [set] port use type",
@ -1505,7 +1553,7 @@ CmdPort(w, cmd)
NULL
};
static char *cmdPortClassTypes[] =
static const char * const cmdPortClassTypes[] =
{
"default",
"input",
@ -1518,7 +1566,7 @@ CmdPort(w, cmd)
NULL
};
static int cmdClassToBitmask[] =
static const int cmdClassToBitmask[] =
{
PORT_CLASS_DEFAULT,
PORT_CLASS_INPUT,
@ -1530,7 +1578,7 @@ CmdPort(w, cmd)
PORT_CLASS_FEEDTHROUGH
};
static char *cmdPortUseTypes[] =
static const char * const cmdPortUseTypes[] =
{
"default",
"analog",
@ -1542,7 +1590,7 @@ CmdPort(w, cmd)
NULL
};
static int cmdUseToBitmask[] =
static const int cmdUseToBitmask[] =
{
PORT_USE_DEFAULT,
PORT_USE_ANALOG,
@ -1553,7 +1601,7 @@ CmdPort(w, cmd)
PORT_USE_CLOCK
};
static char *cmdPortShapeTypes[] =
static const char * const cmdPortShapeTypes[] =
{
"default",
"abutment",
@ -1563,7 +1611,7 @@ CmdPort(w, cmd)
NULL
};
static int cmdShapeToBitmask[] =
static const int cmdShapeToBitmask[] =
{
PORT_SHAPE_DEFAULT,
PORT_SHAPE_ABUT,
@ -1827,7 +1875,7 @@ CmdPort(w, cmd)
{
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, cmdPortClassTypes[idx],
NULL);
(char *)NULL);
#else
TxPrintf("Class = %s\n", cmdPortClassTypes[idx]);
#endif
@ -1872,7 +1920,7 @@ CmdPort(w, cmd)
{
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, cmdPortUseTypes[idx],
NULL);
(char *)NULL);
#else
TxPrintf("Use = %s\n", cmdPortUseTypes[idx]);
#endif
@ -1917,7 +1965,7 @@ CmdPort(w, cmd)
{
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, cmdPortShapeTypes[idx],
NULL);
(char *)NULL);
#else
TxPrintf("Shape = %s\n", cmdPortShapeTypes[idx]);
#endif
@ -1996,7 +2044,7 @@ CmdPort(w, cmd)
if (pos & PORT_DIR_SOUTH) strcat(cdir, "s");
if (pos & PORT_DIR_WEST) strcat(cdir, "w");
#ifdef MAGIC_WRAPPER
Tcl_AppendResult(magicinterp, cdir, NULL);
Tcl_AppendResult(magicinterp, cdir, (char *)NULL);
#else
TxPrintf("Directions = %s\n", cdir);
#endif
@ -2022,11 +2070,13 @@ CmdPort(w, cmd)
* order of the label text). NOTE: Because SPICE is
* case-insensitive, case-insensitive alphabetical order
* is used.
* Update (2/26/2023): Use *natural sort* order so that
* indexes get sorted in numerical, not alphabetical, order.
*/
{
int numlabels, n, p;
Label **slablist, *tlab, *lastlab;
extern int complabel();
extern int complabel(const void *one, const void *two);
/* Create a sortable list of labels */
numlabels = 0;
@ -2126,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;
}
}
}
}
@ -2263,10 +2317,10 @@ parsepositions:
*/
void
CmdDoProperty(def, cmd, argstart)
CellDef *def;
TxCommand *cmd;
int argstart;
CmdDoProperty(
CellDef *def,
TxCommand *cmd,
int argstart)
{
int printPropertiesFunc();
char *value;
@ -2276,8 +2330,9 @@ CmdDoProperty(def, cmd, argstart)
if (locargc == 1)
{
/* print all properties and their values */
DBPropEnum(def, printPropertiesFunc);
DBPropEnum(def, printPropertiesFunc, NULL);
}
else if (locargc == 2)
{
/* print the value of the indicated property */
@ -2294,7 +2349,7 @@ CmdDoProperty(def, cmd, argstart)
/* just return NULL if the property was not found. */
if (strcmp(cmd->tx_argv[1], "list"))
#endif
TxError("Property name %s is not defined\n");
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
}
}
else if (locargc == 3)
@ -2340,9 +2395,9 @@ CmdDoProperty(def, cmd, argstart)
*/
void
CmdProperty(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdProperty(
MagWindow *w,
TxCommand *cmd)
{
CellDef *def;
@ -2365,9 +2420,10 @@ CmdProperty(w, cmd)
*/
int
printPropertiesFunc(name, value)
char *name;
ClientData value;
printPropertiesFunc(
const char *name,
ClientData value,
ClientData cdata) /* not used */
{
#ifdef MAGIC_WRAPPER
char *keyvalue;
@ -2379,14 +2435,14 @@ printPropertiesFunc(name, value)
}
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 */
@ -2417,14 +2473,15 @@ printPropertiesFunc(name, value)
#define NLIST_TERMINAL 3
void
CmdNetlist(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdNetlist(
MagWindow *w,
TxCommand *cmd)
{
int option;
char **msg, *lastargv;
const char * const *msg;
char *lastargv;
Point cursor;
static char *cmdNetlistOption[] =
static const char * const cmdNetlistOption[] =
{
"help print this help information",
"select select the net nearest the cursor",
@ -2500,9 +2557,9 @@ CmdNetlist(w, cmd)
*/
void
CmdOrient(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdOrient(
MagWindow *w,
TxCommand *cmd)
{
Transform trans, t2;
int orientidx, locargc;
@ -2511,7 +2568,7 @@ CmdOrient(w, cmd)
CellDef *rootDef;
bool noAdjust = FALSE;
static char *orientNames[] = { "0", "90", "180", "270",
static const char * const orientNames[] = { "0", "90", "180", "270",
"v", "0v", "90v", "180v", "270v",
"h", "0h", "90h", "180h", "270h",
"N", "E", "S", "W",

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdSubrs.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdSubrs.c,v 1.2 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -52,9 +52,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* Forward declarations */
extern char *cmdCheckNewName();
extern int cmdSaveWindSet();
extern void CmdSetWindCaption();
extern char *cmdCheckNewName(CellDef *def, char *newName, bool tryRename, bool noninteractive);
extern int cmdSaveWindSet(MagWindow *window, CellDef *def);
extern void CmdSetWindCaption(CellUse *newEditUse, CellDef *rootDef);
TileTypeBitMask CmdYMLabel;
TileTypeBitMask CmdYMCell;
@ -100,11 +100,12 @@ TileTypeBitMask CmdYMAllButSpace;
*/
int
cmdScaleCoord(w, arg, is_relative, is_x, scale)
MagWindow *w;
char *arg;
bool is_relative, is_x;
int scale;
cmdScaleCoord(
MagWindow *w,
char *arg,
bool is_relative,
bool is_x,
int scale)
{
char *endptr;
double dval = 0;
@ -190,6 +191,11 @@ cmdScaleCoord(w, arg, is_relative, is_x, scale)
return round(dval);
}
}
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"))
@ -201,7 +207,8 @@ cmdScaleCoord(w, arg, is_relative, is_x, scale)
return round(dval);
}
}
dval /= CIFGetOutputScale(mscale);
if (!isspace(*endptr))
dval /= CIFGetOutputScale(mscale);
return round(dval);
}
@ -224,10 +231,11 @@ cmdScaleCoord(w, arg, is_relative, is_x, scale)
*/
int
cmdParseCoord(w, arg, is_relative, is_x)
MagWindow *w;
char *arg;
bool is_relative, is_x;
cmdParseCoord(
MagWindow *w,
char *arg,
bool is_relative,
bool is_x)
{
return cmdScaleCoord(w, arg, is_relative, is_x, 1);
}
@ -251,7 +259,7 @@ cmdParseCoord(w, arg, is_relative, is_x)
*/
void
CmdInit()
CmdInit(void)
{
TTMaskZero(&CmdYMLabel);
TTMaskSetType(&CmdYMLabel, L_LABEL);
@ -285,12 +293,11 @@ CmdInit()
*/
void
cmdFlushCell(def, force_deref)
CellDef *def;
bool force_deref;
cmdFlushCell(
CellDef *def,
bool force_deref)
{
CellUse *parentUse;
bool dereference;
if (def == NULL) return;
@ -323,8 +330,7 @@ cmdFlushCell(def, force_deref)
}
DBCellClearDef(def);
DBCellClearAvail(def);
dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
(void) DBCellRead(def, TRUE, TRUE, NULL);
DBCellSetAvail(def);
DBReComputeBbox(def);
DBCellSetModified(def, FALSE);
@ -369,9 +375,9 @@ cmdFlushCell(def, force_deref)
*/
bool
CmdParseLayers(s, mask)
char *s;
TileTypeBitMask *mask;
CmdParseLayers(
char *s,
TileTypeBitMask *mask)
{
TileTypeBitMask newmask, tempmask;
char *dp, c;
@ -390,23 +396,23 @@ CmdParseLayers(s, mask)
#define LN_CONNECT 5
static struct
{
char *layer_name;
const char *layer_name;
int layer_value;
}
special[] =
const special[] =
{
"$", LN_DOLLAR,
"*", LN_ALL,
"errors", LN_ERRORS,
"labels", LN_LABELS,
"subcell", LN_CELL,
"connect", LN_CONNECT,
0,
{"$", LN_DOLLAR},
{"*", LN_ALL},
{"errors", LN_ERRORS},
{"labels", LN_LABELS},
{"subcell", LN_CELL},
{"connect", LN_CONNECT},
{0},
};
TTMaskZero(mask);
while (c = *s++)
while ((c = *s++))
{
switch (c)
{
@ -433,7 +439,7 @@ CmdParseLayers(s, mask)
type = DBTechNameTypes(name, &newmask);
if (type == -2)
{
which = LookupStruct(name, (LookupTable *) special, sizeof special[0]);
which = LookupStruct(name, (const LookupTable *) special, sizeof special[0]);
if (which >= 0)
{
switch (special[which].layer_value)
@ -543,8 +549,8 @@ printTypes:
*/
TileType
cmdMaskToType(mask)
TileTypeBitMask *mask;
cmdMaskToType(
TileTypeBitMask *mask)
{
TileType type, t;
@ -589,16 +595,16 @@ cmdMaskToType(mask)
*/
void
cmdSaveCell(cellDef, newName, noninteractive, tryRename)
CellDef *cellDef; /* Pointer to def of cell to be saved */
char *newName; /* Pointer to name of file in which cell is to be
cmdSaveCell(
CellDef *cellDef, /* Pointer to def of cell to be saved */
char *newName, /* Pointer to name of file in which cell is to be
* saved. May be NULL, in which case the name from
* the CellDef is taken.
*/
bool noninteractive;/* If true, try hard but don't ask the user
bool noninteractive,/* If true, try hard but don't ask the user
* questions.
*/
bool tryRename; /* We should rename the cell to the name of the
bool tryRename) /* We should rename the cell to the name of the
* place where it was saved.
*/
{
@ -708,13 +714,13 @@ cleanup:
*/
char *
cmdCheckNewName(def, newName, tryRename, noninteractive)
CellDef *def;
char *newName;
bool tryRename;
bool noninteractive;
cmdCheckNewName(
CellDef *def,
char *newName,
bool tryRename,
bool noninteractive)
{
static char *yesno[] = { "no", "yes", 0 };
static const char * const yesno[] = { "no", "yes", 0 };
char *filename;
char *prompt;
char *returnname;
@ -752,7 +758,7 @@ again:
if (strcmp(returnname, def->cd_name) != 0)
{
if (f = PaOpen(returnname, "r", DBSuffix, ".", (char *) NULL, &filename))
if ((f = PaOpen(returnname, "r", DBSuffix, ".", (char *) NULL, &filename)))
{
(void) fclose(f);
if (noninteractive) {
@ -799,10 +805,10 @@ again:
*/
static char *
nameEllipsis(name, maxlen, prefix)
char *name;
int maxlen;
char **prefix;
nameEllipsis(
char *name,
int maxlen,
char **prefix)
{
int l = strlen(name);
@ -842,9 +848,9 @@ nameEllipsis(name, maxlen, prefix)
*/
int
cmdSaveWindSet(window, def)
MagWindow *window;
CellDef *def;
cmdSaveWindSet(
MagWindow *window,
CellDef *def)
{
char caption[200];
CellDef *rootDef;
@ -896,13 +902,13 @@ static CellDef *newRootDef; /* Pointer to root def of window in which
*/
void
CmdSetWindCaption(newEditUse, rootDef)
CellUse *newEditUse; /* Pointer to new edit cell use */
CellDef *rootDef; /* Root cell def of the window in which the
CmdSetWindCaption(
CellUse *newEditUse, /* Pointer to new edit cell use */
CellDef *rootDef) /* Root cell def of the window in which the
* edit cell was selected.
*/
{
int cmdWindSet();
int cmdWindSet(MagWindow *window);
newEditDef = (newEditUse) ? newEditUse->cu_def : NULL;
newRootDef = rootDef;
@ -937,8 +943,8 @@ CmdSetWindCaption(newEditUse, rootDef)
*/
int
cmdWindSet(window)
MagWindow *window;
cmdWindSet(
MagWindow *window)
{
char caption[200];
CellDef *wDef;
@ -994,9 +1000,9 @@ cmdWindSet(window)
*/
MagWindow *
CmdGetRootPoint(point, rect)
Point *point;
Rect *rect;
CmdGetRootPoint(
Point *point,
Rect *rect)
{
MagWindow *window;
@ -1029,9 +1035,9 @@ CmdGetRootPoint(point, rect)
*/
MagWindow *
CmdGetEditPoint(point, rect)
Point *point;
Rect *rect;
CmdGetEditPoint(
Point *point,
Rect *rect)
{
MagWindow *window;
Rect rootRect;
@ -1066,11 +1072,11 @@ CmdGetEditPoint(point, rect)
*/
bool
CmdWarnWrite()
CmdWarnWrite(void)
{
int count, code;
int cmdWarnWriteFunc();
static char *yesno[] = { "no", "yes", 0 };
int cmdWarnWriteFunc(CellDef *cellDef, int *pcount);
static const char * const yesno[] = { "no", "yes", 0 };
char *prompt;
count = 0;
@ -1088,9 +1094,9 @@ CmdWarnWrite()
}
int
cmdWarnWriteFunc(cellDef, pcount)
CellDef *cellDef;
int *pcount;
cmdWarnWriteFunc(
CellDef *cellDef,
int *pcount)
{
if ((cellDef->cd_flags & CDINTERNAL) == 0)
(*pcount)++;
@ -1114,27 +1120,27 @@ cmdWarnWriteFunc(cellDef, pcount)
*/
void
cmdExpandOneLevel(cu, bitmask, expand)
CellUse *cu;
int bitmask;
bool expand;
cmdExpandOneLevel(
CellUse *cu,
int bitmask,
bool expand)
{
extern int cmdExpand1func();
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
/* first, expand this cell use */
DBExpand(cu, bitmask, expand);
/* now, unexpand its direct children (ONE LEVEL ONLY) */
if (expand)
(void) DBCellEnum(cu->cu_def, cmdExpand1func, (ClientData) bitmask);
(void) DBCellEnum(cu->cu_def, cmdExpand1func, INT2CD(bitmask));
}
int
cmdExpand1func(cu, bitmask)
CellUse *cu;
ClientData bitmask;
cmdExpand1func(
CellUse *cu,
ClientData bitmask)
{
DBExpand(cu, (int) bitmask, FALSE);
DBExpand(cu, (int)CD2INT(bitmask), FALSE);
return 0;
}
@ -1162,13 +1168,13 @@ Transform *cmdSelTrans; /* Shared between CmdGetSelectedCell and
*/
CellUse *
CmdGetSelectedCell(pTrans)
Transform *pTrans; /* If non-NULL, transform from selected
CmdGetSelectedCell(
Transform *pTrans) /* If non-NULL, transform from selected
* cell to root coords is stored here.
*/
{
CellUse *result = NULL;
int cmdGetSelFunc(); /* Forward declaration. */
int cmdGetSelFunc(CellUse *selUse, CellUse *realUse, Transform *transform, CellUse **pResult); /* Forward declaration. */
cmdSelTrans = pTrans;
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
@ -1178,11 +1184,11 @@ CmdGetSelectedCell(pTrans)
/* ARGSUSED */
int
cmdGetSelFunc(selUse, realUse, transform, pResult)
CellUse *selUse; /* Not used. */
CellUse *realUse; /* The first selected use. */
Transform *transform; /* Transform from coords of realUse to root. */
CellUse **pResult; /* Store realUse here. */
cmdGetSelFunc(
CellUse *selUse, /* Not used. */
CellUse *realUse, /* The first selected use. */
Transform *transform, /* Transform from coords of realUse to root. */
CellUse **pResult) /* Store realUse here. */
{
*pResult = realUse;
if (cmdSelTrans != NULL)
@ -1190,6 +1196,17 @@ cmdGetSelFunc(selUse, realUse, transform, pResult)
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;
}
/*
* ----------------------------------------------------------------------------
*
@ -1210,10 +1227,10 @@ cmdGetSelFunc(selUse, realUse, transform, pResult)
*/
bool
CmdIllegalChars(string, illegal, msg)
char *string; /* String to check for illegal chars. */
char *illegal; /* String containing illegal chars. */
char *msg; /* String identifying what string is
CmdIllegalChars(
char *string, /* String to check for illegal chars. */
char *illegal, /* String containing illegal chars. */
char *msg) /* String identifying what string is
* supposed to represent, for ease in
* printing error messages.
*/
@ -1222,7 +1239,7 @@ CmdIllegalChars(string, illegal, msg)
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++)
{
@ -1231,7 +1248,7 @@ CmdIllegalChars(string, illegal, msg)
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

@ -17,7 +17,7 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdTZ.c,v 1.8 2010/06/24 12:37:15 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdTZ.c,v 1.8 2010/06/24 12:37:15 tim Exp $";
#endif /* not lint */
#include <stdio.h>
@ -57,13 +57,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "yacr.h"
#endif /* LLNL */
extern void DisplayWindow();
/* Trivial function that returns 1 if called */
int
existFunc(tile)
Tile *tile;
existFunc(
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
return 1;
}
@ -82,9 +82,9 @@ existFunc(tile)
*/
int
checkForPaintFunc(cellDef, arg)
CellDef *cellDef;
ClientData arg;
checkForPaintFunc(
CellDef *cellDef,
ClientData arg)
{
int numPlanes = *((int *)arg);
int pNum, result;
@ -121,7 +121,7 @@ checkForPaintFunc(cellDef, arg)
*/
bool
CmdCheckForPaintFunc()
CmdCheckForPaintFunc(void)
{
if (DBCellSrDefs(0, checkForPaintFunc, (ClientData)&DBNumPlanes))
return TRUE;
@ -165,21 +165,21 @@ CmdCheckForPaintFunc()
#define TECH_REVERT 11
void
CmdTech(w, cmd)
MagWindow *w; /* Window in which command was invoked. */
TxCommand *cmd; /* Info about command options. */
CmdTech(
MagWindow *w, /* Window in which command was invoked. */
TxCommand *cmd) /* Info about command options. */
{
int option, action, i, locargc;
char **msg;
const char * const *msg;
#ifdef MAGIC_WRAPPER
Tcl_Obj *lobj;
#endif
bool noprompt = FALSE;
static char *actionNames[] =
static const char * const actionNames[] =
{ "no", "yes", 0 };
static char *cmdTechOption[] =
static const char * const cmdTechOption[] =
{
"load filename [-noprompt][-[no]override]\n\
Load a new technology",
@ -218,7 +218,7 @@ CmdTech(w, cmd)
Tcl_SetResult(magicinterp, DBTechName, NULL);
break;
case TECH_FILE:
Tcl_SetResult(magicinterp, TechFileName, NULL);
Tcl_SetResult(magicinterp, (char *)TechFileName, NULL);
break;
case TECH_VERSION:
Tcl_SetResult(magicinterp, DBTechVersion, NULL);
@ -415,10 +415,12 @@ CmdTech(w, cmd)
for (ctype = TT_TECHDEPBASE; ctype < DBNumUserLayers; ctype++)
if (DBIsContact(ctype))
{
if (TTMaskHasType(&DBActiveLayerBits, ctype))
DBUnlockContact(ctype);
else
DBLockContact(ctype);
}
for (ctype = DBNumUserLayers; ctype < DBNumTypes; ctype++)
{
@ -653,9 +655,9 @@ usage2:
*/
void
CmdTool(w, cmd)
MagWindow *w; /* Window in which command was invoked. */
TxCommand *cmd; /* Info about command options. */
CmdTool(
MagWindow *w, /* Window in which command was invoked. */
TxCommand *cmd) /* Info about command options. */
{
if (cmd->tx_argc == 1)
{
@ -671,6 +673,15 @@ CmdTool(w, cmd)
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]);
}
@ -695,13 +706,13 @@ CmdTool(w, cmd)
*/
void
CmdUnexpand(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdUnexpand(
MagWindow *w,
TxCommand *cmd)
{
int windowMask, boxMask;
Rect rootRect;
int cmdUnexpandFunc(); /* Forward reference. */
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
if (cmd->tx_argc != 1)
{
@ -733,9 +744,9 @@ CmdUnexpand(w, cmd)
*/
int
cmdUnexpandFunc(use, windowMask)
CellUse *use; /* Use that was just unexpanded. */
int windowMask; /* Window where it was unexpanded. */
cmdUnexpandFunc(
CellUse *use, /* Use that was just unexpanded. */
int windowMask) /* Window where it was unexpanded. */
{
if (use->cu_parent == NULL) return 0;
DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask,
@ -764,9 +775,9 @@ cmdUnexpandFunc(use, windowMask)
*/
void
CmdUpsidedown(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdUpsidedown(
MagWindow *w,
TxCommand *cmd)
{
Transform trans;
Rect rootBox, bbox;
@ -828,9 +839,11 @@ struct linked_id {
};
int cmdWhatPrintCell(tile, cxp)
Tile *tile;
TreeContext *cxp;
int
cmdWhatPrintCell(
Tile *tile, /* (unused) */
TileType dinfo, /* (unused) */
TreeContext *cxp)
{
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
struct linked_id *curlid = *lid;
@ -882,7 +895,10 @@ static LabelStore *labelBlockTop, *labelEntry;
*/
int
cmdFindWhatTileFunc(Tile *tile, ClientData clientData)
cmdFindWhatTileFunc(
Tile *tile,
TileType dinfo,
ClientData clientData)
{
struct linked_id **lid = (struct linked_id **)clientData;
SearchContext scx;
@ -893,7 +909,7 @@ cmdFindWhatTileFunc(Tile *tile, ClientData clientData)
scx.scx_use = EditCellUse;
scx.scx_trans = GeoIdentityTransform;
if (SplitSide(tile))
if (dinfo & TT_SIDE)
type = SplitRightType(tile);
else
type = SplitLeftType(tile);
@ -928,9 +944,9 @@ cmdFindWhatTileFunc(Tile *tile, ClientData clientData)
*/
void
CmdWhat(w, cmd)
MagWindow *w; /* Window in which command was invoked. */
TxCommand *cmd; /* Information about the command. */
CmdWhat(
MagWindow *w, /* Window in which command was invoked. */
TxCommand *cmd) /* Information about the command. */
{
int i, locargc;
bool foundAny, editNull = FALSE;
@ -940,11 +956,14 @@ CmdWhat(w, cmd)
#ifdef MAGIC_WRAPPER
Tcl_Obj *lobj, *paintobj, *paintcellobj, *celllistobj, *labelobj, *cellobj;
extern int cmdWhatCellListFunc();
extern int cmdWhatCellListFunc(CellUse *selUse, CellUse *realUse, Transform *transform, Tcl_Obj *newobj);
#endif
extern int cmdWhatPaintFunc(), cmdWhatLabelFunc(), cmdWhatCellFunc();
extern int cmdWhatLabelPreFunc(), orderLabelFunc();
extern int cmdWhatPaintFunc(Rect *rect, TileType type, TileTypeBitMask *mask);
extern int cmdWhatLabelFunc(LabelStore *entry, bool *foundAny);
extern int cmdWhatCellFunc(CellUse *selUse, CellUse *realUse, Transform *transform, bool *foundAny);
extern int cmdWhatLabelPreFunc(Label *label, CellUse *cellUse, Transform *transform, bool *foundAny);
extern int orderLabelFunc(const void *, const void *); /* (LabelStore *one, LabelStore *two) */
locargc = cmd->tx_argc;
@ -981,7 +1000,7 @@ CmdWhat(w, cmd)
if (EditCellUse == NULL)
{
editNull = TRUE;
EditCellUse = w->w_surfaceID;
EditCellUse = (CellUse *)w->w_surfaceID;
}
/* Find all the selected paint and print out the layer names. */
@ -1088,11 +1107,13 @@ CmdWhat(w, cmd)
}
#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,
@ -1197,10 +1218,10 @@ CmdWhat(w, cmd)
/*ARGSUSED*/
int
cmdWhatPaintFunc(rect, type, mask)
Rect *rect; /* Not used. */
TileType type; /* Type of this piece of paint. */
TileTypeBitMask *mask; /* Place to OR in type's bit. */
cmdWhatPaintFunc(
Rect *rect, /* Not used. */
TileType type, /* Type of this piece of paint. */
TileTypeBitMask *mask) /* Place to OR in type's bit. */
{
if (type & TT_DIAGONAL)
type = (type & TT_SIDE) ? (type & TT_RIGHTMASK) >> 14 :
@ -1215,11 +1236,11 @@ cmdWhatPaintFunc(rect, type, mask)
/*ARGSUSED*/
int
cmdWhatLabelPreFunc(label, cellUse, transform, foundAny)
Label *label; /* Label that's selected. */
CellUse *cellUse; /* Cell use containing label. */
Transform *transform; /* Not used. */
bool *foundAny; /* Use to print extra stuff for the first
cmdWhatLabelPreFunc(
Label *label, /* Label that's selected. */
CellUse *cellUse, /* Cell use containing label. */
Transform *transform, /* Not used. */
bool *foundAny) /* Use to print extra stuff for the first
* label found.
*/
{
@ -1259,9 +1280,9 @@ cmdWhatLabelPreFunc(label, cellUse, transform, foundAny)
int
cmdWhatLabelFunc(entry, foundAny)
LabelStore *entry; /* stored pointers to label info*/
bool *foundAny; /* Use to print extra stuff for the first
cmdWhatLabelFunc(
LabelStore *entry, /* stored pointers to label info*/
bool *foundAny) /* Use to print extra stuff for the first
* label found.
*/
{
@ -1311,10 +1332,12 @@ cmdWhatLabelFunc(entry, foundAny)
/* they are sorted by label name, then cell name, then attached material */
/* that way all of identical names are grouped together */
int
orderLabelFunc(one, two)
LabelStore *one; /* one of the labels being compared */
LabelStore *two; /* the other label to compare with */
orderLabelFunc(
const void *a, /* one of the labels being compared */
const void *b) /* the other label to compare with */
{
LabelStore *one = (LabelStore *)a; /* qsort compar 1st */
LabelStore *two = (LabelStore *)b; /* qsort compar 2nd */
int i;
if ((i = strcmp(one->lab_text, two->lab_text)) != 0)
@ -1333,16 +1356,16 @@ orderLabelFunc(one, two)
/*ARGSUSED*/
int
cmdWhatCellFunc(selUse, realUse, transform, foundAny)
CellUse *selUse; /* Not used. */
CellUse *realUse; /* Selected cell use. */
Transform *transform; /* Not used. */
bool *foundAny; /* Used to print extra stuff for the first
cmdWhatCellFunc(
CellUse *selUse, /* Not used. */
CellUse *realUse, /* Selected cell use. */
Transform *transform, /* Not used. */
bool *foundAny) /* Used to print extra stuff for the first
* use found.
*/
{
/* Forward reference */
char *dbGetUseName();
char *dbGetUseName(CellUse *celluse);
if (!*foundAny)
{
@ -1359,15 +1382,15 @@ cmdWhatCellFunc(selUse, realUse, transform, foundAny)
/* Same search function as above, but appends use names to a Tcl list */
int
cmdWhatCellListFunc(selUse, realUse, transform, newobj)
CellUse *selUse; /* Not used. */
CellUse *realUse; /* Selected cell use. */
Transform *transform; /* Not used. */
Tcl_Obj *newobj; /* Tcl list object holding use names */
cmdWhatCellListFunc(
CellUse *selUse, /* Not used. */
CellUse *realUse, /* Selected cell use. */
Transform *transform, /* Not used. */
Tcl_Obj *newobj) /* Tcl list object holding use names */
{
Tcl_Obj *tuple;
/* Forward reference */
char *dbGetUseName();
char *dbGetUseName(CellUse *celluse);
tuple = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tuple,
@ -1414,20 +1437,23 @@ cmdWhatCellListFunc(selUse, realUse, transform, newobj)
#define SEGMENT 11
void
CmdWire(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdWire(
MagWindow *w,
TxCommand *cmd)
{
int option, locargc;
char **msg, *lastargv;
const char * const *msg;
char *lastargv;
TileType type;
int width;
Point point, rootPoint;
bool needCoord = FALSE;
#ifdef MAGIC_WRAPPER
Tcl_Obj *lobj;
#endif
static char *cmdWireOption[] =
static const char * const cmdWireOption[] =
{
"decrement layer|width decrement the wire layer or width",
"help print this help information",
@ -1499,11 +1525,11 @@ CmdWire(w, cmd)
int value = 1;
if (cmd->tx_argc == 4)
value = cmdParseCoord(w, cmd->tx_argv[3], TRUE, TRUE);
WirePickType(WireType, WireWidth - value);
WirePickType(WireType, (Point *)NULL, WireWidth - value);
}
else
goto badargs;
return;
break;
case INCREMENT:
if (cmd->tx_argc != 3 && cmd->tx_argc != 4)
@ -1539,11 +1565,11 @@ CmdWire(w, cmd)
int value = 1;
if (cmd->tx_argc == 4)
value = cmdParseCoord(w, cmd->tx_argv[3], TRUE, TRUE);
WirePickType(WireType, WireWidth + value);
WirePickType(WireType, (Point *)NULL, WireWidth + value);
}
else
goto badargs;
return;
break;
case HELP:
@ -1553,15 +1579,41 @@ CmdWire(w, cmd)
{
TxPrintf(" %s\n", *msg);
}
return;
break;
case HORIZONTAL:
WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_HORIZONTAL);
return;
if ((cmd->tx_argc > 2) && strcmp(cmd->tx_argv[2], "to") == 0)
{
if (cmd->tx_argc != 5)
goto badargs;
point.p_x = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
point.p_y = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &point, &rootPoint);
WireAddLeg((Rect *)NULL, &rootPoint, WIRE_HORIZONTAL);
}
else
{
WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_HORIZONTAL);
needCoord = TRUE;
}
break;
case LEG:
WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_CHOOSE);
return;
if ((cmd->tx_argc > 2) && strcmp(cmd->tx_argv[2], "to") == 0)
{
if (cmd->tx_argc != 5)
goto badargs;
point.p_x = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
point.p_y = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &point, &rootPoint);
WireAddLeg((Rect *)NULL, &rootPoint, WIRE_CHOOSE);
}
else
{
WireAddLeg((Rect *)NULL, (Point *)NULL, WIRE_CHOOSE);
needCoord = TRUE;
}
break;
case SHOW:
WireShowLeg();
@ -1595,7 +1647,17 @@ CmdWire(w, cmd)
case TYPE:
if (locargc == 2)
WirePickType(-1, 0);
{
WirePickType(-1, (Point *)NULL, 0);
needCoord = TRUE;
}
else if ((locargc == 5) && !strcmp(cmd->tx_argv[2], "at"))
{
point.p_x = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
point.p_y = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &point, &rootPoint);
WirePickType(-1, &rootPoint, 0);
}
else if (locargc != 3 && locargc != 4)
{
badargs:
@ -1626,7 +1688,7 @@ CmdWire(w, cmd)
}
else
width = cmdParseCoord(w, cmd->tx_argv[3], TRUE, TRUE);
WirePickType(type, width);
WirePickType(type, (Point *)NULL, width);
return;
}
break;
@ -1648,11 +1710,24 @@ CmdWire(w, cmd)
DBTypeLongNameTbl[type], width);
#endif
}
return;
break;
case VERTICAL:
WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_VERTICAL);
return;
if ((cmd->tx_argc > 2) && strcmp(cmd->tx_argv[2], "to") == 0)
{
if (cmd->tx_argc != 5)
goto badargs;
point.p_x = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
point.p_y = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
GeoTransPoint(&EditToRootTransform, &point, &rootPoint);
WireAddLeg((Rect *)NULL, &rootPoint, WIRE_VERTICAL);
}
else
{
WireAddLeg((Rect *) NULL, (Point *) NULL, WIRE_VERTICAL);
needCoord = TRUE;
}
break;
case WIDTH:
if (locargc == 2)
@ -1671,7 +1746,7 @@ CmdWire(w, cmd)
{
width = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE);
type = WireGetType();
WirePickType(type, width);
WirePickType(type, (Point *)NULL, width);
return;
}
break;
@ -1761,6 +1836,7 @@ CmdWire(w, cmd)
TxError("Bad coordinate pair at %s line %d\n",
cmd->tx_argv[4], i + 1);
freeMagic(plist);
fclose(pfile);
return;
}
@ -1820,6 +1896,22 @@ CmdWire(w, cmd)
}
break;
}
/* Recast the command as "wire <option> to <x> <y>" so that it no longer
* depends on the pointer position, for command logging.
*/
if (needCoord)
{
if (ToolGetPoint(&rootPoint, (Rect *)NULL) != NULL)
{
GeoTransPoint(&RootToEditTransform, &rootPoint, &point);
sprintf(cmd->tx_argstring, "wire %s %s %di %di",
cmd->tx_argv[1],
(option == TYPE) ? "at" : "to",
point.p_x, point.p_y);
TxRebuildCommand(cmd);
}
}
}
/*
@ -1852,13 +1944,13 @@ CmdWire(w, cmd)
#define OPT_WRITEALL_MODIFIED 1
void
CmdWriteall(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdWriteall(
MagWindow *w,
TxCommand *cmd)
{
int cmdWriteallFunc();
int cmdWriteallFunc(CellDef *def, TxCommand *cmd);
int option = -1;
static char *writeallOpts[] = { "force", "modified", 0 };
static const char * const writeallOpts[] = { "force", "modified", 0 };
int argc;
int flags = CDMODIFIED | CDBOXESCHANGED | CDSTAMPSCHANGED;
@ -1868,7 +1960,7 @@ CmdWriteall(w, cmd)
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;
}
@ -1909,11 +2001,11 @@ CmdWriteall(w, cmd)
/*ARGSUSED*/
int
cmdWriteallFunc(def, cmd)
CellDef *def; /* Pointer to CellDef to be saved. This def might
cmdWriteallFunc(
CellDef *def, /* Pointer to CellDef to be saved. This def might
* be an internal buffer; if so, we ignore it.
*/
TxCommand *cmd; /* Client data passed to DBCellSrDefs, a pointer
TxCommand *cmd) /* Client data passed to DBCellSrDefs, a pointer
* to the command structure. If cmd->tx_argc == 1,
* then prompt for each action. If cmd->tx_argc
* == 2, then write all cells without asking. If
@ -1923,9 +2015,9 @@ cmdWriteallFunc(def, cmd)
{
char *prompt, *argv;
int i, action, cidx = 0;
static char *actionNames[] =
static const char * const actionNames[] =
{ "write", "flush", "skip", "abort", "autowrite", 0 };
static char *explain[] =
static const char * const explain[] =
{ "", "(bboxes)", "(timestamps)", "(bboxes/timestamps)", 0 };
if (def->cd_flags & CDINTERNAL) return 0;
@ -2012,9 +2104,9 @@ cmdWriteallFunc(def, cmd)
*/
void
CmdXload(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdXload(
MagWindow *w,
TxCommand *cmd)
{
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL)
@ -2060,9 +2152,9 @@ CmdXload(w, cmd)
*/
void
CmdXor(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdXor(
MagWindow *w,
TxCommand *cmd)
{
int rval, xMask;
bool dolabels;

View File

@ -20,10 +20,11 @@
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdWizard.c,v 1.2 2008/02/10 19:30:19 tim Exp $";
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/commands/CmdWizard.c,v 1.2 2008/02/10 19:30:19 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
@ -46,12 +47,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/utils.h"
#include "textio/txcommands.h"
/* For diagnostics */
#include "cif/CIFint.h"
#include "database/databaseInt.h"
/* C99 compat */
#include "extract/extract.h"
/* Forward declarations */
extern void cmdPsearchStats();
extern void cmdPsearchStats(char *str, struct tms *tl, struct tms *td, int count);
void cmdStatsHier(CellDef *, int, CellDef *);
@ -78,9 +83,9 @@ void cmdStatsHier(CellDef *, int, CellDef *);
*/
void
CmdCoord(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdCoord(
MagWindow *w,
TxCommand *cmd)
{
MagWindow *pointW = (MagWindow *) NULL;
Rect editRect, rootRect;
@ -180,14 +185,242 @@ CmdCoord(w, cmd)
#ifndef NO_EXT
void
CmdExtractTest(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdExtractTest(
MagWindow *w,
TxCommand *cmd)
{
ExtractTest(w, cmd);
}
#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);
}
/*
* ----------------------------------------------------------------------------
@ -211,9 +444,9 @@ CmdExtractTest(w, cmd)
*/
void
showTech(outf, verbose)
FILE *outf; /* File to which information is to be output */
bool verbose; /* If TRUE, output detailed erase table */
showTech(
FILE *outf, /* File to which information is to be output */
bool verbose) /* If TRUE, output detailed erase table */
{
int i, j;
int pNum;
@ -231,7 +464,7 @@ showTech(outf, verbose)
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);
@ -358,9 +591,9 @@ showTech(outf, verbose)
}
void
CmdShowtech(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdShowtech(
MagWindow *w,
TxCommand *cmd)
{
FILE *outf;
bool verbose;
@ -426,16 +659,16 @@ CmdShowtech(w, cmd)
*/
void
CmdTilestats(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdTilestats(
MagWindow *w,
TxCommand *cmd)
{
CellUse *selectedUse;
FILE *outf = stdout;
bool allDefs = FALSE;
char **av = cmd->tx_argv + 1;
int ac = cmd->tx_argc - 1;
int cmdStatsFunc();
int cmdStatsFunc(CellDef *def, FILE *outf);
if (ac > 2)
{
@ -510,11 +743,12 @@ int totalTiles[TT_MAXTYPES];
*/
int
cmdStatsFunc(def, outf)
CellDef *def;
FILE *outf;
cmdStatsFunc(
CellDef *def,
FILE *outf)
{
int cmdStatsCount(), cmdStatsOutput();
int cmdStatsCount(CellDef *def, struct countClient *cc);
int cmdStatsOutput(CellDef *def, struct countClient *cc);
struct countClient cc;
int total;
TileType t;
@ -563,15 +797,17 @@ cmdStatsFunc(def, outf)
*/
int
cmdStatsCount(def, cc)
CellDef *def;
struct countClient *cc;
cmdStatsCount(
CellDef *def,
struct countClient *cc)
{
int cmdStatsCountTile();
int pNum;
struct cellInfo *ci;
TileType t;
/* Forward declaration */
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
if (def->cd_client)
return (1);
@ -594,9 +830,10 @@ cmdStatsCount(def, cc)
}
int
cmdStatsCountTile(tile, ci)
Tile *tile;
struct cellInfo *ci;
cmdStatsCountTile(
Tile *tile,
TileType dinfo, /* (unused) */
struct cellInfo *ci)
{
TileType type = TiGetType(tile);
@ -637,9 +874,10 @@ cmdStatsCountTile(tile, ci)
*/
void
cmdStatsHier(parent, nuses, child)
CellDef *parent, *child;
int nuses;
cmdStatsHier(
CellDef *parent,
int nuses,
CellDef *child)
{
struct cellInfo *pi, *ci;
TileType t;
@ -684,9 +922,9 @@ cmdStatsHier(parent, nuses, child)
*/
int
cmdStatsOutput(def, cc)
CellDef *def;
struct countClient *cc;
cmdStatsOutput(
CellDef *def,
struct countClient *cc)
{
TileType t;
struct cellInfo *ci;
@ -749,11 +987,11 @@ cmdStatsOutput(def, cc)
*/
void
CmdPsearch(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdPsearch(
MagWindow *w,
TxCommand *cmd)
{
char *RunStats();
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
static struct tms tlast, tdelta;
Point p;
Plane *plane;
@ -815,12 +1053,13 @@ CmdPsearch(w, cmd)
}
void
cmdPsearchStats(str, tl, td, count)
char *str;
struct tms *tl, *td;
int count;
cmdPsearchStats(
char *str,
struct tms *tl,
struct tms *td,
int count)
{
char *RunStats();
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
char *rstatp;
int us, ups;
@ -860,20 +1099,22 @@ int numTilesFound;
bool cmdTsearchDebug = FALSE;
void
CmdTsearch(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdTsearch(
MagWindow *w,
TxCommand *cmd)
{
int cmdTsrFunc();
char *RunStats(), *rstatp;
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");
@ -972,11 +1213,13 @@ CmdTsearch(w, cmd)
}
int
cmdTsrFunc(tp)
Tile *tp;
cmdTsrFunc(
Tile *tp,
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{
if (cmdTsearchDebug)
TxPrintf("%x\n", tp);
TxPrintf("%lx\n", (intptr_t) tp);
numTilesFound++;
return 0;
}
@ -999,9 +1242,9 @@ cmdTsrFunc(tp)
*/
void
CmdWatch(w, cmd)
MagWindow *w;
TxCommand *cmd;
CmdWatch(
MagWindow *w,
TxCommand *cmd)
{
DBWclientRec *crec;
int pNum;
@ -1042,7 +1285,7 @@ CmdWatch(w, cmd)
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++) {
@ -1052,8 +1295,16 @@ CmdWatch(w, cmd)
};
return;
}
crec->dbw_watchDef = EditCellUse->cu_def;
crec->dbw_watchTrans = EditToRootTransform;
if (EditCellUse != NULL)
{
crec->dbw_watchDef = EditCellUse->cu_def;
crec->dbw_watchTrans = EditToRootTransform;
}
else
{
crec->dbw_watchDef = ((CellUse *)w->w_surfaceID)->cu_def;
crec->dbw_watchTrans = ((CellUse *)w->w_surfaceID)->cu_transform;
}
}
crec->dbw_watchPlane = 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,11 +20,12 @@
* 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"
#include "textio/txcommands.h" /* TxCommand */
/*
* Name of default yank buffer
@ -50,30 +51,28 @@ extern TileTypeBitMask CmdYMAllButSpace;
/* --------------------- Global procedure headers --------------------- */
extern MagWindow *CmdGetRootBox();
extern MagWindow *CmdGetEditPoint();
extern MagWindow *CmdGetRootPoint();
extern bool CmdWarnWrite();
extern bool CmdParseLayers();
extern void CmdAddSlop();
extern void CmdLabelProc();
extern void CmdSetWindCaption();
extern CellUse *CmdGetSelectedCell();
extern bool CmdIllegalChars();
extern void CmdDoMacro();
extern TileType CmdFindNetProc();
extern bool CmdCheckForPaintFunc();
extern MagWindow *CmdGetEditPoint(Point *point, Rect *rect);
extern MagWindow *CmdGetRootPoint(Point *point, Rect *rect);
extern bool CmdWarnWrite(void);
extern bool CmdParseLayers(char *s, TileTypeBitMask *mask);
extern void CmdLabelProc(char *text, int font, int size, int rotate, int offx, int offy,
int pos, bool sticky, TileType type);
extern void CmdSetWindCaption(CellUse *newEditUse, CellDef *rootDef);
extern CellUse *CmdGetSelectedCell(Transform *pTrans);
extern bool CmdIllegalChars(char *string, char *illegal, char *msg);
extern TileType CmdFindNetProc(char *nodename, CellUse *use, Rect *rect, bool warn_not_found, bool *isvalid);
extern bool CmdCheckForPaintFunc(void);
/* C99 compat */
extern int cmdScaleCoord();
extern void FlatCopyAllLabels();
extern bool cmdDumpParseArgs();
extern void cmdFlushCell();
extern int cmdParseCoord();
extern void cmdSaveCell();
extern void CmdInit();
extern int cmdScaleCoord(MagWindow *w, char *arg, bool is_relative, bool is_x, int scale);
extern void FlatCopyAllLabels(SearchContext *scx, TileTypeBitMask *mask, int xMask, CellUse *targetUse);
extern bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dummy, SearchContext *scx);
extern void cmdFlushCell(CellDef *def, bool force_deref);
extern int cmdParseCoord(MagWindow *w, char *arg, bool is_relative, bool is_x);
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
extern void CmdInit(void);
extern void CmdDoProperty();
extern void CmdPaintEraseButton();
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

@ -106,8 +106,57 @@ DBCellFindDup(use, parent)
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
"DBCellFindDup");
while (dupUse = BPEnumNext(&bpe))
if (dupUse->cu_def == use->cu_def) break;
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. Also, array
* counts and separation must match for arrayed devices
*/
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));
/* 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

@ -59,15 +59,15 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
char *
DBPrintUseId(scx, name, size, display_only)
SearchContext *scx; /* Pointer to current search context, specifying a
DBPrintUseId(
SearchContext *scx, /* Pointer to current search context, specifying a
* cell use and X,Y array indices.
*/
char *name; /* Pointer to string into which we will copy the
char *name, /* Pointer to string into which we will copy the
* print name of this instance.
*/
int size; /* Maximum number of characters to copy into string. */
bool display_only; /* TRUE if called for displaying only */
int size, /* Maximum number of characters to copy into string. */
bool display_only) /* TRUE if called for displaying only */
{
CellUse *use = scx->scx_use;
char *sp, *id, *ep;
@ -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

@ -21,6 +21,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */
#include <stdio.h>
#include <string.h> /* For strlen() and strncmp() */
#include <ctype.h> /* for isspace() */
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/geofast.h"
@ -349,6 +352,430 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg);
}
/* Data structure used by dbCopyMaskHintsFunc */
struct propUseDefStruct {
CellDef *puds_source;
CellDef *puds_dest;
Transform *puds_trans; /* Transform from source use to dest */
};
/*
*-----------------------------------------------------------------------------
*
* dbCopyMaskHintsFunc --
*
* Callback function used by DBCellCopyMaskHints(). Does the work
* of copying a "mask-hints" property from a child instance into its
* parent def, modifying coordinates according to the child instance's
* transform.
*
* Results:
* 0 to keep the search going.
*
* Side effects:
* Creates properties in the parent cell.
*
*-----------------------------------------------------------------------------
*/
int
dbCopyMaskHintsFunc(key, value, puds)
char *key;
ClientData value;
struct propUseDefStruct *puds;
{
CellDef *dest = puds->puds_dest;
Transform *trans = puds->puds_trans;
char *propstr = (char *)value;
char *parentprop, *newvalue, *vptr;
Rect r, rnew;
bool propfound;
if (!strncmp(key, "MASKHINTS_", 10))
{
char *vptr, *lastval;
int lastlen;
/* Append to existing mask hint (if any) */
parentprop = (char *)DBPropGet(dest, key, &propfound);
newvalue = (propfound) ? StrDup((char **)NULL, parentprop) : (char *)NULL;
vptr = propstr;
while (*vptr != '\0')
{
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
GeoTransRect(trans, &r, &rnew);
lastval = newvalue;
lastlen = (lastval) ? strlen(lastval) : 0;
newvalue = mallocMagic(40 + lastlen);
if (lastval)
strcpy(newvalue, lastval);
else
*newvalue = '\0';
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
rnew.r_xbot, rnew.r_ybot, rnew.r_xtop, rnew.r_ytop);
if (lastval) freeMagic(lastval);
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
}
else break;
}
if (newvalue)
DBPropPut(dest, key, newvalue);
}
return 0;
}
/*
*-----------------------------------------------------------------------------
*
* DBCellCopyMaskHints --
*
* This function is used by the "flatten -inplace" command option to
* transfer information from mask-hint properties from a flattened
* child cell to the parent.
*
* Results:
* None.
*
* Side effects:
* Properties copied from child to parent cell and modified.
*
*-----------------------------------------------------------------------------
*/
void
DBCellCopyMaskHints(child, parent, transform)
CellUse *child;
CellDef *parent;
Transform *transform;
{
struct propUseDefStruct puds;
puds.puds_source = child->cu_def;
puds.puds_dest = parent;
puds.puds_trans = transform;
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
}
/*
*-----------------------------------------------------------------------------
*
* dbFlatCopyMaskHintsFunc ---
*
* Callback function used by DBFlatCopyMaskHints() to copy mask hint
* properties from a child cell into a flattened cell def. This is
* simply a variant of DBCellCopyMaskHints() above, with arguments
* appropriate to being called from DBTreeSrCells(), and applying
* the transform from the search context.
*
* Results:
* 0 to keep the cell search going.
*
* Side effects:
* Generates properties in the target def.
*
*-----------------------------------------------------------------------------
*/
int
dbFlatCopyMaskHintsFunc(scx, def)
SearchContext *scx;
CellDef *def;
{
struct propUseDefStruct puds;
CellUse *use = scx->scx_use;
puds.puds_source = scx->scx_use->cu_def;
puds.puds_dest = def;
puds.puds_trans = &scx->scx_trans;
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
return 0;
}
/*
*-----------------------------------------------------------------------------
*
* DBFlatCopyMaskHints --
*
* This function is used by the "flatten" command option to copy information
* in mask-hint properties from flattened children to a flattened cell def.
*
* Results:
* None.
*
* Side effects:
* Properties copied from child to parent cell and modified.
*
*-----------------------------------------------------------------------------
*/
void
DBFlatCopyMaskHints(scx, xMask, targetUse)
SearchContext *scx; /* Describes root cell to search, area to
* copy, transform from root cell to coords
* of targetUse.
*/
int xMask; /* Expansion state mask to be used in search */
CellUse *targetUse; /* Cell into which properties will be added */
{
DBTreeSrCells(scx, xMask, dbFlatCopyMaskHintsFunc, (ClientData)targetUse->cu_def);
}
/*
*-----------------------------------------------------------------------------
*
* DBFlattenInPlace --
*
* This function is used by the "flatten" command "-doinplace" option to
* flatten a cell instance into its parent cell.
*
* Results:
* None.
*
* Side effects:
* Indicated cell use is flattened into the edit cell def.
*
*-----------------------------------------------------------------------------
*/
void
DBFlattenInPlace(use, dest, xMask, dolabels, toplabels, doclear)
CellUse *use; /* Cell use to flatten */
CellUse *dest; /* Cell use to flatten into */
int xMask; /* Search mask for flattening */
bool dolabels; /* Option to flatten labels */
bool toplabels; /* Option to selectively flatten top-level labels */
bool doclear; /* Delete the original use if TRUE */
{
Label *lab;
SearchContext scx;
int xsep, ysep, xbase, ybase;
if (dest == NULL)
{
TxError("The target cell does not exist or is not editable.\n");
return;
}
scx.scx_use = use;
scx.scx_area = use->cu_def->cd_bbox;
/* Mark labels in the subcell top level for later handling */
for (lab = scx.scx_use->cu_def->cd_labels; lab; lab = lab->lab_next)
lab->lab_flags |= LABEL_GENERATE;
scx.scx_x = use->cu_xlo;
scx.scx_y = use->cu_ylo;
while (TRUE)
{
if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi))
scx.scx_trans = use->cu_transform;
else
{
if (use->cu_xlo > use->cu_xhi) xsep = -use->cu_xsep;
else xsep = use->cu_xsep;
if (use->cu_ylo > use->cu_yhi) ysep = -use->cu_ysep;
else ysep = use->cu_ysep;
xbase = xsep * (scx.scx_x - use->cu_xlo);
ybase = ysep * (scx.scx_y - use->cu_ylo);
GeoTransTranslate(xbase, ybase, &use->cu_transform, &scx.scx_trans);
}
DBCellCopyAllPaint(&scx, &DBAllButSpaceAndDRCBits, xMask, dest);
if (dolabels)
FlatCopyAllLabels(&scx, &DBAllTypeBits, xMask, dest);
else if (toplabels)
{
int savemask = scx.scx_use->cu_expandMask;
scx.scx_use->cu_expandMask = CU_DESCEND_SPECIAL;
DBCellCopyAllLabels(&scx, &DBAllTypeBits, CU_DESCEND_SPECIAL, dest, NULL);
scx.scx_use->cu_expandMask = savemask;
}
if (xMask != CU_DESCEND_ALL)
DBCellCopyAllCells(&scx, xMask, dest, (Rect *)NULL);
/* Marked labels coming from the subcell top level must not be */
/* ports, and text should be prefixed with the subcell name. */
for (lab = dest->cu_def->cd_labels; lab; lab = lab->lab_next)
{
Label *newlab;
char *newtext;
if (lab->lab_flags & LABEL_GENERATE)
{
newtext = mallocMagic(strlen(lab->lab_text)
+ strlen(scx.scx_use->cu_id) + 2);
if ((use->cu_xlo != use->cu_xhi) && (use->cu_ylo != use->cu_yhi))
sprintf(newtext, "%s[%d][%d]/%s", scx.scx_use->cu_id,
scx.scx_x, scx.scx_y, lab->lab_text);
else if (use->cu_xlo != use->cu_xhi)
sprintf(newtext, "%s[%d]/%s", scx.scx_use->cu_id,
scx.scx_x, lab->lab_text);
else if (use->cu_ylo != use->cu_yhi)
sprintf(newtext, "%s[%d]/%s", scx.scx_use->cu_id,
scx.scx_y, lab->lab_text);
else
sprintf(newtext, "%s/%s", scx.scx_use->cu_id, lab->lab_text);
DBPutFontLabel(dest->cu_def,
&lab->lab_rect, lab->lab_font, lab->lab_size,
lab->lab_rotate, &lab->lab_offset, lab->lab_just,
newtext, lab->lab_type, 0, 0);
DBEraseLabelsByContent(dest->cu_def, &lab->lab_rect,
-1, lab->lab_text);
freeMagic(newtext);
}
}
/* Copy and transform mask hints from child to parent */
DBCellCopyMaskHints(scx.scx_use, dest->cu_def, &scx.scx_trans);
/* Stop processing if the use is not arrayed. */
if ((scx.scx_x == use->cu_xhi) && (scx.scx_y == use->cu_yhi))
break;
if (use->cu_xlo < use->cu_xhi)
scx.scx_x++;
else if (use->cu_xlo > use->cu_xhi)
scx.scx_x--;
if (((use->cu_xlo < use->cu_xhi) && (scx.scx_x > use->cu_xhi)) ||
((use->cu_xlo > use->cu_xhi) && (scx.scx_x < use->cu_xhi)))
{
if (use->cu_ylo < use->cu_yhi)
{
scx.scx_y++;
scx.scx_x = use->cu_xlo;
}
else if (use->cu_ylo > use->cu_yhi)
{
scx.scx_y--;
scx.scx_x = use->cu_xlo;
}
}
}
/* Unmark labels in the subcell top level */
for (lab = scx.scx_use->cu_def->cd_labels; lab; lab = lab->lab_next)
lab->lab_flags &= ~LABEL_GENERATE;
/* Remove the use from the parent def */
if (doclear)
DBDeleteCell(scx.scx_use);
/* Was: &scx.scx_use->cu_def->cd_bbox */
DBWAreaChanged(dest->cu_def, &scx.scx_use->cu_bbox,
DBW_ALLWINDOWS, &DBAllButSpaceAndDRCBits);
}
/* Client data structure used by DBCellFlattenAllCells() */
struct dbFlattenAllData {
CellUse *fad_dest; /* Cell use to flatten into */
int fad_xmask; /* Search mask for flattening */
bool fad_dolabels; /* Option to flatten labels */
bool fad_toplabels; /* Option to selectively flatten top-level labels */
};
/*
*-----------------------------------------------------------------------------
*
* dbCellFlattenCellsFunc --
*
* Do the actual work of flattening cells for DBCellFlattenAllCells().
*
* Results:
* Always return 2.
*
* Side effects:
* Updates the paint planes of EditRootDef.
*
*-----------------------------------------------------------------------------
*/
int
dbCellFlattenCellsFunc(scx, clientData)
SearchContext *scx; /* Pointer to search context containing
* ptr to cell use to be copied,
* and transform to the target def.
*/
ClientData clientData; /* Data passed to client function */
{
CellUse *use, *dest;
int xMask;
bool dolabels;
bool toplabels;
struct dbFlattenAllData *fad = (struct dbFlattenAllData *)clientData;
dest = fad->fad_dest;
xMask = fad->fad_xmask;
dolabels = fad->fad_dolabels;
toplabels = fad->fad_toplabels;
use = scx->scx_use;
DBFlattenInPlace(use, dest, xMask, dolabels, toplabels, FALSE);
return 2;
}
/*
*-----------------------------------------------------------------------------
*
* DBCellFlattenAllCells --
*
* Flatten subcells from the tree rooted at scx->scx_use into the edit root
* CellDef, transforming according to the transform in scx.
*
* Results:
* None.
*
* Side effects:
* Updates the paint planes in EditRootDef.
*
*-----------------------------------------------------------------------------
*/
void
DBCellFlattenAllCells(scx, dest, xMask, dolabels, toplabels)
SearchContext *scx; /* Describes root cell to search and transform
* from root cell to coords of targetUse.
*/
CellUse *dest; /* CellUse to flatten into (usually EditCellUse) */
int xMask; /* Expansion state mask to be passed to
* the flattening routine that determines
* whether to do a shallow or deep flattening.
*/
bool dolabels; /* Option to flatten labels */
bool toplabels; /* Option to selectively flatten top-level labels */
{
int dbCellFlattenCellsFunc();
struct dbFlattenAllData fad;
fad.fad_dest = dest;
fad.fad_xmask = xMask;
fad.fad_dolabels = dolabels;
fad.fad_toplabels = toplabels;
DBTreeSrCells(scx, CU_DESCEND_ALL, dbCellFlattenCellsFunc, (ClientData)&fad);
}
/* Client data structure used by DBCellGenerateSubstrate() */
struct dbCopySubData {
@ -450,6 +877,89 @@ DBCellGenerateSubstrate(scx, subType, notSubMask, subShieldMask, targetDef)
return tempPlane;
}
/*
*-----------------------------------------------------------------------------
*
* DBCellGenerateSimpleSubstrate --
*
* This function is used by the extraction code in "extresist".
* It is similar to DBCellGenerateSubstrate(), above. It finds space
* tiles on the substrate plane and converts them to a substrate type
* in the target, clipped to the cell boundary. This allows the
* extraction to find and record all common (global) substrate regions,
* without requiring a physical substrate type to be drawn into all cells.
*
* Unlike normal paint copying, this can only be done by painting the
* substrate type over the entire cell area and then erasing all areas
* belonging to not-substrate types in the source.
*
* Returns:
* Nothing.
*
* Side Effects:
* Paints into the targetUse's CellDef. This only happens if two
* conditions are met:
* (1) The techfile has defined "substrate"
* (2) The techfile defines a type corresponding to the substrate
*
* ----------------------------------------------------------------------------
*/
Plane *
DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef)
SearchContext *scx;
TileType subType; /* Substrate paint type */
TileTypeBitMask *notSubMask; /* Mask of types that are not substrate */
CellDef *targetDef;
{
struct dbCopySubData csd;
Plane *tempPlane;
int plane;
Rect rect;
TileTypeBitMask allButSubMask;
TileTypeBitMask defaultSubTypeMask;
int dbEraseSubFunc();
int dbPaintSubFunc();
int dbEraseNonSub();
int dbCopySubFunc();
GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &rect);
/* Clip to bounding box of the top level cell */
GEOCLIP(&rect, &scx->scx_use->cu_def->cd_bbox);
plane = DBPlane(subType);
tempPlane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(tempPlane);
csd.csd_subtype = subType;
csd.csd_plane = tempPlane;
csd.csd_pNum = plane;
csd.csd_modified = FALSE;
/* Paint the substrate type in the temporary plane over the area of */
/* the entire cell. */
DBPaintPlane(tempPlane, &rect, DBStdPaintTbl(subType, plane),
(PaintUndoInfo *)NULL);
/* Now erase all areas that are non-substrate types in the source */
DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSub, (ClientData)&csd);
/* Finally, copy the destination plane contents onto tempPlane, */
/* ignoring the substrate type. */
TTMaskZero(&allButSubMask);
TTMaskSetMask(&allButSubMask, &DBAllButSpaceBits);
TTMaskClearType(&allButSubMask, subType);
DBSrPaintArea((Tile *)NULL, targetDef->cd_planes[plane], &TiPlaneRect,
&allButSubMask, dbCopySubFunc, (ClientData)&csd);
/* Now we have a plane where the substrate type occupies the whole */
/* area of the cell except where there are conflicting types (e.g., */
/* nwell). Return this plane. */
return tempPlane;
}
/*
* Callback function for DBCellGenerateSubstrate()
* Finds tiles in the source def that belong to the type that represents
@ -457,14 +967,15 @@ DBCellGenerateSubstrate(scx, subType, notSubMask, subShieldMask, 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 */
@ -473,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);
@ -488,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);
}
@ -500,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 */
@ -516,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);
@ -531,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);
}
@ -544,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;
@ -562,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);
@ -576,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);
}
@ -588,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;
@ -599,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
@ -923,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;
@ -970,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;
@ -979,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;
@ -992,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);
}
@ -1058,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);
@ -1087,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 */
{
@ -1144,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 */
@ -1215,7 +1737,8 @@ DBCellCopyAllCells(scx, xMask, targetUse, pArea)
/* dbCellCopyCellsFunc() allows cells to be left with duplicate IDs */
/* so generate unique IDs as needed now. */
DBGenerateUniqueIds(targetUse->cu_def, FALSE);
if (targetUse != NULL) DBGenerateUniqueIds(targetUse->cu_def, FALSE);
}
/*

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. */
@ -224,7 +232,7 @@ DBCellDelete(cellname, force)
{
HashEntry *entry;
CellDef *celldef;
CellUse *celluse;
CellUse *celluse, *lastuse;
bool result;
entry = HashLookOnly(&dbCellDefTable, cellname);
@ -259,13 +267,36 @@ DBCellDelete(cellname, force)
return FALSE;
}
/* 2nd pass: If there are instances of the cell in */
/* internal cells like SelectDef, etc., then remove the use */
/* from the definition. */
lastuse = NULL;
celluse = celldef->cd_parents;
while (celluse != (CellUse *) NULL)
{
if (celluse->cu_parent != (CellDef *)NULL)
{
if ((celluse->cu_parent->cd_flags & CDINTERNAL) == CDINTERNAL)
{
DBDeleteCell(celluse);
celluse = lastuse;
}
}
lastuse = celluse;
if (lastuse == NULL)
celluse = celldef->cd_parents;
else
celluse = celluse->cu_nextuse;
}
/* Cleared to delete. . . now prompt user if the cell has changes. */
/* Last chance to save! */
if ((force == FALSE) &&
(celldef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED)))
{
static char *yesno[] = { "no", "yes", 0 };
static const char *yesno[] = { "no", "yes", 0 };
int code;
char *prompt = TxPrintString("Cell %s has been modified.\n Do you"
" want to delete it and lose all changes? ",
@ -283,12 +314,13 @@ DBCellDelete(cellname, force)
/* so that WindUnload() will create a new one. */
if (!strcmp(cellname, UNNAMED))
DBCellRename(cellname, "__UNNAMED__");
DBCellRename(cellname, "__UNNAMED__", FALSE);
/* For all top-level cell uses, check if any windows have this */
/* 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)
{
@ -297,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);
@ -368,6 +401,12 @@ dbGetUseName(celluse)
ybuf[0] = '\0';
useID = celluse->cu_id;
if (useID == NULL)
{
newID = (char *)mallocMagic(7);
sprintf(newID, "(null)");
return (newID);
}
newsize = strlen(useID) + 1;
if (isx || isy)
{
@ -637,7 +676,7 @@ DBTopPrint(mw, dolist)
int strcmpbynum(const char *s1, const char *s2)
{
/* Like strcmp() but compare sequences of digits numerically */
/* Like strcasecmp() but compare sequences of digits numerically */
for (;;)
{
if (*s2 == '\0')
@ -646,8 +685,11 @@ int strcmpbynum(const char *s1, const char *s2)
return 1;
else if (!(isdigit(*s1) && isdigit(*s2)))
{
if (*s1 != *s2)
return (int)*s1 - (int)*s2;
char c1, c2;
c1 = tolower(*s1);
c2 = tolower(*s2);
if (c1 != c2)
return (int)c1 - (int)c2;
else
{
++s1;
@ -1118,11 +1160,13 @@ DBUsePrint(CellName, who, dolist)
celldef = DBCellLookDef(CellName);
*lasthier = '/';
}
else
else if (EditCellUse != NULL)
{
/* Referenced cellDef is the current edit def */
celldef = EditCellUse->cu_def;
}
else
return;
switch (who)
{
@ -1304,7 +1348,7 @@ DBLockUse(UseName, bval)
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if (celldef != (CellDef *) NULL)
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL))
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
@ -1383,7 +1427,7 @@ DBOrientUse(UseName, dodef)
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if (celldef != (CellDef *) NULL)
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL))
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
@ -1546,7 +1590,7 @@ DBAbutmentUse(UseName, dolist)
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if (celldef != (CellDef *) NULL)
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL))
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
@ -1598,7 +1642,7 @@ dbAbutmentUseFunc(selUse, use, transform, data)
}
trans = &use->cu_transform;
propvalue = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
propvalue = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
if (!found)
bbox = use->cu_def->cd_bbox;
else
@ -1695,7 +1739,7 @@ DBCellNewDef(cellName)
cellName = UNNAMED;
entry = HashFind(&dbCellDefTable, cellName);
if (HashGetValue(entry) != (ClientData) NULL)
if (HashGetValue(entry) != NULL)
return ((CellDef *) NULL);
cellDef = DBCellDefAlloc();
@ -1856,7 +1900,7 @@ DBCellRenameDef(cellDef, newName)
ASSERT(HashGetValue(oldEntry) == (ClientData) cellDef, "DBCellRenameDef");
newEntry = HashFind(&dbCellDefTable, newName);
if (HashGetValue(newEntry) != (ClientData) NULL)
if (HashGetValue(newEntry) != NULL)
return (FALSE);
HashSetValue(oldEntry, (ClientData) NULL);
@ -1902,6 +1946,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);
@ -1963,8 +2008,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);
@ -2291,8 +2338,14 @@ DBFindUse(id, parentDef)
he = HashLookOnly(&parentDef->cd_idHash, id);
if (delimit != NULL) *delimit = '[';
if (he == NULL)
return (CellUse *) NULL;
{
/* Try again without ignoring the delimiter */
if (delimit != NULL)
he = HashLookOnly(&parentDef->cd_idHash, id);
if (he == NULL)
return (CellUse *) NULL;
}
return (CellUse *) HashGetValue(he);
}
@ -2340,6 +2393,50 @@ DBGenerateUniqueIds(def, warn)
HashKill(&dbUniqueNameTable);
}
/*
* ----------------------------------------------------------------------------
*
* DBSelectionUniqueIds --
*
* This is similar to DBGenerateUniqueIds(), but the purpose is to make
* sure that cell IDs in the selection do not collide with IDs in the
* definition. This is done before copying from Select2Def back to the
* root edit CellDef. Otherwise, any copied cell takes the name of the
* original, and the original gets renamed, which is unexpected behavior.
* Called only from SelectCopy().
*
* Results:
* None.
*
* Side effects:
* May modify the use-id's of the cells in the cell plane of 'selDef'.
*
* ----------------------------------------------------------------------------
*/
void
DBSelectionUniqueIds(selDef, rootDef)
CellDef *selDef; /* Should be Select2Def */
CellDef *rootDef; /* Should be EditRootDef */
{
int dbFindNamesFunc();
int dbGenerateUniqueIdsFunc();
dbWarnUniqueIds = FALSE;
HashInit(&dbUniqueDefTable, 32, 1); /* Indexed by (CellDef *) */
HashInit(&dbUniqueNameTable, 32, 0); /* Indexed by use-id */
/* Build up tables of names */
DBCellEnum(rootDef, dbFindNamesFunc, (ClientData) rootDef);
DBCellEnum(selDef, dbFindNamesFunc, (ClientData) selDef);
/* Assign unique use-ids to all cells in the selection */
DBCellEnum(selDef, dbGenerateUniqueIdsFunc, (ClientData) selDef);
HashKill(&dbUniqueDefTable);
HashKill(&dbUniqueNameTable);
}
/*
* ----------------------------------------------------------------------------
*
@ -2498,7 +2595,7 @@ DBUnLinkCell(use, parentDef)
{
HashEntry *he;
if (he = HashLookOnly(&parentDef->cd_idHash, use->cu_id))
if ((he = HashLookOnly(&parentDef->cd_idHash, use->cu_id)))
HashSetValue(he, (ClientData) NULL);
}
@ -2516,7 +2613,7 @@ DBUnLinkCell(use, parentDef)
* Side effects:
* Fills in *pydef with a newly created CellDef by that name, and
* *pyuse with a newly created CellUse pointing to the new def.
* The CellDef pointed to by *pydef has the CD_INTERNAL flag
* The CellDef pointed to by *pydef has the CDINTERNAL flag
* set, and is marked as being available.
*
* ----------------------------------------------------------------------------

View File

@ -83,16 +83,18 @@ struct seeTypesArg
*/
int
DBSrCellPlaneArea(BPlane *plane, Rect *rect, int (*func)(), ClientData arg)
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))
while ((use = BPEnumNext(bpe)))
{
if ((*func)(use, arg))
{
@ -102,7 +104,7 @@ DBSrCellPlaneArea(BPlane *plane, Rect *rect, int (*func)(), ClientData arg)
}
BPEnumTerm(bpe);
freeMagic(bpe);
/* freeMagic(bpe); */
return rval;
}
@ -118,6 +120,7 @@ DBSrCellPlaneArea(BPlane *plane, Rect *rect, int (*func)(), ClientData arg)
* int
* func(tile, cxp)
* Tile *tile;
* TileType dinfo;
* TreeContext *cxp;
* {
* }
@ -242,10 +245,8 @@ dbCellPlaneSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
context.tc_scx = scx;
context.tc_filter = fp;
@ -364,10 +365,8 @@ dbCellUniqueTileSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
context.tc_scx = scx;
context.tc_filter = fp;
@ -418,6 +417,7 @@ dbCellUniqueTileSrFunc(scx, fp)
* int
* func(tile, cxp)
* Tile *tile;
* TileType dinfo;
* TreeContext *cxp;
* {
* }
@ -476,10 +476,8 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg)
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
filter.tf_func = func;
filter.tf_arg = cdarg;
@ -587,10 +585,8 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels");
if (!DBDescendSubcell(cellUse, xMask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
for (lab = def->cd_labels; lab; lab = lab->lab_next)
{
@ -627,8 +623,8 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
r1.r_ybot = r->r_ytop;
r2.r_xbot = r->r_xtop;
}
is_touching = GEO_TOUCH(&lab->lab_bbox, &r1) ||
GEO_TOUCH(&lab->lab_bbox, &r2);
is_touching = GEO_TOUCH(&lab->lab_rect, &r1) ||
GEO_TOUCH(&lab->lab_rect, &r2);
}
else
is_touching = GEO_TOUCH(&lab->lab_rect, r);
@ -685,7 +681,7 @@ dbCellLabelSrFunc(scx, fp)
{
Label *lab;
Rect *r = &scx->scx_area;
TileTypeBitMask *mask = fp->tf_mask;
const TileTypeBitMask *mask = fp->tf_mask;
CellDef *def = scx->scx_use->cu_def;
char *tnext;
int result;
@ -694,10 +690,8 @@ dbCellLabelSrFunc(scx, fp)
ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc");
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
/* Do not add a path name of a top level window */
if (strncmp(scx->scx_use->cu_id, "Topmost ", 8))
@ -818,11 +812,8 @@ DBTreeSrCells(scx, xMask, func, cdarg)
if (!DBDescendSubcell(cellUse, xMask))
return 0;
if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (cellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(cellUse->cu_def, TRUE, TRUE, NULL))
return 0;
}
context.tc_scx = scx;
context.tc_filter = &filter;
@ -866,11 +857,8 @@ dbTreeCellSrFunc(scx, fp)
else
{
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(use->cu_def, TRUE, TRUE, NULL))
return 0;
}
}
if (fp->tf_xmask == CU_DESCEND_ALL)
{
@ -928,8 +916,9 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
*/
int
dbSeeTypesAllSrFunc(tile, cxp)
dbSeeTypesAllSrFunc(tile, dinfo, cxp)
Tile *tile;
TileType dinfo;
TreeContext *cxp;
{
Rect tileRect;
@ -940,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));
@ -1126,12 +1115,8 @@ DBCellSrArea(scx, func, cdarg)
context.tc_scx = scx;
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(scx->scx_use->cu_def, TRUE, TRUE, NULL))
return 0;
}
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
@ -1253,10 +1238,9 @@ DBCellEnum(cellDef, func, cdarg)
filter.tf_func = func;
filter.tf_arg = cdarg;
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (!DBCellRead(cellDef, TRUE, TRUE, NULL))
return 0;
if (DBSrCellPlaneArea(cellDef->cd_cellPlane,
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
return 1;
@ -1535,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);
@ -1623,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;
@ -1642,17 +1630,20 @@ dbTileScaleFunc(tile, scvals)
if ((targetRect.r_xtop - targetRect.r_xbot == 0) ||
(targetRect.r_ytop - targetRect.r_ybot == 0))
{
TxPrintf("Tile 0x%x at (%d, %d) has zero area after scaling: Removed.\n",
tile, targetRect.r_xbot, targetRect.r_ybot);
TxPrintf("Tile %p at (%d, %d) has zero area after scaling: Removed.\n",
(void *) tile, targetRect.r_xbot, targetRect.r_ybot);
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;
@ -1702,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;
@ -1716,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);
@ -1783,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;
}
@ -1804,7 +1798,7 @@ typedef struct _cellpropstruct {
* dbScaleProp --
*
* Callback function for dbScaleCell. Finds properties that represent
* internal geometry (FIXED_BBOX and MASKHINTS_*) and scale the values
* internal geometry (*_BBOX and MASKHINTS_*) and scale the values
* by the numerator / denominator values passed as a pointer to a Point
* structure, where p_x is the numerator value and p_y is the denominator
* value.
@ -1821,7 +1815,7 @@ int dbScaleProp(name, value, cps)
char *newvalue, *vptr;
Rect r;
if (!strcmp(name, "FIXED_BBOX"))
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
{
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
@ -1899,7 +1893,7 @@ int dbScaleProp(name, value, cps)
* dbMoveProp --
*
* Callback function for ??. Finds properties that represent
* internal geometry (FIXED_BBOX and MASKHINTS_*) and modifies the values
* internal geometry (*_BBOX and MASKHINTS_*) and modifies the values
* by the X, Y values passed as a pointer to a Point structure in ClientData.
*
* ----------------------------------------------------------------------------
@ -1914,7 +1908,8 @@ int dbMoveProp(name, value, cps)
char *newvalue;
Rect r;
if (!strcmp(name, "FIXED_BBOX") || !strncmp(name, "MASKHINTS_", 10))
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|| !strncmp(name, "MASKHINTS_", 10))
{
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
@ -2015,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. */
@ -2072,38 +2069,16 @@ donecell:
DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled);
DBScalePoint(&cellDef->cd_extended.r_ur, scalen, scaled);
/* If the cell is an abstract view with a fixed bounding box, then */
/* adjust the bounding box property to match the new scale. */
if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
{
Rect r;
bool found;
char *propval;
propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
if (found)
{
if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
&r.r_xtop, &r.r_ytop) == 4)
{
DBScalePoint(&r.r_ll, scalen, scaled);
DBScalePoint(&r.r_ur, scalen, scaled);
propval = (char *)mallocMagic(40);
sprintf(propval, "%d %d %d %d", r.r_xbot, r.r_ybot,
r.r_xtop, r.r_ytop);
DBPropPut(cellDef, "FIXED_BBOX", propval);
}
}
}
/* Check all properties for ones with keys beginning with "MASKHINTS_"
* or the key "FIXED_BBOX", and scale them by the same amount as all
* or ending with "_BBOX", and scale them by the same amount as all
* the geometry.
*
* Note: This would be better handled if there were a special type
* for properties which are coordinates; currently the only property
* type is a string, thus requiring the string to be parsed every time
* the coordinates are needed.
*/
cps.cps_point.p_x = scalen;
cps.cps_point.p_y = scaled;
cps.cps_def = cellDef;
@ -2245,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. */
@ -2261,7 +2238,7 @@ DBMoveCell(cellDef, origx, origy)
newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane);
if (dbMovePlane(cellDef->cd_planes[pNum], newplane, pNum,
origx, origy, FALSE))
origx, origy))
cellDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
DBFreePaintPlane(cellDef->cd_planes[pNum]);
TiFreePlane(cellDef->cd_planes[pNum]);
@ -2295,7 +2272,7 @@ donecell:
DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy);
/* Check all properties for ones with keys beginning with "MASKHINTS_"
* or the key "FIXED_BBOX", and move them by the same amount as all
* or ending with "_BBOX", and move them by the same amount as all
* the geometry.
*/

View File

@ -76,12 +76,9 @@ DBDescendSubcell(use, xMask)
case CU_DESCEND_NO_SUBCKT:
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(use->cu_def, TRUE, TRUE, NULL))
return FALSE;
}
return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE;
case CU_DESCEND_NO_LOCK:
@ -221,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;
@ -265,7 +264,7 @@ DBClearPaintPlane(plane)
/* Allocate a new central space tile */
newCenterTile = TiAlloc();
plane->pl_hint = newCenterTile;
PlaneSetHint(plane, newCenterTile);
TiSetBody(newCenterTile, TT_SPACE);
dbSetPlaneTile(plane, newCenterTile);
}

View File

@ -128,7 +128,6 @@ DBInvTransformDiagonal(oldtype, trans)
return dinfo;
}
/*
* ----------------------------------------------------------------------------
*
@ -198,9 +197,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
{
struct conSrArg csa;
int startPlane, result;
Tile *startTile; /* Starting tile for search. */
extern int dbSrConnectFunc(); /* Forward declaration. */
extern int dbSrConnectStartFunc();
TileAndDinfo start_tad; /* Starting tile and split information */
result = 0;
csa.csa_def = def;
@ -211,26 +208,28 @@ 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, (ClientData) &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. */
csa.csa_clientFunc = func;
csa.csa_clientData = clientData;
csa.csa_clientDefault = CLIENTDEFAULT;
csa.csa_clear = FALSE;
csa.csa_connect = connect;
if (dbSrConnectFunc(startTile, &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.
@ -239,18 +238,22 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
SigDisableInterrupts();
csa.csa_clientFunc = NULL;
csa.csa_clear = TRUE;
(void) dbSrConnectFunc(startTile, &csa);
(void) dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo, PTR2CD(&csa));
SigEnableInterrupts();
return result;
}
/** @typedef cb_database_srpaintarea_t */
int
dbSrConnectStartFunc(tile, pTile)
Tile *tile; /* This will be the starting tile. */
Tile **pTile; /* We store tile's address here. */
dbSrConnectStartFunc(
Tile *tile, /* This will be the starting tile. */
TileType dinfo, /* (unused) */
ClientData cdata) /* We store tile and split info here. */
{
*pTile = tile;
TileAndDinfo *tad = (TileAndDinfo *)CD2PTR(cdata);
tad->tad_tile = tile;
tad->tad_dinfo = dinfo;
return 1;
}
@ -288,9 +291,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
{
struct conSrArg csa;
int startPlane, result;
Tile *startTile; /* Starting tile for search. */
extern int dbSrConnectFunc(); /* Forward declaration. */
extern int dbSrConnectStartFunc();
TileAndDinfo tad;
result = 0;
csa.csa_def = def;
@ -301,26 +302,27 @@ 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, (ClientData) &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. */
csa.csa_clientFunc = func;
csa.csa_clientData = clientData;
csa.csa_clientDefault = CLIENTDEFAULT;
csa.csa_clear = FALSE;
csa.csa_connect = connect;
if (dbSrConnectFunc(startTile, &csa) != 0) result = 1;
if (dbSrConnectFunc(tad.tad_tile, tad.tad_dinfo, PTR2CD(&csa)) != 0) result = 1;
return result;
}
@ -343,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;
}
@ -386,15 +391,19 @@ dbcFindTileFunc(tile, arg)
*/
int
dbSrConnectFunc(tile, csa)
Tile *tile; /* Tile that is connected. */
struct conSrArg *csa; /* Contains information about the search. */
dbSrConnectFunc(
Tile *tile, /* Tile that is connected. */
TileType dinfo, /* Split tile information */
ClientData cdata) /* Contains information about the search. */
/* (struct conSrArg *csa) */
{
struct conSrArg *csa = (struct conSrArg *)CD2PTR(cdata);
Tile *t2;
Rect tileArea;
int i, pNum;
int result = 0;
TileTypeBitMask *connectMask;
bool callClient;
const TileTypeBitMask *connectMask;
TileType loctype, checktype;
PlaneMask planes;
@ -403,13 +412,15 @@ dbSrConnectFunc(tile, csa)
/* Drop the first entry on the stack */
pNum = csa->csa_pNum;
STACKPUSH((ClientData)tile, dbConnectStack);
STACKPUSH((ClientData)pNum, dbConnectStack);
STACKPUSH(INT2CD(tile), dbConnectStack);
STACKPUSH(INT2CD(dinfo), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
while (!StackEmpty(dbConnectStack))
{
pNum = (int)STACKPOP(dbConnectStack);
tile = (Tile *)STACKPOP(dbConnectStack);
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
dinfo = (int)CD2INT(STACKPOP(dbConnectStack));
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
if (result == 1) continue;
TiToRect(tile, &tileArea);
@ -422,22 +433,27 @@ dbSrConnectFunc(tile, csa)
* visited.
*/
callClient = TRUE;
if (csa->csa_clear)
{
if (tile->ti_client == (ClientData) CLIENTDEFAULT) continue;
tile->ti_client = (ClientData) CLIENTDEFAULT;
if (tile->ti_client == csa->csa_clientDefault) continue;
tile->ti_client = csa->csa_clientDefault;
}
else
{
if (tile->ti_client != (ClientData) CLIENTDEFAULT) continue;
if (tile->ti_client == (ClientData) 1) continue;
/* Allow a process to mark tiles for skipping the client function */
if (tile->ti_client != csa->csa_clientDefault)
callClient = FALSE;
tile->ti_client = (ClientData) 1;
}
/* Call the client function, if there is one. */
if (csa->csa_clientFunc != NULL)
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;
@ -451,7 +467,7 @@ dbSrConnectFunc(tile, csa)
if (IsSplit(tile))
{
if (SplitSide(tile))
if (dinfo & TT_SIDE)
loctype = SplitRightType(tile);
else
loctype = SplitLeftType(tile);
@ -462,7 +478,7 @@ dbSrConnectFunc(tile, csa)
/* 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))
{
@ -476,20 +492,22 @@ dbSrConnectFunc(tile, csa)
{
if (csa->csa_clear)
{
if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue;
if (t2->ti_client == csa->csa_clientDefault) continue;
}
else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue;
else if (t2->ti_client == (ClientData) 1) continue;
STACKPUSH(INT2CD(t2), dbConnectStack);
if (IsSplit(t2))
TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE)); /* bit set */
STACKPUSH((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)pNum, dbConnectStack);
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
}
/* 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))
@ -504,27 +522,28 @@ bottomside:
{
if (csa->csa_clear)
{
if (t2->ti_client == (ClientData) CLIENTDEFAULT) continue;
if (t2->ti_client == csa->csa_clientDefault) continue;
}
else if (t2->ti_client != (ClientData) CLIENTDEFAULT) continue;
else if (t2->ti_client == (ClientData) 1) continue;
STACKPUSH(INT2CD(t2), dbConnectStack);
if (IsSplit(t2))
{
if (SplitDirection(t2))
/* bit set */
TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE));
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
else
/* bit clear */
TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE));
STACKPUSH(INT2CD(0), dbConnectStack);
}
STACKPUSH((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)pNum, dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
}
/* 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))
{
@ -538,13 +557,12 @@ rightside:
{
if (csa->csa_clear)
{
if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextRight;
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
}
else if (t2->ti_client != (ClientData) CLIENTDEFAULT) goto nextRight;
if (IsSplit(t2))
TiSetBody(t2, (ClientData)(t2->ti_body & ~TT_SIDE)); /* bit clear */
STACKPUSH((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)pNum, dbConnectStack);
else if (t2->ti_client == (ClientData) 1) goto nextRight;
STACKPUSH(INT2CD(t2), dbConnectStack);
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
}
@ -552,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))
{
@ -566,25 +585,28 @@ topside:
{
if (csa->csa_clear)
{
if (t2->ti_client == (ClientData) CLIENTDEFAULT) goto nextTop;
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
}
else if (t2->ti_client != (ClientData) 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, (ClientData)(t2->ti_body & ~TT_SIDE));
STACKPUSH(INT2CD(0), dbConnectStack);
else
/* bit set */
TiSetBody(t2, (ClientData)(t2->ti_body | TT_SIDE));
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
}
STACKPUSH((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)pNum, dbConnectStack);
else
STACKPUSH(INT2CD(0), dbConnectStack);
STACKPUSH(INT2CD(pNum), dbConnectStack);
}
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
}
donesides:
if (pNum < 0) continue; /* Used for single-plane search */
/* Lastly, check to see if this tile connects to anything on
* other planes. If so, search those planes.
@ -596,6 +618,7 @@ donesides:
{
Rect newArea;
GEO_EXPAND(&tileArea, 1, &newArea);
TileAndDinfo tad;
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
{
@ -603,19 +626,21 @@ 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((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)i, 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((ClientData)t2, dbConnectStack);
STACKPUSH((ClientData)i, dbConnectStack);
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
STACKPUSH(INT2CD(i), dbConnectStack);
}
}
}
@ -645,10 +670,13 @@ 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;
@ -740,7 +768,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
CellDef *orig_def = scx->scx_use->cu_def;
Label *slab;
int lidx = lab->lab_port;
TileTypeBitMask *connectMask;
bool foundOne;
const TileTypeBitMask *connectMask;
/* Check for equivalent ports. For any found, call */
/* DBTreeSrTiles recursively on the type and area */
@ -751,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)
@ -769,10 +799,13 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
connectMask = &csa2->csa2_connect[slab->lab_type];
pNum = DBPlane(slab->lab_type);
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
// Do *not* run this check on zero area labels
if (!GEO_RECTNULL(&newarea))
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
&newarea, connectMask, dbcUnconnectFunc,
(ClientData) NULL) == 1)
continue;
continue;
newarea.r_xbot--;
newarea.r_xtop++;
@ -808,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;
}
@ -842,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.
@ -851,12 +899,13 @@ dbcConnectFunc(tile, cx)
{
struct conSrArg2 *csa2;
Rect tileArea, newarea;
TileTypeBitMask *connectMask, notConnectMask;
const TileTypeBitMask *connectMask;
TileTypeBitMask notConnectMask;
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;
@ -888,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
@ -927,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;
@ -936,8 +985,7 @@ dbcConnectFunc(tile, cx)
* the storage for the current list element.
*/
if ((retval == 1) || DBIsContact(loctype))
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
DBNMPaintPlane(def->cd_planes[pNum], newdinfo,
&newarea, DBStdPaintTbl(loctype, pNum),
(PaintUndoInfo *) NULL);
@ -954,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;
@ -1001,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;
}
@ -1067,7 +1115,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse)
*/
{
struct conSrArg2 csa2;
TileTypeBitMask *newmask;
const TileTypeBitMask *newmask;
TileType newtype;
unsigned char searchtype;
@ -1156,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

@ -50,12 +50,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* cell graph; if it returns 0 then the subcells of 'def' are visited;
* if it returns 1 then the subcells are not visited.
*
* int
* void
* hiercount(parent, uses, child, cdata)
* CellDef *parent, *child;
* CellDef *parent;
* int uses; /# Scale factor: number of times child
* # is used by parent
* #/
* CellDef *child;
* ClientData cdata;
* {
* }
@ -103,7 +104,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
struct countArg
{
int (*ca_count)();
int (*ca_hiercount)();
void (*ca_hiercount)();
ClientData ca_cdata;
};
@ -111,7 +112,7 @@ void
DBTreeCountPaint(def, count, hiercount, cleanup, cdata)
CellDef *def;
int (*count)();
int (*hiercount)();
void (*hiercount)();
int (*cleanup)();
ClientData cdata;
{

View File

@ -82,8 +82,7 @@ DBExpand(cellUse, expandMask, expandFlag)
def = cellUse->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
if (!DBCellRead(def, TRUE, TRUE, NULL))
return;
/* Note: we don't have to recompute the bbox here, because
* if it changed, then a timestamp violation must have occurred
@ -144,13 +143,9 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
int dbExpandFunc(), dbUnexpandFunc();
SearchContext scontext;
struct expandArg arg;
bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0)
{
(void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, dereference, NULL);
}
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
/*
* Walk through the area and set the expansion state
@ -160,7 +155,7 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
arg.ea_xmask = expandMask;
arg.ea_func = func;
arg.ea_arg = cdarg;
arg.ea_deref = dereference;
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform;
@ -200,12 +195,16 @@ dbExpandFunc(scx, arg)
/* If the cell is unavailable, then don't expand it.
*/
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, arg->ea_deref, NULL))
{
/* If the parent is dereferenced, then the child should be, too */
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
{
TxError("Cell %s is unavailable. It could not be expanded.\n",
childUse->cu_def->cd_name);
return 2;
}
}
childUse->cu_expandMask |= arg->ea_xmask;
if (arg->ea_func != NULL)
@ -275,8 +274,8 @@ dbUnexpandFunc(scx, arg)
* the given rectangle.
*
* Results:
* If "halt_on_error" is TRUE, then return 1 if any subcell could not
* be read. Otherwise, return 0.
* If "halt_on_error" is TRUE, then return a pointer to the first
* subcell that could not be read. Otherwise, return NULL.
*
* Side effects:
* May make new cells known to the database. Sets the CDAVAILABLE
@ -285,7 +284,7 @@ dbUnexpandFunc(scx, arg)
* ----------------------------------------------------------------------------
*/
int
CellDef *
DBCellReadArea(rootUse, rootRect, halt_on_error)
CellUse *rootUse; /* Root cell use from which search begins */
Rect *rootRect; /* Area to be read, in root coordinates */
@ -293,33 +292,44 @@ DBCellReadArea(rootUse, rootRect, halt_on_error)
{
int dbReadAreaFunc();
SearchContext scontext;
CellDef *err_def = NULL;
scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform;
scontext.scx_area = *rootRect;
if (dbReadAreaFunc(&scontext, halt_on_error) == 1)
return 1;
if (dbReadAreaFunc(&scontext, ((halt_on_error == TRUE) ? &err_def : NULL)) == 1)
return err_def;
return 0;
return NULL;
}
int
dbReadAreaFunc(scx, halt_on_error)
dbReadAreaFunc(scx, err_ptr)
SearchContext *scx; /* Pointer to context specifying
* the cell use to be read in, and
* an area to be recursively read in
* coordinates of the cell use's def.
*/
bool halt_on_error; /* If TURE, failure to find a cell causes a halt */
CellDef **err_ptr; /* If non-NULL, failure to find a cell causes a halt
* and the CellDef in error is returned in err_def.
* If NULL, failure to find a cell still causes a
* halt but no information is passed back to the
* calling routine.
*/
{
CellDef *def = scx->scx_use->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (DBCellRead(def, (char *)NULL, TRUE, dereference, NULL) == FALSE)
if (halt_on_error)
if (DBCellRead(def, TRUE, TRUE, NULL) == FALSE)
{
if (err_ptr != NULL) {
*err_ptr = def;
return 1;
}
else
return 0;
}
/* Note: we don't have to invoke DBReComputeBbox here because
* if the bbox changed then there was a timestamp mismatch and
@ -327,9 +337,8 @@ dbReadAreaFunc(scx, halt_on_error)
*/
}
if (DBCellSrArea(scx, dbReadAreaFunc, (ClientData)halt_on_error))
if (halt_on_error)
return 1;
if (DBCellSrArea(scx, dbReadAreaFunc, (ClientData)err_ptr))
return 1;
/* Be clever about handling arrays: if the search area covers this
* whole definition, then there's no need to look at any other

File diff suppressed because it is too large Load Diff

View File

@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <math.h> /* For sin(), cos(), and round() functions */
#include <ctype.h>
@ -36,12 +37,13 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h"
#include "database/fonts.h"
#include "database/databaseInt.h"
#include "extract/extractInt.h" /* for ExtCurStyle */
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "commands/commands.h"
#include "textio/textio.h"
static TileType DBPickLabelLayer(/* CellDef *def, Label *lab, int noreconnect */);
static TileType DBPickLabelLayer(/* CellDef *def, Label *lab, bool doCalma */);
/* Globally-accessible font information */
@ -278,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)
@ -292,7 +295,7 @@ DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
*/
if (!(lab->lab_type == TT_SPACE))
{
newType = DBPickLabelLayer(cellDef, lab, 0);
newType = DBPickLabelLayer(cellDef, lab, FALSE);
if (DBConnectsTo(newType, lab->lab_type)) goto nextLab;
}
}
@ -311,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;
@ -319,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;
@ -440,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)
@ -455,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!
@ -465,6 +470,7 @@ DBEraseLabelsByContent(def, rect, type, text)
if (lab == NULL) break;
else goto nextCheck;
}
freeMagic1_end(&mm1);
}
/*
@ -493,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)
@ -506,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!
@ -516,6 +523,7 @@ DBRemoveLabel(def, refLab)
if (lab == NULL) break;
else goto nextCheck;
}
freeMagic1_end(&mm1);
}
/*
@ -560,6 +568,42 @@ DBReOrientLabel(cellDef, area, newPos)
}
}
/*
* ----------------------------------------------------------------------------
*
* dbGetLabelArea ---
*
* Callback function used by DBAdjustLabels. Find all material under a label
* that is *not* the label type, and return the
*
* Note: This clips in a regular order, and does not consider what is the
* largest rectangular area outside the area that has been clipped out.
*
* ----------------------------------------------------------------------------
*/
int
dbGetLabelArea(tile, dinfo, area)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information (unused) */
Rect *area; /* Area to be modified. */
{
Rect r;
TiToRect(tile, &r);
if (r.r_xbot > area->r_xbot)
area->r_xtop = r.r_xbot;
else if (r.r_xtop < area->r_xtop)
area->r_xbot = r.r_xtop;
else if (r.r_ybot > area->r_ybot)
area->r_ytop = r.r_ybot;
else if (r.r_ytop < area->r_ytop)
area->r_ybot = r.r_ytop;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -589,7 +633,7 @@ DBAdjustLabels(def, area)
{
Label *lab;
TileType newType;
bool modified = FALSE;
bool modified = FALSE, adjusted = FALSE;
/* First, find each label that crosses the area we're
* interested in.
@ -598,18 +642,63 @@ DBAdjustLabels(def, area)
for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
{
if (!GEO_TOUCH(&lab->lab_rect, area)) continue;
newType = DBPickLabelLayer(def, lab, 0);
newType = DBPickLabelLayer(def, lab, FALSE);
if (newType == lab->lab_type) continue;
if (lab->lab_flags & LABEL_STICKY) continue;
if (DBVerbose && ((def->cd_flags & CDINTERNAL) == 0)) {
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
};
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
/* New behavior (5/2024) (idea from Philipp Guhring)---If the new
* type is space, then instead of immediately casting the label off
* of its material, find the amount of the label that is still
* covered by the material. If the material covers more than half
* the label area, then adjust the label area to match the material.
*/
adjusted = FALSE;
if (newType == TT_SPACE)
{
Rect r;
TileTypeBitMask lmask;
TTMaskSetOnlyType(&lmask, lab->lab_type);
/* To do: Add compatible types (contact, residue) */
TTMaskCom(&lmask);
r = lab->lab_rect;
DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)],
&lab->lab_rect, &lmask, dbGetLabelArea, (ClientData) &r);
if (!GEO_RECTNULL(&r))
{
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
{
TxPrintf("Adjusting size of label \"%s\" in cell %s.\n",
lab->lab_text, def->cd_name);
}
DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
lab->lab_rect = r;
DBFontLabelSetBBox(lab);
DBUndoPutLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
modified = TRUE;
adjusted = TRUE;
}
}
if (!adjusted)
{
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
{
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
}
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
}
}
if (modified) DBCellSetModified(def, TRUE);
@ -617,16 +706,32 @@ DBAdjustLabels(def, area)
/*
* Extended version of DBAdjustLabels. If noreconnect==0,
* this is supposed to be the same as DBAdjustlabels() above.
*---------------------------------------------------------------
*
* DBAdjustLabelsNew--
*
* Modified version of DBAdjustLabels, used with reading
* GDS and LEF files. Since those files use GDS layers and
* not magic layers, there is no exact relationship between
* the two. Instead, the cifinput rules are used to set an
* initial type only. The rules for label adjustment are
* different from DBAdjustLabels(), and so a different
* routine is called.
*
* Results:
* None.
*
* Side effects:
* The layer attachments of labels may change. For each
* such change, a message is output.
*
*---------------------------------------------------------------
*/
void
DBAdjustLabelsNew(def, area, noreconnect)
DBAdjustLabelsNew(def, area)
CellDef *def; /* Cell whose paint was changed. */
Rect *area; /* Area where paint was modified. */
int noreconnect; /* if 1, don't move label to a type that doesn't
* connect to the original type, delete instead
*/
{
Label *lab, *labPrev;
TileType newType;
@ -640,46 +745,59 @@ DBAdjustLabelsNew(def, area, noreconnect)
lab = def->cd_labels;
while (lab != NULL)
{
int locnoreconnect = noreconnect;
if (!GEO_TOUCH(&lab->lab_rect, area)) {
goto nextLab;
}
if (lab->lab_type == TT_SPACE) locnoreconnect = FALSE;
newType = DBPickLabelLayer(def, lab, locnoreconnect);
if (newType == lab->lab_type) {
goto nextLab;
}
if(newType < 0 && !(lab->lab_flags & LABEL_STICKY)) {
TxPrintf("Deleting ambiguous-layer label \"%s\" from %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
def->cd_name);
bool doCalma = TRUE;
if (!GEO_TOUCH(&lab->lab_rect, area)) goto nextLab;
if (lab->lab_type == TT_SPACE) doCalma = FALSE;
newType = DBPickLabelLayer(def, lab, doCalma);
if (newType == lab->lab_type)
goto nextLab;
if (labPrev == NULL)
def->cd_labels = lab->lab_next;
else
labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev;
DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
freeMagic((char *) lab);
lab = lab->lab_next;
modified = TRUE;
continue;
} else if (!(lab->lab_flags & LABEL_STICKY)) {
if (DBVerbose && ((def->cd_flags & CDINTERNAL) == 0)) {
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
}
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
if (((newType < 0) || (newType == TT_SPACE)) && !(lab->lab_flags & LABEL_STICKY))
{
if (lab->lab_type == TT_SPACE)
{
TxPrintf("Deleting unattached label \"%s\" in cell %s.\n",
lab->lab_text, def->cd_name);
if (labPrev == NULL)
def->cd_labels = lab->lab_next;
else
labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev;
DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *) lab);
lab = lab->lab_next;
freeMagic1_end(&mm1);
modified = TRUE;
continue;
}
nextLab:
labPrev = lab;
lab = lab->lab_next;
else
{
TxPrintf("Making label \"%s\" on type %s in cell %s sticky.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
def->cd_name);
lab->lab_flags |= LABEL_STICKY;
}
}
else if (!(lab->lab_flags & LABEL_STICKY))
{
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
{
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
}
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
}
nextLab:
labPrev = lab;
lab = lab->lab_next;
}
if (modified) DBCellSetModified(def, TRUE);
@ -715,10 +833,10 @@ TileTypeBitMask *dbAdjustPlaneTypes; /* Mask of all types in current
* plane being searched.
*/
TileType
DBPickLabelLayer(def, lab, noreconnect)
DBPickLabelLayer(def, lab, doCalma)
CellDef *def; /* Cell definition containing label. */
Label *lab; /* Label for which a home must be found. */
int noreconnect; /* if 1, return -1 if rule 5 or 6 would succeed */
bool doCalma; /* if TRUE, use rules for GDS and LEF */
{
TileTypeBitMask types[3], types2[3];
Rect check1, check2;
@ -819,112 +937,147 @@ DBPickLabelLayer(def, lab, noreconnect)
}
/* If the label's layer covers the label's area, use it.
* Otherwise, look for a layer in the following order:
* 1. A layer on the same plane as the original layer and that
* covers the label and connects to its original layer.
* 2. A layer on the same plane as the original layer and that
* is a component of material that covers the label and
* connects to its original layer.
* 3. A layer that covers the label and connects to the
* old layer.
* 4. A layer that is a component of material that covers
* the label and connects to the old layer.
* 5. A layer that covers the label.
* 6. A layer that is a component of material that covers the label.
* 7. Space.
* Otherwise, look for a layer in the following order
* (Note: "covers" means covers the area of the label if the
* label has area or touches the entire label if it doesn't.):
*
* If "doCalma" is TRUE, then:
* 1. A layer on the same plane as the original layer and that
* covers the label and is not a device type.
* 2. A layer on the same plane as the original layer and that
* covers the label.
* 3. A layer on the same plane as the original layer and that
* is a component of material that covers the label.
* 4. -1
*
* If "doCalma" is FALSE, then:
* 1. A layer on the same plane as the original layer and that
* covers the label and connects to its original layer.
* 2. A layer on the same plane as the original layer and that
* is a component of material that covers the label and
* connects to its original layer.
* 3. A layer that covers the label and connects to the old layer.
* 4. A layer that is a component of material that covers the
* label and connects to the old layer.
* 5. A layer that covers the label and is on the same plane as the
* label.
* 6. A layer that is a component of material that covers the label
* and is on the same plane as the label.
* 7. Space.
*
* All searches are done from the lowest to highest plane, so that
* the label connects to material on the highest plane that matches
* the criteria above. This avoids weirdnesses caused by declaring
* types out of order in the techfile.
*
* Note that when the "label" command is used with no type given,
* then lab_type is TT_SPACE and "same plane as the label" is all
* planes. This should never be true when called during GDS or
* LEF reads, so only needs to be checked when "doCalma" is FALSE.
*/
if (TTMaskHasType(&types[0], lab->lab_type)) return lab->lab_type;
plane = DBPlane(lab->lab_type);
choice1 = choice2 = choice3 = choice4 = choice5 = choice6 = TT_SPACE;
for (j = PL_SELECTBASE; j < DBNumPlanes; j++)
if (doCalma)
{
choice1 = choice2 = choice3 = -1;
for (i = TT_SELECTBASE; i < DBNumUserLayers; i += 1)
{
if (!TTMaskHasType(&DBPlaneTypes[j], i)) continue;
if (!TTMaskHasType(&DBPlaneTypes[plane], i)) continue;
if (DBConnectsTo(i, lab->lab_type))
if (TTMaskHasType(&types[0], i) && (ExtCurStyle != NULL))
{
if (DBPlane(i) == plane)
{
if (TTMaskHasType(&types[0], i))
{
choice1 = i;
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice2 = i;
continue;
}
}
if (TTMaskHasType(&types[0], i))
{
choice3 = i;
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice4 = i;
continue;
}
}
if (TTMaskHasType(&types[0], i))
{
/* A type that connects to more than itself is preferred */
if (choice5 == TT_SPACE)
choice5 = i;
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, i))
choice2 = i;
else
{
TileTypeBitMask ctest;
TTMaskZero(&ctest);
TTMaskSetMask(&ctest, &DBConnectTbl[i]);
TTMaskClearType(&ctest, i);
if (!TTMaskIsZero(&ctest))
choice5 = i;
else if (TTMaskHasType(&types[1], i))
choice6 = i;
}
choice1 = i;
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice6 = i;
choice3 = i;
continue;
}
}
}
if (choice1 != TT_SPACE) return choice1;
else if (choice2 != TT_SPACE) return choice2;
else if (choice3 != TT_SPACE) return choice3;
else if (choice4 != TT_SPACE) return choice4;
else if (noreconnect) {
#ifdef notdef
TxPrintf("DBPickLabelLayer \"%s\" (on %s at %d,%d) choice4=%s choice5=%s choice6=%s.\n",
lab->lab_text,
DBTypeLongName(lab->lab_type),
lab->lab_rect.r_xbot,
lab->lab_rect.r_ytop,
DBTypeLongName(choice4),
DBTypeLongName(choice5),
DBTypeLongName(choice6));
#endif
/* If the flag is set, don't cause a netlist change by moving a
the label. So unless there's only space here, delete the label */
if(choice5 == TT_SPACE && choice6 == TT_SPACE)
return TT_SPACE;
else
return -1;
if (choice1 != -1) return choice1;
else if (choice2 != -1) return choice2;
else return choice3;
}
else
{
choice1 = choice2 = choice3 = choice4 = choice5 = choice6 = TT_SPACE;
for (j = PL_SELECTBASE; j < DBNumPlanes; j++)
{
for (i = TT_SELECTBASE; i < DBNumUserLayers; i += 1)
{
if (!TTMaskHasType(&DBPlaneTypes[j], i)) continue;
if (DBConnectsTo(i, lab->lab_type))
{
if (DBPlane(i) == plane)
{
if (TTMaskHasType(&types[0], i))
{
choice1 = i;
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice2 = i;
continue;
}
}
if (TTMaskHasType(&types[0], i))
{
choice3 = i;
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice4 = i;
continue;
}
}
if ((DBPlane(i) == plane) || (lab->lab_type == TT_SPACE))
{
if (TTMaskHasType(&types[0], i))
{
/* A type that connects to more than itself is preferred */
if (choice5 == TT_SPACE)
choice5 = i;
else
{
TileTypeBitMask ctest;
TTMaskZero(&ctest);
TTMaskSetMask(&ctest, &DBConnectTbl[i]);
TTMaskClearType(&ctest, i);
if (!TTMaskIsZero(&ctest))
choice5 = i;
else if (TTMaskHasType(&types[1], i))
choice6 = i;
}
continue;
}
else if (TTMaskHasType(&types[1], i))
{
choice6 = i;
continue;
}
}
}
}
if (choice1 != TT_SPACE) return choice1;
else if (choice2 != TT_SPACE) return choice2;
else if (choice3 != TT_SPACE) return choice3;
else if (choice4 != TT_SPACE) return choice4;
else if (choice5 != TT_SPACE) return choice5;
else return choice6;
}
else if (choice5 != TT_SPACE) return choice5;
else return choice6;
}
/* Search function for DBPickLabelLayer: just OR in the type of
@ -933,14 +1086,15 @@ DBPickLabelLayer(def, lab, noreconnect)
*/
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);
@ -959,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);
@ -1405,7 +1560,7 @@ DBLoadFont(fontfile, scale)
float scale;
{
FILE *ff;
char *ascii_names[] = {
const char * const ascii_names[] = {
"space", "exclam", "quotedbl", "numbersign", "dollar",
"percent", "ampersand", "quoteright", "parenleft", "parenright",
"asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
@ -1510,7 +1665,7 @@ DBLoadFont(fontfile, scale)
{
if (psname != NULL)
{
asciiidx = LookupStructFull(psname, ascii_names, sizeof(char *));
asciiidx = LookupStructFull(psname, ascii_names, sizeof(const char *));
if (asciiidx >= 0)
chardef = 2;
}
@ -1600,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

@ -225,7 +225,7 @@ DBSrLabelLoc(rootUse, name, func, cdarg)
char csave;
Rect r;
if (cp = strrchr(name, '/'))
if ((cp = strrchr(name, '/')))
{
csave = *cp;
*cp = '\0';
@ -294,10 +294,7 @@ DBTreeFindUse(name, use, scx)
* is read in from disk.
*/
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
}
(void) DBCellRead(def, TRUE, TRUE, NULL);
cp = name;
he = HashLookOnly(&def->cd_idHash, name);
@ -346,10 +343,7 @@ DBTreeFindUse(name, use, scx)
/* Ensure that the leaf cell is read in */
def = use->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
}
DBCellRead(def, TRUE, TRUE, NULL);
scx->scx_use = use;
}

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 */
@ -240,7 +242,7 @@ int
DBPaintPlane0(plane, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */
PaintResultType *resultTbl; /* Table, indexed by the type of tile already
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to
* which the existing tile must change as a
* result of this paint operation.
@ -271,9 +273,10 @@ 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 = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -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)");
@ -648,7 +669,7 @@ done:
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
while (TOP(tile) > area->r_ybot)
@ -696,7 +717,8 @@ enum2:
}
done2:
plane->pl_hint = tile;
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -719,7 +741,7 @@ DBSplitTile(plane, point, splitx)
int splitx;
{
Tile *tile, *newtile, *tp;
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, point);
if (IsSplit(tile)) /* This should always be true */
@ -766,7 +788,7 @@ void
DBFracturePlane(plane, area, resultTbl, undo)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */
PaintResultType *resultTbl; /* Paint table, to pinpoint those tiles
const PaintResultType *resultTbl; /* Paint table, to pinpoint those tiles
* that interact with the paint type.
*/
PaintUndoInfo *undo; /* Record containing everything needed to
@ -793,7 +815,7 @@ DBFracturePlane(plane, area, resultTbl, undo)
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -990,7 +1012,7 @@ paintdone:
}
done:
plane->pl_hint = tile;
PlaneSetHint(plane, tile);
}
/*
@ -1032,11 +1054,12 @@ 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;
start.p_y = area->r_ytop - 1;
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -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 */
@ -1306,7 +1329,8 @@ nmenum:
}
nmdone:
plane->pl_hint = tile;
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -1315,7 +1339,7 @@ nmdone:
* DBDiagonalProc(type) --
*
* Return the result type of a diagonal tile painted on oldtype;
* Argument "cdata", gives direction and side of diagonal, and the
* Argument "dinfo", gives direction and side of diagonal, and the
* paint result table for the given diagonal side.
*
* If the result cannot be described with a single tile, then
@ -1333,15 +1357,14 @@ nmdone:
*/
int
DBDiagonalProc(oldtype, cdata)
DBDiagonalProc(oldtype, dinfo)
TileType oldtype;
ClientData cdata;
DiagInfo *dinfo;
{
TileType old_n, old_s, old_e, old_w;
TileType new_n, new_s, new_e, new_w;
TileType newtype;
DiagInfo *dinfo = (DiagInfo *)cdata;
PaintResultType *resultTbl = dinfo->resultTbl;
const PaintResultType *resultTbl = dinfo->resultTbl;
/* Disassemble old and new types into four quadrants, find the */
/* paint result for each quadrant, then reassemble the result. */
@ -1412,10 +1435,6 @@ DBDiagonalProc(oldtype, cdata)
else
return -1;
/* For purposes of "undo" recording, record which side we just painted */
if (dinfo->side)
newtype |= TT_SIDE;
return newtype;
}
@ -1458,7 +1477,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */
TileType exacttype; /* diagonal info for tile to be changed */
Rect *area; /* Area to be changed */
PaintResultType *resultTbl; /* Table, indexed by the type of tile already
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to
* which the existing tile must change as a
* result of this paint operation.
@ -1500,7 +1519,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
/* linked list out of them. */
lhead = NULL;
DBSrPaintArea(plane->pl_hint, plane, area, &DBAllTypeBits,
DBSrPaintArea(PlaneGetHint(plane), plane, area, &DBAllTypeBits,
dbNMEnumFunc, (ClientData) &lhead);
/*--------------------------------------------------------------*/
@ -1520,7 +1539,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
GeoClip(&lhead->r_r, area);
start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1;
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Ignore tiles that don't interact. This has */
@ -1609,7 +1628,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
{
result = DBPaintPlane(plane, &(lr->r_r), DBSpecialPaintTbl,
(PaintUndoInfo *)NULL);
tile = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &(lr->r_r.r_ll));
if (undo && UndoIsEnabled())
{
@ -1769,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) ?
@ -1795,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);
@ -1886,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;
@ -1992,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");
@ -2008,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");
@ -2017,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");
@ -2026,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);
}
@ -2065,7 +2089,7 @@ void
DBPaintType(plane, area, resultTbl, client, undo, tileMask)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */
PaintResultType *resultTbl; /* Table, indexed by the type of tile already
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to
* which the existing tile must change as a
* result of this paint operation.
@ -2095,9 +2119,10 @@ 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 = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -2187,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 */
@ -2211,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
@ -2277,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)");
@ -2287,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,7 +2359,8 @@ paintdone:
}
done:
plane->pl_hint = tile;
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
}
/*
@ -2381,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;
@ -2482,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");
@ -2498,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");
@ -2507,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");
@ -2516,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);
}
@ -2556,7 +2584,7 @@ int
DBPaintPlaneVert(plane, area, resultTbl, undo)
Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */
PaintResultType *resultTbl; /* Table, indexed by the type of tile already
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to
* which the existing tile must change as a
* result of this paint operation.
@ -2582,9 +2610,10 @@ 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 = plane->pl_hint;
tile = PlaneGetHint(plane);
GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -2663,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 */
@ -2679,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
@ -2741,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)");
@ -2750,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,7 +2826,8 @@ paintdone:
}
done:
plane->pl_hint = tile;
PlaneSetHint(plane, tile);
TiFreeIf(delayed);
return 0;
}
@ -2850,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;
@ -2944,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");
@ -2957,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");
@ -2967,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");
@ -2976,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);
}
@ -3005,7 +3037,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
* ----------------------------------------------------------------------------
*/
#include "styles.h"
#include "utils/styles.h"
void
dbPaintShowTile(tile, undo, str)
@ -3028,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 */
@ -3317,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;
@ -3348,7 +3391,7 @@ TiNMMergeRight(tile, plane)
else
newtile = tile;
// Join tp to newtile
TiJoinX(newtile, tp, plane);
TiJoinX1(&delayed, newtile, tp, plane);
}
tp = tp2;
}
@ -3365,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;
}
@ -3397,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;
@ -3429,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;
@ -3447,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;
}
@ -283,6 +284,7 @@ DBPaintValid(cellDef, rect, mask, dinfo)
for (t = TT_SELECTBASE; t < DBNumUserLayers; t++)
if (TTMaskHasType(&mmask, t))
{
if (DBIsContact(t))
{
tMask = DBResidueMask(t);
@ -310,6 +312,7 @@ DBPaintValid(cellDef, rect, mask, dinfo)
(t << 14) : t) : t);
DBPaint(cellDef, rect, tloc);
}
}
}
/*
@ -382,6 +385,7 @@ DBEraseValid(cellDef, rect, mask, dinfo)
for (t = TT_SELECTBASE; t < DBNumUserLayers; t++)
if (TTMaskHasType(&mmask, t))
{
if (DBIsContact(t))
{
tMask = DBResidueMask(t);
@ -409,4 +413,5 @@ DBEraseValid(cellDef, rect, mask, dinfo)
(t << 14) : t) : t);
DBErase(cellDef, rect, tloc);
}
}
}

View File

@ -895,6 +895,24 @@ DBIsContact(type)
return FALSE;
}
/*
* ----------------------------------------------------------------------------
*
* DBLayerPlanes --
*
* Like LayerPlaneMask(), except as a subroutine, not a macro. For export
* to other routines.
*
* ----------------------------------------------------------------------------
*/
PlaneMask
DBLayerPlanes(type)
TileType type;
{
return LayerPlaneMask(type);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -223,7 +223,7 @@ DBTechSetVersion(sectionName, argc, argv)
major = minor = rev = 0;
rmajor = rminor = rrev = 0;
if (sscanf(vstring, "%d.%d.%d", &rmajor, &rminor, &rrev) == 0)
if (sscanf(vstring, "%d.%d.%d", &rmajor, &rminor, &rrev) != 3)
{
TechError("Badly formed magic version string, should be major.minor.rev\n");
return FALSE;

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};
@ -70,28 +70,28 @@ TileTypeBitMask DBTechActiveLayerBits; /* Layers marked locked in the techfile *
/* Table of default, builtin planes */
DefaultPlane dbTechDefaultPlanes[] =
{
PL_ROUTER, "router",
PL_DRC_ERROR, "designRuleError",
PL_DRC_CHECK, "designRuleCheck",
PL_M_HINT, "mhint",
PL_F_HINT, "fhint",
PL_R_HINT, "rhint",
0, 0, 0
{PL_ROUTER, "router"},
{PL_DRC_ERROR, "designRuleError"},
{PL_DRC_CHECK, "designRuleCheck"},
{PL_M_HINT, "mhint"},
{PL_F_HINT, "fhint"},
{PL_R_HINT, "rhint"},
{0, NULL}
};
/* Table of default, builtin types */
DefaultType dbTechDefaultTypes[] =
{
TT_SPACE, -1, "space", FALSE,
TT_CHECKPAINT, PL_DRC_CHECK, "checkpaint,CP", FALSE,
TT_CHECKSUBCELL, PL_DRC_CHECK, "checksubcell,CS", FALSE,
TT_ERROR_P, PL_DRC_ERROR, "error_p,EP", FALSE,
TT_ERROR_S, PL_DRC_ERROR, "error_s,ES", FALSE,
TT_ERROR_PS, PL_DRC_ERROR, "error_ps,EPS", FALSE,
TT_MAGNET, PL_M_HINT, "magnet,mag", TRUE,
TT_FENCE, PL_F_HINT, "fence,f", TRUE,
TT_ROTATE, PL_R_HINT, "rotate,r", TRUE,
0, 0, NULL, 0
{TT_SPACE, -1, "space", FALSE},
{TT_CHECKPAINT, PL_DRC_CHECK, "checkpaint,CP", FALSE},
{TT_CHECKSUBCELL, PL_DRC_CHECK, "checksubcell,CS", FALSE},
{TT_ERROR_P, PL_DRC_ERROR, "error_p,EP", FALSE},
{TT_ERROR_S, PL_DRC_ERROR, "error_s,ES", FALSE},
{TT_ERROR_PS, PL_DRC_ERROR, "error_ps,EPS", FALSE},
{TT_MAGNET, PL_M_HINT, "magnet,mag", TRUE},
{TT_FENCE, PL_F_HINT, "fence,f", TRUE},
{TT_ROTATE, PL_R_HINT, "rotate,r", TRUE},
{0, 0, NULL, 0}
};
/* Forward declarations */
@ -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 */
@ -140,7 +142,7 @@ DBTechInitPlane()
for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++)
{
cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane,
cp = dbTechNameAdd(dpp->dp_names, INT2CD(dpp->dp_plane),
&dbPlaneNameLists, FALSE);
if (cp == NULL)
{
@ -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 */
@ -223,7 +227,7 @@ DBTechInitType()
*/
for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
{
cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type,
cp = dbTechNameAdd(dtp->dt_names, INT2CD(dtp->dt_type),
&dbTypeNameLists, FALSE);
if (cp == NULL)
{
@ -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)
{
@ -283,7 +287,7 @@ DBTechAddPlane(sectionName, argc, argv)
return FALSE;
}
cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists, FALSE);
cp = dbTechNameAdd(argv[0], INT2CD(DBNumPlanes), &dbPlaneNameLists, FALSE);
if (cp == NULL)
return FALSE;
DBPlaneLongNameTbl[DBNumPlanes++] = cp;
@ -315,7 +319,7 @@ DBTechAddNameToType(newname, ttype, canonical)
{
char *cp;
cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists, TRUE);
cp = dbTechNameAdd(newname, INT2CD(ttype), &dbTypeNameLists, TRUE);
if (canonical)
DBTypeLongNameTbl[ttype] = cp;
}
@ -455,7 +459,7 @@ DBTechAddType(sectionName, argc, argv)
}
else
{
cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
cp = dbTechNameAdd(argv[1], INT2CD(DBNumTypes), &dbTypeNameLists, FALSE);
if (cp == NULL)
return FALSE;
@ -513,7 +517,7 @@ dbTechNewStackedType(type1, type2)
}
sprintf(buf, "%s+%s", DBTypeShortName(type1), DBTypeShortName(type2));
cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
cp = dbTechNameAdd(buf, INT2CD(DBNumTypes), &dbTypeNameLists, FALSE);
if (cp == NULL)
{
TechError("Couldn't generate new stacking type %s\n", buf);

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. */
@ -121,7 +412,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
start.p_x = rect->r_xbot;
start.p_y = rect->r_ytop - 1;
tp = hintTile ? hintTile : plane->pl_hint;
tp = hintTile ? hintTile : PlaneGetHint(plane);
GOTOPOINT(tp, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -129,7 +420,7 @@ DBSrPaintNMArea(hintTile, plane, ttype, rect, mask, func, arg)
{
/* Each iteration enumerates another tile */
nm_enum:
plane->pl_hint = 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, (ClientData)(tpt & ~TT_SIDE)); /* bit clear */
if ((*func)(tp, arg)) return (1);
}
if (!(ignore_sides & IGNORE_RIGHT))
{
TiSetBody(tp, (ClientData)(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;
* {
* }
@ -372,7 +543,7 @@ DBSrPaintArea(hintTile, plane, rect, mask, func, arg)
start.p_x = rect->r_xbot;
start.p_y = rect->r_ytop - 1;
tp = hintTile ? hintTile : plane->pl_hint;
tp = hintTile ? hintTile : PlaneGetHint(plane);
GOTOPOINT(tp, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -380,7 +551,7 @@ DBSrPaintArea(hintTile, plane, rect, mask, func, arg)
{
/* Each iteration enumerates another tile */
enumerate:
plane->pl_hint = tp;
PlaneSetHint(plane, tp);
if (SigInterruptPending)
return (1);
@ -416,9 +587,7 @@ enumerate:
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
{
TiSetBody(tp, (ClientData)((TileType)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, (ClientData)((TileType)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;
* {
* }
@ -532,7 +700,7 @@ DBSrPaintClient(hintTile, plane, rect, mask, client, func, arg)
start.p_x = rect->r_xbot;
start.p_y = rect->r_ytop - 1;
tp = hintTile ? hintTile : plane->pl_hint;
tp = hintTile ? hintTile : PlaneGetHint(plane);
GOTOPOINT(tp, &start);
/* Each iteration visits another tile on the LHS of the search area */
@ -540,7 +708,7 @@ DBSrPaintClient(hintTile, plane, rect, mask, client, func, arg)
{
/* Each iteration enumerates another tile */
enumerate:
plane->pl_hint = tp;
PlaneSetHint(plane, tp);
if (SigInterruptPending)
return (1);
@ -565,20 +733,18 @@ enumerate:
theight = TOP(tp) - BOTTOM(tp);
twidth = RIGHT(tp) - LEFT(tp);
f1 = (rect->r_ybot > MINFINITY + 2) ?
(TOP(tp) - rect->r_ybot) * twidth : DLONG_MAX;
(dlong)(TOP(tp) - rect->r_ybot) * (dlong)twidth : DLONG_MAX;
f2 = (rect->r_ytop < INFINITY - 2) ?
(rect->r_ytop - BOTTOM(tp)) * twidth : DLONG_MAX;
(dlong)(rect->r_ytop - BOTTOM(tp)) * (dlong)twidth : DLONG_MAX;
if (TTMaskHasType(mask, SplitLeftType(tp)))
{
/* !Outside-of-triangle check */
f4 = (rect->r_xbot > MINFINITY + 2) ?
(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
{
TiSetBody(tp, (ClientData)((TileType)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);
}
}
@ -587,19 +753,18 @@ enumerate:
{
/* !Outside-of-triangle check */
f3 = (rect->r_xtop < INFINITY - 2) ?
(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
{
TiSetBody(tp, (ClientData)((TileType)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);
@ -657,7 +822,7 @@ DBResetTilePlane(plane, cdata)
ClientData cdata;
{
Tile *tp, *tpnew;
Rect *rect = &TiPlaneRect;
const Rect *rect = &TiPlaneRect;
/* Start with the leftmost non-infinity tile in the plane */
tp = TR(plane->pl_left);
@ -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.
*
* --------------------------------------------------------------------
*/
@ -735,11 +980,12 @@ DBFreePaintPlane(plane)
Plane *plane; /* Plane whose storage is to be freed */
{
Tile *tp, *tpnew;
Rect *rect = &TiPlaneRect;
const Rect *rect = &TiPlaneRect;
/* 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

@ -84,6 +84,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
int timestamp;
typedef struct _celllist {
CellDef *cl_cell;
struct _celllist *cl_next;
} CellList;
/*
* ----------------------------------------------------------------------------
@ -107,9 +111,9 @@ DBFixMismatch()
{
CellDef *cellDef;
CellUse *parentUse;
CellList *cl = NULL, *clnew;
Rect oldArea, parentArea, tmp;
int redisplay;
int firstOne = TRUE;
Mismatch *tmpm;
/* It's very important to disable interrupts during this section!
@ -118,7 +122,7 @@ DBFixMismatch()
redisplay = FALSE;
if (mismatch == NULL) return;
TxPrintf("Processing timestamp mismatches:");
TxPrintf("Processing timestamp mismatches.\n");
SigDisableInterrupts();
for (tmpm = mismatch; tmpm; tmpm = tmpm->mm_next)
@ -126,8 +130,6 @@ DBFixMismatch()
while (mismatch != NULL)
{
bool dereference;
/* Be careful to remove the front element from the mismatch
* list before processing it, because while processing it we
* may add new elements to the list.
@ -135,12 +137,13 @@ 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;
dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL);
(void) DBCellRead(cellDef, TRUE, TRUE, NULL);
/* Jimmy up the cell's current bounding box, so the following
* procedure call will absolutely and positively know that
@ -174,15 +177,22 @@ DBFixMismatch()
redisplay = TRUE;
}
cellDef->cd_flags |= CDPROCESSED;
if (firstOne)
{
TxPrintf(" %s", cellDef->cd_name);
firstOne = FALSE;
}
else TxPrintf(", %s", cellDef->cd_name);
TxFlush(); /* This is needed to prevent _doprnt screwups */
clnew = (CellList *)mallocMagic(sizeof(CellList));
clnew->cl_cell = cellDef;
clnew->cl_next = cl;
cl = clnew;
}
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(", ");
freeMagic1(&mm1, cl);
cl = cl->cl_next;
}
freeMagic1_end(&mm1);
TxPrintf(".\n");
TxFlush();
if (redisplay) WindAreaChanged((MagWindow *) NULL, (Rect *) NULL);
@ -221,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);
@ -241,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;

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