Compare commits

..

No commits in common. "master" and "8.3.18" have entirely different histories.

866 changed files with 32521 additions and 77838 deletions

View File

@ -1 +0,0 @@
./appimage

5
.gitconfig Normal file
View File

@ -0,0 +1,5 @@
[filter "header"]
smudge = ./.git-expand-header %f
clean = sed -e's/\\$Header:[^$]*\\$/\\$Header\\$/g'
[diff "gds"]
textconv = hexdump -v -C

View File

@ -1,170 +0,0 @@
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}}

View File

@ -1,170 +0,0 @@
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}}

View File

@ -1,170 +0,0 @@
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}}

View File

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

View File

@ -1,291 +0,0 @@
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
sudo apt-get update
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

View File

@ -1,23 +0,0 @@
# CI for native ARM64 Linux build.
name: CI-aarch64
on:
push:
pull_request:
workflow_dispatch:
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)

View File

@ -1,475 +0,0 @@
# 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

@ -1,256 +0,0 @@
name: CI-wasm
# Builds the Magic WebAssembly target (both the non-TCL and TCL variants)
# on every push and pull request as a CI check. **Publishing** only happens
# when a release tag of the form <x.y.z>... (optionally v-prefixed) is
# pushed — the same tag that triggers the AppImage release workflows:
#
# # bump magic/VERSION, commit, push to default branch
# git tag 8.3.638
# git push origin 8.3.638
#
# The tag name (minus any leading "v") provides the base; the workflow appends
# the commit date and short SHA: 8.3.799 → 8.3.799020261231+git01234cde.
# Forks publish under their own namespace via the @<owner>/ scope.
on:
push:
pull_request:
workflow_dispatch:
inputs:
emsdk_version:
description: 'emsdk version to build with (default: latest; pin a version number to bisect)'
type: string
default: 'latest'
tcl_ref:
description: 'TCL ref to build against (default: auto-resolve latest stable tag). Use a tag like core-9-0-3, a branch, or a commit SHA to bisect a regression.'
type: string
default: ''
tcl_repo_url:
description: 'TCL repository URL (default: https://github.com/tcltk/tcl.git)'
type: string
default: ''
dry_run:
description: 'Dry run: pack only, do not publish even on tag pushes'
type: boolean
default: true
# actions/upload-artifact@v5 still runs on Node.js 20. Force Node 24 to
# silence the deprecation warning until upload-artifact ships a Node-24
# release. Drop this once upgraded.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
packages: write
jobs:
build-wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 2
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: '22'
registry-url: 'https://npm.pkg.github.com'
- name: Install emsdk
env:
# Defaults to latest so CI tracks emsdk HEAD and catches breakage early.
# Override via workflow_dispatch to pin a specific version when needed
# (e.g. to bisect a regression or verify a post-build.sh patch still applies).
EMSDK_VERSION: ${{ github.event.inputs.emsdk_version || 'latest' }}
run: |
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install "$EMSDK_VERSION"
./emsdk activate "$EMSDK_VERSION"
# Dump native + emscripten preprocessor defines. Useful for diagnosing
# WASM-build differences after an emsdk bump.
- name: Emscripten Diagnostic
run: |
source ./emsdk/emsdk_env.sh
echo "===== gcc -dM -E - ====="; echo | gcc -dM -E - | sort
echo "===== g++ -dM -E - ====="; echo | g++ -dM -E - | sort
echo "===== emcc -dM -E - ====="; echo | emcc -dM -E - | sort
echo "===== em++ -dM -E - ====="; echo | em++ -dM -E - | sort
# Determine which TCL ref to build against.
# Priority: workflow_dispatch input > auto-resolved latest stable tag.
# TCL stable releases follow the core-<major>-<even_minor>-<patch>
# naming convention; core-9-0-x is the current stable series.
# Falls back to main only if no release tags are found at all.
- name: Resolve TCL ref
id: resolve-tcl
env:
TCL_REPO_URL: ${{ github.event.inputs.tcl_repo_url || 'https://github.com/tcltk/tcl.git' }}
TCL_REF_INPUT: ${{ github.event.inputs.tcl_ref || '' }}
run: |
if [ -n "$TCL_REF_INPUT" ]; then
TCL_REF="$TCL_REF_INPUT"
echo "Using workflow_dispatch TCL_REF: $TCL_REF"
else
TCL_REF=$(git ls-remote --tags --sort=-version:refname "$TCL_REPO_URL" \
'refs/tags/core-9-0-*' \
| grep -v '\^{}' \
| head -1 \
| awk '{print $2}' \
| sed 's|refs/tags/||')
if [ -z "$TCL_REF" ]; then
TCL_REF=main
echo "Warning: no stable core-9-0-x tag found, falling back to main"
else
echo "Auto-resolved latest stable TCL tag: $TCL_REF"
fi
fi
echo "tcl_ref=$TCL_REF" >> "$GITHUB_OUTPUT"
echo "tcl_repo_url=$TCL_REPO_URL" >> "$GITHUB_OUTPUT"
# Clone tcltk/tcl into a sibling directory at the resolved ref.
# Done as an explicit step so the exact commit is visible in the job
# log. The source tree is read-only — the WASM build runs inside magic.
- name: Clone tcltk/tcl
env:
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
run: |
# autocrlf=false: ubuntu-latest is already LF, but make it explicit.
git -c core.autocrlf=false clone "$TCL_REPO_URL" ../tcl
cd ../tcl
git checkout --detach "$TCL_REF"
echo "=== TCL commit ==="
git log -n1 --format="commit %H%nauthor %an <%ae>%ndate %ci%nref %D%n%n %s"
- name: Build WASM — both variants (tcl + notcl)
env:
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
run: |
source ./emsdk/emsdk_env.sh
bash npm/build.sh --variant=both
- name: Run example tests (non-TCL variant)
run: cd npm && npm test
- name: Run full test suite (TCL variant)
run: cd npm && npm run test:tcl
# Dump generated text outputs (.ext, .spice, .cif, …) into the CI log
# so a regression in extraction / netlisting / cifoutput is visible
# without having to download artifacts. The .gds output is binary —
# skip it and just record its size.
- name: Display example outputs
run: |
shopt -s nullglob
for dir in npm/examples/output npm/examples/output-tcl; do
[ -d "$dir" ] || continue
echo "======== $dir ========"
for f in "$dir"/*; do
name=$(basename "$f")
case "$f" in
*.gds) echo "===== $name (binary, $(wc -c < "$f") bytes — skipped) =====" ;;
*) echo "===== $name ====="; cat "$f" ;;
esac
done
done
# The release gate. We publish a new npm version only when a tag of the
# shape <x.y.z>... (optionally v-prefixed) is pushed, matching the
# AppImage release workflows so one tag releases everything.
#
# Version scheme (per dmiles' recommendation):
# {MAJOR}.{MINOR}.{PATCH}0{YYYYMMDD}+git{SHORT_SHA}
# e.g. 8.3.799 pushed on 2026-12-31 → 8.3.799020261231+git01234cde
#
# The leading zero between PATCH and date keeps the number readable and
# ensures correct numeric ordering: 799020261231 < 800020261231.
# Build metadata (+git...) is ignored by npm for comparison but retained
# for traceability. Security patches for the 799 series can be inserted
# as later dates (799020270101, 799020270201, …) and are matched by the
# range <=8.3.799900000000 or <8.3.8000000000000.
- name: Determine release version (tag-driven only)
id: release
run: |
date=$(git show -s --format=%cs | tr -d '-')
hash=$(git show -s --format=%h)
if [ "${{ github.event_name }}" = "push" ] && \
echo "${{ github.ref }}" | grep -Eq '^refs/tags/v?[0-9]+\.[0-9]+\.[0-9]+'; then
tag="${GITHUB_REF#refs/tags/}"
base="${tag#v}"
echo "publish=true" >> "$GITHUB_OUTPUT"
echo "version=${base}0${date}+git${hash}" >> "$GITHUB_OUTPUT"
echo "Tag release: $tag → npm version ${base}0${date}+git${hash}"
else
base=$(cat VERSION)
echo "publish=false" >> "$GITHUB_OUTPUT"
echo "version=${base}0${date}+git${hash}" >> "$GITHUB_OUTPUT"
echo "Non-tag build: will not publish."
fi
- name: Set package version and scope
env:
VERSION: ${{ steps.release.outputs.version }}
run: |
# Scope the package to the repo owner so it lands in the right
# GitHub Packages namespace regardless of who hosts the repo.
SCOPED_NAME="@${{ github.repository_owner }}/magic-vlsi-wasm"
cd npm
npm pkg set name="$SCOPED_NAME"
npm pkg set publishConfig.registry="https://npm.pkg.github.com"
npm version "$VERSION" --no-git-tag-version --allow-same-version
- name: Pack
run: ./npm/pack.sh
- name: Upload tarball as artifact
uses: actions/upload-artifact@v5
with:
name: magic-vlsi-wasm-npm
path: npm/*.tgz
- name: Publish to GitHub Packages
if: steps.release.outputs.publish == 'true' && github.event.inputs.dry_run != 'true'
run: cd npm && npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Write a Markdown summary visible next to the artifacts on the Actions
# page. Captures the exact versions used so a future regression can be
# bisected without scrolling through raw logs.
- name: Build summary
if: always()
env:
TCL_REF: ${{ steps.resolve-tcl.outputs.tcl_ref }}
TCL_REPO_URL: ${{ steps.resolve-tcl.outputs.tcl_repo_url }}
run: |
source ./emsdk/emsdk_env.sh 2>/dev/null || true
EMCC_VER=$(emcc --version 2>/dev/null | head -1 || echo "unavailable")
GCC_VER=$(gcc --version 2>/dev/null | head -1 || echo "unavailable")
NODE_VER=$(node --version 2>/dev/null || echo "unavailable")
MAGIC_VER=$(cat VERSION 2>/dev/null || echo "unavailable")
if [ -d ../tcl/.git ]; then
TCL_SHA=$(cd ../tcl && git rev-parse HEAD)
TCL_DATE=$(cd ../tcl && git log -1 --format="%ci")
TCL_SUBJECT=$(cd ../tcl && git log -1 --format="%s")
else
TCL_SHA="(not cloned)"; TCL_DATE=""; TCL_SUBJECT=""
fi
printf '## Build info\n\n' >> "$GITHUB_STEP_SUMMARY"
printf '| Component | Details |\n' >> "$GITHUB_STEP_SUMMARY"
printf '|-----------|----------|\n' >> "$GITHUB_STEP_SUMMARY"
printf '| Magic | `%s` |\n' "$MAGIC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| Emscripten | %s |\n' "$EMCC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| GCC | %s |\n' "$GCC_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| Node.js | %s |\n' "$NODE_VER" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL repo | %s |\n' "$TCL_REPO_URL" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL ref | `%s` |\n' "$TCL_REF" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL commit | `%s` |\n' "$TCL_SHA" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL date | %s |\n' "$TCL_DATE" >> "$GITHUB_STEP_SUMMARY"
printf '| TCL subject | %s |\n' "$TCL_SUBJECT" >> "$GITHUB_STEP_SUMMARY"

View File

@ -1,21 +0,0 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
jobs:
simple_build_linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- 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)

50
.gitignore vendored
View File

@ -1,63 +1,29 @@
# Autoconf / configure outputs
defs.mak defs.mak
!toolchains/emscripten/defs.mak */Depend
config.cache config.cache
config.log config.log
scripts/config.log scripts/config.log
scripts/config.status scripts/config.status
scripts/defs.mak scripts/defs.mak
install.log
make.log
reconfigure.sh
# Compiled objects / libraries
*.o
*.a
*.so
*/Depend
database/database.h
# Editor / OS cruft
.*.swp .*.swp
.*.swo *.o
*.so
*~ *~
.DS_Store
.vscode/
.idea/
# Magic runtime-generated files
magic/proto.magicrc
scmos/cif_template/objs/* scmos/cif_template/objs/*
database/database.h
install.log
magic/proto.magicrc
make.log
readline/readline
scmos/gdsquery.tech scmos/gdsquery.tech
scmos/minimum.tech scmos/minimum.tech
scmos/scmos-sub.tech scmos/scmos-sub.tech
scmos/scmos-tm.tech scmos/scmos-tm.tech
scmos/scmos.tech scmos/scmos.tech
scmos/scmosWR.tech scmos/scmosWR.tech
scmos/nmos.tech
# Native build artifacts
magic/magic
magic/tclmagic.dylib
tcltk/magic.sh tcltk/magic.sh
tcltk/magic.tcl tcltk/magic.tcl
tcltk/magicdnull tcltk/magicdnull
tcltk/magicexec tcltk/magicexec
tcltk/ext2spice.sh tcltk/ext2spice.sh
tcltk/ext2sim.sh tcltk/ext2sim.sh
tcltk/magicdnull.dSYM/
tcltk/magicexec.dSYM/
pfx/
# WASM build artifacts
magic/magic.js
magic/magic.js.symbols
magic/magic.symbols
magic/magic.wasm
build-tcl-wasm/
net2ir/net2ir
net2ir/net2ir.js
net2ir/net2ir.wasm
# Generated test output
npm/examples/output/

View File

@ -47,12 +47,6 @@ Autoconf Capsule Summary:
Disable threaded X11 and OpenGL graphics. Disable threaded X11 and OpenGL graphics.
Normally enabled. 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: Notes to Magic maintainers:
-------------------------- --------------------------

View File

@ -1,79 +0,0 @@
# Installing Magic on macOS (Tested on Big Sur)
## With Brew
Get [Homebrew](https://brew.sh).
```sh
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
```
## Without Brew
Get [XQuartz](https://github.com/XQuartz/XQuartz)
### Build Tcl for X11
We are following the instructions from xschem (https://github.com/StefanSchippers/xschem/blob/master/README_MacOS.md).
* Download Tcl from https://prdownloads.sourceforge.net/tcl/tcl8.6.10-src.tar.gz
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
make install
```
### Build Tk for X11
* 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 \
--x-includes=/opt/X11/include --x-libraries=/opt/X11/lib
make
make install
```
### Build magic
We need to provide this `tcl-tk` and suppress compilation errors.
```
./configure --with-tcl=/usr/local/opt2/tcl-tk/lib \
--with-tk=/usr/local/opt2/tcl-tk/lib \
--x-includes=/opt/X11/include \
--x-libraries=/opt/X11/lib \
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.

110
Makefile
View File

@ -4,33 +4,31 @@
MAGICDIR = . MAGICDIR = .
PROGRAMS = magic PROGRAMS = magic
TECHS = scmos TECH = scmos
LIBRARIES = database utils extflat LIBRARIES = database utils extflat
MODULES = bplane cmwind commands database dbwind debug drc extflat \ MODULES = bplane cmwind commands database dbwind debug drc extflat \
extract graphics netmenu plow resis select sim textio tiles \ extract graphics netmenu plow resis select sim textio tiles \
utils windows wiring utils windows wiring
# This was `cat VERSION`
VERSION := $(shell cat ${MAGICDIR}/VERSION)
MAKEFLAGS = MAKEFLAGS =
INSTALL_CAD_DIRS = windows doc ${TECHS} INSTALL_CAD_DIRS = windows doc ${TECH}
-include defs.mak -include defs.mak
all: $(ALL_TARGET) techs all: $(ALL_TARGET)
standard: mains standard:
@echo --- errors and warnings logged in file make.log
@${MAKE} mains 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)"
tcl: tcllibrary tcl:
@echo --- errors and warnings logged in file make.log
@${MAKE} tcllibrary 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)"
force: force: clean all
@${MAKE} clean
@${MAKE} all
defs.mak: defs.mak:
@echo No \"defs.mak\" file found. Run "configure" to make one. @echo No \"defs.mak\" file found. Run "configure" to make one.
@exit 1
config: config:
${MAGICDIR}/configure ${MAGICDIR}/configure
@ -38,70 +36,39 @@ config:
tcllibrary: database/database.h modules tcllibrary: database/database.h modules
@echo --- making Tcl shared libraries @echo --- making Tcl shared libraries
for dir in ${PROGRAMS}; do \ for dir in ${PROGRAMS}; do \
(cd $$dir && ${MAKE} tcl-main) || exit 1; done (cd $$dir && ${MAKE} tcl-main); done
mains: database/database.h modules libs mains: database/database.h modules libs
@echo --- making main programs @echo --- making main programs
for dir in ${PROGRAMS}; do \ for dir in ${PROGRAMS}; do \
(cd $$dir && ${MAKE} main) || exit 1; done (cd $$dir && ${MAKE} main); done
database/database.h: ${MAGICDIR}/database/database.h.in database/database.h: database/database.h.in
@echo --- making header file database/database.h @echo --- making header file database/database.h
${SCRIPTS}/makedbh ${MAGICDIR}/database/database.h.in database/database.h ${SCRIPTS}/makedbh database/database.h.in database/database.h
# tiles xyz => tiles/libtiles.o xyz/libxyz.o modules: database/database.h depend
MODULES_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.o"; done) @echo --- making modules
# tiles xyz => tiles/libtiles.a xyz/libxyz.a for dir in ${MODULES} ${PROGRAMS}; do \
LIBS_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.a"; done) (cd $$dir && ${MAKE} module); done
.PHONY: FORCE libs:
${MODULES_SUBDIR}: FORCE @echo --- making libraries
@${MAKE} -C $(dir $@) module for dir in ${LIBRARIES}; do \
(cd $$dir && ${MAKE} lib); done
.PHONY: modules depend: database/database.h
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 @echo --- making dependencies
${MAKE} -C $(dir $@) depend ${RM} */Depend
for dir in ${MODULES} ${UNUSED_MODULES} ${PROGRAMS}; do \
.PHONY: depend (cd $$dir && ${MAKE} depend); done
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) install: $(INSTALL_TARGET)
install-magic: install-magic:
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-real @${MAKE} install-real 2>&1 >> install.log
install-real: install-dirs install-real: install-dirs
for dir in ${INSTALL_CAD_DIRS}; do \ for dir in ${INSTALL_CAD_DIRS}; do \
@ -122,14 +89,14 @@ install-dirs:
install-tcl: install-tcl:
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-tcl-real @${MAKE} install-tcl-real 2>&1 >> install.log
install-tcl-real: install-tcl-dirs install-tcl-real: install-tcl-dirs
for dir in ${INSTALL_CAD_DIRS} ${PROGRAMS}; do \ for dir in ${INSTALL_CAD_DIRS} ${PROGRAMS}; do \
(cd $$dir && ${MAKE} install-tcl); done (cd $$dir && ${MAKE} install-tcl); done
clean: clean:
for dir in ${SUBDIRS_FILTERED} ${TECHS} ${BUNDLED_MODULES}; do \ for dir in ${MODULES} ${PROGRAMS} ${TECH} ${UNUSED_MODULES}; do \
(cd $$dir && ${MAKE} clean); done (cd $$dir && ${MAKE} clean); done
${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags ${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags
@ -139,19 +106,18 @@ distclean:
${RM} defs.mak old.defs.mak ${MAGICDIR}/scripts/defs.mak ${RM} defs.mak old.defs.mak ${MAGICDIR}/scripts/defs.mak
${RM} ${MAGICDIR}/scripts/default.conf ${RM} ${MAGICDIR}/scripts/default.conf
${RM} ${MAGICDIR}/scripts/config.log ${MAGICDIR}/scripts/config.status ${RM} ${MAGICDIR}/scripts/config.log ${MAGICDIR}/scripts/config.status
${RM} database/database.h ${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz
${RM} scripts/magic.spec magic-${VERSION} magic-${VERSION}.tgz
${RM} *.log ${RM} *.log
dist: dist:
${RM} scripts/magic.spec magic-${VERSION} magic-${VERSION}.tgz ${RM} scripts/magic.spec magic-`cat VERSION` magic-`cat VERSION`.tgz
${SED} -e /@VERSION@/s%@VERSION@%${VERSION}% \ sed -e /@VERSION@/s%@VERSION@%`cat VERSION`% \
scripts/magic.spec.in > scripts/magic.spec scripts/magic.spec.in > scripts/magic.spec
${LN} -nsf . magic-${VERSION} ln -nsf . magic-`cat VERSION`
tar zchvf magic-${VERSION}.tgz --exclude CVS \ tar zchvf magic-`cat VERSION`.tgz --exclude CVS \
--exclude magic-${VERSION}/magic-${VERSION} \ --exclude magic-`cat VERSION`/magic-`cat VERSION` \
--exclude magic-${VERSION}/magic-${VERSION}.tgz \ --exclude magic-`cat VERSION`/magic-`cat VERSION`.tgz \
magic-${VERSION} magic-`cat VERSION`
clean-mains: clean-mains:
for dir in ${PROGRAMS}; do \ for dir in ${PROGRAMS}; do \
@ -168,6 +134,6 @@ TAGS:
setup-git: setup-git:
git config --local include.path ../.gitconfig git config --local include.path ../.gitconfig
git stash save git stash save
${RM} .git/index rm .git/index
git checkout HEAD -- "$$(git rev-parse --show-toplevel)" git checkout HEAD -- "$$(git rev-parse --show-toplevel)"
git stash pop git stash pop

View File

@ -1,40 +1,23 @@
![Continuous Integration](https://github.com/RTimothyEdwards/magic/actions/workflows/main.yml/badge.svg)
# MAGIC
1. General Information: 1. General Information:
--------------------------------- ---------------------------------
Use your World Wide Web browser to read: Use your World Wide Web browser to read:
http://opencircuitdesign.com/magic/ http://opencircuitdesign.com/magic/
http://vlsi.csl.cornell.edu/magic/
http://www.research.digital.com/wrl/magic/magic.html
Primary documentation is on the opencircuitdesign.com website under Primary documentation is on the opencircuitdesign.com website under
various links, including "Download", "Compile", and "Install" for the "Documentation" link.
information on obtaining, compiling, and installing the tool from
source; "Code History" for detailed comments on all code changes;
"Using Magic" for basic usage information including a complete on-line
command reference; "Technology Files" for essential documentation on how
to understand, edit, or write technology files for Magic; "Documentation"
for miscellaneous papers and historical documentation converted to HTML
format.
The current distribution version of magic is maintained by Tim Edwards
<tim@opencircuitdesign.com>. Please let me know of any problems/bugs
you find through the github Issues tracker.
Additional information from developer Rajit Manohar:
https://csl.yale.edu/~rajit/magic/
Of mainly historical interest only, now (available through the WayBack machine):
https://web.archive.org/web/20051217204815/http://www.research.compaq.com:80/wrl/projects/magic/magic.html
The current development versions of magic are maintained by Tim Edwards
<tim@opencircuitdesign.com> and the current distribution version is
maintained by Rajit Manohar <rajit@csl.cornell.edu>. Please let us
know of any problems/bugs you find. Development of versions 7.2 and
newer is generously funded by MultiGiG, Inc.
2. Compilation and Installation: 2. Compilation and Installation:
--------------------------------- ---------------------------------
See the file "INSTALL" in this directory, or "INSTALL_MacOS.md" for MacOS. See the file "INSTALL" in this directory.
3. Version 8.3 Release Notes: 3. Version 8.3 Release Notes:
--------------------------------- ---------------------------------

View File

@ -1 +1 @@
8.3.664 8.3.18

4
appimage/.gitignore vendored
View File

@ -1,4 +0,0 @@
*.tar.gz
prefix/
*.AppImage
appimagetool

View File

@ -1,59 +0,0 @@
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"]

View File

@ -1,46 +0,0 @@
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

View File

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

View File

@ -1,68 +0,0 @@
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"]

View File

@ -1,46 +0,0 @@
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

View File

@ -1,137 +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.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 |

View File

@ -1,58 +0,0 @@
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"]

View File

@ -1,46 +0,0 @@
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

View File

@ -1,126 +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.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 |

View File

@ -1,59 +0,0 @@
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"]

View File

@ -1,46 +0,0 @@
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

View File

@ -1,128 +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.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,39 +0,0 @@
#!/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"
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

@ -1,8 +0,0 @@
[Desktop Entry]
Type=Application
Name=Magic
Icon=magic
Exec=magic
Comment=Magic - A VLSI Layout System
Categories=Development;
Terminal=true

View File

@ -1,65 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 464.731 464.731" style="enable-background:new 0 0 464.731 464.731;" xml:space="preserve">
<g id="XMLID_207_">
<path id="XMLID_212_" d="M463.056,441.971l-45.894-43.145l29.759-55.521c0.8-1.508,0.379-3.398-1.029-4.395
c-1.388-1.011-3.305-0.832-4.487,0.424l-43.146,45.895l-55.533-29.746c-1.515-0.803-3.399-0.377-4.395,1.027
c-1.017,1.392-0.815,3.309,0.438,4.488l45.911,43.162l-29.747,55.518c-0.816,1.525-0.378,3.401,1.01,4.412
c1.41,0.996,3.326,0.816,4.502-0.438l43.149-45.912l55.507,29.746c1.506,0.802,3.393,0.378,4.393-1.027
C464.506,445.072,464.308,443.136,463.056,441.971z"/>
<path id="XMLID_211_" d="M369.086,94.641l-20.273,37.826c-1.04,1.918-0.479,4.307,1.285,5.588c1.783,1.271,4.215,1.029,5.71-0.559
l29.417-31.269l37.78,20.26c1.921,1.024,4.323,0.484,5.589-1.285c1.271-1.783,1.048-4.215-0.555-5.709l-31.245-29.385
l20.274-37.814c1.028-1.918,0.466-4.307-1.297-5.59c-1.766-1.268-4.216-1.025-5.713,0.558l-29.381,31.257l-37.814-20.273
c-1.936-1.026-4.325-0.467-5.589,1.301c-1.273,1.766-1.042,4.214,0.544,5.711L369.086,94.641z"/>
<path id="XMLID_210_" d="M123.956,360.06l-44.659,6.239l-17.611-41.484c-0.906-2.113-3.217-3.232-5.423-2.631
c-2.226,0.623-3.626,2.78-3.313,5.051l6.239,44.639L17.69,389.489c-2.1,0.908-3.23,3.217-2.614,5.424
c0.609,2.219,2.767,3.629,5.032,3.31l44.657-6.241l17.611,41.5c0.896,2.118,3.218,3.236,5.425,2.629
c2.206-0.617,3.626-2.765,3.312-5.043l-6.238-44.658l41.5-17.617c2.099-0.904,3.234-3.217,2.612-5.423
C128.383,361.147,126.221,359.745,123.956,360.06z"/>
<path id="XMLID_209_" d="M4.908,45.161l34.646,9.537l-0.23,35.832c-0.012,2.01,1.449,3.704,3.447,3.99
c1.976,0.271,3.851-0.969,4.377-2.901l9.521-34.565l35.923,0.225c2.01,0.016,3.702-1.447,3.992-3.441
c0.271-1.982-0.97-3.853-2.905-4.383l-34.627-9.547l0.213-35.881c0.018-2.01-1.466-3.701-3.441-3.988
c-1.983-0.273-3.856,0.965-4.383,2.901l-9.533,34.608L5.996,37.324c-1.991,0-3.701,1.463-3.974,3.441
C1.751,42.747,2.992,44.633,4.908,45.161z"/>
<path id="XMLID_208_" d="M278.019,234.519l139.775-18.477c1.586-0.21,2.762-1.555,2.762-3.143c0-1.587-1.176-2.928-2.762-3.142
L278.019,191.28l20.476-57.755c0.857-2.446,0.235-5.183-1.603-7.009c-1.828-1.844-4.567-2.445-7.01-1.586l-57.697,20.484
L213.708,5.688c-0.194-1.588-1.554-2.764-3.14-2.764c-1.584,0-2.935,1.176-3.146,2.764l-18.457,139.744l-57.772-20.502
c-2.448-0.875-5.181-0.258-7.014,1.586c-1.84,1.826-2.46,4.563-1.586,7.009l20.489,57.772l-139.73,18.46
c-1.584,0.214-2.762,1.555-2.762,3.142c0,1.588,1.178,2.933,2.762,3.143l139.73,18.461l-20.489,57.742
c-0.874,2.447-0.254,5.182,1.586,7.01c1.833,1.842,4.565,2.462,7.014,1.582l57.772-20.467l18.457,139.743
c0.212,1.583,1.563,2.764,3.146,2.764c1.586,0,2.945-1.181,3.14-2.764l18.477-139.743l57.727,20.486
c2.441,0.876,5.181,0.256,7.009-1.589c1.845-1.825,2.461-4.562,1.584-7.007L278.019,234.519z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,4 +0,0 @@
# 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 */ /* allocate array */
size = sizeof(BinArray) + numBins*(sizeof(void *)); size = sizeof(BinArray) + numBins*(sizeof(void *));
new = (BinArray *)callocMagic(1, size); new = (BinArray *)callocMagic(size);
/* initial */ /* initial */
new->ba_bbox = *bbox; new->ba_bbox = *bbox;
@ -567,9 +567,6 @@ BinArray *bpBinArrayBuild(Rect bbox,
int numBins; int numBins;
int count; 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); if(BPD) DumpRect("#### bpBinArrayBuild, TOP bbox= ", &bbox);

View File

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

View File

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

View File

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

View File

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

View File

@ -27,12 +27,12 @@
#ifndef _MAGIC__BPLANE__BPOPAQUE_H #ifndef _BPOPAQUE_H
#define _MAGIC__BPLANE__BPOPAQUE_H #define _BPOPAQUE_H
#ifndef _MAGIC__UTILS__IHASH_H #ifndef _IHASH_H
#include "utils/ihash.h" #include "utils/ihash.h"
#endif #endif /* _IHASH_H */
/* /*
* bpOpaque.h -- * bpOpaque.h --
@ -106,7 +106,7 @@ static __inline__ bool bpBinType(BinArray *ba, int i)
static __inline__ Element *bpBinList(BinArray *ba, int i) static __inline__ Element *bpBinList(BinArray *ba, int i)
{ {
#ifdef BPARANOID #ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList"); ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif #endif
return (Element *) ba->ba_bins[i]; 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) static __inline__ Element **bpBinListHead(BinArray *ba, int i)
{ {
#ifdef BPARANOID #ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList"); ASSERT(bpBinType(ba,i)==BT_LIST,"bpBinList");
#endif #endif
return (Element **) &ba->ba_bins[i]; 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) static __inline__ BinArray *bpSubArray(BinArray *ba, int i)
{ {
#ifdef BPARANOID #ifdef PARANOID
ASSERT(bpBinType(ba,i)==BT_ARRAY,"bpSubArray"); ASSERT(bpBinType(ba,i)==BT_ARRAY,"bpSubArray");
#endif #endif
return (BinArray *) ((pointertype) ba->ba_bins[i] & ~BT_TYPE_MASK); return (BinArray *) ((pointertype) ba->ba_bins[i] & ~BT_TYPE_MASK);
@ -182,7 +182,7 @@ typedef struct bpenum
BPlane *bpe_plane; /* plane being searched */ BPlane *bpe_plane; /* plane being searched */
Rect bpe_srchArea; /* area being searched */ Rect bpe_srchArea; /* area being searched */
int bpe_match; /* match criteria */ int bpe_match; /* match criteria */
const char *bpe_id; /* for debug */ char *bpe_id; /* for debug */
int bpe_subBinMinX; int bpe_subBinMinX;
int bpe_subBinMinY; /* consider subbinning int bpe_subBinMinY; /* consider subbinning
* for bins bigger than this. * for bins bigger than this.
@ -192,4 +192,4 @@ typedef struct bpenum
BPStack bpe_stack[10000]; /* stack for tree traversal during enum */ BPStack bpe_stack[10000]; /* stack for tree traversal during enum */
} BPEnum; } BPEnum;
#endif /* _MAGIC__BPLANE__BPOPAQUE_H */ #endif /* _BPOPAQUE_H */

View File

@ -27,8 +27,8 @@
#ifndef _MAGIC__BPLANE__BPLANE_H #ifndef _BPLANE_H
#define _MAGIC__BPLANE__BPLANE_H #define _BPLANE_H
/* /*
* bplane.h -- * bplane.h --
@ -160,6 +160,17 @@
* *
*/ */
/* 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 */ /* data-structures opaque to clients */
#include "bplane/bpOpaque.h" #include "bplane/bpOpaque.h"
@ -185,9 +196,9 @@ extern void BPEnumInit(BPEnum *bpe, /* this procedure initializes this
* enumeration. * enumeration.
*/ */
BPlane *bp, /* bplane to search */ BPlane *bp, /* bplane to search */
const Rect *area, /* area to search */ Rect *area, /* area to search */
int match, /* see below */ int match, /* see below */
const char *id); /* for debugging */ char *id); /* for debugging */
/* match values */ /* match values */
/* enum all elements in the bplane (area arg must be null) */ /* enum all elements in the bplane (area arg must be null) */
@ -232,4 +243,4 @@ BPStat(BPlane *bp,
int *totUnbinned, /* ret tot num of e's not binned */ int *totUnbinned, /* ret tot num of e's not binned */
int *maxDepth); /* ret max bin array depth */ int *maxDepth); /* ret max bin array depth */
#endif /* _MAGIC__BPLANE__BPLANE_H */ #endif /* _BPLANE_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -18,12 +18,11 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -46,12 +45,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "textio/textio.h" #include "textio/textio.h"
#include "calma/calmaInt.h" #include "calma/calmaInt.h"
/* C99 compat */
#include "calma/calma.h"
/* Forward declarations */ /* Forward declarations */
bool calmaReadR8(double *pd); bool calmaReadR8();
bool calmaSkipBytes(int nbytes); bool calmaSkipBytes();
/* /*
@ -73,9 +69,9 @@ bool calmaSkipBytes(int nbytes);
*/ */
bool bool
calmaReadTransform( calmaReadTransform(ptrans, name)
Transform *ptrans, /* Fill in this transform */ Transform *ptrans; /* Fill in this transform */
char *name) /* Name of subcell (for errors) */ char *name; /* Name of subcell (for errors) */
{ {
int nbytes, rtype, flags, angle; int nbytes, rtype, flags, angle;
double dangle; double dangle;
@ -205,9 +201,9 @@ calmaReadTransform(
*/ */
bool bool
calmaReadI2Record( calmaReadI2Record(type, pvalue)
int type, /* Type of record expected */ int type; /* Type of record expected */
int *pvalue) /* Store value here */ int *pvalue; /* Store value here */
{ {
int nbytes, rtype, n; int nbytes, rtype, n;
@ -222,7 +218,7 @@ calmaReadI2Record(
/* Read the value */ /* Read the value */
READI2(n); READI2(n);
if (FEOF(calmaInputFile)) goto eof; if (feof(calmaInputFile)) goto eof;
*pvalue = n; *pvalue = n;
return (TRUE); return (TRUE);
@ -250,9 +246,9 @@ eof:
*/ */
bool bool
calmaReadI4Record( calmaReadI4Record(type, pvalue)
int type, /* Type of record expected */ int type; /* Type of record expected */
int *pvalue) /* Store value here */ int *pvalue; /* Store value here */
{ {
int nbytes, rtype, n; int nbytes, rtype, n;
@ -267,7 +263,7 @@ calmaReadI4Record(
/* Read the value */ /* Read the value */
READI4(n); READI4(n);
if (FEOF(calmaInputFile)) goto eof; if (feof(calmaInputFile)) goto eof;
*pvalue = n; *pvalue = n;
return (TRUE); return (TRUE);
@ -276,81 +272,6 @@ eof:
return (FALSE); return (FALSE);
} }
/*
* ----------------------------------------------------------------------------
*
* calmaReadStampRecord --
*
* Read a record that contains a pair of timestamps for creation and
* modification dates.
*
* Results:
* TRUE on success, FALSE if the record type we read is not
* what we're expecting.
*
* Side effects:
* Consumes input.
* Translates the creation timestamp from GDS format to a standard
* UNIX (time.h) timestamp (seconds since the epoch).
* Stores the result in the integer pointed to by 'stampptr'.
*
* ----------------------------------------------------------------------------
*/
bool
calmaReadStampRecord(
int type,
int *stampptr)
{
int nbytes, rtype;
struct tm gds_timestamp;
READRH(nbytes, rtype);
if (nbytes < 0)
goto eof;
if (type != rtype)
{
calmaUnexpected(type, rtype);
return (FALSE);
}
nbytes -= CALMAHEADERLENGTH;
if (nbytes != 24)
{
/* Not dealing with any timestamp that is not in I2 format */
calmaSkipBytes(nbytes);
if (stampptr) *stampptr = 0;
CalmaReadError("Unknown timestamp format; setting timestamp to zero.\n");
return TRUE;
}
gds_timestamp.tm_wday = 0; /* Not used by mktime() */
gds_timestamp.tm_yday = 0; /* Not used by mktime() */
gds_timestamp.tm_isdst = -1;
READI2(gds_timestamp.tm_year);
READI2(gds_timestamp.tm_mon);
READI2(gds_timestamp.tm_mday);
READI2(gds_timestamp.tm_hour);
READI2(gds_timestamp.tm_min);
READI2(gds_timestamp.tm_sec);
/* GDS timestamps differ from UNIX time structure only by a */
/* difference of 1 in the month count. */
gds_timestamp.tm_mon--;
/* Skip the modification date timestamp */
(void) calmaSkipBytes(nbytes - 12);
if (stampptr) *stampptr = (int)mktime(&gds_timestamp);
return (TRUE);
eof:
CalmaReadError("Unexpected EOF.\n");
return (FALSE);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -371,9 +292,9 @@ eof:
*/ */
bool bool
calmaReadStringRecord( calmaReadStringRecord(type, str)
int type, int type;
char **str) char **str;
{ {
int nbytes, rtype; int nbytes, rtype;
@ -389,7 +310,7 @@ calmaReadStringRecord(
nbytes -= CALMAHEADERLENGTH; nbytes -= CALMAHEADERLENGTH;
*str = (char *) mallocMagic(nbytes + 1); *str = (char *) mallocMagic(nbytes + 1);
if (magicFREAD(*str, sizeof (char), nbytes, calmaInputFile) != nbytes) if (fread(*str, sizeof (char), nbytes, calmaInputFile) != nbytes)
goto eof; goto eof;
*(*str + nbytes) = '\0'; *(*str + nbytes) = '\0';
@ -420,21 +341,21 @@ eof:
*/ */
bool bool
calmaReadR8( calmaReadR8(pd)
double *pd) /* Store result in *pd */ double *pd; /* Store result in *pd */
{ {
int i, exponent; int i, exponent;
unsigned char dchars[8]; unsigned char dchars[8];
double mantissa, d; double mantissa, d;
bool isneg; bool isneg;
if (magicFREAD((char *) dchars, sizeof (char), sizeof dchars, if (fread((char *) dchars, sizeof (char), sizeof dchars,
calmaInputFile) != sizeof dchars) calmaInputFile) != sizeof dchars)
return (FALSE); return (FALSE);
/* Extract the sign and exponent */ /* Extract the sign and exponent */
exponent = dchars[0]; exponent = dchars[0];
if ((isneg = (exponent & 0x80))) if (isneg = (exponent & 0x80))
exponent &= ~0x80; exponent &= ~0x80;
exponent -= 64; exponent -= 64;
@ -489,10 +410,10 @@ calmaReadR8(
*/ */
void void
calmaSkipSet( calmaSkipSet(skipwhat)
const int *skipwhat) int *skipwhat;
{ {
const int *skipp; int *skipp;
int nbytes, rtype; int nbytes, rtype;
for (;;) for (;;)
@ -533,8 +454,8 @@ skipit:
*/ */
bool bool
calmaSkipExact( calmaSkipExact(type)
int type) int type;
{ {
int nbytes, rtype; int nbytes, rtype;
@ -579,8 +500,8 @@ eof:
*/ */
bool bool
calmaSkipTo( calmaSkipTo(what)
int what) int what;
{ {
int nbytes, rtype; int nbytes, rtype;
@ -615,11 +536,11 @@ calmaSkipTo(
*/ */
bool bool
calmaSkipBytes( calmaSkipBytes(nbytes)
int nbytes) /* Skip this many bytes */ int nbytes; /* Skip this many bytes */
{ {
while (nbytes-- > 0) while (nbytes-- > 0)
if (FGETC(calmaInputFile) < 0) if (getc(calmaInputFile) < 0)
return (FALSE); return (FALSE);
return (TRUE); return (TRUE);

View File

@ -18,7 +18,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -48,17 +48,14 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "calma/calmaInt.h" #include "calma/calmaInt.h"
#include "calma/calma.h" #include "calma/calma.h"
/* C99 compat */
#include "drc/drc.h"
extern int calmaNonManhattan; extern int calmaNonManhattan;
extern int CalmaPolygonCount; extern int CalmaPolygonCount;
extern int CalmaPathCount; extern int CalmaPathCount;
extern HashTable calmaDefInitHash; extern HashTable calmaDefInitHash;
extern void calmaLayerError(char *mesg, int layer, int dt); extern void calmaLayerError();
CIFPath *calmaReadPath(int iscale); bool calmaReadPath();
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -82,9 +79,8 @@ CIFPath *calmaReadPath(int iscale);
*/ */
void void
calmaInputRescale( calmaInputRescale(n, d)
int n, int n, d;
int d)
{ {
HashEntry *h; HashEntry *h;
HashSearch hs; HashSearch hs;
@ -102,8 +98,8 @@ calmaInputRescale(
{ {
/* Scale the GDS planes in this cell's cd_client record */ /* Scale the GDS planes in this cell's cd_client record */
Plane **gdsplanes = (Plane **)def->cd_client; Plane **gdsplanes = (Plane **)def->cd_client;
/* Should not happen, but punt if client record is not set; */ /* Should not happen, but punt if client record is not set */
if (def->cd_client != (ClientData)0) if (def->cd_client != (ClientData)CLIENTDEFAULT)
CIFScalePlanes(n, d, gdsplanes); CIFScalePlanes(n, d, gdsplanes);
} }
} }
@ -114,8 +110,6 @@ calmaInputRescale(
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* calmaReadX ---
* calmaReadY ---
* calmaReadPoint --- * calmaReadPoint ---
* *
* Read a point from the input. * Read a point from the input.
@ -134,19 +128,13 @@ calmaInputRescale(
* encountered, then everything in the GDS planes is rescaled * encountered, then everything in the GDS planes is rescaled
* to match. * to match.
* *
* Notes:
* This routine has been split into individual X and Y reads so that
* array data can be read while ignoring offset information when there
* is only one row or column; otherwise, bad or uninitialized data
* in the record can cause unnecessary and incorrect scaling.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
void void
calmaReadX( calmaReadPoint(p, iscale)
Point *p, Point *p;
int iscale) int iscale;
{ {
int rescale; int rescale;
@ -171,15 +159,6 @@ calmaReadX(
} }
} }
p->p_x /= calmaReadScale2; p->p_x /= calmaReadScale2;
}
void
calmaReadY(
Point *p,
int iscale)
{
int rescale;
READI4((p)->p_y); READI4((p)->p_y);
p->p_y *= (calmaReadScale1 * iscale); p->p_y *= (calmaReadScale1 * iscale);
@ -205,15 +184,6 @@ calmaReadY(
p->p_y /= calmaReadScale2; p->p_y /= calmaReadScale2;
} }
void
calmaReadPoint(
Point *p,
int iscale)
{
calmaReadX(p, iscale);
calmaReadY(p, iscale);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -232,14 +202,14 @@ calmaReadPoint(
*/ */
void void
calmaElementBoundary(void) calmaElementBoundary()
{ {
int dt, layer, ciftype; int dt, layer, ciftype;
CIFPath *pathheadp; CIFPath *pathheadp;
LinkedRect *rp; LinkedRect *rp;
Plane *plane; Plane *plane;
CellUse *use; CellUse *use;
CellDef *savedef = NULL, *newdef = NULL; CellDef *savedef, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */ /* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore); calmaSkipSet(calmaElementIgnore);
@ -263,8 +233,7 @@ calmaElementBoundary(void)
plane = cifCurReadPlanes[ciftype]; plane = cifCurReadPlanes[ciftype];
/* Read the path itself, building up a path structure */ /* Read the path itself, building up a path structure */
pathheadp = calmaReadPath((plane == NULL) ? 0 : 1); if (!calmaReadPath(&pathheadp, (plane == NULL) ? 0 : 1))
if (pathheadp == NULL)
{ {
if (plane != NULL) if (plane != NULL)
CalmaReadError("Error while reading path for boundary/box; ignored.\n"); CalmaReadError("Error while reading path for boundary/box; ignored.\n");
@ -275,27 +244,23 @@ calmaElementBoundary(void)
/* so we need to set it again. */ /* so we need to set it again. */
if (ciftype >= 0) plane = cifCurReadPlanes[ciftype]; if (ciftype >= 0) plane = cifCurReadPlanes[ciftype];
/* Save non-Manhattan polygons in their own subcells. */ /* Convert the polygon to rectangles. */
/* 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 != CALMA_POLYGON_NONE) && (calmaNonManhattan > 0)) if (CalmaSubcellPolygons && (calmaNonManhattan > 0))
{ {
/* Place the polygon in its own subcell */ /* Place the polygon in its own subcell */
char newname[20]; char newname[] = "polygonXXXXX";
HashEntry *he; HashEntry *he;
savedef = cifReadCellDef; savedef = cifReadCellDef;
/* Make up name for cell */ /* Make up name for cell */
snprintf(newname, sizeof(newname), "polygon%05d", ++CalmaPolygonCount); sprintf(newname + 7, "%05d", ++CalmaPolygonCount);
he = HashFind(&calmaDefInitHash, newname); he = HashFind(&calmaDefInitHash, newname);
if (!HashGetValue(he)) if (!HashGetValue(he))
{ {
newdef = calmaFindCell(newname, NULL, NULL); newdef = calmaFindCell(newname, NULL);
cifReadCellDef = newdef; cifReadCellDef = newdef;
DBCellClearDef(cifReadCellDef); DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef); DBCellSetAvail(cifReadCellDef);
@ -309,9 +274,7 @@ calmaElementBoundary(void)
} }
} }
/* Convert the polygon to rectangles. */ rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL, TRUE);
CIFFreePath(pathheadp); CIFFreePath(pathheadp);
/* If the input layer is designated for ports by a "label" */ /* If the input layer is designated for ports by a "label" */
@ -353,47 +316,18 @@ calmaElementBoundary(void)
if (lab == NULL) if (lab == NULL)
{ {
/* There was no label in the area. Create a placeholder label */ /* There was no label in the area. Create a placeholder label */
lab = DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 0, 0); DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 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) */ /* Paint the rectangles (if any) */
free_magic1_t mm1 = freeMagic1_init();
for (; rp != NULL ; rp = rp->r_next) for (; rp != NULL ; rp = rp->r_next)
{ {
if (plane) if (plane)
DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL); DBPaintPlane(plane, &rp->r_r, CIFPaintTable, (PaintUndoInfo *)NULL);
freeMagic1(&mm1, (char *) rp); freeMagic((char *) rp);
} }
freeMagic1_end(&mm1);
if (cifCurReadPlanes == cifEditCellPlanes) if (cifCurReadPlanes == cifEditCellPlanes)
{ {
@ -436,7 +370,7 @@ calmaElementBoundary(void)
*/ */
void void
calmaElementBox(void) calmaElementBox()
{ {
int nbytes, rtype, npoints, savescale; int nbytes, rtype, npoints, savescale;
int dt, layer, ciftype; int dt, layer, ciftype;
@ -531,16 +465,17 @@ calmaElementBox(void)
*/ */
void void
calmaElementPath(void) calmaElementPath()
{ {
int nbytes = -1, rtype = 0, extend1, extend2; int nbytes, rtype, extend1, extend2;
int layer, dt, width, pathtype, ciftype, savescale; int layer, dt, width, pathtype, ciftype, savescale;
int xmin, ymin, xmax, ymax, temp; int xmin, ymin, xmax, ymax, temp;
CIFPath *pathheadp, *pathp, *previousp; CIFPath *pathheadp, *pathp, *previousp;
Rect segment;
Plane *plane; Plane *plane;
int first,last; int first,last;
CellUse *use; CellUse *use;
CellDef *savedef = NULL, *newdef = NULL; CellDef *savedef, *newdef = NULL;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */ /* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore); calmaSkipSet(calmaElementIgnore);
@ -623,8 +558,7 @@ calmaElementPath(void)
/* Read the points in the path */ /* Read the points in the path */
savescale = calmaReadScale1; savescale = calmaReadScale1;
pathheadp = calmaReadPath(2); if (!calmaReadPath(&pathheadp, 2))
if (pathheadp == NULL)
{ {
CalmaReadError("Improper path; ignored.\n"); CalmaReadError("Improper path; ignored.\n");
return; return;
@ -692,18 +626,18 @@ calmaElementPath(void)
if (CalmaSubcellPaths) if (CalmaSubcellPaths)
{ {
/* Place the path in its own subcell */ /* Place the path in its own subcell */
char newname[16]; char newname[] = "pathXXXXX";
HashEntry *he; HashEntry *he;
savedef = cifReadCellDef; savedef = cifReadCellDef;
/* Make up name for cell */ /* Make up name for cell */
snprintf(newname, sizeof(newname), "path%05d", ++CalmaPathCount); sprintf(newname + 4, "%05d", ++CalmaPathCount);
he = HashFind(&calmaDefInitHash, newname); he = HashFind(&calmaDefInitHash, newname);
if (!HashGetValue(he)) if (!HashGetValue(he))
{ {
newdef = calmaFindCell(newname, NULL, NULL); newdef = calmaFindCell(newname, NULL);
cifReadCellDef = newdef; cifReadCellDef = newdef;
DBCellClearDef(cifReadCellDef); DBCellClearDef(cifReadCellDef);
DBCellSetAvail(cifReadCellDef); DBCellSetAvail(cifReadCellDef);
@ -717,12 +651,7 @@ calmaElementPath(void)
} }
} }
/* If requested by command option, record the path centerline as a CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
* property of the cell def.
*/
if (CalmaRecordPaths)
CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
CIFPaintWirePath(pathheadp, width, CIFPaintWirePath(pathheadp, width,
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ? (pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL); FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
@ -764,16 +693,17 @@ calmaElementPath(void)
*/ */
void void
calmaElementText(void) calmaElementText()
{ {
static const int ignore[] = { CALMA_PATHTYPE, CALMA_WIDTH, -1 }; static int ignore[] = { CALMA_PATHTYPE, CALMA_WIDTH, -1 };
char *textbody = NULL; char *textbody = NULL;
int nbytes = -1, rtype = 0; int nbytes, rtype;
int layer, textt, cifnum, textpres; int layer, textt, cifnum;
TileType type; TileType type;
Rect r; Rect r;
unsigned short textpres;
double dval; double dval;
int size, micron, angle, font, pos, portnum, idx; int size, angle, font, pos;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */ /* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore); calmaSkipSet(calmaElementIgnore);
@ -795,29 +725,10 @@ calmaElementText(void)
font = -1; font = -1;
angle = 0; angle = 0;
portnum = 0;
/* Use the minimum width of the layer on which the text is placed /* Default size is 1um */
* as the default text size, or 1um, whichever is smaller. Account size = (int)((1000 * cifCurReadStyle->crs_multiplier)
* 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); / cifCurReadStyle->crs_scaleFactor);
if ((size == 0) || (size > micron))
size = micron;
/* Default position is bottom-right (but what the spec calls "top-left"!) */ /* Default position is bottom-right (but what the spec calls "top-left"!) */
pos = GEO_SOUTHEAST; pos = GEO_SOUTHEAST;
@ -898,20 +809,11 @@ calmaElementText(void)
if (nbytes > 0 && rtype == CALMA_MAG) if (nbytes > 0 && rtype == CALMA_MAG)
{ {
calmaReadR8(&dval); calmaReadR8(&dval);
/* Sanity check on dval (must be nonzero positive) */
if ((dval <= 0) || (dval > 10000)) /* Assume that MAG is the label size in microns */
{ /* "size" is the label size in 10 * (database units) */
CalmaReadError("Invalid text magnification %lg.\n", dval); size = (int)((dval * 1000 * cifCurReadStyle->crs_multiplier)
/* Keep default size */ / cifCurReadStyle->crs_scaleFactor);
}
else
/* Assume that MAG is the label size in microns */
/* "size" is the label size in 10 * (database units) */
/* 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 else
UNREADRH(nbytes, rtype); UNREADRH(nbytes, rtype);
@ -1037,6 +939,8 @@ calmaElementText(void)
flags = 0; flags = 0;
else if (cifnum >= 0 && (cifCurReadStyle->crs_labelSticky[cifnum] != LABEL_TYPE_NONE)) else if (cifnum >= 0 && (cifCurReadStyle->crs_labelSticky[cifnum] != LABEL_TYPE_NONE))
flags = LABEL_STICKY; flags = LABEL_STICKY;
else if (cifCurReadStyle->crs_flags & CRF_NO_RECONNECT_LABELS)
flags = LABEL_STICKY;
else else
flags = 0; flags = 0;
@ -1058,26 +962,6 @@ calmaElementText(void)
sl->lab_next = lab->lab_next; sl->lab_next = lab->lab_next;
if (cifReadCellDef->cd_lastLabel == lab) if (cifReadCellDef->cd_lastLabel == lab)
cifReadCellDef->cd_lastLabel = sl; 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); freeMagic((char *)lab);
break; break;
} }
@ -1086,14 +970,16 @@ calmaElementText(void)
} }
if (font < 0) if (font < 0)
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, portnum); lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags);
else else
lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle, lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle,
&GeoOrigin, pos, textbody, type, flags, portnum); &GeoOrigin, pos, textbody, type, flags);
if ((lab != NULL) && (cifnum >= 0) && if ((lab != NULL) && (cifnum >= 0) &&
(cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT)) (cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT))
{ {
int idx;
/* No port information can be encoded in the GDS file, so */ /* No port information can be encoded in the GDS file, so */
/* assume defaults, and assume that the port order is the */ /* assume defaults, and assume that the port order is the */
/* order in which labels arrive in the GDS stream. If */ /* order in which labels arrive in the GDS stream. If */
@ -1102,7 +988,7 @@ calmaElementText(void)
i = -1; i = -1;
for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next) for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next)
{ {
idx = sl->lab_port; idx = sl->lab_flags & PORT_NUM_MASK;
if (idx > i) i = idx; if (idx > i) i = idx;
if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, textbody)) if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, textbody))
{ {
@ -1111,7 +997,7 @@ calmaElementText(void)
} }
} }
i++; i++;
lab->lab_port = i; lab->lab_flags |= (PORT_NUM_MASK & i);
lab->lab_flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH | lab->lab_flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH |
PORT_DIR_EAST | PORT_DIR_WEST; PORT_DIR_EAST | PORT_DIR_WEST;
} }
@ -1132,24 +1018,26 @@ calmaElementText(void)
* centerline, to avoid roundoff errors. * centerline, to avoid roundoff errors.
* *
* Results: * Results:
* non-NULL CIFPath* the caller takes ownership of * TRUE is returned if the path was parsed successfully,
* if the path was parsed successfully, otherwise NULL. * FALSE otherwise.
* *
* Side effects: * Side effects:
* None * Modifies the parameter pathheadpp to point to the path
* that is constructed.
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
CIFPath * bool
calmaReadPath( calmaReadPath(pathheadpp, iscale)
int iscale) CIFPath **pathheadpp;
int iscale;
{ {
CIFPath path, *pathheadp, *pathtailp, *newpathp; CIFPath path, *pathtailp, *newpathp;
int nbytes, rtype, npoints, savescale; int nbytes, rtype, npoints, savescale;
bool nonManhattan = FALSE; bool nonManhattan = FALSE;
pathheadp = (CIFPath *) NULL; *pathheadpp = (CIFPath *) NULL;
pathtailp = (CIFPath *) NULL; pathtailp = (CIFPath *) NULL;
path.cifp_next = (CIFPath *) NULL; path.cifp_next = (CIFPath *) NULL;
@ -1158,12 +1046,12 @@ calmaReadPath(
if (nbytes < 0) if (nbytes < 0)
{ {
CalmaReadError("EOF when reading path.\n"); CalmaReadError("EOF when reading path.\n");
return (NULL); return (FALSE);
} }
if (rtype != CALMA_XY) if (rtype != CALMA_XY)
{ {
calmaUnexpected(CALMA_XY, rtype); calmaUnexpected(CALMA_XY, rtype);
return (NULL); return (FALSE);
} }
/* Read this many points (pairs of four-byte integers) */ /* Read this many points (pairs of four-byte integers) */
@ -1174,7 +1062,7 @@ calmaReadPath(
calmaReadPoint(&path.cifp_point, iscale); calmaReadPoint(&path.cifp_point, iscale);
if (savescale != calmaReadScale1) if (savescale != calmaReadScale1)
{ {
CIFPath *phead = pathheadp; CIFPath *phead = *pathheadpp;
int newscale = calmaReadScale1 / savescale; int newscale = calmaReadScale1 / savescale;
while (phead != NULL) while (phead != NULL)
{ {
@ -1187,10 +1075,10 @@ calmaReadPath(
CalmaReadError("Warning: Very large point in path: (%d, %d)\n", CalmaReadError("Warning: Very large point in path: (%d, %d)\n",
path.cifp_x, path.cifp_y); path.cifp_x, path.cifp_y);
} }
if (FEOF(calmaInputFile)) if (feof(calmaInputFile))
{ {
CIFFreePath(pathheadp); CIFFreePath(*pathheadpp);
return (NULL); return (FALSE);
} }
if (iscale != 0) if (iscale != 0)
@ -1198,7 +1086,7 @@ calmaReadPath(
newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath)));
*newpathp = path; *newpathp = path;
if (pathheadp) if (*pathheadpp)
{ {
/* /*
* Check that this segment is Manhattan. If not, remember the * Check that this segment is Manhattan. If not, remember the
@ -1219,11 +1107,11 @@ calmaReadPath(
} }
pathtailp->cifp_next = newpathp; pathtailp->cifp_next = newpathp;
} }
else pathheadp = newpathp; else *pathheadpp = newpathp;
pathtailp = newpathp; pathtailp = newpathp;
} }
} }
return (pathheadp); return (*pathheadpp != NULL);
} }
/* /*
@ -1248,10 +1136,10 @@ calmaReadPath(
*/ */
void void
calmaLayerError( calmaLayerError(mesg, layer, dt)
char *mesg, char *mesg;
int layer, int layer;
int dt) int dt;
{ {
CalmaLayerType clt; CalmaLayerType clt;
HashEntry *he; HashEntry *he;

View File

@ -17,10 +17,9 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -28,12 +27,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <netinet/in.h> #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/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -53,17 +46,14 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "textio/textio.h" #include "textio/textio.h"
#include "calma/calmaInt.h" #include "calma/calmaInt.h"
#include "commands/commands.h" /* for CmdGetRootPoint */ #include "commands/commands.h" /* for CmdGetRootPoint */
#include "utils/main.h" /* for EditCellUse */
#include "utils/undo.h" #include "utils/undo.h"
/* C99 compat */
#include "calma/calma.h"
/* Globals for Calma reading */ /* Globals for Calma reading */
FILETYPE calmaInputFile = NULL; /* Read from this stream */ FILE *calmaInputFile = NULL; /* Read from this stream */
FILE *calmaErrorFile = NULL; /* Write error output here */ FILE *calmaErrorFile = NULL; /* Write error output here */
unsigned char CalmaSubcellPolygons = CALMA_POLYGON_NONE; bool CalmaSubcellPolygons = FALSE; /* Put non-Manhattan polygons
/* Read non-Manhattan polygons as-is */ * in their own subcells.
*/
int CalmaPolygonCount; int CalmaPolygonCount;
bool CalmaSubcellPaths = FALSE; /* Put paths in their own subcells. */ bool CalmaSubcellPaths = FALSE; /* Put paths in their own subcells. */
int CalmaPathCount; int CalmaPathCount;
@ -73,21 +63,10 @@ bool CalmaFlattenUses = FALSE; /* If TRUE, small cells in the input
* performance when handling contacts * performance when handling contacts
* saved as subcell arrays. * saved as subcell arrays.
*/ */
char **CalmaFlattenUsesByName = NULL; /* NULL-terminated list of strings
* to do glob-style pattern matching
* to determine what cells to flatten
* by cellname.
*/
bool CalmaReadOnly = FALSE; /* Set files to read-only and bool CalmaReadOnly = FALSE; /* Set files to read-only and
* retain file position information * retain file position information
* so cells can be written verbatim. * 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 bool CalmaNoDRCCheck = FALSE; /* If TRUE, don't mark cells as needing
* a DRC check; they will be assumed * a DRC check; they will be assumed
* DRC clean. * DRC clean.
@ -98,21 +77,9 @@ bool CalmaPostOrder = FALSE; /* If TRUE, forces the GDS parser to
* flatten cells that are contact cuts. * flatten cells that are contact cuts.
* Added by Nishit 8/16/2004 * Added by Nishit 8/16/2004
*/ */
bool CalmaNoDuplicates = FALSE; /* If TRUE, then if a cell exists in extern void calmaUnexpected();
* memory with the same name as a cell
* in the GDS file, then the cell in
* the GDS file is skipped.
*/
bool CalmaUnique = FALSE; /* If TRUE, then if a cell exists in
* memory with the same name as a cell
* in the GDS file, then the cell in
* memory is renamed to a unique
* identifier with a _N suffix.
*/
extern bool CalmaDoLibrary; /* Also used by GDS write */
extern void calmaUnexpected(int wanted, int got); bool calmaParseUnits();
extern int calmaWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */
/* /*
* Scaling. * Scaling.
@ -147,7 +114,7 @@ HashTable calmaLayerHash;
HashTable calmaDefInitHash; HashTable calmaDefInitHash;
/* Common stuff to ignore */ /* Common stuff to ignore */
const int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 }; int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -167,24 +134,18 @@ const int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 };
*/ */
void void
CalmaReadFile( CalmaReadFile(file, filename)
FILETYPE file, /* File from which to read Calma */ FILE *file; /* File from which to read Calma */
char *filename) /* The real name of the file read */ char *filename; /* The real name of the file read */
{ {
int k, version; int k, version;
char *libname = NULL, *libnameptr = NULL; char *libname = NULL;
MagWindow *mw; MagWindow *mw;
static const int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS, static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE, CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
CALMA_STYPTABLE, CALMA_GENERATIONS, -1 }; CALMA_STYPTABLE, CALMA_GENERATIONS, -1 };
static const int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME, static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
CALMA_LIBSECUR, -1 }; CALMA_LIBSECUR, -1 };
if (EditCellUse == (CellUse *)NULL)
{
TxError("Cannot read GDS: There is no edit cell.\n");
return;
}
/* We will use full cell names as keys in this hash table */ /* We will use full cell names as keys in this hash table */
CIFReadCellInit(0); CIFReadCellInit(0);
@ -211,12 +172,6 @@ CalmaReadFile(
CalmaPolygonCount = 0; CalmaPolygonCount = 0;
CalmaPathCount = 0; CalmaPathCount = 0;
/* Reset cd_client pointers (using init function from CalmaWrite.c) */
/* This is in case a cell already in memory is being referenced; */
/* it is probably better to avoid those kinds of naming collisions */
/* though. . . */
(void) DBCellSrDefs(0, calmaWriteInitFunc, (ClientData) NULL);
HashInit(&calmaDefInitHash, 32, 0); HashInit(&calmaDefInitHash, 32, 0);
calmaLApresent = FALSE; calmaLApresent = FALSE;
calmaInputFile = file; calmaInputFile = file;
@ -231,43 +186,15 @@ CalmaReadFile(
if (!calmaSkipExact(CALMA_BGNLIB)) goto done; if (!calmaSkipExact(CALMA_BGNLIB)) goto done;
calmaSkipSet(skipBeforeLib); calmaSkipSet(skipBeforeLib);
if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done; if (!calmaReadStringRecord(CALMA_LIBNAME, &libname)) goto done;
if ((libname != NULL) && (libname[0] != '\0'))
/* Use CalmaDoLibrary similarly for input as for output; if set to */
/* TRUE, the library name is considered meaningless and discarded; */
/* the GDS file contents are read into memory but no view is loaded */
if (CalmaDoLibrary)
libnameptr = NULL;
else
libnameptr = libname;
if ((libnameptr != NULL) && (libname[0] != '\0'))
{ {
bool modified = FALSE;
char *sptr;
/* Avoid generating a magic name with spaces in it. . . */ /* Avoid generating a magic name with spaces in it. . . */
/* (added by Mike Godfrey, 7/17/05) */ /* (added by Mike Godfrey, 7/17/05) */
for (k = 0; k < strlen(libname); k++) for (k = 0; k < strlen(libname); k++)
if (libname[k] == ' ') if (libname[k] == ' ')
{
libname[k] = '_'; libname[k] = '_';
modified = TRUE; TxPrintf("Library name: %s\n", libname);
}
/* Avoid generating a magic name with slashes in it. . . */
/* (added by Tim, 8/26/2022) */
if ((sptr = strrchr(libname, '/')) != NULL)
{
libnameptr = sptr + 1;
modified = TRUE;
}
if (modified)
TxPrintf("Library name modified to make legal cell name syntax.\n");
TxPrintf("Library name: %s\n", libnameptr);
} }
/* Skip the reflibs, fonts, etc. cruft */ /* Skip the reflibs, fonts, etc. cruft */
@ -292,15 +219,15 @@ done:
/* top-level cell, so magic-produced GDS can be read back */ /* top-level cell, so magic-produced GDS can be read back */
/* with the expected cell appearing in the layout window. */ /* with the expected cell appearing in the layout window. */
if (libnameptr != NULL) if (libname != NULL)
{ {
mw = CmdGetRootPoint((Point *)NULL, (Rect *)NULL); mw = CmdGetRootPoint((Point *)NULL, (Rect *)NULL);
if (mw == NULL) if (mw == NULL)
windCheckOnlyWindow(&mw, DBWclientID); windCheckOnlyWindow(&mw, DBWclientID);
if (mw != NULL) if (mw != NULL)
{ {
if (calmaLookCell(libnameptr) != (CellDef *)NULL) if (calmaLookCell(libname, NULL) != (CellDef *)NULL)
DBWloadWindow(mw, libnameptr, 0); DBWloadWindow(mw, libname, FALSE, FALSE);
} }
freeMagic(libname); freeMagic(libname);
} }
@ -309,11 +236,7 @@ done:
HashKill(&calmaDefInitHash); HashKill(&calmaDefInitHash);
UndoEnable(); UndoEnable();
if (calmaErrorFile != NULL) if (calmaErrorFile != NULL) fclose(calmaErrorFile);
{
fclose(calmaErrorFile);
calmaErrorFile = NULL;
}
} }
/* /*
@ -347,13 +270,12 @@ done:
*/ */
bool bool
calmaParseUnits(void) calmaParseUnits()
{ {
int nbytes, rtype = 0; int nbytes, rtype;
double metersPerDBUnit; double metersPerDBUnit;
double userUnitsPerDBUnit; double userUnitsPerDBUnit;
double cuPerDBUnit; double cuPerDBUnit;
bool compatible;
READRH(nbytes, rtype); READRH(nbytes, rtype);
#ifdef lint #ifdef lint
@ -372,39 +294,6 @@ calmaParseUnits(void)
/* Read meters per database unit */ /* Read meters per database unit */
if (!calmaReadR8(&metersPerDBUnit)) return (FALSE); 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 #ifdef notdef
TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit); TxPrintf("1 database unit equals %e user units\n", userUnitsPerDBUnit);
TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit); TxPrintf("1 database unit equals %e meters\n", metersPerDBUnit);
@ -459,17 +348,19 @@ calmaParseUnits(void)
*/ */
void void
CalmaReadError(const char *format, ...) /*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;
{ {
va_list args; off_t filepos;
OFFTYPE filepos;
calmaTotalErrors++; calmaTotalErrors++;
if (CIFWarningLevel == CIF_WARN_NONE) return; if (CIFWarningLevel == CIF_WARN_NONE) return;
if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) if ((calmaTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
{ {
filepos = FTELL(calmaInputFile); filepos = ftello(calmaInputFile);
if (CIFWarningLevel == CIF_WARN_REDIRECT) if (CIFWarningLevel == CIF_WARN_REDIRECT)
{ {
@ -477,20 +368,17 @@ CalmaReadError(const char *format, ...)
{ {
fprintf(calmaErrorFile, "Error while reading cell \"%s\" ", fprintf(calmaErrorFile, "Error while reading cell \"%s\" ",
cifReadCellDef->cd_name); cifReadCellDef->cd_name);
fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"d): ", fprintf(calmaErrorFile, "(byte position %"DLONG_PREFIX"ld): ",
(dlong)filepos); (dlong)filepos);
va_start(args, format); fprintf(calmaErrorFile, format, a1, a2, a3, a4, a5, a6, a7,
Vfprintf(calmaErrorFile, format, args); a8, a9, a10);
va_end(args);
} }
} }
else else
{ {
TxError("Error while reading cell \"%s\" ", cifReadCellDef->cd_name); TxError("Error while reading cell \"%s\" ", cifReadCellDef->cd_name);
TxError("(byte position %"DLONG_PREFIX"d): ", (dlong)filepos); TxError("(byte position %"DLONG_PREFIX"d): ", (dlong)filepos);
va_start(args, format); TxError(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
TxErrorV(format, args);
va_end(args);
} }
} }
else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT)) else if ((calmaTotalErrors == 100) && (CIFWarningLevel == CIF_WARN_LIMIT))
@ -516,9 +404,9 @@ CalmaReadError(const char *format, ...)
*/ */
void void
calmaUnexpected( calmaUnexpected(wanted, got)
int wanted, /* Type of record we wanted */ int wanted; /* Type of record we wanted */
int got) /* Type of record we got */ int got; /* Type of record we got */
{ {
CalmaReadError("Unexpected record type in input: \n"); CalmaReadError("Unexpected record type in input: \n");
@ -558,12 +446,12 @@ calmaUnexpected(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
const char * char *
calmaRecordName( calmaRecordName(rtype)
int rtype) int rtype;
{ {
static char numeric[10]; static char numeric[10];
static const char * const calmaRecordNames[] = static char *calmaRecordNames[] =
{ {
"HEADER", "BGNLIB", "LIBNAME", "UNITS", "HEADER", "BGNLIB", "LIBNAME", "UNITS",
"ENDLIB", "BGNSTR", "STRNAME", "ENDSTR", "ENDLIB", "BGNSTR", "STRNAME", "ENDSTR",
@ -608,28 +496,8 @@ calmaRecordName(
*/ */
void void
CalmaTechInit(void) CalmaTechInit()
{ {
ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h"); ASSERT(sizeof(FourByteInt)==4, "definition in calmaInt.h");
ASSERT(sizeof(TwoByteInt)==2, "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

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
MODULE = calma MODULE = calma
MAGICDIR = .. MAGICDIR = ..
SRCS = CalmaRead.c CalmaRdcl.c CalmaRdio.c CalmaRdpt.c CalmaWrite.c CalmaWriteZ.c SRCS = CalmaRead.c CalmaRdcl.c CalmaRdio.c CalmaRdpt.c CalmaWrite.c
include ${MAGICDIR}/defs.mak include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak include ${MAGICDIR}/rules.mak

View File

@ -19,85 +19,29 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/calma/calma.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $ * rcsid $Header: /usr/cvsroot/magic-8.0/calma/calma.h,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $
*/ */
#ifndef _MAGIC__CALMA__CALMA_H #ifndef _CALMA_H
#define _MAGIC__CALMA__CALMA_H #define _CALMA_H
#include "utils/magic.h" #include "utils/magic.h"
/* Externally visible variables */ /* Externally visible variables */
extern unsigned char CalmaSubcellPolygons; extern bool CalmaSubcellPolygons;
extern bool CalmaSubcellPaths; extern bool CalmaSubcellPaths;
extern bool CalmaDoLabels; extern bool CalmaDoLabels;
extern bool CalmaDoLibrary;
extern bool CalmaDoLower; extern bool CalmaDoLower;
extern bool CalmaAddendum;
extern bool CalmaNoDuplicates;
extern time_t *CalmaDateStamp;
extern bool CalmaUnique;
extern TileTypeBitMask *CalmaMaskHints;
extern bool CalmaMergeTiles; extern bool CalmaMergeTiles;
extern bool CalmaFlattenArrays; extern bool CalmaFlattenArrays;
extern bool CalmaNoDRCCheck; extern bool CalmaNoDRCCheck;
extern bool CalmaRecordPaths;
extern bool CalmaFlattenUses; extern bool CalmaFlattenUses;
extern int CalmaFlattenLimit;
extern float CalmaMagScale;
extern char **CalmaFlattenUsesByName;
extern bool CalmaReadOnly; extern bool CalmaReadOnly;
extern bool CalmaContactArrays; extern bool CalmaContactArrays;
#ifdef HAVE_ZLIB
extern int CalmaCompression;
#endif
extern bool CalmaPostOrder; 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: */ /* Externally-visible procedures: */
extern bool CalmaWrite(CellDef *rootDef, FILE *f); extern bool CalmaWrite();
extern void CalmaReadFile(FILETYPE file, char *filename); extern void CalmaReadFile();
extern void CalmaTechInit(void); extern void CalmaTechInit();
extern bool CalmaGenerateArray(FILE *f, TileType type, int llx, int lly, int pitch, int cols, int rows); extern bool CalmaGenerateArray();
extern void CalmaReadError(const char *format, ...) ATTR_FORMAT_PRINTF_1; extern void CalmaReadError();
/* C99 compat */ #endif /* _CALMA_H */
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 calmaReadX(Point *p, int iscale);
extern void calmaReadY(Point *p, int iscale);
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(CellDef *rootDef, gzFile f);
extern bool CalmaGenerateArrayZ(gzFile f, TileType type, int llx, int lly, int pitch, int cols, int rows);
#endif
#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 $ * rcsid $Header: /usr/cvsroot/magic-8.0/calma/calmaInt.h,v 1.2 2010/06/24 12:37:15 tim Exp $
*/ */
#ifndef _MAGIC__CALMA__CALMAINT_H #ifndef _CALMAINT_H
#define _MAGIC__CALMA__CALMAINT_H #define _CALMAINT_H
#include "utils/magic.h" #include "utils/magic.h"
#include "database/database.h" #include "database/database.h"
@ -99,7 +99,6 @@
#define CALMA_NUMRECORDTYPES 60 /* Number of above types */ #define CALMA_NUMRECORDTYPES 60 /* Number of above types */
/* Property types defined for magic */ /* Property types defined for magic */
#define CALMA_PROP_USENAME_STD 61 /* To record non-default cell use ids */
#define CALMA_PROP_USENAME 98 /* To record non-default cell use ids */ #define CALMA_PROP_USENAME 98 /* To record non-default cell use ids */
#define CALMA_PROP_ARRAY_LIMITS 99 /* To record non-default array limits */ #define CALMA_PROP_ARRAY_LIMITS 99 /* To record non-default array limits */
@ -131,17 +130,13 @@ typedef struct
/* Length of record header */ /* Length of record header */
#define CALMAHEADERLENGTH 4 #define CALMAHEADERLENGTH 4
/* Label types /* Label types */
* The intention is all the values can be stored/converted with unsigned char type, typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CELLID } labelType;
* 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 ----------------------------- */ /* ------------------------- Input macros ----------------------------- */
/* Globals for Calma reading */ /* Globals for Calma reading */
extern FILETYPE calmaInputFile; extern FILE *calmaInputFile;
extern FILE *calmaInputFileNoCompression;
extern char *calmaFilename; extern char *calmaFilename;
extern int calmaReadScale1; extern int calmaReadScale1;
extern int calmaReadScale2; extern int calmaReadScale2;
@ -172,8 +167,8 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI2(z) \ #define READI2(z) \
{ \ { \
TwoByteInt u; \ TwoByteInt u; \
u.uc[0] = FGETC(calmaInputFile); \ u.uc[0] = getc(calmaInputFile); \
u.uc[1] = FGETC(calmaInputFile); \ u.uc[1] = getc(calmaInputFile); \
(z) = (int) ntohs(u.us); \ (z) = (int) ntohs(u.us); \
} }
@ -181,10 +176,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
#define READI4(z) \ #define READI4(z) \
{ \ { \
FourByteInt u; \ FourByteInt u; \
u.uc[0] = FGETC(calmaInputFile); \ u.uc[0] = getc(calmaInputFile); \
u.uc[1] = FGETC(calmaInputFile); \ u.uc[1] = getc(calmaInputFile); \
u.uc[2] = FGETC(calmaInputFile); \ u.uc[2] = getc(calmaInputFile); \
u.uc[3] = FGETC(calmaInputFile); \ u.uc[3] = getc(calmaInputFile); \
(z) = (int) ntohl(u.ul); \ (z) = (int) ntohl(u.ul); \
} }
@ -197,10 +192,10 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
calmaLApresent = FALSE; \ calmaLApresent = FALSE; \
} else { \ } else { \
READI2(nb); \ READI2(nb); \
if (FEOF(calmaInputFile)) nb = -1; \ if (feof(calmaInputFile)) nb = -1; \
else { \ else { \
(rt) = FGETC(calmaInputFile); \ (rt) = getc(calmaInputFile); \
(void) FGETC(calmaInputFile); \ (void) getc(calmaInputFile); \
} \ } \
} \ } \
} }
@ -219,52 +214,19 @@ typedef union { char uc[4]; unsigned int ul; } FourByteInt;
UNREADRH(nb, rt); \ 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 */ /* Other commonly used globals */
extern HashTable calmaLayerHash; extern HashTable calmaLayerHash;
extern const int calmaElementIgnore[]; extern int calmaElementIgnore[];
extern CellDef *calmaFindCell(const char *name, bool *was_called, bool *predefined); extern CellDef *calmaFindCell();
/* (Added by Nishit, 8/18/2004--8/24/2004) */ /* (Added by Nishit, 8/18/2004--8/24/2004) */
extern CellDef *calmaLookCell(char *name); extern CellDef *calmaLookCell();
extern void calmaWriteContacts(FILE *f); extern void calmaWriteContact();
extern CellDef *calmaGetContactCell(TileType type, bool lookOnly); extern CellDef *calmaGetContactCell();
extern bool calmaIsContactCell; extern bool calmaIsContactCell;
extern const char *calmaRecordName(int rtype); extern char *calmaRecordName();
extern void calmaSkipSet(const int *skipwhat); extern void calmaSkipSet();
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 ----------------------- */ /* ------------------- Imports from CIF reading ----------------------- */
@ -274,4 +236,4 @@ extern Plane **cifCurReadPlanes;
extern HashTable CifCellTable; extern HashTable CifCellTable;
extern Plane *cifEditCellPlanes[]; extern Plane *cifEditCellPlanes[];
#endif /* _MAGIC__CALMA__CALMAINT_H */ #endif /* _CALMAINT_H */

File diff suppressed because it is too large Load Diff

3980
cif/CIFgen.c.test Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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 $" * rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFint.h,v 1.3 2008/12/04 17:10:29 tim Exp $"
*/ */
#ifndef _MAGIC__CIF__CIFINT_H #ifndef _CIFINT_H
#define _MAGIC__CIF__CIFINT_H #define _CIFINT_H
#include "database/database.h" #include "database/database.h"
@ -52,11 +52,6 @@ typedef struct bloat_data
int bl_distance[TT_MAXTYPES]; int bl_distance[TT_MAXTYPES];
} BloatData; } BloatData;
typedef struct bridge_data
{
int br_width; /* Minimum width rule for bridge */
} BridgeData;
typedef struct squares_data typedef struct squares_data
{ {
int sq_border; int sq_border;
@ -86,9 +81,8 @@ typedef struct cifop
* below for the legal ones. * below for the legal ones.
*/ */
int co_distance; /* Grow or shrink distance (if needed). */ int co_distance; /* Grow or shrink distance (if needed). */
ClientData co_client; /* Pointer to a BloatData, SquaresData, ClientData co_client; /* Pointer to a BloatData, SquaresData, or
* SlotsData, or BridgeData structure, * SlotsData structure, or NULL.
* or NULL.
*/ */
struct cifop *co_next; /* Next in list of operations to perform. */ struct cifop *co_next; /* Next in list of operations to perform. */
} CIFOp; } CIFOp;
@ -134,19 +128,12 @@ typedef struct cifop
* box coordinates into CIF layer geometry. * box coordinates into CIF layer geometry.
* CIFOP_NET - Added 11/3/08---pull an entire electrical net into * CIFOP_NET - Added 11/3/08---pull an entire electrical net into
* the CIF layer, selectively picking layers. * the CIF layer, selectively picking layers.
* CIFOP_MAXRECT - Reduce all disjoint regions to the largest internal fitting * CIFOP_MAXRECT - Reduce all areas to the largest internal fitting
* rectangle. * 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, * CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer,
* which will be painted into parent cells instead of the * which will be painted into parent cells instead of the
* current cell. This replaces the "fault" method. * current cell. This replaces the "fault" method.
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated * 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.
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
* CIFOP_TAGGED - Added 3/11/26---Find geometry attached to the given text label
*/ */
#define CIFOP_AND 1 #define CIFOP_AND 1
@ -167,19 +154,8 @@ typedef struct cifop
#define CIFOP_BOUNDARY 16 #define CIFOP_BOUNDARY 16
#define CIFOP_NET 17 #define CIFOP_NET 17
#define CIFOP_MAXRECT 18 #define CIFOP_MAXRECT 18
#define CIFOP_INTERACT 19 #define CIFOP_COPYUP 19
#define CIFOP_COPYUP 20 #define CIFOP_CLOSE 20
#define CIFOP_CLOSE 21
#define CIFOP_MANHATTAN 22
#define CIFOP_BRIDGE 23
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26
#define CIFOP_TAGGED 27
/* 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 */ /* Added by Tim 10/21/2004 */
/* The following structure is used to pass information on how to draw /* The following structure is used to pass information on how to draw
@ -237,12 +213,12 @@ typedef struct
* *
* CIF_TEMP: Means that this is a temporary layer used to build * CIF_TEMP: Means that this is a temporary layer used to build
* up CIF information. It isn't output in the CIF file. * up CIF information. It isn't output in the CIF file.
* CIF_LABEL: This layer is used to generate fixed labels in the * CIF_BBOX_TOP: Indicates that the bounding box rectangle should
* output file. * only be generated if the cell is a top-level cell.
*/ */
#define CIF_TEMP 1 #define CIF_TEMP 1
#define CIF_LABEL 2 #define CIF_BBOX_TOP 2
/* The following data structure describes a complete set of CIF /* The following data structure describes a complete set of CIF
* layers. The number of CIF layers (MAXCIFLAYERS) must not be * layers. The number of CIF layers (MAXCIFLAYERS) must not be
@ -305,12 +281,9 @@ typedef struct cifstyle
* layer. * layer.
*/ */
int cs_portLayer[TT_MAXTYPES]; int cs_portLayer[TT_MAXTYPES];
/* Similar to cs_labelLayer, to use as /* Similar to cs_labelLayer, to distinguish
* a type for geometry attached to port labels. * between output types used for "normal"
*/ * text and those used specifically for ports.
int cs_portText[TT_MAXTYPES];
/* Similar to cs_labelLayer, to use as
* a text type for port labels
*/ */
CIFLayer *cs_layers[MAXCIFLAYERS]; CIFLayer *cs_layers[MAXCIFLAYERS];
/* Describes how to generate each layer.*/ /* Describes how to generate each layer.*/
@ -323,40 +296,21 @@ typedef struct cifstyle
#define CWF_GROW_SLIVERS 0x02 #define CWF_GROW_SLIVERS 0x02
#define CWF_ANGSTROMS 0x04 #define CWF_ANGSTROMS 0x04
#define CWF_GROW_EUCLIDEAN 0x08 #define CWF_GROW_EUCLIDEAN 0x08
#define CWF_SEE_NO_VENDOR 0x10 /* Hide magic's GDS from vendor cells */ #define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */
#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */ #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_STRING_LIMIT 0x40 /* Use older Calma format character limit */
#define CWF_MINIMUM_GRID 0x80 /* Force minimum grid scaling */
/* procedures */ /* procedures */
extern bool CIFNameToMask(char *name, TileTypeBitMask *result, TileTypeBitMask *depend); extern bool CIFNameToMask();
extern void CIFGenSubcells(CellDef *def, Rect *area, Plane **output); extern void CIFGenSubcells();
extern void CIFGenArrays(CellDef *def, Rect *area, Plane **output); extern void CIFGenArrays();
extern void CIFGen(CellDef *cellDef, CellDef *origDef, const Rect *area, Plane **planes, TileTypeBitMask *layers, extern void CIFGen();
bool replace, bool genAllPlanes, bool hier, ClientData clientdata); extern void CIFClearPlanes();
extern void CIFClearPlanes(Plane **planes); extern Plane *CIFGenLayer();
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[], extern void CIFInitCells();
bool hier, ClientData clientdata); extern int cifHierCopyFunc();
extern void CIFInitCells(void); extern void CIFLoadStyle();
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
extern void CIFLoadStyle(char *stylename);
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
/* C99 compat */
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: */ /* Shared variables and structures: */
@ -370,9 +324,6 @@ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
* def. * def.
*/ */
extern Plane *CIFTotalPlanes[]; /* Exported for diagnostics */
extern Plane *CIFComponentPlanes[]; /* Exported for diagnostics */
/* Valid values of CIFWarningLevel (see cif.h) */ /* Valid values of CIFWarningLevel (see cif.h) */
typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN, typedef enum {CIF_WARN_DEFAULT, CIF_WARN_NONE, CIF_WARN_ALIGN,
@ -387,13 +338,13 @@ extern int CIFHierRects;
/* Tables used for painting and erasing CIF. */ /* Tables used for painting and erasing CIF. */
extern const PaintResultType CIFPaintTable[], CIFEraseTable[]; extern PaintResultType CIFPaintTable[], CIFEraseTable[];
/* Procedures and variables for reporting errors. */ /* Procedures and variables for reporting errors. */
extern int CIFErrorLayer; extern int CIFErrorLayer;
extern CellDef *CIFErrorDef; extern CellDef *CIFErrorDef;
extern void CIFError(Rect *area, char *message); extern void CIFError();
/* The following determines the tile type used to hold the CIF /* The following determines the tile type used to hold the CIF
* information on its paint plane. * information on its paint plane.
@ -402,4 +353,4 @@ extern void CIFError(Rect *area, char *message);
#define CIF_SOLIDTYPE 1 #define CIF_SOLIDTYPE 1
extern TileTypeBitMask CIFSolidBits; extern TileTypeBitMask CIFSolidBits;
#endif /* _MAGIC__CIF__CIFINT_H */ #endif /* _CIFINT_H */

View File

@ -17,7 +17,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -95,7 +95,7 @@ global int CIFErrorLayer; /* Index of CIF layer associated with errors.*/
*/ */
void void
CIFPrintStats(void) CIFPrintStats()
{ {
TxPrintf("CIF statistics (recent/total):\n"); TxPrintf("CIF statistics (recent/total):\n");
cifTotalTileOps += CIFTileOps; cifTotalTileOps += CIFTileOps;
@ -136,8 +136,8 @@ CIFPrintStats(void)
*/ */
float float
CIFGetOutputScale( CIFGetOutputScale(convert)
int convert) int convert;
{ {
if (CIFCurStyle == NULL) return 1.0; if (CIFCurStyle == NULL) return 1.0;
@ -145,28 +145,6 @@ CIFGetOutputScale(
(float)(CIFCurStyle->cs_expander * convert)); (float)(CIFCurStyle->cs_expander * convert));
} }
/*
* ----------------------------------------------------------------------------
*
* CIFGetScale --
*
* Same as the above routine, but provides the scalefactor to get CIF
* units from centimicrons (which generally means just returning the
* expander value to show if units have been declared in nanometers or
* angstroms).
*
* ----------------------------------------------------------------------------
*/
float
CIFGetScale(
int convert)
{
if (CIFCurStyle == NULL) return 1.0;
return (1.0 / (float)(CIFCurStyle->cs_expander * convert));
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -185,10 +163,10 @@ CIFGetScale(
*/ */
void void
CIFPrintStyle( CIFPrintStyle(dolist, doforall, docurrent)
bool dolist, /* Return as a list if true */ bool dolist; /* Return as a list if true */
bool doforall, /* Print all known styles if true */ bool doforall; /* Print all known styles if true */
bool docurrent) /* Print current style if true */ bool docurrent; /* Print current style if true */
{ {
CIFKeep *style; CIFKeep *style;
@ -254,13 +232,12 @@ CIFPrintStyle(
*/ */
void void
CIFSetStyle( CIFSetStyle(name)
char *name) /* Name of the new style. If NULL, just char *name; /* Name of the new style. If NULL, just
* print out the valid styles. * print out the valid styles.
*/ */
{ {
CIFKeep *style, *match, *exactmatch; CIFKeep *style, *match;
bool ambiguous = FALSE;
int length; int length;
if (name == NULL) return; if (name == NULL) return;
@ -270,25 +247,18 @@ CIFSetStyle(
for (style = CIFStyleList; style != NULL; style = style->cs_next) for (style = CIFStyleList; style != NULL; style = style->cs_next)
{ {
if (!strcmp(name, style->cs_name)) { if (strncmp(name, style->cs_name, length) == 0)
match = style;
ambiguous = FALSE;
break;
}
else if (!strncmp(name, style->cs_name, length))
{ {
if (match != NULL) ambiguous = TRUE; if (match != NULL)
{
TxError("CIF output style \"%s\" is ambiguous.\n", name);
CIFPrintStyle(FALSE, TRUE, TRUE);
return;
}
match = style; match = style;
} }
} }
if (ambiguous)
{
TxError("CIF output style \"%s\" is ambiguous.\n", name);
CIFPrintStyle(FALSE, TRUE, TRUE);
return;
}
if (match != NULL) if (match != NULL)
{ {
CIFLoadStyle(match->cs_name); CIFLoadStyle(match->cs_name);
@ -320,10 +290,10 @@ CIFSetStyle(
*/ */
bool bool
CIFNameToMask( CIFNameToMask(name, result, depend)
char *name, char *name;
TileTypeBitMask *result, TileTypeBitMask *result;
TileTypeBitMask *depend) TileTypeBitMask *depend;
{ {
int i, j; int i, j;
CIFOp *op; CIFOp *op;
@ -414,11 +384,11 @@ CIFNameToMask(
*/ */
void void
CIFError( CIFError(area, message)
Rect *area, /* Place in CIFErrorDef where there was a Rect *area; /* Place in CIFErrorDef where there was a
* problem in generating CIFErrorLayer. * problem in generating CIFErrorLayer.
*/ */
char *message) /* Short note about what went wrong. */ char *message; /* Short note about what went wrong. */
{ {
char msg[200]; char msg[200];
@ -452,7 +422,7 @@ CIFError(
*/ */
int int
CIFOutputScaleFactor(void) CIFOutputScaleFactor()
{ {
if (CIFCurStyle == NULL) return 1; if (CIFCurStyle == NULL) return 1;
return CIFCurStyle->cs_scaleFactor; return CIFCurStyle->cs_scaleFactor;

View File

@ -19,7 +19,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -126,8 +126,8 @@ char *cifSubcellId = NULL;
*/ */
void void
CIFReadCellInit( CIFReadCellInit(ptrkeys)
int ptrkeys) int ptrkeys;
{ {
int i; int i;
@ -162,8 +162,8 @@ CIFReadCellInit(
*/ */
bool bool
cifForgetCell( cifForgetCell(cifNum)
int cifNum) int cifNum;
{ {
HashEntry *h; HashEntry *h;
@ -196,8 +196,8 @@ cifForgetCell(
*/ */
void void
cifUniqueCell( cifUniqueCell(cifNum)
int cifNum) int cifNum;
{ {
HashEntry *h; HashEntry *h;
CellDef *def, *testdef; CellDef *def, *testdef;
@ -256,8 +256,8 @@ cifUniqueCell(
*/ */
CellDef * CellDef *
cifFindCell( cifFindCell(cifNum)
int cifNum) /* The CIF number of the desired cell. */ int cifNum; /* The CIF number of the desired cell. */
{ {
HashEntry *h; HashEntry *h;
CellDef *def, *testdef; CellDef *def, *testdef;
@ -299,10 +299,10 @@ cifFindCell(
*/ */
void void
CIFScalePlanes( CIFScalePlanes(scalen, scaled, planearray)
int scalen, int scalen;
int scaled, int scaled;
Plane **planearray) Plane **planearray;
{ {
int pNum; int pNum;
Plane *newplane; Plane *newplane;
@ -348,9 +348,8 @@ CIFScalePlanes(
*/ */
void void
CIFInputRescale( CIFInputRescale(n, d)
int n, int n, d;
int d)
{ {
CIFReadStyle *istyle = cifCurReadStyle; CIFReadStyle *istyle = cifCurReadStyle;
CIFReadLayer *cl; CIFReadLayer *cl;
@ -387,10 +386,8 @@ CIFInputRescale(
} }
} }
CIFScalePlanes(n, d, cifCurReadPlanes); CIFScalePlanes(n, d, cifEditCellPlanes);
if (cifCurReadPlanes != cifEditCellPlanes) if (cifEditCellPlanes != cifSubcellPlanes)
CIFScalePlanes(n, d, cifEditCellPlanes);
if ((const Plane*)cifEditCellPlanes != (const Plane*)cifSubcellPlanes && cifCurReadPlanes != cifSubcellPlanes)
CIFScalePlanes(n, d, cifSubcellPlanes); CIFScalePlanes(n, d, cifSubcellPlanes);
CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n", CIFReadWarning("CIF style %s: units rescaled by factor of %d / %d\n",
@ -418,7 +415,7 @@ CIFInputRescale(
*/ */
bool bool
CIFParseStart(void) CIFParseStart()
{ {
int number; int number;
@ -503,10 +500,9 @@ CIFParseStart(void)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
int cifCheckPaintFunc( int cifCheckPaintFunc(tile, clientData)
Tile *tile, Tile *tile;
TileType dinfo, ClientData clientData;
ClientData clientData)
{ {
return 1; return 1;
} }
@ -514,70 +510,34 @@ int cifCheckPaintFunc(
/* Callback function for copying paint from one CIF cell into another */ /* Callback function for copying paint from one CIF cell into another */
int int
cifCopyPaintFunc( cifCopyPaintFunc(tile, cifCopyRec)
Tile *tile, Tile *tile;
TileType dinfo, CIFCopyRec *cifCopyRec;
CIFCopyRec *cifCopyRec)
{ {
int pNum; int pNum;
TileType newdinfo; TileType dinfo;
Rect sourceRect, targetRect; Rect sourceRect, targetRect;
Transform *trans = cifCopyRec->trans; Transform *trans = cifCopyRec->trans;
Plane *plane = cifCopyRec->plane; Plane *plane = cifCopyRec->plane;
newdinfo = TiGetTypeExact(tile) | dinfo; dinfo = TiGetTypeExact(tile);
if (trans) if (trans)
{ {
TiToRect(tile, &sourceRect); TiToRect(tile, &sourceRect);
GeoTransRect(trans, &sourceRect, &targetRect); GeoTransRect(trans, &sourceRect, &targetRect);
if (IsSplit(tile)) if (IsSplit(tile))
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans); dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
} }
else else
TiToRect(tile, &targetRect); TiToRect(tile, &targetRect);
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable, DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);
return 0; return 0;
} }
/*
* ----------------------------------------------------------------------------
*
* cifMaskHintFunc --
*
* For each tile in the scanned plane, convert the tile into a coordinate
* string by appending the coordinates to the list passed as clientData.
*
* Results:
* Return 0 to keep the search going.
*
* Side effects:
* Allocates memory for and seeds a linked rect entry
*
* ----------------------------------------------------------------------------
*/
int
cifMaskHintFunc(
Tile *tile,
TileType dinfo, /* Unused, do not support non-manhattan hints */
LinkedRect **lrecp)
{
Rect r;
LinkedRect *newlr;
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
newlr->r_next = *lrecp;
(*lrecp) = newlr;
TiToRect(tile, &newlr->r_r);
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -597,12 +557,11 @@ cifMaskHintFunc(
*/ */
int int
CIFPaintCurrent( CIFPaintCurrent(filetype)
int filetype) bool filetype;
{ {
/* Forward declarations. */ extern int cifMakeBoundaryFunc(); /* Forward declaration. */
extern int cifMakeBoundaryFunc(Tile *tile, TileType dinfo, ClientData clientdata); extern int cifPaintCurrentFunc(); /* Forward declaration. */
extern int cifPaintCurrentFunc(Tile *tile, TileType dinfo, TileType type);
Plane *plane, *swapplane; Plane *plane, *swapplane;
int i; int i;
@ -613,8 +572,7 @@ CIFPaintCurrent(
CIFOp *op; CIFOp *op;
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops, plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
&TiPlaneRect, cifReadCellDef, cifReadCellDef, &TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL, cifCurReadPlanes);
cifCurReadPlanes, FALSE, (ClientData)NULL);
/* Generate a paint/erase table, then paint from the CIF /* Generate a paint/erase table, then paint from the CIF
* plane into the current Magic cell. * plane into the current Magic cell.
@ -644,13 +602,13 @@ CIFPaintCurrent(
Plane **parray; Plane **parray;
extern char *(cifReadLayers[MAXCIFRLAYERS]); extern char *(cifReadLayers[MAXCIFRLAYERS]);
/* NOTE: The condition cd_client == 0 when CDFLATGDS /* NOTE: There should be no need to check for cd_client
* indicates that the cell was already in memory when the * here as cd_client should not be CLIENTDEFAULT if CDFLATGDS
* GDS was read. This condition should be properly caught * is set in flags. This condition has occurred, though, and
* and handled. * needs to be debugged.
*/ */
if ((cifReadCellDef->cd_flags & CDFLATGDS) && if ((cifReadCellDef->cd_flags & CDFLATGDS) &&
(cifReadCellDef->cd_client != (ClientData)0)) (cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT))
parray = (Plane **)cifReadCellDef->cd_client; parray = (Plane **)cifReadCellDef->cd_client;
else else
{ {
@ -688,8 +646,6 @@ CIFPaintCurrent(
} }
else if (op == NULL) else if (op == NULL)
{ {
LinkedRect *lrec = NULL, *lsrch;
/* Handle boundary layer */ /* Handle boundary layer */
op = cifCurReadStyle->crs_layers[i]->crl_ops; op = cifCurReadStyle->crs_layers[i]->crl_ops;
@ -703,103 +659,7 @@ CIFPaintCurrent(
&DBAllButSpaceBits, cifCheckPaintFunc, &DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1)) (ClientData)NULL) == 1))
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype)); &CIFSolidBits, cifMakeBoundaryFunc, (ClientData)filetype);
/* Handle mask-hints input operator */
op = cifCurReadStyle->crs_layers[i]->crl_ops;
while (op)
{
if (op->co_opcode == CIFOP_MASKHINTS) break;
op = op->co_next;
}
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
{
/* (To do: remove the linked Rects and paint directly
* into the plane in cifMaskHintFunc())
*/
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMaskHintFunc,
(ClientData)&lrec);
if (lrec != NULL)
{
PropertyRecord *proprec, *proporig;
char *propname, *layername;
int proplen, i, savescale;
bool origfound = FALSE;
Plane *plane;
layername = (char *)op->co_client;
propname = (char *)mallocMagic(11 + strlen(layername));
sprintf(propname, "MASKHINTS_%s", layername);
/* If there is already a mask hint plane for this layer,
* then add to it; otherwise, create a new plane.
*/
proprec = DBPropGet(cifReadCellDef, layername, &origfound);
if (origfound)
plane = proprec->prop_value.prop_plane;
else
{
proprec = (PropertyRecord *)mallocMagic(
sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0; /* (unused) */
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
DBPropPut(cifReadCellDef, propname, proprec);
}
while (lrec != NULL)
{
lrec->r_r.r_xtop =
CIFScaleCoord(lrec->r_r.r_xtop, COORD_EXACT);
savescale = cifCurReadStyle->crs_scaleFactor;
lrec->r_r.r_ytop =
CIFScaleCoord(lrec->r_r.r_ytop, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
savescale = cifCurReadStyle->crs_scaleFactor;
}
lrec->r_r.r_xbot =
CIFScaleCoord(lrec->r_r.r_xbot, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_ytop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
savescale = cifCurReadStyle->crs_scaleFactor;
}
lrec->r_r.r_ybot =
CIFScaleCoord(lrec->r_r.r_ybot, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_ytop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_xbot *=
(savescale / cifCurReadStyle->crs_scaleFactor);
}
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
(PaintUndoInfo *)NULL);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
freeMagic1_end(&mm1);
}
freeMagic(propname);
}
}
} }
/* Swap planes */ /* Swap planes */
@ -811,7 +671,7 @@ CIFPaintCurrent(
{ {
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifPaintCurrentFunc, &CIFSolidBits, cifPaintCurrentFunc,
INT2CD(type)); (ClientData)type);
} }
/* Recycle the plane, which was dynamically allocated. */ /* Recycle the plane, which was dynamically allocated. */
@ -820,166 +680,6 @@ CIFPaintCurrent(
TiFreePlane(plane); TiFreePlane(plane);
} }
/* If mask hints were requested, then for each GDS/CIF layer in the */
/* input, if the layer has a corresponding output layer and the */
/* output layer has a mask hints operator, then generate the output */
/* plane for that layer, compare to the input plane, and create */
/* mask hint properties to make the output the same as the input. */
if ((CalmaMaskHints != NULL) && (!TTMaskIsZero(CalmaMaskHints)))
{
int j;
CIFOp *op, newop, subop;
Plane *presult;
TileTypeBitMask genMask;
int *in_out_map;
extern char *(cifReadLayers[MAXCIFRLAYERS]);
TTMaskZero(&genMask);
in_out_map = (int *)mallocMagic(cifNReadLayers * sizeof(int));
for (i = 0; i < cifNReadLayers; i++)
{
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
/* Does the input layer have a corresponding output layer? */
in_out_map[i] = -1;
for (j = 0; j < CIFCurStyle->cs_nLayers; j++)
{
if (!strcmp(CIFCurStyle->cs_layers[j]->cl_name, cifReadLayers[i]))
{
/* Does the layer have a mask-hints operator? */
for (op = CIFCurStyle->cs_layers[j]->cl_ops; op; op = op->co_next)
if (op->co_opcode == CIFOP_MASKHINTS)
{
TTMaskSetType(&genMask, j);
in_out_map[i] = j;
break;
}
}
if (in_out_map[i] >= 0) break;
}
}
/* Multiply input planes to the same scale as the generated output */
CIFScalePlanes(CIFCurStyle->cs_scaleFactor, cifCurReadStyle->crs_scaleFactor,
cifCurReadPlanes);
/* Generate the output for these layers from the cell contents */
CIFClearPlanes(CIFPlanes);
/* TO-DO: Replace DBAllTypeBits with genMask. Requires that genMask */
/* be expanded to include all dependent layers. */
CIFGen(cifReadCellDef, cifReadCellDef, &TiPlaneRect, CIFPlanes, &DBAllTypeBits,
TRUE, FALSE, FALSE, (ClientData)NULL);
/* Set up double operator for OR and ANDNOT functions */
newop.co_opcode = CIFOP_OR;
newop.co_distance = 0;
newop.co_next = &subop;
newop.co_client = (ClientData)NULL;
TTMaskZero(&newop.co_paintMask);
subop.co_opcode = CIFOP_ANDNOT;
subop.co_distance = 0;
subop.co_next = NULL;
subop.co_client = (ClientData)NULL;
TTMaskZero(&subop.co_paintMask);
for (i = 0; i < cifNReadLayers; i++)
{
LinkedRect *lrec = NULL, *lsrch;
Plane *tempp;
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
j = in_out_map[i];
if (j < 0) continue;
TTMaskSetOnlyType(&subop.co_cifMask, j);
/* Replace last layer + 1 on CIFPlanes with input layer i */
tempp = CIFPlanes[CIFCurStyle->cs_nLayers];
TTMaskSetOnlyType(&newop.co_cifMask, CIFCurStyle->cs_nLayers);
CIFPlanes[CIFCurStyle->cs_nLayers] = cifCurReadPlanes[i];
CIFCurStyle->cs_nLayers++;
/* Compute result (i AND-NOT j), which will be all the areas of
* the input on layer i that are not generated by writing output
* layer j.
*/
presult = CIFGenLayer(&newop, &TiPlaneRect, (CellDef *)NULL,
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
/* Scan the resulting plane and generate linked Rect structures for
* each shape found. (To do: Remove the linked Rects and paint
* directly into the plane in cifMaskHintFunc(), which is more
* efficient but not hugely so.)
*/
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
cifMaskHintFunc, (ClientData)&lrec);
if (lrec != NULL)
{
PropertyRecord *proprec;
bool propfound;
char *propname;
Plane *plane;
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
/* Paint all linked Rects into a mask-hints property plane
* in the target cell.
*/
proprec = DBPropGet(cifReadCellDef, propname, &propfound);
if (!propfound)
{
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
proprec->prop_type = PROPERTY_TYPE_PLANE;
proprec->prop_len = 0; /* (unused) */
plane = DBNewPlane((ClientData)TT_SPACE);
proprec->prop_value.prop_plane = plane;
DBPropPut(cifReadCellDef, propname, proprec);
}
else
plane = proprec->prop_value.prop_plane;
while (lrec != NULL)
{
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
(PaintUndoInfo *)NULL);
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
freeMagic1_end(&mm1);
}
freeMagic(propname);
}
/* Delete the generated plane */
DBFreePaintPlane(presult);
TiFreePlane(presult);
/* Replace the input plane that was shuffled out */
CIFCurStyle->cs_nLayers--;
CIFPlanes[CIFCurStyle->cs_nLayers] = tempp;
}
/* Free up the planes used to create the output */
CIFClearPlanes(CIFPlanes);
freeMagic((char *)in_out_map);
}
/* Now go through all the current planes and zero them out. */ /* Now go through all the current planes and zero them out. */
for (i = 0; i < MAXCIFRLAYERS; i++) for (i = 0; i < MAXCIFRLAYERS; i++)
@ -991,20 +691,18 @@ CIFPaintCurrent(
/* Use CIF layer geometry to define a fixed bounding box for the current cell */ /* Use CIF layer geometry to define a fixed bounding box for the current cell */
int int
cifMakeBoundaryFunc( cifMakeBoundaryFunc(tile, clientdata)
Tile *tile, /* Tile of CIF information. */ Tile *tile; /* Tile of CIF information. */
TileType dinfo, /* Split tile information (unused) */ ClientData clientdata; /* Pass the file type (CIF or CALMA) */
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
{ {
/* It is assumed that there is one rectangle for the boundary. */ /* It is assumed that there is one rectangle for the boundary. */
/* If there are multiple rectangles defined with the boundary */ /* If there are multiple rectangles defined with the boundary */
/* layer, then the last one defines the FIXED_BBOX property. */ /* layer, then the last one defines the FIXED_BBOX property. */
PropertyRecord *proprec;
Rect area; Rect area;
char propertyvalue[128], *storedvalue; char propertyvalue[128], *storedvalue;
int savescale; int savescale;
int filetype = (int)CD2INT(clientdata); bool filetype = (bool)clientdata;
TiToRect(tile, &area); TiToRect(tile, &area);
area.r_xtop = CIFScaleCoord(area.r_xtop, COORD_EXACT); area.r_xtop = CIFScaleCoord(area.r_xtop, COORD_EXACT);
@ -1032,24 +730,19 @@ cifMakeBoundaryFunc(
if (cifReadCellDef->cd_flags & CDFIXEDBBOX) if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
{ {
PropertyRecord *proprec; char *propvalue;
bool found; bool found;
/* Only flag a warning if the redefined boundary was */ /* Only flag a warning if the redefined boundary was */
/* different from the original. */ /* different from the original. */
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found); propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
if (found) if (found)
{ {
Rect bbox; Rect bbox;
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) && if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
(proprec->prop_len == 4)) &bbox.r_xtop, &bbox.r_ytop) == 4)
{ {
bbox.r_xbot = proprec->prop_value.prop_integer[0];
bbox.r_ybot = proprec->prop_value.prop_integer[1];
bbox.r_xtop = proprec->prop_value.prop_integer[2];
bbox.r_ytop = proprec->prop_value.prop_integer[3];
if ((bbox.r_xbot != area.r_xbot) || if ((bbox.r_xbot != area.r_xbot) ||
(bbox.r_ybot != area.r_ybot) || (bbox.r_ybot != area.r_ybot) ||
(bbox.r_xtop != area.r_xtop) || (bbox.r_xtop != area.r_xtop) ||
@ -1066,15 +759,10 @@ cifMakeBoundaryFunc(
} }
} }
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int)); sprintf(propertyvalue, "%d %d %d %d",
proprec->prop_type = PROPERTY_TYPE_DIMENSION; area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
proprec->prop_len = 4; storedvalue = StrDup((char **)NULL, propertyvalue);
proprec->prop_value.prop_integer[0] = area.r_xbot; DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
proprec->prop_value.prop_integer[1] = area.r_ybot;
proprec->prop_value.prop_integer[2] = area.r_xtop;
proprec->prop_value.prop_integer[3] = area.r_ytop;
DBPropPut(cifReadCellDef, "FIXED_BBOX", proprec);
cifReadCellDef->cd_flags |= CDFIXEDBBOX; cifReadCellDef->cd_flags |= CDFIXEDBBOX;
return 0; return 0;
} }
@ -1082,10 +770,9 @@ cifMakeBoundaryFunc(
/* Paint CIF layer geometry into the current cell def as magic layer "type" */ /* Paint CIF layer geometry into the current cell def as magic layer "type" */
int int
cifPaintCurrentFunc( cifPaintCurrentFunc(tile, type)
Tile *tile, /* Tile of CIF information. */ Tile *tile; /* Tile of CIF information. */
TileType dinfo, /* Split tile information */ TileType type; /* Magic type to be painted. */
TileType type) /* Magic type to be painted. */
{ {
Rect area; Rect area;
int pNum; int pNum;
@ -1134,7 +821,7 @@ cifPaintCurrentFunc(
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (DBPaintOnPlane(type, pNum)) if (DBPaintOnPlane(type, pNum))
{ {
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo, DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL); &area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
} }
@ -1160,7 +847,7 @@ cifPaintCurrentFunc(
*/ */
bool bool
CIFParseFinish(void) CIFParseFinish()
{ {
if (!cifSubcellBeingRead) if (!cifSubcellBeingRead)
{ {
@ -1215,7 +902,7 @@ CIFParseFinish(void)
*/ */
bool bool
CIFParseDelete(void) CIFParseDelete()
{ {
int number; int number;
@ -1257,7 +944,7 @@ CIFParseDelete(void)
*/ */
char * char *
cifParseName(void) cifParseName()
{ {
char ch; char ch;
char *bufferp; char *bufferp;
@ -1299,7 +986,7 @@ cifParseName(void)
*/ */
bool bool
cifParseUser9(void) cifParseUser9()
{ {
char *name; char *name;
@ -1331,7 +1018,7 @@ cifParseUser9(void)
*/ */
bool bool
CIFParseCall(void) CIFParseCall()
{ {
int called; int called;
Transform transform; Transform transform;
@ -1398,7 +1085,7 @@ CIFParseCall(void)
*/ */
bool bool
cifParseUser91(void) cifParseUser91()
{ {
if (cifSubcellId != NULL) if (cifSubcellId != NULL)
{ {
@ -1429,7 +1116,7 @@ cifParseUser91(void)
*/ */
bool bool
cifParseUser94(void) cifParseUser94()
{ {
Rect rectangle; Rect rectangle;
char *name = NULL; char *name = NULL;
@ -1493,7 +1180,7 @@ cifParseUser94(void)
flags = LABEL_STICKY; flags = LABEL_STICKY;
else else
flags = 0; flags = 0;
(void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags, 0); (void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags);
} }
freeMagic(name); freeMagic(name);
return TRUE; return TRUE;
@ -1519,7 +1206,7 @@ cifParseUser94(void)
*/ */
bool bool
cifParseUser95(void) cifParseUser95()
{ {
/* Modified by BIM 1/8/2018 */ /* Modified by BIM 1/8/2018 */
Rect rectangle; Rect rectangle;
@ -1654,7 +1341,7 @@ cifParseUser95(void)
flags = LABEL_STICKY; flags = LABEL_STICKY;
else else
flags = 0; flags = 0;
(void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags, 0); (void) DBPutLabel(cifReadCellDef, &rectangle, -1, name, type, flags);
} }
freeMagic(name); freeMagic(name);
@ -1679,7 +1366,7 @@ cifParseUser95(void)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
bool bool
CIFParseUser(void) CIFParseUser()
{ {
char ch; char ch;
@ -1731,8 +1418,8 @@ CIFParseUser(void)
*/ */
void void
CIFReadCellCleanup( CIFReadCellCleanup(filetype)
int filetype) bool filetype;
{ {
HashEntry *h; HashEntry *h;
HashSearch hs; HashSearch hs;
@ -1775,19 +1462,15 @@ CIFReadCellCleanup(
def->cd_flags &= ~CDPROCESSEDGDS; def->cd_flags &= ~CDPROCESSEDGDS;
if ((filetype == FILE_CIF && CIFNoDRCCheck == FALSE) || if ((filetype == FILE_CIF && CIFNoDRCCheck == FALSE) ||
(filetype == FILE_CALMA && CalmaNoDRCCheck == FALSE)) (filetype == 1 && CalmaNoDRCCheck == FALSE))
DRCCheckThis(def, TT_CHECKPAINT, &def->cd_bbox); DRCCheckThis(def, TT_CHECKPAINT, &def->cd_bbox);
DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits);
DBCellSetModified(def, TRUE); DBCellSetModified(def, TRUE);
/* Only mark cell as needing a timestamp update if the timestamp is zero */
if (def->cd_timestamp != 0)
def->cd_flags &= ~CDGETNEWSTAMP;
} }
/* Do geometrical processing on the top-level cell. */ /* Do geometrical processing on the top-level cell. */
if (filetype == FILE_CIF) CIFPaintCurrent(filetype);
CIFPaintCurrent(FILE_CIF);
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect); DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
DBReComputeBbox(EditCellUse->cu_def); DBReComputeBbox(EditCellUse->cu_def);
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox, DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
@ -1808,10 +1491,6 @@ CIFReadCellCleanup(
if (def->cd_flags & CDFLATGDS) if (def->cd_flags & CDFLATGDS)
{ {
/* These cells have been flattened and are no longer needed. */ /* These cells have been flattened and are no longer needed. */
/* Do not remove the actual CellDef, though, because it is */
/* still instanced, and that instance tells the GDS write */
/* routine that the subcell needs to be included in the */
/* output. But all clientdata and labels should be removed. */
int pNum; int pNum;
Plane **cifplanes = (Plane **)def->cd_client; Plane **cifplanes = (Plane **)def->cd_client;
@ -1819,8 +1498,9 @@ CIFReadCellCleanup(
UndoDisable(); UndoDisable();
/* cifplanes should be valid, but don't crash magic if not */ /* cifplanes should be valid, but don't crash magic if not */
if (cifplanes != (Plane **)0) if (cifplanes != (Plane **)CLIENTDEFAULT)
{ {
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
{ {
if (cifplanes[pNum] != NULL) if (cifplanes[pNum] != NULL)
@ -1831,9 +1511,44 @@ CIFReadCellCleanup(
} }
freeMagic((char *)def->cd_client); freeMagic((char *)def->cd_client);
} }
def->cd_client = (ClientData)0; def->cd_client = (ClientData)CLIENTDEFAULT;
def->cd_flags &= ~CDFLATGDS;
#if 0
/* If the CDFLATTENED flag was not set, then this geometry */
/* was never instantiated, and should generate a message. */
/* However, this is not an error condition as there are a */
/* number of useful reasons to copy lots of information up */
/* the GDS hierarchy for "just in case" scenarios. */
if (!(def->cd_flags & CDFLATTENED))
CIFReadWarning("%s read: Unresolved geometry in cell"
" %s maps to no magic layers\n",
(filetype == FILE_CIF) ? "CIF" : "GDS", def->cd_name);
#endif
#if 0
/* Remove the cell if it has no parents, no children, and no geometry */
/* To-do: Check that these conditions are valid */
if (def->cd_parents == (CellUse *)NULL)
{
char *savename = StrDup((char **)NULL, def->cd_name);
if (DBCellDeleteDef(def) == FALSE)
{
CIFReadError("%s read error: Unable to delete cell %s\n",
(filetype == FILE_CIF) ? "CIF" : "GDS", savename);
}
else
{
if (filetype == FILE_CIF)
TxPrintf("CIF read: Removed flattened cell %s\n", savename);
else
TxPrintf("GDS read: Removed flattened cell %s\n", savename);
}
freeMagic(savename);
}
#endif
UndoEnable(); UndoEnable();
} }
} }

View File

@ -17,11 +17,10 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* For qsort() */
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -29,7 +28,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "database/database.h" #include "database/database.h"
#include "cif/CIFint.h" #include "cif/CIFint.h"
#include "cif/CIFread.h" #include "cif/CIFread.h"
#include "calma/calma.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#define HEDGE 0 /* Horizontal edge */ #define HEDGE 0 /* Horizontal edge */
@ -55,14 +53,10 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
*/ */
int int
cifLowX( cifLowX(a, b)
const void *aa, CIFPath **a, **b;
const void *bb)
{ {
const CIFPath **a = (const CIFPath **)aa; Point *p, *q;
const CIFPath **b = (const CIFPath **)bb;
const Point *p, *q;
p = &(*a)->cifp_point; p = &(*a)->cifp_point;
q = &(*b)->cifp_point; q = &(*b)->cifp_point;
@ -92,12 +86,9 @@ cifLowX(
*/ */
int int
cifLowY( cifLowY(a, b)
const void *aa, Point **a, **b;
const void *bb)
{ {
const Point **a = (const Point **)aa;
const Point **b = (const Point **)bb;
if ((*a)->p_y < (*b)->p_y) if ((*a)->p_y < (*b)->p_y)
return (-1); return (-1);
if ((*a)->p_y > (*b)->p_y) if ((*a)->p_y > (*b)->p_y)
@ -126,10 +117,10 @@ cifLowY(
*/ */
bool bool
cifOrient( cifOrient(edges, nedges, dir)
CIFPath *edges[], /* Array of edges to be categorized. */ CIFPath *edges[]; /* Array of edges to be categorized. */
int nedges, /* Size of arrays. */ int dir[]; /* Array to hold directions. */
int dir[]) /* Array to hold directions. */ int nedges; /* Size of arrays. */
{ {
Point *p, *q; Point *p, *q;
int n; int n;
@ -186,11 +177,10 @@ cifOrient(
*/ */
bool bool
cifCross( cifCross(edge, dir, ybot, ytop)
CIFPath *edge, /* Pointer to first of 2 path points in edge */ CIFPath *edge; /* Pointer to first of 2 path points in edge */
int dir, /* Direction of edge */ int dir; /* Direction of edge */
int ybot, int ybot, ytop; /* Range of interest */
int ytop) /* Range of interest */
{ {
int ebot, etop; int ebot, etop;
@ -231,12 +221,11 @@ cifCross(
*/ */
LinkedRect * LinkedRect *
CIFPolyToRects( CIFPolyToRects(path, plane, resultTbl, ui)
CIFPath *path, /* Path describing a polygon. */ CIFPath *path; /* Path describing a polygon. */
Plane *plane, /* Plane to draw on */ Plane *plane; /* Plane to draw on */
const PaintResultType *resultTbl, PaintResultType *resultTbl;
PaintUndoInfo *ui, PaintUndoInfo *ui;
bool isCalma) /* TRUE for Calma, FALSE for CIF */
{ {
int npts = 0, n, *dir, curr, wrapno; int npts = 0, n, *dir, curr, wrapno;
int xbot, xtop, ybot, ytop; int xbot, xtop, ybot, ytop;
@ -250,9 +239,6 @@ CIFPolyToRects(
if ((tail->cifp_x != path->cifp_x) || (tail->cifp_y != path->cifp_y)) 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 = (CIFPath *) mallocMagic ((unsigned) sizeof (CIFPath));
p->cifp_x = path->cifp_x; p->cifp_x = path->cifp_x;
p->cifp_y = path->cifp_y; p->cifp_y = path->cifp_y;

View File

@ -18,7 +18,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -37,8 +37,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "cif/CIFint.h" #include "cif/CIFint.h"
#include "cif/CIFread.h" #include "cif/CIFread.h"
/* C99 compat */
#include "textio/textio.h"
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -65,7 +63,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
*/ */
bool bool
CIFParseBox(void) CIFParseBox()
{ {
Point center; Point center;
Point direction; Point direction;
@ -176,7 +174,7 @@ CIFParseBox(void)
*/ */
bool bool
CIFParseFlash(void) CIFParseFlash()
{ {
int diameter; int diameter;
int savescale; int savescale;
@ -236,69 +234,47 @@ CIFParseFlash(void)
*/ */
void void
CIFPropRecordPath( CIFPropRecordPath(def, pathheadp, iswire, propname)
CellDef *def, CellDef *def;
CIFPath *pathheadp, CIFPath *pathheadp;
bool iswire, char *propname;
char *propname)
{ {
extern float CIFGetOutputScale(int convert); extern float CIFGetOutputScale();
CIFPath *pathp; CIFPath *pathp;
char *namestr = NULL; char *pathstr, *sptr;
int components, i, x, y, mult, pathnum; int components;
PropertyRecord *proprec; float x, y, oscale, mult;
bool propfound;
/* If "name" is a property, then append a suffix to it to ensure uniqueness */ oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
DBPropGet(def, propname, &propfound); if (oscale == 0.0) oscale = 1.0;
if (propfound) mult = (iswire == TRUE) ? 0.5 : 1.0;
{
pathnum = 0;
namestr = mallocMagic(strlen(propname) + 10);
while (propfound)
{
sprintf(namestr, "%s_%d", propname, pathnum);
DBPropGet(def, namestr, &propfound);
pathnum++;
}
}
mult = (iswire == TRUE) ? 1 : 0;
/* Count the number of components in the path */
pathp = pathheadp; pathp = pathheadp;
components = 0; components = 0;
/* Count the number of components in the path */
while (pathp != NULL) while (pathp != NULL)
{ {
components++;
pathp = pathp->cifp_next; pathp = pathp->cifp_next;
components++;
} }
/* Allocate enough space to hold 2 * N points. */ /* Allocate enough space to hold 2 * N points at "infinity" */
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + pathstr = (char *)mallocMagic(components * 40);
((components - 1) * 2) * sizeof(int));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = components * 2;
pathp = pathheadp; pathp = pathheadp;
i = 0; sptr = pathstr;
while (pathp != NULL) while (pathp != NULL)
{ {
x = pathp->cifp_x >> mult; x = (float)pathp->cifp_x * oscale * mult;
y = pathp->cifp_y >> mult; y = (float)pathp->cifp_y * oscale * mult;
sprintf(sptr, "%.3f %.3f ", x, y);
proprec->prop_value.prop_integer[i] = x; sptr = sptr + strlen(sptr);
proprec->prop_value.prop_integer[i + 1] = y;
i += 2;
pathp = pathp->cifp_next; pathp = pathp->cifp_next;
} }
if (namestr)
{ /* Reallocate pathstr to be no larger than needed to hold the path contents */
DBPropPut(def, namestr, proprec); StrDup(&pathstr, pathstr);
freeMagic(namestr); DBPropPut(def, propname, (ClientData)pathstr);
}
else
DBPropPut(def, propname, proprec);
} }
/* /*
@ -337,13 +313,13 @@ CIFPropRecordPath(
*/ */
void void
CIFPaintWirePath( CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui)
CIFPath *pathheadp, CIFPath *pathheadp;
int width, int width;
bool endcap, bool endcap;
Plane *plane, Plane *plane;
const PaintResultType *ptable, PaintResultType *ptable;
PaintUndoInfo *ui) PaintUndoInfo *ui;
{ {
CIFPath *pathp, *previousp, *nextp, *polypath; CIFPath *pathp, *previousp, *nextp, *polypath;
CIFPath *returnpath, *newpath, *savepath; CIFPath *returnpath, *newpath, *savepath;
@ -359,20 +335,18 @@ CIFPaintWirePath(
pathp = pathheadp->cifp_next; pathp = pathheadp->cifp_next;
if (pathp != NULL) if (pathp != NULL)
{ {
free_magic1_t mm1 = freeMagic1_init();
while (pathp->cifp_next != NULL) while (pathp->cifp_next != NULL)
{ {
if (pathp->cifp_next->cifp_x == pathp->cifp_x && if (pathp->cifp_next->cifp_x == pathp->cifp_x &&
pathp->cifp_next->cifp_y == pathp->cifp_y) pathp->cifp_next->cifp_y == pathp->cifp_y)
{ {
previousp->cifp_next = pathp->cifp_next; previousp->cifp_next = pathp->cifp_next;
freeMagic1(&mm1, pathp); freeMagic(pathp);
} }
else else
previousp = pathp; previousp = pathp;
pathp = pathp->cifp_next; pathp = pathp->cifp_next;
} }
freeMagic1_end(&mm1);
} }
previousp = pathheadp; previousp = pathheadp;
@ -462,22 +436,8 @@ CIFPaintWirePath(
/* Wire reverses direction. Break wire here, */ /* Wire reverses direction. Break wire here, */
/* draw, and start new polygon. */ /* draw, and start new polygon. */
/* Check first if last point and current point */ TxError("Warning: direction reversal in path.\n");
/* are the same, in which case a different */
/* message should be issued (and possibly */
/* should be handled differently?) */
if (previousp && previousp->cifp_x == pathp->cifp_x
&& previousp->cifp_y == pathp->cifp_y)
{
TxError("Warning: duplicate point in path at (%d, %d).\n",
pathp->cifp_x / 2, pathp->cifp_y / 2);
}
else
{
TxError("Warning: direction reversal in path at (%d, %d).\n",
pathp->cifp_x / 2, pathp->cifp_y / 2);
}
phi = theta; phi = theta;
if (endcap) if (endcap)
{ {
@ -488,8 +448,7 @@ CIFPaintWirePath(
firstpoint = TRUE; firstpoint = TRUE;
} }
else { else {
TxError("Error: mitre limit exceeded at wire junction at (%d, %d).\n", TxError("Error: mitre limit exceeded at wire junction.\n");
pathp->cifp_x, pathp->cifp_y);
TxError("Route has been truncated.\n"); TxError("Route has been truncated.\n");
break; break;
} }
@ -519,16 +478,14 @@ CIFPaintWirePath(
/* Slow draw for non-Manhattan paths: */ /* Slow draw for non-Manhattan paths: */
/* Break the area up into triangles and rectangles */ /* Break the area up into triangles and rectangles */
rectp = CIFPolyToRects(polypath, plane, ptable, ui, FALSE); rectp = CIFPolyToRects(polypath, plane, ptable, ui);
CIFFreePath(polypath); CIFFreePath(polypath);
free_magic1_t mm1 = freeMagic1_init();
for (; rectp != NULL ; rectp = rectp->r_next) for (; rectp != NULL ; rectp = rectp->r_next)
{ {
DBPaintPlane(plane, &rectp->r_r, ptable, ui); DBPaintPlane(plane, &rectp->r_r, ptable, ui);
freeMagic1(&mm1, (char *) rectp); freeMagic((char *) rectp);
} }
freeMagic1_end(&mm1);
polypath = NULL; polypath = NULL;
} }
else else
@ -602,13 +559,13 @@ CIFPaintWirePath(
*/ */
LinkedRect * LinkedRect *
PaintPolygon( PaintPolygon(pointlist, number, plane, ptable, ui, keep)
Point *pointlist, /* Array of Point structures */ Point *pointlist; /* Array of Point structures */
int number, /* total number of points */ int number; /* total number of points */
Plane *plane, /* Plane structure to paint into */ Plane *plane; /* Plane structure to paint into */
PaintResultType *ptable, /* Paint result table */ PaintResultType *ptable; /* Paint result table */
PaintUndoInfo *ui, /* Undo record */ PaintUndoInfo *ui; /* Undo record */
bool keep) /* Return list of rects if true */ bool keep; /* Return list of rects if true */
{ {
LinkedRect *rectp, *rectlist; LinkedRect *rectp, *rectlist;
CIFPath *newpath, *cifpath = (CIFPath *)NULL; CIFPath *newpath, *cifpath = (CIFPath *)NULL;
@ -623,16 +580,14 @@ PaintPolygon(
cifpath = newpath; cifpath = newpath;
} }
rectlist = CIFPolyToRects(cifpath, plane, ptable, ui, FALSE); rectlist = CIFPolyToRects(cifpath, plane, ptable, ui);
CIFFreePath(cifpath); CIFFreePath(cifpath);
free_magic1_t mm1 = freeMagic1_init();
for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next) for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next)
{ {
DBPaintPlane(plane, &rectp->r_r, ptable, ui); DBPaintPlane(plane, &rectp->r_r, ptable, ui);
if (!keep) freeMagic1(&mm1, (char *) rectp); if (!keep) freeMagic((char *) rectp);
} }
freeMagic1_end(&mm1);
return (keep) ? rectlist : (LinkedRect *)NULL; return (keep) ? rectlist : (LinkedRect *)NULL;
} }
@ -659,14 +614,14 @@ PaintPolygon(
*/ */
void void
PaintWireList( PaintWireList(pointlist, number, width, endcap, plane, ptable, ui)
Point *pointlist, /* Array of Point structures */ Point *pointlist; /* Array of Point structures */
int number, /* total number of points */ int number; /* total number of points */
int width, /* Route width of path */ int width; /* Route width of path */
bool endcap, /* Whether or not to add 1/2 width endcaps */ bool endcap; /* Whether or not to add 1/2 width endcaps */
Plane *plane, /* Plane structure to paint into */ Plane *plane; /* Plane structure to paint into */
PaintResultType *ptable, /* Paint result table */ PaintResultType *ptable; /* Paint result table */
PaintUndoInfo *ui) /* Undo record */ PaintUndoInfo *ui; /* Undo record */
{ {
CIFPath *newpath, *cifpath = (CIFPath *)NULL; CIFPath *newpath, *cifpath = (CIFPath *)NULL;
int i; int i;
@ -703,7 +658,7 @@ PaintWireList(
*/ */
bool bool
CIFParseWire(void) CIFParseWire()
{ {
int width; int width;
CIFPath *pathheadp, *polypath; CIFPath *pathheadp, *polypath;
@ -729,8 +684,7 @@ CIFParseWire(void)
width /= cifReadScale2; width /= cifReadScale2;
savescale = cifReadScale1; savescale = cifReadScale1;
pathheadp = CIFParsePath(2); if (!CIFParsePath(&pathheadp, 2))
if (pathheadp == NULL)
{ {
CIFReadError("wire, but improper path; ignored.\n"); CIFReadError("wire, but improper path; ignored.\n");
CIFSkipToSemi(); CIFSkipToSemi();
@ -764,7 +718,7 @@ CIFParseWire(void)
*/ */
bool bool
CIFParseLayer(void) CIFParseLayer()
{ {
#define MAXCHARS 4 #define MAXCHARS 4
char name[MAXCHARS+1]; char name[MAXCHARS+1];
@ -827,7 +781,7 @@ CIFParseLayer(void)
*/ */
bool bool
CIFParsePoly(void) CIFParsePoly()
{ {
CIFPath *pathheadp; CIFPath *pathheadp;
LinkedRect *rectp; LinkedRect *rectp;
@ -840,8 +794,7 @@ CIFParsePoly(void)
CIFSkipToSemi(); CIFSkipToSemi();
return FALSE; return FALSE;
} }
pathheadp = CIFParsePath(1); if (!CIFParsePath(&pathheadp, 1))
if (pathheadp == NULL)
{ {
CIFReadError("polygon, but improper path; ignored.\n"); CIFReadError("polygon, but improper path; ignored.\n");
CIFSkipToSemi(); CIFSkipToSemi();
@ -851,7 +804,7 @@ CIFParsePoly(void)
/* Convert the polygon to rectangles. */ /* Convert the polygon to rectangles. */
rectp = CIFPolyToRects(pathheadp, cifReadPlane, CIFPaintTable, rectp = CIFPolyToRects(pathheadp, cifReadPlane, CIFPaintTable,
(PaintUndoInfo *)NULL, FALSE); (PaintUndoInfo *)NULL);
CIFFreePath(pathheadp); CIFFreePath(pathheadp);
if (rectp == NULL) if (rectp == NULL)
{ {
@ -861,13 +814,11 @@ CIFParsePoly(void)
CIFSkipToSemi(); CIFSkipToSemi();
return FALSE; return FALSE;
} }
free_magic1_t mm1 = freeMagic1_init();
for (; rectp != NULL ; rectp = rectp->r_next) for (; rectp != NULL ; rectp = rectp->r_next)
{ {
DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable, DBPaintPlane(cifReadPlane, &rectp->r_r, CIFPaintTable,
(PaintUndoInfo *) NULL); (PaintUndoInfo *) NULL);
freeMagic1(&mm1, (char *) rectp); freeMagic((char *) rectp);
} }
freeMagic1_end(&mm1);
return TRUE; return TRUE;
} }

View File

@ -18,7 +18,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -40,9 +40,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "calma/calmaInt.h" #include "calma/calmaInt.h"
#include "utils/malloc.h" #include "utils/malloc.h"
/* C99 compat */
#include "cif/cif.h"
/* Pointer to a list of all the CIF-reading styles: */ /* Pointer to a list of all the CIF-reading styles: */
CIFReadKeep *cifReadStyleList = NULL; CIFReadKeep *cifReadStyleList = NULL;
@ -62,8 +59,8 @@ CIFReadLayer *cifCurReadLayer; /* Current layer being processed. */
CIFOp *cifCurReadOp; /* Last geometric operation seen. */ CIFOp *cifCurReadOp; /* Last geometric operation seen. */
/* Forward declarations */ /* Forward declarations */
void cifReadStyleInit(void); void cifReadStyleInit();
void CIFReadLoadStyle(char *stylename); void CIFReadLoadStyle();
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -90,9 +87,8 @@ void CIFReadLoadStyle(char *stylename);
*/ */
bool bool
CIFReadTechLimitScale( CIFReadTechLimitScale(ns, ds)
int ns, int ns, ds;
int ds)
{ {
int gridup, scaledown; int gridup, scaledown;
int scale, limit, mult; int scale, limit, mult;
@ -132,9 +128,9 @@ CIFReadTechLimitScale(
*/ */
int int
CIFReadNameToType( CIFReadNameToType(name, newOK)
char *name, /* Name of a CIF layer. */ char *name; /* Name of a CIF layer. */
bool newOK) /* TRUE means OK to create a new layer if this bool newOK; /* TRUE means OK to create a new layer if this
* name is one we haven't seen before. * name is one we haven't seen before.
*/ */
{ {
@ -197,34 +193,34 @@ CIFReadNameToType(
*/ */
int int
CIFCalmaLayerToCifLayer( CIFCalmaLayerToCifLayer(layer, datatype, calmaStyle)
int layer, /* Calma layer number */ int layer; /* Calma layer number */
int datatype, /* Calma datatype */ int datatype; /* Calma datatype */
CIFReadStyle *calmaStyle) CIFReadStyle *calmaStyle;
{ {
CalmaLayerType clt; CalmaLayerType clt;
HashEntry *he; HashEntry *he;
clt.clt_layer = layer; clt.clt_layer = layer;
clt.clt_type = datatype; clt.clt_type = datatype;
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))) if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
return ((spointertype) HashGetValue(he)); return ((spointertype) HashGetValue(he));
/* Try wildcarding the datatype */ /* Try wildcarding the datatype */
clt.clt_type = -1; clt.clt_type = -1;
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))) if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
return ((spointertype) HashGetValue(he)); return ((spointertype) HashGetValue(he));
/* Try wildcarding the layer */ /* Try wildcarding the layer */
clt.clt_layer = -1; clt.clt_layer = -1;
clt.clt_type = datatype; clt.clt_type = datatype;
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))) if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
return ((spointertype) HashGetValue(he)); return ((spointertype) HashGetValue(he));
/* Try wildcarding them both, for a default value */ /* Try wildcarding them both, for a default value */
clt.clt_layer = -1; clt.clt_layer = -1;
clt.clt_type = -1; clt.clt_type = -1;
if ((he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))) if (he = HashLookOnly(&(calmaStyle->cifCalmaToCif), (char *) &clt))
return ((spointertype) HashGetValue(he)); return ((spointertype) HashGetValue(he));
/* No luck */ /* No luck */
@ -252,10 +248,9 @@ CIFCalmaLayerToCifLayer(
*/ */
void void
CIFParseReadLayers( CIFParseReadLayers(string, mask)
char *string, /* Comma-separated list of CIF layers. */ char *string; /* Comma-separated list of CIF layers. */
TileTypeBitMask *mask, /* Where to store bit mask. */ TileTypeBitMask *mask; /* Where to store bit mask. */
bool newok) /* If TRUE, create new layers if they don't exist */
{ {
int i; int i;
char *p; char *p;
@ -270,10 +265,10 @@ CIFParseReadLayers(
if (p != NULL) if (p != NULL)
*p = 0; *p = 0;
i = CIFReadNameToType(string, newok); i = CIFReadNameToType(string, TRUE);
if (i >= 0) if (i >= 0)
TTMaskSetType(mask, i); TTMaskSetType(mask, i);
else if (newok) else
{ {
HashEntry *he; HashEntry *he;
TileTypeBitMask *amask; TileTypeBitMask *amask;
@ -285,8 +280,6 @@ CIFParseReadLayers(
TTMaskSetMask(mask, amask); TTMaskSetMask(mask, amask);
} }
} }
else
TxError("Error: CIF layer \"%s\" is unknown.\n", string);
if (p == NULL) break; if (p == NULL) break;
*p = ','; *p = ',';
@ -314,7 +307,7 @@ CIFParseReadLayers(
*/ */
void void
cifNewReadStyle(void) cifNewReadStyle()
{ {
int i; int i;
CIFOp *op; CIFOp *op;
@ -324,20 +317,13 @@ cifNewReadStyle(void)
{ {
/* Destroy old style and free all memory allocated to it */ /* Destroy old style and free all memory allocated to it */
for (i = 0; i < MAXCIFRLAYERS; i++) for (i=0; i<MAXCIFRLAYERS; i+=1)
{ {
layer = cifCurReadStyle->crs_layers[i]; layer = cifCurReadStyle->crs_layers[i];
if (layer != NULL) if (layer != NULL)
{ {
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->crl_ops; op != NULL; op = op->co_next) for (op = layer->crl_ops; op != NULL; op = op->co_next)
{ freeMagic((char *)op);
if (op->co_opcode == CIFOP_MASKHINTS ||
op->co_opcode == CIFOP_TAGGED)
freeMagic((char *)op->co_client);
freeMagic1(&mm1, (char *)op);
}
freeMagic1_end(&mm1);
freeMagic((char *)layer); freeMagic((char *)layer);
} }
} }
@ -361,7 +347,7 @@ cifNewReadStyle(void)
*/ */
void void
cifReadStyleInit(void) cifReadStyleInit()
{ {
int i; int i;
@ -403,7 +389,7 @@ cifReadStyleInit(void)
*/ */
void void
CIFReadTechInit(void) CIFReadTechInit()
{ {
CIFReadKeep *style; CIFReadKeep *style;
@ -415,13 +401,11 @@ CIFReadTechInit(void)
/* forget the list of styles */ /* forget the list of styles */
free_magic1_t mm1 = freeMagic1_init();
for (style = cifReadStyleList; style != NULL; style = style->crs_next) for (style = cifReadStyleList; style != NULL; style = style->crs_next)
{ {
freeMagic(style->crs_name); freeMagic(style->crs_name);
freeMagic1(&mm1, style); freeMagic(style);
} }
freeMagic1_end(&mm1);
cifReadStyleList = NULL; cifReadStyleList = NULL;
} }
@ -443,7 +427,7 @@ CIFReadTechInit(void)
*/ */
void void
CIFReadTechStyleInit(void) CIFReadTechStyleInit()
{ {
cifNReadLayers = 0; cifNReadLayers = 0;
cifCurReadLayer = NULL; cifCurReadLayer = NULL;
@ -470,10 +454,10 @@ CIFReadTechStyleInit(void)
*/ */
/* ARGSUSED */ /* ARGSUSED */
bool bool
CIFReadTechLine( CIFReadTechLine(sectionName, argc, argv)
char *sectionName, /* Name of this section ("cifinput"). */ char *sectionName; /* Name of this section ("cifinput"). */
int argc, /* Number of fields on line. */ int argc; /* Number of fields on line. */
char *argv[]) /* Values of fields. */ char *argv[]; /* Values of fields. */
{ {
CIFOp *newOp = NULL; CIFOp *newOp = NULL;
CIFReadKeep *newStyle, *p; CIFReadKeep *newStyle, *p;
@ -759,7 +743,7 @@ CIFReadTechLine(
cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp));
cifCurReadOp->co_opcode = CIFOP_OR; cifCurReadOp->co_opcode = CIFOP_OR;
cifCurReadOp->co_client = (ClientData)NULL; cifCurReadOp->co_client = (ClientData)NULL;
CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask, TRUE); CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask);
TTMaskZero(&cifCurReadOp->co_paintMask); TTMaskZero(&cifCurReadOp->co_paintMask);
cifCurReadOp->co_next = NULL; cifCurReadOp->co_next = NULL;
cifCurReadOp->co_distance = 0; cifCurReadOp->co_distance = 0;
@ -809,7 +793,7 @@ CIFReadTechLine(
cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp)); cifCurReadOp = (CIFOp *) mallocMagic(sizeof(CIFOp));
cifCurReadOp->co_opcode = CIFOP_OR; cifCurReadOp->co_opcode = CIFOP_OR;
cifCurReadOp->co_client = (ClientData)NULL; cifCurReadOp->co_client = (ClientData)NULL;
CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask, TRUE); CIFParseReadLayers(argv[2], &cifCurReadOp->co_cifMask);
TTMaskZero(&cifCurReadOp->co_paintMask); TTMaskZero(&cifCurReadOp->co_paintMask);
cifCurReadOp->co_next = NULL; cifCurReadOp->co_next = NULL;
cifCurReadOp->co_distance = 0; cifCurReadOp->co_distance = 0;
@ -881,34 +865,11 @@ CIFReadTechLine(
else else
goto wrongNumArgs; goto wrongNumArgs;
} }
CIFParseReadLayers(argv[1], &mask, TRUE); CIFParseReadLayers(argv[1], &mask);
for (i = 0; i < MAXCIFRLAYERS; i++) for (i=0; i<MAXCIFRLAYERS; i+=1)
{ {
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] cifCurReadStyle->crs_labelLayer[i]
= cifCurReadLayer->crl_magicType; = cifCurReadLayer->crl_magicType;
if (argc == 3) if (argc == 3)
@ -930,10 +891,10 @@ CIFReadTechLine(
int i; int i;
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
CIFParseReadLayers(argv[1], &mask, TRUE); CIFParseReadLayers(argv[1], &mask);
/* trash the value in crs_labelLayer so that any labels on this /* 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++) for (i=0; i < cifNReadLayers; i++)
{ {
if (TTMaskHasType(&mask,i)) if (TTMaskHasType(&mask,i))
@ -949,15 +910,14 @@ CIFReadTechLine(
/* miscellaneous cif-reading boolean options */ /* miscellaneous cif-reading boolean options */
if (strcmp(argv[0], "options") == 0) { if(strcmp(argv[0], "options") == 0) {
int i; int i;
if (argc < 2) goto wrongNumArgs; if (argc < 2) goto wrongNumArgs;
for (i = 1; i < argc; i++) { for(i = 1; i < argc; i++) {
if (strcmp(argv[i], "ignore-unknown-layer-labels") == 0) if(strcmp(argv[i], "ignore-unknown-layer-labels") == 0)
cifCurReadStyle->crs_flags |= CRF_IGNORE_UNKNOWNLAYER_LABELS; cifCurReadStyle->crs_flags |= CRF_IGNORE_UNKNOWNLAYER_LABELS;
/* Allow "no-reconnect-labels", although it has been deprecated */ if(strcmp(argv[i], "no-reconnect-labels") == 0)
else if (strcmp(argv[i], "no-reconnect-labels") != 0) cifCurReadStyle->crs_flags |= CRF_NO_RECONNECT_LABELS;
TechError("Unknown cifinput option \"%s\".\n", argv[i]);
} }
return TRUE; return TRUE;
} }
@ -995,12 +955,6 @@ CIFReadTechLine(
newOp->co_opcode = CIFOP_COPYUP; newOp->co_opcode = CIFOP_COPYUP;
else if (strcmp(argv[0], "boundary") == 0) else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY; newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "not-square") == 0)
newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "tagged") == 0)
newOp->co_opcode = CIFOP_TAGGED;
else else
{ {
TechError("Unknown statement \"%s\".\n", argv[0]); TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1014,7 +968,7 @@ CIFReadTechLine(
case CIFOP_OR: case CIFOP_OR:
case CIFOP_COPYUP: case CIFOP_COPYUP:
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
CIFParseReadLayers(argv[1], &newOp->co_cifMask, TRUE); CIFParseReadLayers(argv[1], &newOp->co_cifMask);
break; break;
case CIFOP_GROW: case CIFOP_GROW:
case CIFOP_GROW_G: case CIFOP_GROW_G:
@ -1027,16 +981,6 @@ CIFReadTechLine(
goto errorReturn; goto errorReturn;
} }
break; break;
case CIFOP_MASKHINTS:
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break;
case CIFOP_TAGGED:
if ((argc != 2) && (argc != 3)) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
if (argc == 3)
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
break;
} }
/* Link the new CIFOp onto the list. */ /* Link the new CIFOp onto the list. */
@ -1077,7 +1021,7 @@ CIFReadTechLine(
*/ */
void void
CIFReadTechFinal(void) CIFReadTechFinal()
{ {
/* Reduce the scale by the multiplier, as much as possible while */ /* Reduce the scale by the multiplier, as much as possible while */
/* keeping all CIF input ops in integer units. */ /* keeping all CIF input ops in integer units. */
@ -1120,10 +1064,9 @@ CIFReadTechFinal(void)
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
void void
CIFReadLoadStyle( CIFReadLoadStyle(stylename)
char *stylename) char *stylename;
{ {
SectionID invcifr; SectionID invcifr;
@ -1165,8 +1108,8 @@ CIFReadLoadStyle(
*/ */
int int
CIFReadGetGrowSize( CIFReadGetGrowSize(type)
TileType type) TileType type;
{ {
CIFReadStyle *istyle = cifCurReadStyle; CIFReadStyle *istyle = cifCurReadStyle;
CIFOp *op; CIFOp *op;
@ -1220,8 +1163,8 @@ CIFReadGetGrowSize(
*/ */
float float
CIFGetInputScale( CIFGetInputScale(convert)
int convert) int convert;
{ {
/* Avoid divide-by-0 error if there is no cif input style */ /* Avoid divide-by-0 error if there is no cif input style */
/* in the tech file. */ /* in the tech file. */
@ -1253,10 +1196,10 @@ CIFGetInputScale(
*/ */
void void
CIFPrintReadStyle( CIFPrintReadStyle(dolist, doforall, docurrent)
bool dolist, /* Return as a list if true */ bool dolist; /* Return as a list if true */
bool doforall, /* Return list of all styles if true */ bool doforall; /* Return list of all styles if true */
bool docurrent) /* Return current style if true */ bool docurrent; /* Return current style if true */
{ {
CIFReadKeep *style; CIFReadKeep *style;
@ -1324,8 +1267,8 @@ CIFPrintReadStyle(
*/ */
void void
CIFSetReadStyle( CIFSetReadStyle(name)
char *name) /* Name of the new style. If NULL, char *name; /* Name of the new style. If NULL,
* just print the name of the current * just print the name of the current
* style. * style.
*/ */
@ -1385,10 +1328,10 @@ CIFSetReadStyle(
*/ */
int int
cifParseCalmaNums( cifParseCalmaNums(str, numArray, numNums)
char *str, /* String to parse */ char *str; /* String to parse */
int *numArray, /* Array to fill in */ int *numArray; /* Array to fill in */
int numNums) /* Maximum number of entries in numArray */ int numNums; /* Maximum number of entries in numArray */
{ {
int numFilled, num; int numFilled, num;
@ -1448,10 +1391,9 @@ cifParseCalmaNums(
*/ */
int int
CIFTechInputScale( CIFTechInputScale(n, d, opt)
int n, int n, d;
int d, bool opt;
bool opt)
{ {
CIFReadStyle *istyle = cifCurReadStyle; CIFReadStyle *istyle = cifCurReadStyle;
CIFReadLayer *cl; CIFReadLayer *cl;

View File

@ -19,7 +19,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -27,12 +27,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.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/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -46,16 +40,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/undo.h" #include "utils/undo.h"
#include "utils/malloc.h" #include "utils/malloc.h"
/* C99 compat */
#include "lef/lef.h"
#include "drc/drc.h"
#include "extract/extract.h"
#include "wiring/wiring.h"
#include "router/router.h"
#include "mzrouter/mzrouter.h"
#include "irouter/irouter.h"
#include "plow/plow.h"
/* The following variables are used to provide one character of /* The following variables are used to provide one character of
* lookahead. cifParseLaAvail is TRUE if cifParseLaChar contains * lookahead. cifParseLaAvail is TRUE if cifParseLaChar contains
* a valid character, FALSE otherwise. The PEEK and TAKE macros * a valid character, FALSE otherwise. The PEEK and TAKE macros
@ -76,7 +60,6 @@ FILE *cifErrorFile;
int cifLineNumber; /* Number of current line. */ int cifLineNumber; /* Number of current line. */
int cifTotalWarnings; /* Number of warnings detected */ int cifTotalWarnings; /* Number of warnings detected */
int cifTotalErrors; /* Number of errors detected */ int cifTotalErrors; /* Number of errors detected */
bool cifSeenSnapWarning; /* Track this to prevent excessive messaging */
/* The variables used below hold general information about what /* The variables used below hold general information about what
* we're currently working on. * we're currently working on.
@ -129,7 +112,7 @@ Plane *cifReadPlane; /* Plane into which to paint material
/* VARARGS1 */ /* VARARGS1 */
void void
CIFReadError(const char *format, ...) CIFReadError(char *format, ...)
{ {
va_list args; va_list args;
@ -140,7 +123,7 @@ CIFReadError(const char *format, ...)
if (cifLineNumber > 0) if (cifLineNumber > 0)
TxError("Error at line %d of CIF file: ", cifLineNumber); TxError("Error at line %d of CIF file: ", cifLineNumber);
else else
TxError("CIF file read error: "); TxError("CIF file read error: ", cifLineNumber);
va_start(args, format); va_start(args, format);
Vfprintf(stderr, format, args); Vfprintf(stderr, format, args);
va_end(args); va_end(args);
@ -153,7 +136,7 @@ CIFReadError(const char *format, ...)
void void
CIFReadWarning(const char *format, ...) CIFReadWarning(char *format, ...)
{ {
va_list args; va_list args;
@ -205,9 +188,9 @@ CIFReadWarning(const char *format, ...)
*/ */
int int
CIFScaleCoord( CIFScaleCoord(cifCoord, snap_type)
int cifCoord, /* A coordinate in CIF units. */ int cifCoord; /* A coordinate in CIF units. */
int snap_type) /* How to deal with fractional results */ int snap_type; /* How to deal with fractional results */
{ {
int result, scale, remain, denom; int result, scale, remain, denom;
int mult, mfactor; int mult, mfactor;
@ -235,10 +218,8 @@ CIFScaleCoord(
switch (snap_type) switch (snap_type)
{ {
case COORD_EXACT: case COORD_EXACT:
if (!cifSeenSnapWarning) CIFReadWarning("Input off lambda grid by %d/%d; grid redefined.\n",
CIFReadWarning("Input off lambda grid by %d/%d; grid redefined.\n",
remain, denom); remain, denom);
cifSeenSnapWarning = TRUE;
CIFTechInputScale(1, denom, FALSE); CIFTechInputScale(1, denom, FALSE);
CIFTechOutputScale(1, denom); CIFTechOutputScale(1, denom);
@ -262,10 +243,8 @@ CIFScaleCoord(
case COORD_HALF_U: case COORD_HALF_L: case COORD_HALF_U: case COORD_HALF_L:
if (denom > 2) if (denom > 2)
{ {
if (!cifSeenSnapWarning) CIFReadWarning("Input off lambda grid by %d/%d; grid redefined.\n",
CIFReadWarning("Input off lambda grid by %d/%d; " remain, denom);
"grid redefined.\n", remain, denom);
cifSeenSnapWarning = TRUE;
/* scale to nearest half-lambda */ /* scale to nearest half-lambda */
if (!(denom & 0x1)) denom >>= 1; if (!(denom & 0x1)) denom >>= 1;
@ -276,10 +255,8 @@ CIFScaleCoord(
PlowAfterTech(); PlowAfterTech();
ExtTechScale(1, denom); ExtTechScale(1, denom);
WireTechScale(1, denom); WireTechScale(1, denom);
#ifdef ROUTE_MODULE
MZAfterTech(); MZAfterTech();
IRAfterTech(); IRAfterTech();
#endif
#ifdef LEF_MODULE #ifdef LEF_MODULE
LefTechScale(1, denom); LefTechScale(1, denom);
#endif #endif
@ -300,10 +277,8 @@ CIFScaleCoord(
break; break;
case COORD_ANY: case COORD_ANY:
if (!cifSeenSnapWarning) CIFReadWarning("Input off lambda grid by %d/%d; snapped to grid.\n",
CIFReadWarning("Input off lambda grid by %d/%d; snapped to grid.\n", abs(remain), abs(denom));
abs(remain), abs(denom));
cifSeenSnapWarning = TRUE;
/* Careful: must round down a bit more for negative numbers, in /* Careful: must round down a bit more for negative numbers, in
* order to ensure that a point exactly halfway between Magic units * order to ensure that a point exactly halfway between Magic units
@ -345,8 +320,8 @@ CIFScaleCoord(
*/ */
bool bool
cifIsBlank( cifIsBlank(ch)
int ch) int ch;
{ {
if ( isdigit(ch) || isupper(ch) if ( isdigit(ch) || isupper(ch)
@ -378,7 +353,7 @@ cifIsBlank(
*/ */
void void
CIFSkipBlanks(void) CIFSkipBlanks()
{ {
while (cifIsBlank(PEEK())) { while (cifIsBlank(PEEK())) {
@ -407,7 +382,7 @@ CIFSkipBlanks(void)
*/ */
void void
CIFSkipSep(void) CIFSkipSep()
{ {
int ch; int ch;
@ -437,7 +412,7 @@ CIFSkipSep(void)
*/ */
void void
CIFSkipToSemi(void) CIFSkipToSemi()
{ {
int ch; int ch;
@ -466,7 +441,7 @@ CIFSkipToSemi(void)
*/ */
void void
CIFSkipSemi(void) CIFSkipSemi()
{ {
CIFSkipBlanks(); CIFSkipBlanks();
@ -497,8 +472,8 @@ CIFSkipSemi(void)
*/ */
bool bool
CIFParseSInteger( CIFParseSInteger(valuep)
int *valuep) int *valuep;
{ {
bool is_signed; bool is_signed;
char buffer[ BUFSIZ ]; char buffer[ BUFSIZ ];
@ -542,8 +517,8 @@ CIFParseSInteger(
*/ */
bool bool
CIFParseInteger( CIFParseInteger(valuep)
int *valuep) int *valuep;
{ {
if (!CIFParseSInteger(valuep)) if (!CIFParseSInteger(valuep))
@ -583,9 +558,9 @@ CIFParseInteger(
*/ */
bool bool
CIFParsePoint( CIFParsePoint(pointp, iscale)
Point *pointp, Point *pointp;
int iscale) int iscale;
{ {
int rescale; int rescale;
@ -651,11 +626,12 @@ CIFParsePoint(
* one or more points. * one or more points.
* *
* Results: * Results:
* non-NULL CIFPath* the caller takes ownership of * TRUE is returned if the path was parsed successfully,
* if the path was parsed successfully, otherwise NULL. * FALSE otherwise.
* *
* Side effects: * Side effects:
* None * Modifies the parameter pathheadpp to point to the path
* that is constructed.
* *
* Corrections: * Corrections:
* CIF coordinates are multiplied by 2 to cover the case where * CIF coordinates are multiplied by 2 to cover the case where
@ -667,16 +643,17 @@ CIFParsePoint(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
CIFPath * bool
CIFParsePath( CIFParsePath(pathheadpp, iscale)
int iscale) CIFPath **pathheadpp;
int iscale;
{ {
CIFPath *pathheadp, *pathtailp, *newpathp; CIFPath *pathtailp, *newpathp;
bool nonManhattan = FALSE; /* diagnostic only */ bool nonManhattan = FALSE; /* diagnostic only */
CIFPath path; CIFPath path;
int savescale; int savescale;
pathheadp = NULL; *pathheadpp = NULL;
pathtailp = NULL; pathtailp = NULL;
path.cifp_next = NULL; path.cifp_next = NULL;
while (TRUE) while (TRUE)
@ -688,12 +665,12 @@ CIFParsePath(
savescale = cifReadScale1; savescale = cifReadScale1;
if (!CIFParsePoint(&path.cifp_point, iscale)) if (!CIFParsePoint(&path.cifp_point, iscale))
{ {
CIFFreePath(pathheadp); CIFFreePath(*pathheadpp);
return NULL; return FALSE;
} }
if (savescale != cifReadScale1) if (savescale != cifReadScale1)
{ {
CIFPath *phead = pathheadp; CIFPath *phead = *pathheadpp;
int newscale = cifReadScale1 / savescale; int newscale = cifReadScale1 / savescale;
while (phead != NULL) while (phead != NULL)
{ {
@ -704,7 +681,7 @@ CIFParsePath(
} }
newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath))); newpathp = (CIFPath *) mallocMagic((unsigned) (sizeof (CIFPath)));
*newpathp = path; *newpathp = path;
if (pathheadp) if (*pathheadpp)
{ {
/* /*
* Check that this segment is Manhattan. If not, remember the * Check that this segment is Manhattan. If not, remember the
@ -721,10 +698,10 @@ CIFParsePath(
} }
pathtailp->cifp_next = newpathp; pathtailp->cifp_next = newpathp;
} }
else pathheadp = newpathp; else *pathheadpp = newpathp;
pathtailp = newpathp; pathtailp = newpathp;
} }
return pathheadp; return (*pathheadpp != NULL);
} }
/* /*
@ -744,9 +721,9 @@ CIFParsePath(
*/ */
bool bool
test_insideness( test_insideness(start, tpoint)
CIFPath *start, CIFPath *start;
Point *tpoint) Point *tpoint;
{ {
Rect tmprect, irect; Rect tmprect, irect;
@ -782,11 +759,10 @@ test_insideness(
*/ */
bool bool
seg_intersect( seg_intersect(tstart, bf, bs, respt)
CIFPath *tstart, CIFPath *tstart;
Point *bf, Point *bf, *bs;
Point *bs, Point *respt;
Point *respt)
{ {
int afx = tstart->cifp_x; int afx = tstart->cifp_x;
int afy = tstart->cifp_y; int afy = tstart->cifp_y;
@ -849,10 +825,9 @@ seg_intersect(
*/ */
bool bool
path_intersect( path_intersect(pathHead, start, respt)
CIFPath *pathHead, CIFPath *pathHead, *start;
CIFPath *start, Point *respt;
Point *respt)
{ {
CIFPath *path, *segcrossed, *new; CIFPath *path, *segcrossed, *new;
Point tmppt; Point tmppt;
@ -955,8 +930,8 @@ path_intersect(
*/ */
bool bool
is_clockwise( is_clockwise(pathHead)
CIFPath *pathHead) CIFPath *pathHead;
{ {
CIFPath *path, *midx = NULL, *last; CIFPath *path, *midx = NULL, *last;
Point *p1, *p2, *p3; Point *p1, *p2, *p3;
@ -1049,11 +1024,11 @@ is_clockwise(
*/ */
void void
CIFMakeManhattanPath( CIFMakeManhattanPath(pathHead, plane, resultTbl, ui)
CIFPath *pathHead, CIFPath *pathHead;
Plane *plane, Plane *plane;
const PaintResultType *resultTbl, PaintResultType *resultTbl;
PaintUndoInfo *ui) PaintUndoInfo *ui;
{ {
CIFPath *new, *new2, *next, *path; CIFPath *new, *new2, *next, *path;
int xinit, xdiff, xincr, xlast, x; int xinit, xdiff, xincr, xlast, x;
@ -1156,11 +1131,7 @@ CIFMakeManhattanPath(
/* Final check---ensure that rectangle is not degenerate */ /* Final check---ensure that rectangle is not degenerate */
if (plane && (tr.r_xtop - tr.r_xbot > 0) && (tr.r_ytop - tr.r_ybot > 0)) if (plane && (tr.r_xtop - tr.r_xbot > 0) && (tr.r_ytop - tr.r_ybot > 0))
{
DBNMPaintPlane(plane, type, &tr, resultTbl, ui); DBNMPaintPlane(plane, type, &tr, resultTbl, ui);
GEO_EXPAND(&tr, 1, &tr);
DBMergeNMTiles(plane, &tr, ui);
}
} }
} }
@ -1187,9 +1158,8 @@ CIFMakeManhattanPath(
*/ */
int int
CIFEdgeDirection( CIFEdgeDirection(first, last)
CIFPath *first, CIFPath *first, *last; /* Edge to be categorized. */
CIFPath *last) /* Edge to be categorized. */
{ {
if (first->cifp_x < last->cifp_x) if (first->cifp_x < last->cifp_x)
@ -1236,8 +1206,8 @@ CIFEdgeDirection(
*/ */
void void
CIFCleanPath( CIFCleanPath(pathHead)
CIFPath *pathHead) CIFPath *pathHead;
{ {
CIFPath *next, *path, *prev, *last; CIFPath *next, *path, *prev, *last;
int dir1, dir2; int dir1, dir2;
@ -1256,7 +1226,7 @@ CIFCleanPath(
if (!path) return; if (!path) return;
} }
while ((next = path->cifp_next)) while (next = path->cifp_next)
{ {
if ((dir2 = CIFEdgeDirection(path, next)) == CIF_ZERO) if ((dir2 = CIFEdgeDirection(path, next)) == CIF_ZERO)
{ {
@ -1335,16 +1305,14 @@ path_inc:
*/ */
void void
CIFFreePath( CIFFreePath(path)
CIFPath *path) /* Path to be freed. */ CIFPath *path; /* Path to be freed. */
{ {
free_magic1_t mm1 = freeMagic1_init();
while (path != NULL) while (path != NULL)
{ {
freeMagic1(&mm1, (char *) path); freeMagic((char *) path);
path = path->cifp_next; path = path->cifp_next;
} }
freeMagic1_end(&mm1);
} }
/* /*
@ -1366,7 +1334,7 @@ CIFFreePath(
*/ */
void void
cifCommandError(void) cifCommandError()
{ {
CIFReadError("unknown command `%c'; ignored.\n" , PEEK()); CIFReadError("unknown command `%c'; ignored.\n" , PEEK());
CIFSkipToSemi(); CIFSkipToSemi();
@ -1391,7 +1359,7 @@ cifCommandError(void)
*/ */
bool bool
cifParseEnd(void) cifParseEnd()
{ {
TAKE(); TAKE();
CIFSkipBlanks(); CIFSkipBlanks();
@ -1420,7 +1388,7 @@ cifParseEnd(void)
*/ */
bool bool
cifParseComment(void) cifParseComment()
{ {
int opens; int opens;
int ch; int ch;
@ -1471,9 +1439,9 @@ cifParseComment(void)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
const Transform * Transform *
CIFDirectionToTrans( CIFDirectionToTrans(point)
const Point *point) /* Direction vector from origin. */ Point *point; /* Direction vector from origin. */
{ {
if ((point->p_x != 0) && (point->p_y == 0)) if ((point->p_x != 0) && (point->p_y == 0))
{ {
@ -1512,8 +1480,8 @@ CIFDirectionToTrans(
*/ */
bool bool
CIFParseTransform( CIFParseTransform(transformp)
Transform *transformp) Transform *transformp;
{ {
char ch; char ch;
Point point; Point point;
@ -1606,8 +1574,8 @@ CIFParseTransform(
*/ */
void void
CIFReadFile( CIFReadFile(file)
FILE *file) /* File from which to read CIF. */ FILE *file; /* File from which to read CIF. */
{ {
/* We will use 1-word CIF numbers as keys in this hash table */ /* We will use 1-word CIF numbers as keys in this hash table */
CIFReadCellInit(1); CIFReadCellInit(1);
@ -1623,7 +1591,6 @@ CIFReadFile(
cifTotalWarnings = 0; cifTotalWarnings = 0;
cifTotalErrors = 0; cifTotalErrors = 0;
CifPolygonCount = 0; CifPolygonCount = 0;
cifSeenSnapWarning = FALSE;
cifInputFile = file; cifInputFile = file;
cifReadScale1 = 1; cifReadScale1 = 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 $ * rcsid "$Header: /usr/cvsroot/magic-8.0/cif/CIFread.h,v 1.3 2010/08/25 17:33:55 tim Exp $
*/ */
#ifndef _MAGIC__CIF__CIFREAD_H #ifndef _CIFREAD_H
#define _MAGIC__CIF__CIFREAD_H #define _CIFREAD_H
#include "cif/CIFint.h" #include "cif/CIFint.h"
@ -104,10 +104,8 @@ typedef struct cifrstyle
/* Gives the Magic layer to use for labels /* Gives the Magic layer to use for labels
* on each possible CIF layer. * on each possible CIF layer.
*/ */
/* enum labelType */ unsigned char crs_labelSticky[MAXCIFRLAYERS]; bool crs_labelSticky[MAXCIFRLAYERS];
/* Marker if label layer makes sticky labels /* Marker if label layer makes sticky labels */
* enum labelType LABEL_TYPE_xxxxxx
*/
CIFReadLayer *crs_layers[MAXCIFRLAYERS]; CIFReadLayer *crs_layers[MAXCIFRLAYERS];
HashTable cifCalmaToCif; /* Table mapping from Calma layer numbers to HashTable cifCalmaToCif; /* Table mapping from Calma layer numbers to
* CIF layers * CIF layers
@ -117,6 +115,7 @@ typedef struct cifrstyle
/* option bitmasks used in crs_flags */ /* option bitmasks used in crs_flags */
#define CRF_IGNORE_UNKNOWNLAYER_LABELS 1 #define CRF_IGNORE_UNKNOWNLAYER_LABELS 1
#define CRF_NO_RECONNECT_LABELS 2
/* Methods to deal with fractional results of conversion from CIF to magic */ /* Methods to deal with fractional results of conversion from CIF to magic */
/* units (see routine CIFScaleCoord() for details). */ /* units (see routine CIFScaleCoord() for details). */
@ -154,45 +153,22 @@ typedef struct cifpath
/* Procedures */ /* Procedures */
extern bool CIFParseBox(void); extern bool CIFParseBox(), CIFParseWire(), CIFParsePoly();
extern bool CIFParseWire(void); extern bool CIFParseFlash(), CIFParseLayer(), CIFParseStart();
extern bool CIFParsePoly(void); extern bool CIFParseFinish(), CIFParseDelete(), CIFParseUser();
extern bool CIFParseFlash(void); extern bool CIFParseCall(), CIFParseTransform(), CIFParseInteger();
extern bool CIFParseLayer(void); extern bool CIFParsePath(), CIFParsePoint(), CIFParseSInteger();
extern bool CIFParseStart(void); extern void CIFSkipToSemi(), CIFSkipSep(), CIFSkipBlanks();
extern bool CIFParseFinish(void); extern void CIFFreePath(), CIFCleanPath();
extern bool CIFParseDelete(void); extern void CIFReadCellInit(), CIFReadCellCleanup();
extern bool CIFParseUser(void); extern LinkedRect *CIFPolyToRects();
extern bool CIFParseCall(void); extern Transform *CIFDirectionToTrans();
extern bool CIFParseTransform(Transform *transformp); extern int CIFReadNameToType();
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 */ /* Variable argument procedures require complete prototype */
extern void CIFReadError(const char *format, ...) ATTR_FORMAT_PRINTF_1; extern void CIFReadError(char *format, ...);
extern void CIFReadWarning(const char *format, ...) ATTR_FORMAT_PRINTF_1; extern void CIFReadWarning(char *format, ...);
/* Variables shared by the CIF-reading modules, see CIFreadutils.c /* Variables shared by the CIF-reading modules, see CIFreadutils.c
* for more details: * for more details:
@ -221,4 +197,4 @@ extern int cifParseLaChar;
? (cifParseLaAvail = FALSE, cifParseLaChar) \ ? (cifParseLaAvail = FALSE, cifParseLaChar) \
: (cifParseLaChar = getc(cifInputFile))) : (cifParseLaChar = getc(cifInputFile)))
#endif /* _MAGIC__CIF__CIFREAD_H */ #endif /* _CIFREAD_H */

View File

@ -17,11 +17,10 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -35,9 +34,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/undo.h" #include "utils/undo.h"
/* C99 compat */
#include "drc/drc.h"
/* The following variable holds the CellDef into which feedback /* The following variable holds the CellDef into which feedback
* is to be placed for displaying CIF. * is to be placed for displaying CIF.
*/ */
@ -76,10 +72,9 @@ typedef struct {
*/ */
int int
cifPaintDBFunc( cifPaintDBFunc(tile, pld)
Tile *tile, /* Tile of CIF information. */ Tile *tile; /* Tile of CIF information. */
TileType dinfo, PaintLayerData *pld;
PaintLayerData *pld)
{ {
Rect area; Rect area;
int pNum; int pNum;
@ -107,7 +102,7 @@ cifPaintDBFunc(
if (DBPaintOnPlane(type, pNum)) if (DBPaintOnPlane(type, pNum))
{ {
ui.pu_pNum = pNum; ui.pu_pNum = pNum;
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo, DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui); &area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
} }
@ -133,14 +128,14 @@ cifPaintDBFunc(
*/ */
void void
CIFPaintLayer( CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef)
CellDef *rootDef, /* Cell for which to generate CIF. Must be CellDef *rootDef; /* Cell for which to generate CIF. Must be
* the rootDef of a window. * the rootDef of a window.
*/ */
Rect *area, /* Area in which to generate CIF. */ Rect *area; /* Area in which to generate CIF. */
char *cifLayer, /* CIF layer to highlight on the screen. */ char *cifLayer; /* CIF layer to highlight on the screen. */
int magicLayer, /* Magic layer to paint with the result */ int magicLayer; /* Magic layer to paint with the result */
CellDef *paintDef) /* CellDef to paint into (may be NULL) */ CellDef *paintDef; /* CellDef to paint into (may be NULL) */
{ {
int oldCount, i; int oldCount, i;
char msg[100]; char msg[100];
@ -166,15 +161,10 @@ CIFPaintLayer(
scx.scx_use = CIFDummyUse; scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform; scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef); cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount; oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, FALSE, CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE);
(ClientData)NULL);
DBCellClearDef(CIFComponentDef); DBCellClearDef(CIFComponentDef);
/* Report any errors that occurred. */ /* Report any errors that occurred. */
@ -218,10 +208,9 @@ CIFPaintLayer(
*/ */
int int
cifSeeFunc( cifSeeFunc(tile, sld)
Tile *tile, /* Tile to be entered as feedback. */ Tile *tile; /* Tile to be entered as feedback. */
TileType dinfo, /* Split tile information */ SeeLayerData *sld; /* Layer and explanation for the feedback. */
SeeLayerData *sld) /* Layer and explanation for the feedback. */
{ {
Rect area; Rect area;
@ -235,10 +224,10 @@ cifSeeFunc(
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor); (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, DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
sld->style | ((TiGetTypeExact(tile) | dinfo) & sld->style |
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE))); (TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
/* (preserve information about the geometry of a diagonal tile) */
return 0; return 0;
} }
@ -260,12 +249,12 @@ cifSeeFunc(
*/ */
void void
CIFSeeLayer( CIFSeeLayer(rootDef, area, layer)
CellDef *rootDef, /* Cell for which to generate CIF. Must be CellDef *rootDef; /* Cell for which to generate CIF. Must be
* the rootDef of a window. * the rootDef of a window.
*/ */
Rect *area, /* Area in which to generate CIF. */ Rect *area; /* Area in which to generate CIF. */
char *layer) /* CIF layer to highlight on the screen. */ char *layer; /* CIF layer to highlight on the screen. */
{ {
int oldCount, i; int oldCount, i;
char msg[100]; char msg[100];
@ -287,14 +276,9 @@ CIFSeeLayer(
scx.scx_use = CIFDummyUse; scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform; scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef); cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
(ClientData)CIFComponentDef);
oldCount = DBWFeedbackCount; oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE);
FALSE, (ClientData)NULL);
DBCellClearDef(CIFComponentDef); DBCellClearDef(CIFComponentDef);
/* Report any errors that occurred. */ /* Report any errors that occurred. */
@ -350,14 +334,14 @@ CIFSeeLayer(
*/ */
void void
CIFSeeHierLayer( CIFSeeHierLayer(rootDef, area, layer, arrays, subcells)
CellDef *rootDef, /* Def in which to compute CIF. Must be CellDef *rootDef; /* Def in which to compute CIF. Must be
* the root definition of a window. * the root definition of a window.
*/ */
Rect *area, /* Area in which to generate CIF. */ Rect *area; /* Area in which to generate CIF. */
char *layer, /* CIF layer to be highlighted. */ char *layer; /* CIF layer to be highlighted. */
bool arrays, /* TRUE means show array interactions. */ bool arrays; /* TRUE means show array interactions. */
bool subcells) /* TRUE means show subcell interactions. */ bool subcells; /* TRUE means show subcell interactions. */
{ {
int i, oldCount; int i, oldCount;
SeeLayerData sld; SeeLayerData sld;
@ -428,11 +412,10 @@ typedef struct {
} coverstats; } coverstats;
void void
CIFCoverageLayer( CIFCoverageLayer(rootDef, area, layer)
CellDef *rootDef, /* Def in which to compute CIF coverage */ CellDef *rootDef; /* Def in which to compute CIF coverage */
Rect *area, /* Area in which to compute coverage */ Rect *area; /* Area in which to compute coverage */
char *layer, /* CIF layer for coverage computation. */ char *layer; /* CIF layer for coverage computation. */
bool dolist) /* If TRUE, report only the value, in decimal */
{ {
coverstats cstats; coverstats cstats;
int i, scale; int i, scale;
@ -440,11 +423,9 @@ CIFCoverageLayer(
SearchContext scx; SearchContext scx;
TileTypeBitMask mask, depend; TileTypeBitMask mask, depend;
float fcover; float fcover;
int cifCoverageFunc();
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE; bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
/* Forward declaration */
int cifCoverageFunc(Tile *tile, TileType dinfo, ClientData *arg);
/* Check out the CIF layer name. */ /* Check out the CIF layer name. */
if (!CIFNameToMask(layer, &mask, &depend)) return; if (!CIFNameToMask(layer, &mask, &depend)) return;
@ -459,13 +440,8 @@ CIFCoverageLayer(
scx.scx_use = CIFDummyUse; scx.scx_use = CIFDummyUse;
scx.scx_trans = GeoIdentityTransform; scx.scx_trans = GeoIdentityTransform;
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
cifHierCopyFunc, (ClientData) CIFComponentDef); cifHierCopyFunc, (ClientData) CIFComponentDef);
CIFCopyMaskHints(&scx, CIFComponentDef); CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE);
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
(ClientData)CIFComponentDef);
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
FALSE, (ClientData)NULL);
DBCellClearDef(CIFComponentDef); DBCellClearDef(CIFComponentDef);
cstats.coverage = 0; cstats.coverage = 0;
@ -491,39 +467,24 @@ CIFCoverageLayer(
atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot); atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot);
atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot); atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot);
if (dolist) TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
{
#ifdef MAGIC_WRAPPER
Tcl_Obj *pobj;
pobj = Tcl_NewDoubleObj((double)fcover);
Tcl_SetObjResult(magicinterp, pobj);
#else
TxPrintf("%g\n", fcover);
#endif
}
else
{
TxPrintf("%s Area = %"DLONG_PREFIX"d CIF units^2\n", doBox ? "Cursor Box" :
"Cell", btotal); "Cell", btotal);
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal); TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage); TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" : TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
"cell", 100.0 * fcover); "cell", 100.0 * fcover);
}
} }
int int
cifCoverageFunc( cifCoverageFunc(tile, arg)
Tile *tile, Tile *tile;
TileType dinfo, /* (unused) */ ClientData *arg;
ClientData *arg)
{ {
coverstats *cstats = (coverstats *)arg; coverstats *cstats = (coverstats *)arg;
Rect r; Rect r;
TiToRect(tile, &r); TiToRect(tile, &r);
cstats->coverage += (long long)(r.r_xtop - r.r_xbot) * (long long)(r.r_ytop - r.r_ybot); cstats->coverage += (long long)((r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot));
GeoInclude(&r, &cstats->bounds); GeoInclude(&r, &cstats->bounds);
return(0); return(0);

View File

@ -18,7 +18,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -42,11 +42,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "cif/cif.h" #include "cif/cif.h"
#include "drc/drc.h" /* For WRL's DRC-CIF extensions */ #include "drc/drc.h" /* For WRL's DRC-CIF extensions */
/* C99 compat */
#include "calma/calma.h"
#include "dbwind/dbwind.h"
#include "drc/drc.h"
/* The following statics are used to keep track of things between /* The following statics are used to keep track of things between
* calls to CIFTechLine. * calls to CIFTechLine.
*/ */
@ -64,8 +59,8 @@ TileTypeBitMask CIFSolidBits;
/* Forward Declarations */ /* Forward Declarations */
void cifTechStyleInit(void); void cifTechStyleInit();
bool cifCheckCalmaNum(char *str); bool cifCheckCalmaNum();
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -85,7 +80,7 @@ bool cifCheckCalmaNum(char *str);
*/ */
void void
cifTechFreeStyle(void) cifTechFreeStyle()
{ {
int i; int i;
CIFOp *op; CIFOp *op;
@ -100,7 +95,6 @@ cifTechFreeStyle(void)
layer = CIFCurStyle->cs_layers[i]; layer = CIFCurStyle->cs_layers[i];
if (layer != NULL) if (layer != NULL)
{ {
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->cl_ops; op != NULL; op = op->co_next) for (op = layer->cl_ops; op != NULL; op = op->co_next)
{ {
if (op->co_client != (ClientData)NULL) if (op->co_client != (ClientData)NULL)
@ -111,8 +105,6 @@ cifTechFreeStyle(void)
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_BOUNDARY: case CIFOP_BOUNDARY:
case CIFOP_INTERACT:
case CIFOP_MANHATTAN:
/* These options use co_client to hold a single */ /* These options use co_client to hold a single */
/* integer value, so it is not allocated. */ /* integer value, so it is not allocated. */
break; break;
@ -121,9 +113,8 @@ cifTechFreeStyle(void)
break; break;
} }
} }
freeMagic1(&mm1, (char *)op); freeMagic((char *)op);
} }
freeMagic1_end(&mm1);
freeMagic((char *)layer); freeMagic((char *)layer);
} }
} }
@ -152,7 +143,7 @@ cifTechFreeStyle(void)
*/ */
void void
cifTechNewStyle(void) cifTechNewStyle()
{ {
cifTechFreeStyle(); cifTechFreeStyle();
cifTechStyleInit(); cifTechStyleInit();
@ -169,7 +160,7 @@ cifTechNewStyle(void)
*/ */
void void
cifTechStyleInit(void) cifTechStyleInit()
{ {
int i; int i;
@ -192,7 +183,6 @@ cifTechStyleInit(void)
{ {
CIFCurStyle->cs_labelLayer[i] = -1; CIFCurStyle->cs_labelLayer[i] = -1;
CIFCurStyle->cs_portLayer[i] = -1; CIFCurStyle->cs_portLayer[i] = -1;
CIFCurStyle->cs_portText[i] = -1;
} }
for (i = 0; i < MAXCIFLAYERS; i++) for (i = 0; i < MAXCIFLAYERS; i++)
CIFCurStyle->cs_layers[i] = NULL; CIFCurStyle->cs_layers[i] = NULL;
@ -220,23 +210,23 @@ cifTechStyleInit(void)
*/ */
void void
cifParseLayers( cifParseLayers(string, style, paintMask, cifMask, spaceOK)
char *string, /* List of layers. */ char *string; /* List of layers. */
CIFStyle *style, /* Gives CIF style for parsing string.*/ CIFStyle *style; /* Gives CIF style for parsing string.*/
TileTypeBitMask *paintMask, /* Place to store mask of paint layers. If TileTypeBitMask *paintMask; /* Place to store mask of paint layers. If
* NULL, then only CIF layer names are * NULL, then only CIF layer names are
* considered. * 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 * NULL, then only paint layer names are
* considered. * considered.
*/ */
int spaceOK) /* are space layers permissible in this cif int spaceOK; /* are space layers permissible in this cif
layer? layer?
*/ */
{ {
TileTypeBitMask curCifMask, curPaintMask; TileTypeBitMask curCifMask, curPaintMask;
char curLayer[512], *p, *cp; char curLayer[40], *p, *cp;
TileType paintType; TileType paintType;
int i; int i;
bool allResidues; bool allResidues;
@ -248,10 +238,6 @@ cifParseLayers(
{ {
p = curLayer; p = curLayer;
if (*string == '(')
while ((*string != ')') && (*string != 0))
*p++ = *string++;
if (*string == '*') if (*string == '*')
{ {
allResidues = TRUE; allResidues = TRUE;
@ -269,22 +255,7 @@ cifParseLayers(
if (paintMask != NULL) if (paintMask != NULL)
{ {
if (*curLayer == '(') paintType = DBTechNameTypes(curLayer, &curPaintMask);
{
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; if (paintType >= 0) goto okpaint;
} }
else paintType = -2; else paintType = -2;
@ -320,7 +291,7 @@ okpaint:
TechError("Ambiguous layer (type) \"%s\".\n", curLayer); TechError("Ambiguous layer (type) \"%s\".\n", curLayer);
continue; continue;
} }
if ((paintType >= 0) || (paintType == -3)) if (paintType >= 0)
{ {
if (paintType == TT_SPACE && spaceOK ==0) if (paintType == TT_SPACE && spaceOK ==0)
TechError("\"Space\" layer not permitted in CIF rules.\n"); TechError("\"Space\" layer not permitted in CIF rules.\n");
@ -380,7 +351,7 @@ okpaint:
*/ */
void void
CIFTechInit(void) CIFTechInit()
{ {
CIFKeep *style; CIFKeep *style;
@ -390,13 +361,11 @@ CIFTechInit(void)
/* forget the list of styles */ /* forget the list of styles */
free_magic1_t mm1 = freeMagic1_init();
for (style = CIFStyleList; style != NULL; style = style->cs_next) for (style = CIFStyleList; style != NULL; style = style->cs_next)
{ {
freeMagic(style->cs_name); freeMagic(style->cs_name);
freeMagic1(&mm1, style); freeMagic(style);
} }
freeMagic1_end(&mm1);
CIFStyleList = NULL; CIFStyleList = NULL;
} }
@ -418,7 +387,7 @@ CIFTechInit(void)
*/ */
void void
CIFTechStyleInit(void) CIFTechStyleInit()
{ {
CalmaTechInit(); CalmaTechInit();
@ -459,9 +428,8 @@ CIFTechStyleInit(void)
*/ */
bool bool
CIFTechLimitScale( CIFTechLimitScale(ns, ds)
int ns, int ns, ds;
int ds)
{ {
int gridup, scaledown; int gridup, scaledown;
int scale, limit, expand; int scale, limit, expand;
@ -500,9 +468,9 @@ CIFTechLimitScale(
*/ */
int int
CIFParseScale( CIFParseScale(true_scale, expander)
char *true_scale, char *true_scale;
int *expander) int *expander;
{ {
char *decimal; char *decimal;
short places; short places;
@ -551,10 +519,10 @@ CIFParseScale(
*/ */
bool bool
CIFTechLine( CIFTechLine(sectionName, argc, argv)
char *sectionName, /* The name of this section. */ char *sectionName; /* The name of this section. */
int argc, /* Number of fields on line. */ int argc; /* Number of fields on line. */
char *argv[]) /* Values of fields. */ char *argv[]; /* Values of fields. */
{ {
TileTypeBitMask mask, tempMask, cifMask, bloatLayers; TileTypeBitMask mask, tempMask, cifMask, bloatLayers;
int i, j, l, distance; int i, j, l, distance;
@ -563,7 +531,6 @@ CIFTechLine(
CIFKeep *newStyle, *p; CIFKeep *newStyle, *p;
char **bloatArg; char **bloatArg;
BloatData *bloats; BloatData *bloats;
BridgeData *bridge;
SquaresData *squares; SquaresData *squares;
SlotsData *slots; SlotsData *slots;
@ -817,7 +784,7 @@ CIFTechLine(
else else
{ {
l = strlen(CIFCurStyle->cs_name) - strlen(tptr); l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
if ((l > 0) && !strcmp(tptr, CIFCurStyle->cs_name + l)) if (!strcmp(tptr, CIFCurStyle->cs_name + l))
{ {
CIFCurStyle->cs_status = TECH_PENDING; CIFCurStyle->cs_status = TECH_PENDING;
return TRUE; return TRUE;
@ -836,8 +803,7 @@ CIFTechLine(
if (CIFCurStyle->cs_status != TECH_PENDING) return TRUE; if (CIFCurStyle->cs_status != TECH_PENDING) return TRUE;
newLayer = NULL; newLayer = NULL;
if ((strcmp(argv[0], "templayer") == 0) || (strcmp(argv[0], "layer") == 0) || if ((strcmp(argv[0], "templayer") == 0) || (strcmp(argv[0], "layer") == 0))
(strcmp(argv[0], "labellayer") == 0))
{ {
if (CIFCurStyle->cs_nLayers == MAXCIFLAYERS) if (CIFCurStyle->cs_nLayers == MAXCIFLAYERS)
{ {
@ -872,8 +838,6 @@ CIFTechLine(
#endif #endif
if (strcmp(argv[0], "templayer") == 0) if (strcmp(argv[0], "templayer") == 0)
newLayer->cl_flags |= CIF_TEMP; newLayer->cl_flags |= CIF_TEMP;
else if (strcmp(argv[0], "labellayer") == 0)
newLayer->cl_flags |= CIF_LABEL;
cifCurLayer = newLayer; cifCurLayer = newLayer;
cifCurOp = NULL; cifCurOp = NULL;
cifGotLabels = FALSE; cifGotLabels = FALSE;
@ -898,7 +862,7 @@ CIFTechLine(
if (strcmp(argv[0], "labels") == 0) if (strcmp(argv[0], "labels") == 0)
{ {
bool portOnly = FALSE, noPort = FALSE, textOnly = FALSE; bool portOnly = FALSE, noPort = FALSE;
if (cifCurLayer == NULL) if (cifCurLayer == NULL)
{ {
@ -913,8 +877,6 @@ CIFTechLine(
portOnly = TRUE; portOnly = TRUE;
else if (!strncmp(argv[2], "noport", 6)) else if (!strncmp(argv[2], "noport", 6))
noPort = TRUE; noPort = TRUE;
else if (!strncmp(argv[2], "text", 6))
textOnly = TRUE;
else else
{ {
TechError("Unknown option %s for labels statement.\n", argv[2]); TechError("Unknown option %s for labels statement.\n", argv[2]);
@ -927,28 +889,10 @@ CIFTechLine(
{ {
if (TTMaskHasType(&mask, i)) if (TTMaskHasType(&mask, i))
{ {
if (portOnly == 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; CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1;
if (noPort == FALSE) if (noPort != TRUE)
CIFCurStyle->cs_portText[i] = CIFCurStyle->cs_nLayers-1; CIFCurStyle->cs_portLayer[i] = CIFCurStyle->cs_nLayers-1;
}
} }
} }
cifGotLabels = TRUE; cifGotLabels = TRUE;
@ -1044,12 +988,10 @@ CIFTechLine(
{ {
if (strcmp(argv[i], "calma-permissive-labels") == 0) if (strcmp(argv[i], "calma-permissive-labels") == 0)
CIFCurStyle->cs_flags |= CWF_PERMISSIVE_LABELS; 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) else if (strcmp(argv[i], "grow-euclidean") == 0)
CIFCurStyle->cs_flags |= CWF_GROW_EUCLIDEAN; CIFCurStyle->cs_flags |= CWF_GROW_EUCLIDEAN;
else if (strcmp(argv[i], "see-no-vendor") == 0) else if (strcmp(argv[i], "see-vendor") == 0)
CIFCurStyle->cs_flags |= CWF_SEE_NO_VENDOR; CIFCurStyle->cs_flags |= CWF_SEE_VENDOR;
else if (strcmp(argv[i], "no-errors") == 0) else if (strcmp(argv[i], "no-errors") == 0)
CIFCurStyle->cs_flags |= CWF_NO_ERRORS; CIFCurStyle->cs_flags |= CWF_NO_ERRORS;
else if (strcmp(argv[i], "string-limit") == 0) else if (strcmp(argv[i], "string-limit") == 0)
@ -1107,41 +1049,12 @@ CIFTechLine(
newOp->co_opcode = CIFOP_BBOX; newOp->co_opcode = CIFOP_BBOX;
else if (strcmp(argv[0], "net") == 0) else if (strcmp(argv[0], "net") == 0)
newOp->co_opcode = CIFOP_NET; newOp->co_opcode = CIFOP_NET;
else if (strcmp(argv[0], "tagged") == 0)
newOp->co_opcode = CIFOP_TAGGED;
else if (strcmp(argv[0], "maxrect") == 0) else if (strcmp(argv[0], "maxrect") == 0)
newOp->co_opcode = CIFOP_MAXRECT; newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0) else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY; newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "close") == 0) else if (strcmp(argv[0], "close") == 0)
newOp->co_opcode = CIFOP_CLOSE; newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "orthogonal") == 0)
newOp->co_opcode = CIFOP_MANHATTAN;
else if (strcmp(argv[0], "not-square") == 0)
newOp->co_opcode = CIFOP_NOTSQUARE;
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 else
{ {
TechError("Unknown statement \"%s\".\n", argv[0]); TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1153,7 +1066,6 @@ CIFTechLine(
case CIFOP_AND: case CIFOP_AND:
case CIFOP_ANDNOT: case CIFOP_ANDNOT:
case CIFOP_OR: case CIFOP_OR:
case CIFOP_INTERACT:
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask, cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask,FALSE); &newOp->co_cifMask,FALSE);
@ -1163,6 +1075,7 @@ CIFTechLine(
case CIFOP_GROWMIN: case CIFOP_GROWMIN:
case CIFOP_GROW_G: case CIFOP_GROW_G:
case CIFOP_SHRINK: case CIFOP_SHRINK:
case CIFOP_CLOSE:
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]); newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0) if (newOp->co_distance <= 0)
@ -1172,67 +1085,8 @@ CIFTechLine(
} }
break; 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]);
if (newOp->co_distance <= 0)
{
TechError("Bridge distance must be greater than zero.\n");
goto errorReturn;
}
bridge = (BridgeData *)mallocMagic(sizeof(BridgeData));
bridge->br_width = atoi(argv[2]);
if (bridge->br_width <= 0)
{
TechError("Bridge width must be greater than zero.\n");
freeMagic(bridge);
goto errorReturn;
}
newOp->co_client = (ClientData)bridge;
break;
case CIFOP_BRIDGELIM:
if (argc != 4) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
{
TechError("Bridge distance must be greater than zero.\n");
goto errorReturn;
}
bridge = (BridgeData *)mallocMagic(sizeof(BridgeData));
bridge->br_width = atoi(argv[2]);
if (bridge->br_width <= 0)
{
TechError("Bridge width must be greater than zero.\n");
freeMagic(bridge);
goto errorReturn;
}
cifParseLayers(argv[3], CIFCurStyle, &newOp->co_paintMask, &newOp->co_cifMask,FALSE);
newOp->co_client = (ClientData)bridge;
break;
case CIFOP_BLOATALL: case CIFOP_BLOATALL:
if (argc != 3 && argc != 4) goto wrongNumArgs; if (argc != 3) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask, cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask, FALSE); &newOp->co_cifMask, FALSE);
bloats = (BloatData *)mallocMagic(sizeof(BloatData)); bloats = (BloatData *)mallocMagic(sizeof(BloatData));
@ -1248,21 +1102,6 @@ CIFTechLine(
if (!TTMaskIsZero(&mask) && !TTMaskIsZero(&cifMask)) if (!TTMaskIsZero(&mask) && !TTMaskIsZero(&cifMask))
TechError("Can't mix CIF and magic layers in bloat statement.\n"); 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 */ /* 10/15/2019: Lifting restriction that the types that */
/* trigger the bloating must be in the same plane as the */ /* trigger the bloating must be in the same plane as the */
/* types that are bloated into. */ /* types that are bloated into. */
@ -1355,21 +1194,13 @@ bloatCheck:
} }
} }
TechError("Not all bloat layers fall in the same plane.\n"); TechError("Not all bloat layers fall in the same plane.\n");
bloats->bl_plane = 0; /* Prevents magic from segfaulting */
bloatDone: break; bloatDone: break;
case CIFOP_NET: case CIFOP_NET:
case CIFOP_TAGGED: if (argc != 3) goto wrongNumArgs;
if ((argc != 2) && (argc != 3)) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
if (argc == 3)
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask, FALSE);
break;
case CIFOP_MASKHINTS:
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]); newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
&newOp->co_cifMask, FALSE);
break; break;
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
@ -1385,19 +1216,6 @@ bloatCheck:
goto wrongNumArgs; goto wrongNumArgs;
break; 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: case CIFOP_BBOX:
if (argc == 2) if (argc == 2)
{ {
@ -1624,8 +1442,8 @@ bloatCheck:
*/ */
bool bool
cifCheckCalmaNum( cifCheckCalmaNum(str)
char *str) char *str;
{ {
int n = atoi(str); int n = atoi(str);
@ -1661,9 +1479,9 @@ cifCheckCalmaNum(
*/ */
void void
cifComputeRadii( cifComputeRadii(layer, des)
CIFLayer *layer, /* Layer for which to compute distances. */ CIFLayer *layer; /* Layer for which to compute distances. */
CIFStyle *des) /* CIF style (used to find temp layer CIFStyle *des; /* CIF style (used to find temp layer
* distances. * distances.
*/ */
{ {
@ -1675,14 +1493,6 @@ cifComputeRadii(
for (op = layer->cl_ops; op != NULL; op = op->co_next) for (op = layer->cl_ops; op != NULL; op = op->co_next)
{ {
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
/* used hierarchically so ignore any grow/shrink operators that */
/* come after them. */
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
break;
/* If CIF layers are used, switch to the max of current /* If CIF layers are used, switch to the max of current
* distances and those of the layers used. * distances and those of the layers used.
*/ */
@ -1705,12 +1515,11 @@ cifComputeRadii(
switch (op->co_opcode) switch (op->co_opcode)
{ {
case CIFOP_AND: case CIFOP_AND: break;
case CIFOP_ANDNOT:
case CIFOP_OR: case CIFOP_ANDNOT: break;
case CIFOP_INTERACT:
case CIFOP_MASKHINTS: case CIFOP_OR: break;
break;
case CIFOP_GROW: case CIFOP_GROW:
case CIFOP_GROWMIN: case CIFOP_GROWMIN:
@ -1740,11 +1549,8 @@ cifComputeRadii(
shrink += curShrink; shrink += curShrink;
break; break;
case CIFOP_BRIDGE: break;
case CIFOP_BRIDGELIM: break;
case CIFOP_SQUARES: break; case CIFOP_SQUARES: break;
case CIFOP_SQUARES_G: break; case CIFOP_SQUARES_G: break;
} }
} }
@ -1770,8 +1576,8 @@ cifComputeRadii(
*/ */
void void
cifComputeHalo( cifComputeHalo(style)
CIFStyle *style) CIFStyle *style;
{ {
int maxGrow, maxShrink, i; int maxGrow, maxShrink, i;
@ -1787,8 +1593,7 @@ cifComputeHalo(
if (maxGrow > maxShrink) if (maxGrow > maxShrink)
style->cs_radius = 2*maxGrow; style->cs_radius = 2*maxGrow;
else style->cs_radius = 2*maxShrink; else style->cs_radius = 2*maxShrink;
if (style->cs_scaleFactor > 0) style->cs_radius /= style->cs_scaleFactor;
style->cs_radius /= style->cs_scaleFactor;
style->cs_radius++; style->cs_radius++;
/* TxPrintf("Radius for %s CIF is %d.\n", /* TxPrintf("Radius for %s CIF is %d.\n",
@ -1841,7 +1646,7 @@ cifComputeHalo(
*/ */
void void
CIFTechFinal(void) CIFTechFinal()
{ {
CIFStyle *style = CIFCurStyle; CIFStyle *style = CIFCurStyle;
CIFOp *op; CIFOp *op;
@ -1912,7 +1717,6 @@ CIFTechFinal(void)
if (op->co_client) if (op->co_client)
{ {
BloatData *bloats; BloatData *bloats;
BridgeData *bridge;
SquaresData *squares; SquaresData *squares;
SlotsData *slots; SlotsData *slots;
if (op->co_opcode == CIFOP_SLOTS) if (op->co_opcode == CIFOP_SLOTS)
@ -1990,29 +1794,18 @@ CIFTechFinal(void)
} }
} }
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */ /* 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 */ /* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */ /* as a flag field, while CIFOP_NET uses it for a string. */
/* CIFOP_TAGGED use it for a string. */
else else
{ {
switch (op->co_opcode) switch (op->co_opcode)
{ {
case CIFOP_OR: case CIFOP_OR:
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_MASKHINTS:
case CIFOP_BOUNDARY: case CIFOP_BOUNDARY:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET: case CIFOP_NET:
case CIFOP_TAGGED:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
c = FindGCF(style->cs_scaleFactor,
bridge->br_width);
if (c < minReduce) minReduce = c;
break; break;
default: default:
bloats = (BloatData *)op->co_client; bloats = (BloatData *)op->co_client;
@ -2079,18 +1872,11 @@ CIFTechFinal(void)
case CIFOP_BLOAT: case CIFOP_BLOAT:
case CIFOP_BLOATMAX: case CIFOP_BLOATMAX:
case CIFOP_BLOATMIN: case CIFOP_BLOATMIN:
bloats = (BloatData *)op->co_client;
for (j = 0; j < TT_MAXTYPES; j++)
if (bloats->bl_distance[j] != bloats->bl_distance[TT_SPACE])
TTMaskSetType(&ourYank, j);
needThisLayer = TRUE;
break;
case CIFOP_BLOATALL: case CIFOP_BLOATALL:
bloats = (BloatData *)op->co_client; bloats = (BloatData *)op->co_client;
for (j = 0; j < TT_MAXTYPES; j++) for (j = 0; j < TT_MAXTYPES; j++)
{ {
if (bloats->bl_distance[j] != 0) if (bloats->bl_distance[j] != bloats->bl_distance[TT_SPACE])
{ {
if (bloats->bl_plane < 0) if (bloats->bl_plane < 0)
TTMaskSetType(&ourDepend, j); TTMaskSetType(&ourDepend, j);
@ -2103,11 +1889,7 @@ CIFTechFinal(void)
case CIFOP_AND: case CIFOP_AND:
case CIFOP_ANDNOT: case CIFOP_ANDNOT:
case CIFOP_INTERACT:
case CIFOP_SHRINK: case CIFOP_SHRINK:
case CIFOP_CLOSE:
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
needThisLayer = TRUE; needThisLayer = TRUE;
break; break;
} }
@ -2139,27 +1921,6 @@ CIFTechFinal(void)
TTMaskSetType(&style->cs_hierLayers, i); TTMaskSetType(&style->cs_hierLayers, i);
} }
/* Added by Tim, 6/17/20: Do not set dependencies of BOUNDARY */
/* or BBOX because these are unable to be represented in a */
/* hierarchy without producing conflicting parent/child mask */
/* geometry. Generally, BOUNDARY and BBOX operations are */
/* intended to be restricted to the child cell and should not */
/* interact hierarchically. Possibly it would be useful to */
/* provide some method to preserve the bounding box information */
/* when flattening? */
for (i = 0; i < style->cs_nLayers; i++)
{
for (op = style->cs_layers[i]->cl_ops; op != NULL; op = op->co_next)
{
if (op->co_opcode == CIFOP_BOUNDARY || op->co_opcode == CIFOP_BBOX)
{
TTMaskClearType(&style->cs_hierLayers, i);
break;
}
}
}
/* Added by Tim, 10/18/04 */ /* Added by Tim, 10/18/04 */
/* Go through the layer operators looking for those that */ /* Go through the layer operators looking for those that */
@ -2176,8 +1937,7 @@ CIFTechFinal(void)
for (op = style->cs_layers[i]->cl_ops; (op != NULL) && for (op = style->cs_layers[i]->cl_ops; (op != NULL) &&
(op->co_opcode == CIFOP_OR) && (op->co_opcode == CIFOP_OR) &&
(TTMaskIsZero(&op->co_cifMask)); op = op->co_next); (TTMaskIsZero(&op->co_cifMask)); op = op->co_next);
if (op && ((op->co_opcode == CIFOP_SQUARES) || if (op && (op->co_opcode == CIFOP_SQUARES) && (op->co_next == NULL))
(op->co_opcode == CIFOP_SQUARES_G)) && (op->co_next == NULL))
{ {
clientdata = op->co_client; clientdata = op->co_client;
for (op = style->cs_layers[i]->cl_ops; op->co_opcode == CIFOP_OR; for (op = style->cs_layers[i]->cl_ops; op->co_opcode == CIFOP_OR;
@ -2228,8 +1988,8 @@ CIFTechFinal(void)
*/ */
void void
CIFLoadStyle( CIFLoadStyle(stylename)
char *stylename) char *stylename;
{ {
SectionID invcif; SectionID invcif;
@ -2277,11 +2037,11 @@ CIFLoadStyle(
*/ */
int int
CIFGetContactSize( CIFGetContactSize(type, edge, spacing, border)
TileType type, TileType type;
int *edge, int *edge;
int *spacing, int *border;
int *border) int *spacing;
{ {
CIFStyle *style = CIFCurStyle; CIFStyle *style = CIFCurStyle;
CIFOp *op, *sop; CIFOp *op, *sop;
@ -2323,11 +2083,7 @@ CIFGetContactSize(
/* Anything other than an OR function will break */ /* Anything other than an OR function will break */
/* the relationship between magic layers and cuts. */ /* the relationship between magic layers and cuts. */
/* NOTE: Making an exception for AND_NOT, which is */ else if (sop->co_opcode != CIFOP_OR)
/* used to distinguish between small and large via */
/* areas. */
else if ((sop->co_opcode != CIFOP_OR) &&
(sop->co_opcode != CIFOP_ANDNOT))
break; break;
} }
} }
@ -2374,9 +2130,8 @@ CIFGetContactSize(
*/ */
void void
CIFTechOutputScale( CIFTechOutputScale(n, d)
int n, int n, d;
int d)
{ {
int i, j, lgcf, lexpand; int i, j, lgcf, lexpand;
CIFStyle *ostyle = CIFCurStyle; CIFStyle *ostyle = CIFCurStyle;
@ -2385,7 +2140,6 @@ CIFTechOutputScale(
SquaresData *squares; SquaresData *squares;
SlotsData *slots; SlotsData *slots;
BloatData *bloats; BloatData *bloats;
BridgeData *bridge;
bool has_odd_space = FALSE; bool has_odd_space = FALSE;
if (ostyle == NULL) return; if (ostyle == NULL) return;
@ -2537,20 +2291,8 @@ CIFTechOutputScale(
case CIFOP_OR: case CIFOP_OR:
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_BOUNDARY: case CIFOP_BOUNDARY:
case CIFOP_MASKHINTS:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET: case CIFOP_NET:
case CIFOP_TAGGED:
case CIFOP_INTERACT:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
bridge->br_width *= d;
lgcf = FindGCF(abs(bridge->br_width),
ostyle->cs_expander);
lexpand = FindGCF(lexpand, lgcf);
break; break;
default: default:
bloats = (BloatData *)op->co_client; bloats = (BloatData *)op->co_client;
@ -2578,7 +2320,7 @@ CIFTechOutputScale(
/* Reduce the scale and all distances by the greatest common */ /* Reduce the scale and all distances by the greatest common */
/* factor of everything. */ /* factor of everything. */
/* fprintf(stderr, "All CIF units divisible by %d\n", lexpand); */ /* fprintf(stderr, "All CIF units divisible by %d\n", lexpand); */
/* fflush(stderr); */ /* fflush(stderr); */
lgcf = FindGCF(ostyle->cs_scaleFactor, ostyle->cs_expander); lgcf = FindGCF(ostyle->cs_scaleFactor, ostyle->cs_expander);
@ -2649,16 +2391,10 @@ CIFTechOutputScale(
if (bloats->bl_distance[j] != 0) if (bloats->bl_distance[j] != 0)
bloats->bl_distance[j] /= lexpand; bloats->bl_distance[j] /= lexpand;
break; break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
bridge->br_width /= lexpand;
break;
default: default:
/* op->co_opcode in CIFOP_OR is a pointer copy, */ /* op->co_opcode in CIFOP_OR is a pointer copy */
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */ /* and in CIFOP_BBOX and CIFOP_MAXRECT is a */
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */ /* flag, and in CIFOP_NET is a string. */
/* CIFOP_TAGGED is a string. */
break; break;
} }
} }

View File

@ -17,7 +17,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdlib.h> #include <stdlib.h>
@ -44,15 +44,14 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "textio/textio.h" #include "textio/textio.h"
/* Forward declarations */ /* Forward declarations */
extern int cifWriteInitFunc(CellDef *def, ClientData cdata); /* UNUSED */ extern int cifWriteInitFunc();
extern int cifWriteMarkFunc(CellUse *use); extern int cifWriteMarkFunc();
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f); extern int cifWritePaintFunc();
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f); extern int cifWriteUseFunc();
extern int cifWriteUseFunc(CellUse *use, FILE *f); extern void cifOutPreamble();
extern void cifOutPreamble(FILE *outf, CellDef *cell); extern void cifOut();
extern void cifOut(FILE *outf); extern void cifOutFunc();
extern void cifOutFunc(CellDef *def, FILE *f); extern int GrClipTriangle();
extern void GrClipTriangle(Rect *r, Rect *c, int clipped, TileType dinfo, Point *points, int *np);
/* Current cell number in CIF numbering scheme */ /* Current cell number in CIF numbering scheme */
@ -118,13 +117,12 @@ bool CIFArrayWriteDisable = FALSE;
*/ */
bool bool
CIFWrite( CIFWrite(rootDef, f)
CellDef *rootDef, /* Pointer to CellDef to be written */ CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f) /* Open output file */ FILE *f; /* Open output file */
{ {
bool good; bool good;
int oldCount = DBWFeedbackCount; int oldCount = DBWFeedbackCount;
CellDef *err_def;
CellUse dummy; CellUse dummy;
/* /*
@ -134,20 +132,14 @@ CIFWrite(
*/ */
dummy.cu_def = rootDef; dummy.cu_def = rootDef;
err_def = DBCellReadArea(&dummy, &rootDef->cd_bbox, TRUE); DBCellReadArea(&dummy, &rootDef->cd_bbox);
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(); DBFixMismatch();
if (CIFCurStyle->cs_reducer == 0) if (CIFCurStyle->cs_reducer == 0)
{ {
TxError("The current CIF output style can only be used for writing\n"); TxError("The current CIF output style can only be used for writing\n");
TxError("Calma output. Try picking another output style.\n"); TxError("Calma output. Try picking another output style.\n");
return (FALSE); return (TRUE);
} }
/* /*
@ -167,8 +159,8 @@ CIFWrite(
cifOutPreamble(f, rootDef); cifOutPreamble(f, rootDef);
cifOut(f); cifOut(f);
StackFree(cifStack); StackFree(cifStack);
if ((int) CD2INT(rootDef->cd_client) < 0) if ((int) rootDef->cd_client < 0)
rootDef->cd_client = INT2CD(- (int) CD2INT(rootDef->cd_client)); rootDef->cd_client = (ClientData) (- (int) rootDef->cd_client);
/* See if any problems occurred. */ /* See if any problems occurred. */
@ -182,7 +174,7 @@ CIFWrite(
* Now we are almost done. * Now we are almost done.
* Just output a call on the root cell * Just output a call on the root cell
*/ */
fprintf(f, "C %d;\nEnd\n", (int) CD2INT(rootDef->cd_client)); fprintf(f, "C %d;\nEnd\n", (int) rootDef->cd_client);
good = !ferror(f); good = !ferror(f);
return (good); return (good);
} }
@ -204,11 +196,9 @@ CIFWrite(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
cifWriteInitFunc( cifWriteInitFunc(def)
CellDef *def, CellDef *def;
ClientData cdata) /* UNUSED */
{ {
def->cd_client = (ClientData) 0; def->cd_client = (ClientData) 0;
return (0); return (0);
@ -231,11 +221,11 @@ cifWriteInitFunc(
*/ */
int int
cifWriteMarkFunc( cifWriteMarkFunc(use)
CellUse *use) CellUse *use;
{ {
if (use->cu_def->cd_client != (ClientData) 0) return 0; if (use->cu_def->cd_client != (ClientData) 0) return 0;
use->cu_def->cd_client = INT2CD(cifCellNum); use->cu_def->cd_client = (ClientData) cifCellNum;
cifCellNum -= 1; cifCellNum -= 1;
StackPush((ClientData) use->cu_def, cifStack); StackPush((ClientData) use->cu_def, cifStack);
return (0); return (0);
@ -257,9 +247,9 @@ cifWriteMarkFunc(
*/ */
void void
cifOutPreamble( cifOutPreamble(outf, cell)
FILE *outf, FILE *outf;
CellDef *cell) CellDef *cell;
{ {
extern char *MagicVersion; extern char *MagicVersion;
extern char *MagicCompileTime; extern char *MagicCompileTime;
@ -306,24 +296,25 @@ cifOutPreamble(
*/ */
void void
cifOut( cifOut(outf)
FILE *outf) FILE *outf;
{ {
CellDef *def; CellDef *def;
bool needHier;
while (!StackEmpty(cifStack)) while (!StackEmpty(cifStack))
{ {
def = (CellDef *) StackPop(cifStack); def = (CellDef *) StackPop(cifStack);
if ((int) CD2INT(def->cd_client) >= 0) continue; /* Already output */ if ((int) def->cd_client >= 0) continue; /* Already output */
if (SigInterruptPending) continue; if (SigInterruptPending) continue;
def->cd_client = INT2CD(- (int) CD2INT(def->cd_client)); def->cd_client = (ClientData) (- (int) def->cd_client);
/* Read the cell in if it is not already available. */ /* Read the cell in if it is not already available. */
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, TRUE, TRUE, NULL)) {
continue; bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) continue;
}
/* Add any subcells to the stack. This must be done before /* Add any subcells to the stack. This must be done before
* outputting CIF to make sure that the subcells all have * outputting CIF to make sure that the subcells all have
@ -355,16 +346,16 @@ cifOut(
*/ */
void void
cifOutFunc( cifOutFunc(def, f)
CellDef *def, /* Pointer to cell def to be written */ CellDef *def; /* Pointer to cell def to be written */
FILE *f) /* Open output file */ FILE *f; /* Open output file */
{ {
Rect bigArea; Rect bigArea;
Label *lab; Label *lab;
int type; int type;
CIFLayer *layer; CIFLayer *layer;
fprintf(f, "DS %d %d %d;\n", (int) CD2INT(def->cd_client), fprintf(f, "DS %d %d %d;\n", (int) def->cd_client,
CIFCurStyle->cs_reducer, 2 * CIFCurStyle->cs_expander); CIFCurStyle->cs_reducer, 2 * CIFCurStyle->cs_expander);
if (def->cd_name != (char *) NULL) if (def->cd_name != (char *) NULL)
@ -387,28 +378,20 @@ cifOutFunc(
GEO_EXPAND(&def->cd_bbox, CIFCurStyle->cs_radius, &bigArea); GEO_EXPAND(&def->cd_bbox, CIFCurStyle->cs_radius, &bigArea);
CIFErrorDef = def; CIFErrorDef = def;
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE, CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE);
(ClientData)NULL);
if (!CIFHierWriteDisable) if (!CIFHierWriteDisable)
CIFGenSubcells(def, &bigArea, CIFPlanes); CIFGenSubcells(def, &bigArea, CIFPlanes);
if (!CIFArrayWriteDisable) if (!CIFArrayWriteDisable)
CIFGenArrays(def, &bigArea, CIFPlanes); CIFGenArrays(def, &bigArea, CIFPlanes);
for (type = 0; type < CIFCurStyle->cs_nLayers; type++) for (type = 0; type < CIFCurStyle->cs_nLayers; type++)
{ {
layer = CIFCurStyle->cs_layers[type]; layer = CIFCurStyle->cs_layers[type];
if (layer->cl_flags & CIF_TEMP) continue; if (layer->cl_flags & CIF_TEMP) continue;
cifPaintLayerName = layer->cl_name; cifPaintLayerName = layer->cl_name;
cifPaintScale = 1; cifPaintScale = 1;
if (layer->cl_flags & CIF_LABEL) (void) DBSrPaintArea((Tile *) NULL, CIFPlanes[type],
DBSrPaintArea((Tile *) NULL, CIFPlanes[type], &TiPlaneRect, &CIFSolidBits, cifWritePaintFunc,
&TiPlaneRect, &CIFSolidBits, cifWriteLabelFunc, (ClientData) f);
(ClientData) f);
else
DBSrPaintArea((Tile *) NULL, CIFPlanes[type],
&TiPlaneRect, &CIFSolidBits, cifWritePaintFunc,
(ClientData) f);
} }
/* Output labels */ /* Output labels */
@ -486,16 +469,16 @@ cifOutFunc(
*/ */
int int
cifWriteUseFunc( cifWriteUseFunc(use, f)
CellUse *use, CellUse *use;
FILE *f) FILE *f;
{ {
int x, y, topx, topy; int x, y, topx, topy;
int realx, realy; int realx, realy;
Transform *t; Transform *t;
int cifnum; int cifnum;
cifnum = (int) CD2INT(use->cu_def->cd_client); cifnum = (int) use->cu_def->cd_client;
if (cifnum < 0) cifnum = (-cifnum); if (cifnum < 0) cifnum = (-cifnum);
topx = use->cu_xhi - use->cu_xlo; topx = use->cu_xhi - use->cu_xlo;
if (topx < 0) topx = -topx; if (topx < 0) topx = -topx;
@ -565,68 +548,6 @@ cifWriteUseFunc(
return 0; return 0;
} }
/*
* ----------------------------------------------------------------------------
*
* cifWriteLabelFunc --
*
* Filter function used to write out a label corresponding to a
* single paint tile. The CIF layer name is used as the label to
* output.
*
* Results:
* Always return 0
*
* Side effects:
* Writes to the disk file.
*
* ----------------------------------------------------------------------------
*/
int
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;
Point center, size;
if (IsSplit(tile)) return 0; /* Ignore non-manhattan tiles */
if (cifPaintLayerName == NULL) return 0; /* Shouldn't happen */
TiToRect(tile, &r);
type = CIFCurStyle->cs_labelLayer[TiGetType(tile)];
center.p_x = r.r_xbot + r.r_xtop;
center.p_y = r.r_ybot + r.r_ytop;
center.p_x *= CIFCurStyle->cs_scaleFactor;
center.p_x /= CIFCurStyle->cs_reducer;
center.p_y *= CIFCurStyle->cs_scaleFactor;
center.p_y /= CIFCurStyle->cs_reducer;
if (CIFDoAreaLabels)
{
size.p_x = r.r_xtop - r.r_xbot;
size.p_y = r.r_ytop - r.r_ybot;
size.p_x *= 2 * CIFCurStyle->cs_scaleFactor;
size.p_x /= CIFCurStyle->cs_reducer;
size.p_y *= 2 * CIFCurStyle->cs_scaleFactor;
size.p_y /= CIFCurStyle->cs_reducer;
fprintf(f, "95 %s %d %d %d %d;\n",
cifPaintLayerName, size.p_x, size.p_y, center.p_x, center.p_y);
}
else
{
fprintf(f, "94 %s %d %d;\n",
cifPaintLayerName, center.p_x, center.p_y);
}
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -644,10 +565,9 @@ cifWriteLabelFunc(
*/ */
int int
cifWritePaintFunc( cifWritePaintFunc(tile, f)
Tile *tile, /* Tile to be written out. */ Tile *tile; /* Tile to be written out. */
TileType dinfo, /* Split tile information */ FILE *f; /* File in which to write. */
FILE *f) /* File in which to write. */
{ {
Rect r; Rect r;
@ -666,7 +586,7 @@ cifWritePaintFunc(
Point points[5]; Point points[5];
int i, np; int i, np;
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile) | dinfo, points, &np); GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile), points, &np);
/* Write triangle as a CIF polygon */ /* Write triangle as a CIF polygon */
@ -726,9 +646,9 @@ cifWritePaintFunc(
*/ */
bool bool
CIFWriteFlat( CIFWriteFlat(rootDef, f)
CellDef *rootDef, /* Pointer to CellDef to be written */ CellDef *rootDef; /* Pointer to CellDef to be written */
FILE *f) /* Open output file */ FILE *f; /* Open output file */
{ {
bool good; bool good;
int oldCount = DBWFeedbackCount; int oldCount = DBWFeedbackCount;
@ -777,7 +697,7 @@ CIFWriteFlat(
* Just output a call on the root cell * Just output a call on the root cell
*/ */
fprintf(f, "C %d;\nEnd\n", (int) CD2INT(CIFComponentDef->cd_client)); fprintf(f, "C %d;\nEnd\n", (int) CIFComponentDef->cd_client);
DBCellClearDef(CIFComponentDef); DBCellClearDef(CIFComponentDef);
good = !ferror(f); 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 $ * rcsid "$Header: /usr/cvsroot/magic-8.0/cif/cif.h,v 1.4 2010/06/24 12:37:15 tim Exp $
*/ */
#ifndef _MAGIC__CIF__CIF_H #ifndef _CIF_H
#define _MAGIC__CIF__CIF_H #define _CIF_H
#include "database/database.h" #include "database/database.h"
@ -51,48 +51,42 @@ extern bool CIFUnfracture;
/* Procedures that parse the cif sections of a technology file. */ /* Procedures that parse the cif sections of a technology file. */
extern void CIFTechStyleInit(void); extern void CIFTechStyleInit();
extern void CIFTechInit(void); extern void CIFTechInit();
extern bool CIFTechLine(char *sectionName, int argc, char *argv[]); extern bool CIFTechLine();
extern void CIFTechFinal(void); extern void CIFTechFinal();
extern void CIFTechOutputScale(int n, int d); extern void CIFTechOutputScale();
extern int CIFTechInputScale(int n, int d, bool opt); extern void CIFTechInputScale();
extern bool CIFTechLimitScale(int ns, int ds); extern bool CIFTechLimitScale();
extern void CIFReadTechStyleInit(void); extern void CIFReadTechStyleInit();
extern void CIFReadTechInit(void); extern void CIFReadTechInit();
extern bool CIFReadTechLine(char *sectionName, int argc, char *argv[]); extern bool CIFReadTechLine();
extern void CIFReadTechFinal(void); extern void CIFReadTechFinal();
extern void CIFParseReadLayers(char *string, TileTypeBitMask *mask, bool newok);
/* Externally-visible procedures: */ /* Externally-visible procedures: */
extern float CIFGetOutputScale(int convert); extern float CIFGetOutputScale();
extern float CIFGetScale(int convert); extern float CIFGetInputScale();
extern float CIFGetInputScale(int convert); extern int CIFGetDefaultContactSize();
extern int CIFPaintCurrent(int filetype); extern int CIFPaintCurrent();
extern void CIFSeeLayer(CellDef *rootDef, Rect *area, char *layer); extern void CIFSeeLayer();
extern void CIFPaintLayer(CellDef *rootDef, Rect *area, char *cifLayer, int magicLayer, CellDef *paintDef); extern void CIFPaintLayer();
extern void CIFSeeHierLayer(CellDef *rootDef, Rect *area, char *layer, int arrays, int subcells); extern void CIFSeeHierLayer();
extern void CIFPrintStats(void); extern void CIFPrintStats();
extern bool CIFWrite(CellDef *rootDef, FILE *f); extern bool CIFWrite();
extern void CIFReadFile(FILE *file); extern void CIFReadFile();
extern void CIFSetStyle(char *name); extern void CIFSetStyle();
extern void CIFSetReadStyle(char *name); extern void CIFSetReadStyle();
extern void CIFPrintStyle(bool dolist, bool doforall, bool docurrent); extern void CIFPrintStyle();
extern void CIFPrintReadStyle(bool dolist, bool doforall, bool docurrent); extern void CIFPrintReadStyle();
extern int CIFOutputScaleFactor(void); extern int CIFOutputScaleFactor();
extern void PaintWireList(Point *pointlist, int number, int width, int endcap, Plane *plane, extern void PaintWireList();
PaintResultType *ptable, PaintUndoInfo *ui); extern LinkedRect *PaintPolygon();
extern LinkedRect *PaintPolygon(Point *pointlist, int number, Plane *plane, PaintResultType *ptable,
PaintUndoInfo *ui, int keep);
/* C99 compat */ #endif /* _CIF_H */
extern int CIFGetContactSize(TileType type, int *edge, int *spacing, int *border);
#endif /* _MAGIC__CIF__CIF_H */

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -35,6 +35,12 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
*/ */
UndoType cmwUndoClientID; UndoType cmwUndoClientID;
/*
* Functions to play events forward/backward.
*/
void cmwUndoForw(), cmwUndoBack();
void cmwUndoStart(), cmwUndoDone();
/* /*
* A single undo event for the * A single undo event for the
* color map module. * color map module.
@ -52,14 +58,6 @@ UndoType cmwUndoClientID;
*/ */
bool cmwColorsChanged[256]; bool cmwColorsChanged[256];
/*
* Functions to play events forward/backward.
*/
void cmwUndoForw(colorUE *up);
void cmwUndoBack(colorUE *up);
void cmwUndoStart(void);
void cmwUndoDone(void);
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -79,7 +77,7 @@ void cmwUndoDone(void);
*/ */
void void
CMWundoInit(void) CMWundoInit()
{ {
cmwUndoClientID = UndoAddClient(cmwUndoStart, cmwUndoDone, NULL, NULL, cmwUndoClientID = UndoAddClient(cmwUndoStart, cmwUndoDone, NULL, NULL,
cmwUndoForw, cmwUndoBack, "color map"); cmwUndoForw, cmwUndoBack, "color map");
@ -104,16 +102,16 @@ CMWundoInit(void)
*/ */
void void
cmwUndoForw( cmwUndoForw(up)
colorUE *up) colorUE *up;
{ {
(void) GrPutColor(up->cue_color, up->new_r, up->new_g, up->new_b); (void) GrPutColor(up->cue_color, up->new_r, up->new_g, up->new_b);
cmwColorsChanged[up->cue_color] = TRUE; cmwColorsChanged[up->cue_color] = TRUE;
} }
void void
cmwUndoBack( cmwUndoBack(up)
colorUE *up) colorUE *up;
{ {
(void) GrPutColor(up->cue_color, up->old_r, up->old_g, up->old_b); (void) GrPutColor(up->cue_color, up->old_r, up->old_g, up->old_b);
cmwColorsChanged[up->cue_color] = TRUE; cmwColorsChanged[up->cue_color] = TRUE;
@ -136,14 +134,10 @@ cmwUndoBack(
*/ */
void void
cmwUndoColor( cmwUndoColor(color, oldr, oldg, oldb, newr, newg, newb)
int color, int color;
int oldr, int oldr, oldg, oldb;
int oldg, int newr, newg, newb;
int oldb,
int newr,
int newg,
int newb)
{ {
colorUE *up; colorUE *up;
@ -177,7 +171,7 @@ cmwUndoColor(
*/ */
void void
cmwUndoStart(void) cmwUndoStart()
{ {
int i; int i;
@ -204,13 +198,13 @@ cmwUndoStart(void)
*/ */
void void
cmwUndoDone(void) cmwUndoDone()
{ {
int i; int i;
extern int cmwRedisplayFunc(MagWindow *w, int color); extern int cmwRedisplayFunc();
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
if (cmwColorsChanged[i]) if (cmwColorsChanged[i])
(void) WindSearch(CMWclientID, (ClientData) NULL, (Rect *) NULL, (void) WindSearch(CMWclientID, (ClientData) NULL, (Rect *) NULL,
cmwRedisplayFunc, INT2CD(i)); cmwRedisplayFunc, (ClientData) 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 $ * rcsid $Header: /usr/cvsroot/magic-8.0/cmwind/cmwind.h,v 1.2 2009/09/10 20:32:51 tim Exp $
*/ */
#ifndef _MAGIC__CMWIND__CMWIND_H #ifndef _CMWIND_H
#define _MAGIC__CMWIND__CMWIND_H #define _CMWIND_H
#include "windows/windows.h" #include "windows/windows.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"
@ -69,16 +69,12 @@ typedef struct
extern void CMWloadWindow(MagWindow *, int); extern void CMWloadWindow(MagWindow *, int);
extern void CMWcommand(MagWindow *, TxCommand *); extern void CMWcommand(MagWindow *, TxCommand *);
extern const Rect colorWindowRect; extern Rect colorWindowRect;
extern WindClient CMWclientID; extern WindClient CMWclientID;
extern const ColorBar colorBars[]; extern ColorBar colorBars[];
extern const ColorPump colorPumps[]; extern ColorPump colorPumps[];
extern const Rect cmwCurrentColorArea; extern Rect cmwCurrentColorArea;
extern void cmwUndoColor(int, int, int, int, int, int, int); extern void cmwUndoColor(int, int, int, int, int, int, int);
extern bool CMWCheckWritten(void); extern bool CMWCheckWritten(void);
/* C99 compat */ #endif /* _CMWIND_H */
extern void CMWinit(void);
#endif /* _MAGIC__CMWIND__CMWIND_H */

View File

@ -17,7 +17,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -50,7 +50,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
* CmdAddPath -- * CmdAddPath --
* *
* Implement the "addpath" command: append to the global cell search path. * Implement the "addpath" command: append to the global cell search path.
* (Usage superseded by extended "path" command; retained for compatibility) * (Usage superceded by extended "path" command; retained for compatibility)
* *
* Usage: * Usage:
* addpath path * addpath path
@ -70,9 +70,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
/*ARGSUSED*/ /*ARGSUSED*/
void void
CmdAddPath( CmdAddPath( w, cmd )
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
if (cmd->tx_argc != 2) { if (cmd->tx_argc != 2) {
TxError("Usage: %s appended_search_path\n", cmd->tx_argv[0]); TxError("Usage: %s appended_search_path\n", cmd->tx_argv[0]);
@ -81,70 +81,6 @@ CmdAddPath(
PaAppend(&Path, cmd->tx_argv[1]); 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 */ /* Linked-list structure for returning information about arrayed cells */
@ -194,11 +130,11 @@ typedef struct LA1
#define ARRAY_DEFAULT 6 #define ARRAY_DEFAULT 6
void void
CmdArray( CmdArray(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
static const char * const cmdArrayOption[] = { static char *cmdArrayOption[] = {
"count [[xlo] xhi [ylo] yhi] array subcells", "count [[xlo] xhi [ylo] yhi] array subcells",
"width [value] set or return array x-spacing", "width [value] set or return array x-spacing",
"height [value] set or return array y-spacing", "height [value] set or return array y-spacing",
@ -208,7 +144,7 @@ CmdArray(
NULL NULL
}; };
const char * const *msg; char **msg;
int option, locargc, argstart; int option, locargc, argstart;
bool doList = FALSE; bool doList = FALSE;
ArrayInfo a; ArrayInfo a;
@ -220,7 +156,7 @@ CmdArray(
Tcl_Obj *tobj; Tcl_Obj *tobj;
#endif #endif
extern int selGetArrayFunc(CellUse *selUse, CellUse *use, Transform *trans, LinkedArray **arg); extern int selGetArrayFunc();
locargc = cmd->tx_argc; locargc = cmd->tx_argc;
argstart = 1; argstart = 1;
@ -338,17 +274,14 @@ CmdArray(
case ARRAY_WIDTH: case ARRAY_WIDTH:
if (locargc == 2) if (locargc == 2)
{ {
char *xsepvalue;
for (la = lahead; la != NULL; la = la->ar_next) for (la = lahead; la != NULL; la = la->ar_next)
{ {
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
if (doList) if (doList)
{ {
tobj = Tcl_NewListObj(0, NULL); tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(xsepvalue, -1)); Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_SetObjResult(magicinterp, tobj); Tcl_SetObjResult(magicinterp, tobj);
} }
else else
@ -358,7 +291,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id); TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name); TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %s\n", xsepvalue); TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
} }
#endif #endif
@ -377,17 +310,14 @@ CmdArray(
case ARRAY_HEIGHT: case ARRAY_HEIGHT:
if (locargc == 2) if (locargc == 2)
{ {
char *ysepvalue;
for (la = lahead; la != NULL; la = la->ar_next) for (la = lahead; la != NULL; la = la->ar_next)
{ {
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
if (doList) if (doList)
{ {
tobj = Tcl_NewListObj(0, NULL); tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(ysepvalue, -1)); Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_SetObjResult(magicinterp, tobj); Tcl_SetObjResult(magicinterp, tobj);
} }
else else
@ -397,7 +327,7 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id); TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name); TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("y separation %s\n", ysepvalue); TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
} }
#endif #endif
@ -416,21 +346,16 @@ CmdArray(
case ARRAY_PITCH: case ARRAY_PITCH:
if (locargc == 2) if (locargc == 2)
{ {
char *xpitch, *ypitch;
for (la = lahead; la != NULL; la = la->ar_next) for (la = lahead; la != NULL; la = la->ar_next)
{ {
xpitch = DBWPrintValue(la->arrayInfo.ar_xsep,
w, TRUE);
ypitch = DBWPrintValue(la->arrayInfo.ar_ysep,
w, FALSE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
if (doList) if (doList)
{ {
tobj = Tcl_NewListObj(0, NULL); tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(xpitch, -1)); Tcl_NewIntObj(la->arrayInfo.ar_xsep));
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(ypitch, -1)); Tcl_NewIntObj(la->arrayInfo.ar_ysep));
Tcl_SetObjResult(magicinterp, tobj); Tcl_SetObjResult(magicinterp, tobj);
} }
else else
@ -440,8 +365,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id); TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name); TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x separation %s ", xpitch); TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
TxPrintf("y separation %s\n", ypitch); TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
} }
#endif #endif
@ -461,21 +386,16 @@ CmdArray(
case ARRAY_POSITION: case ARRAY_POSITION:
if (locargc == 2) if (locargc == 2)
{ {
char *xpos, *ypos;
for (la = lahead; la != NULL; la = la->ar_next) for (la = lahead; la != NULL; la = la->ar_next)
{ {
xpos = DBWPrintValue(la->cellUse->cu_bbox.r_xbot,
w, TRUE);
ypos = DBWPrintValue(la->cellUse->cu_bbox.r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
if (doList) if (doList)
{ {
tobj = Tcl_NewListObj(0, NULL); tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(xpos, -1)); Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
Tcl_ListObjAppendElement(magicinterp, tobj, Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(ypos, -1)); Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
Tcl_SetObjResult(magicinterp, tobj); Tcl_SetObjResult(magicinterp, tobj);
} }
else else
@ -485,8 +405,8 @@ CmdArray(
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id); TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
else else
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name); TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
TxPrintf("x=%s ", xpos); TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
TxPrintf("y=%s\n", ypos); TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
} }
#endif #endif
@ -546,15 +466,11 @@ badusage:
} }
freelist: freelist:
la = lahead;
while (la != NULL)
{ {
la = lahead; freeMagic((char *)la);
while (la != NULL) la = la->ar_next;
{
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, (char *)la);
la = la->ar_next;
freeMagic1_end(&mm1);
}
} }
return; return;
} }
@ -564,11 +480,11 @@ freelist:
*/ */
int int
selGetArrayFunc( selGetArrayFunc(selUse, use, trans, arg)
CellUse *selUse, CellUse *selUse;
CellUse *use, CellUse *use;
Transform *trans, Transform *trans;
LinkedArray **arg) LinkedArray **arg;
{ {
/* Check "use" for array information and pass this to arrayInfo */ /* Check "use" for array information and pass this to arrayInfo */
@ -629,8 +545,6 @@ selGetArrayFunc(
* box size [width height] * box size [width height]
* box position [llx lly] [-edit] * box position [llx lly] [-edit]
* box values [llx lly urx ury] [-edit] * box values [llx lly urx ury] [-edit]
* box remove
* box select
* *
* box <direction> <distance> | cursor * box <direction> <distance> | cursor
* *
@ -666,29 +580,25 @@ selGetArrayFunc(
#define BOX_SIZE 2 #define BOX_SIZE 2
#define BOX_POSITION 3 #define BOX_POSITION 3
#define BOX_VALUES 4 #define BOX_VALUES 4
#define BOX_REMOVE 5 #define BOX_MOVE 5
#define BOX_SELECT 6 #define BOX_GROW 6
#define BOX_MOVE 7 #define BOX_SHRINK 7
#define BOX_GROW 8 #define BOX_CORNER 8
#define BOX_SHRINK 9 #define BOX_EXISTS 9
#define BOX_CORNER 10 #define BOX_HELP 10
#define BOX_EXISTS 11 #define BOX_DEFAULT 11
#define BOX_HELP 12
#define BOX_DEFAULT 13
void void
CmdBox( CmdBox(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
static const char * const cmdBoxOption[] = { static char *cmdBoxOption[] = {
"width [value] set or return box width", "width [value] set or return box width",
"height [value] set or return box height", "height [value] set or return box height",
"size [width height] set or return box size", "size [width height] set or return box size",
"position [llx lly] [-edit] set or return box position", "position [llx lly] [-edit] set or return box position",
"values [llx lly urx ury] [-edit] set or return box coordinates", "values [llx lly urx ury] [-edit] set or return box coordinates",
"remove remove cursor box from display",
"select set box to selection bounding box",
"move <direction> <distance> move box position", "move <direction> <distance> move box position",
"grow <direction> <distance> expand box size", "grow <direction> <distance> expand box size",
"shrink <direction> <distance> shrink box size", "shrink <direction> <distance> shrink box size",
@ -699,7 +609,7 @@ CmdBox(
}; };
CellDef *rootBoxDef; CellDef *rootBoxDef;
Rect rootBox, editbox, savebox, *boxptr; Rect rootBox, editbox, *boxptr;
Point ll; Point ll;
int option, direction, distancex, distancey; int option, direction, distancex, distancey;
int width, height; int width, height;
@ -710,7 +620,7 @@ CmdBox(
bool needBox = TRUE; /* require that box be defined */ bool needBox = TRUE; /* require that box be defined */
bool refEdit = FALSE; /* referenced to edit cell coordinates */ bool refEdit = FALSE; /* referenced to edit cell coordinates */
bool cursorRef = FALSE; /* reference position is the cursor */ bool cursorRef = FALSE; /* reference position is the cursor */
const char * const *msg; char **msg;
argc = cmd->tx_argc; argc = cmd->tx_argc;
if (argc > 7) goto badusage; if (argc > 7) goto badusage;
@ -748,12 +658,6 @@ CmdBox(
windCheckOnlyWindow(&w, DBWclientID); windCheckOnlyWindow(&w, DBWclientID);
if (option == BOX_REMOVE)
{
DBWSetBox((CellDef *)NULL, &GeoNullRect);
return;
}
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
/* Check for the command options which do not require a box */ /* Check for the command options which do not require a box */
/* to be present. */ /* to be present. */
@ -779,8 +683,8 @@ CmdBox(
break; break;
case BOX_EXISTS: case BOX_EXISTS:
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE)); NULL);
#else #else
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False"); TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
#endif #endif
@ -840,7 +744,6 @@ CmdBox(
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
boxptr = (refEdit) ? &editbox : &rootBox; boxptr = (refEdit) ? &editbox : &rootBox;
savebox = *boxptr;
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
/* Parse arguments according to class */ /* Parse arguments according to class */
@ -881,25 +784,15 @@ CmdBox(
ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef); ToolMoveCorner(tcorner, &cmd->tx_p, TRUE, rootBoxDef);
break; 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; return;
} }
else if (DBWUnits != DBW_UNITS_USER) else if (DBWSnapToGrid != DBW_SNAP_USER)
{ {
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE); distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
distancey = distancex; distancey = distancex;
} }
else else
{ {
/* For user units, the distance may be different in the X and Y
* directions for a given value.
*/
switch (direction) switch (direction)
{ {
case GEO_EAST: case GEO_WEST: case GEO_EAST: case GEO_WEST:
@ -927,14 +820,15 @@ CmdBox(
case BOX_WIDTH: case BOX_WIDTH:
if (argc == 2) if (argc == 2)
{ {
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
w, TRUE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1)); char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_xtop - boxptr->r_xbot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
#else #else
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root", TxPrintf("%s box width is %d\n",
boxvalues); (refEdit) ? "Edit" : "Root",
boxptr->r_xtop - boxptr->r_xbot);
#endif #endif
return; return;
} }
@ -946,14 +840,15 @@ CmdBox(
case BOX_HEIGHT: case BOX_HEIGHT:
if (argc == 2) if (argc == 2)
{ {
char *boxvalues;
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1)); char *boxvalues = (char *)Tcl_Alloc(50);
sprintf(boxvalues, "%d",
boxptr->r_ytop - boxptr->r_ybot);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
#else #else
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root", TxPrintf("%s box height is %d\n",
boxvalues); (refEdit) ? "Edit" : "Root",
boxptr->r_ytop - boxptr->r_ybot);
#endif #endif
return; return;
} }
@ -966,24 +861,16 @@ CmdBox(
if (argc == 2) if (argc == 2)
{ {
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_Obj *tobj; char *boxvalues = (char *)Tcl_Alloc(50);
#endif sprintf(boxvalues, "%d %d",
char *boxvaluex, *boxvaluey; boxptr->r_xtop - boxptr->r_xbot,
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot, boxptr->r_ytop - boxptr->r_ybot);
w, TRUE); Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
boxvaluey = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else #else
TxPrintf("%s box size is %s x %s\n", TxPrintf("%s box size is %d x %d\n",
(refEdit) ? "Edit" : "Root", (refEdit) ? "Edit" : "Root",
boxvaluex, boxvaluey); boxptr->r_xtop - boxptr->r_xbot,
boxptr->r_ytop - boxptr->r_ybot);
#endif #endif
return; return;
} }
@ -998,22 +885,14 @@ CmdBox(
if (argc == 2) if (argc == 2)
{ {
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_Obj *tobj; char *boxvalues = (char *)Tcl_Alloc(50);
#endif sprintf(boxvalues, "%d %d",
char *boxvaluex, *boxvaluey; boxptr->r_xbot, boxptr->r_ybot);
boxvaluex = DBWPrintValue(boxptr->r_xbot, w, TRUE); Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
boxvaluey = DBWPrintValue(boxptr->r_ybot, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluex, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluey, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else #else
TxPrintf("%s box lower-left corner at (%s, %s)\n", TxPrintf("%s box lower-left corner at (%d, %d)\n",
(refEdit) ? "Edit" : "Root", (refEdit) ? "Edit" : "Root",
boxvaluex, boxvaluey); boxptr->r_xbot, boxptr->r_ybot);
#endif #endif
return; return;
} }
@ -1028,48 +907,20 @@ CmdBox(
boxptr->r_ytop = boxptr->r_ybot + height; boxptr->r_ytop = boxptr->r_ybot + height;
break; break;
case BOX_SELECT:
if (argc == 2)
{
Rect selarea;
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
boxptr->r_xbot = selarea.r_xbot;
boxptr->r_ybot = selarea.r_ybot;
boxptr->r_xtop = selarea.r_xtop;
boxptr->r_ytop = selarea.r_ytop;
}
else goto badusage;
break;
case BOX_VALUES: case BOX_VALUES:
if (argc == 2) if (argc == 2)
{ {
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_Obj *tobj; char *boxvalues = (char *)Tcl_Alloc(50);
#endif sprintf(boxvalues, "%d %d %d %d",
char *boxvaluellx, *boxvaluelly; boxptr->r_xbot, boxptr->r_ybot,
char *boxvalueurx, *boxvalueury; boxptr->r_xtop, boxptr->r_ytop);
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
boxvaluellx = DBWPrintValue(boxptr->r_xbot, w, TRUE);
boxvaluelly = DBWPrintValue(boxptr->r_ybot, w, FALSE);
boxvalueurx = DBWPrintValue(boxptr->r_xtop, w, TRUE);
boxvalueury = DBWPrintValue(boxptr->r_ytop, w, FALSE);
#ifdef MAGIC_WRAPPER
tobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluellx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvaluelly, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueurx, -1));
Tcl_ListObjAppendElement(magicinterp, tobj,
Tcl_NewStringObj(boxvalueury, -1));
Tcl_SetObjResult(magicinterp, tobj);
#else #else
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n", TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
(refEdit) ? "Edit" : "Root", (refEdit) ? "Edit" : "Root",
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury); boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop);
#endif #endif
return; return;
} }
@ -1242,13 +1093,13 @@ CmdBox(
if (area > 0) if (area > 0)
TxPrintf(" area (units^2)"); TxPrintf(" area (units^2)");
TxPrintf("\n\nmicrons: %6.3f x %-6.3f (% 6.3f, % -6.3f), " TxPrintf("\n\nmicrons: %6.2f x %-6.2f (% 6.2f, % -6.2f), "
"(% 6.3f, % -6.3f)", "(% 6.2f, % -6.2f)",
(float)width *oscale, (float)height * oscale, (float)width *oscale, (float)height * oscale,
(float)boxptr->r_xbot * oscale, (float)boxptr->r_ybot * oscale, (float)boxptr->r_xbot * oscale, (float)boxptr->r_ybot * oscale,
(float)boxptr->r_xtop * oscale, (float)boxptr->r_ytop * oscale); (float)boxptr->r_xtop * oscale, (float)boxptr->r_ytop * oscale);
if (area > 0) if (area > 0)
TxPrintf(" %-10.3f", (float)area * oscale * oscale); TxPrintf(" %-10.2f", (float)area * oscale * oscale);
TxPrintf("\nlambda:"); TxPrintf("\nlambda:");
if (DBLambda[0] != DBLambda[1]) if (DBLambda[0] != DBLambda[1])
@ -1271,7 +1122,7 @@ CmdBox(
boxptr->r_xbot, boxptr->r_ybot, boxptr->r_xbot, boxptr->r_ybot,
boxptr->r_xtop, boxptr->r_ytop); boxptr->r_xtop, boxptr->r_ytop);
if (area > 0) if (area > 0)
TxPrintf(" %-10"DLONG_PREFIX"d", area); TxPrintf(" %-10lld", area);
TxPrintf("\n"); TxPrintf("\n");
break; break;
@ -1291,18 +1142,6 @@ badusage:
if (refEdit) if (refEdit)
GeoTransRect(&EditToRootTransform, &editbox, &rootBox); GeoTransRect(&EditToRootTransform, &editbox, &rootBox);
/*----------------------------------------------------------*/
/* Check for numerical overflow in box values */
/*----------------------------------------------------------*/
if (boxptr->r_ll.p_x < (MINFINITY + 2) || boxptr->r_ll.p_x > (INFINITY - 2) ||
boxptr->r_ll.p_y < (MINFINITY + 2) || boxptr->r_ll.p_y > (INFINITY - 2))
{
*boxptr = savebox;
TxError("Box out of bounds.\n");
return;
}
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
/* Change the position of the box in the layout window */ /* Change the position of the box in the layout window */
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -42,12 +42,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "drc/drc.h" #include "drc/drc.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"
#include "extract/extract.h" #include "extract/extract.h"
#include "extract/extractInt.h"
#include "select/select.h" #include "select/select.h"
/* C99 compat */
#include "dbwind/dbwtech.h"
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -56,12 +52,10 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
* *
* Implement the "edit" command. * Implement the "edit" command.
* Use the cell that is currently selected as the edit cell. If more than * 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. If the * one cell is selected, use the point to choose between them.
* optional argument "<instname>" is provided, then edit the specified
* instance (if it exists in the current layout window).
* *
* Usage: * Usage:
* edit [<instname>] * edit
* *
* Results: * Results:
* None. * None.
@ -79,29 +73,18 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
static bool cmdFoundNewEdit; static bool cmdFoundNewEdit;
void void
CmdEdit( CmdEdit(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
Rect area, pointArea; Rect area, pointArea;
CellUse *usave, *use = NULL; CellUse *usave;
CellDef *csave; CellDef *csave;
int cmdEditRedisplayFunc(MagWindow *w, Rect *area); /* Forward declaration. */ int cmdEditRedisplayFunc(); /* Forward declaration. */
int cmdEditEnumFunc(CellUse *selUse, CellUse *use, Transform *transform, Rect *area); /* Forward declaration. */ int cmdEditEnumFunc(); /* Forward declaration. */
bool noCurrentUse = FALSE; bool noCurrentUse = FALSE;
if ((w != NULL) && (cmd->tx_argc == 2)) if (cmd->tx_argc > 1)
{
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"); TxError("Usage: edit\nMaybe you want the \"load\" command\n");
return; return;
@ -134,18 +117,10 @@ CmdEdit(
cmdFoundNewEdit = FALSE; cmdFoundNewEdit = FALSE;
csave = EditRootDef; csave = EditRootDef;
usave = EditCellUse; usave = EditCellUse;
EditCellUse = NULL;
if (use == NULL) (void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
{ cmdEditEnumFunc, (ClientData) &pointArea);
EditCellUse = NULL;
SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
cmdEditEnumFunc, (ClientData) &pointArea);
}
else
{
EditCellUse = use;
cmdFoundNewEdit = TRUE;
}
if (EditCellUse == (CellUse *)NULL) if (EditCellUse == (CellUse *)NULL)
{ {
@ -155,7 +130,11 @@ CmdEdit(
return; return;
} }
else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE)) else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE))
DBCellRead(EditCellUse->cu_def, TRUE, TRUE, NULL); {
bool dereference = (EditCellUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, dereference, NULL);
}
if (EditCellUse->cu_def->cd_flags & CDNOEDIT) if (EditCellUse->cu_def->cd_flags & CDNOEDIT)
{ {
@ -179,14 +158,6 @@ CmdEdit(
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area); GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
(void) WindSearch(DBWclientID, (ClientData) NULL, (void) WindSearch(DBWclientID, (ClientData) NULL,
(Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area); (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 /* Search function to handle redisplays for CmdEdit: it checks to
@ -197,11 +168,11 @@ CmdEdit(
*/ */
int int
cmdEditRedisplayFunc( cmdEditRedisplayFunc(w, area)
MagWindow *w, /* Window containing edit cell. */ MagWindow *w; /* Window containing edit cell. */
Rect *area) /* Area to be redisplayed. */ Rect *area; /* Area to be redisplayed. */
{ {
static const Rect origin = {{-1, -1}, {1, 1}}; static Rect origin = {-1, -1, 1, 1};
Rect tmp; Rect tmp;
DBWclientRec *crec = (DBWclientRec *) w->w_clientData; DBWclientRec *crec = (DBWclientRec *) w->w_clientData;
@ -226,13 +197,13 @@ cmdEditRedisplayFunc(
*/ */
int int
cmdEditEnumFunc( cmdEditEnumFunc(selUse, use, transform, area)
CellUse *selUse, /* Use from selection (not used). */ CellUse *selUse; /* Use from selection (not used). */
CellUse *use, /* Use from layout that corresponds to CellUse *use; /* Use from layout that corresponds to
* selUse (could be an array!). * selUse (could be an array!).
*/ */
Transform *transform, /* Transform from use->cu_def to root coords. */ Transform *transform; /* Transform from use->cu_def to root coords. */
Rect *area) /* We're looking for a use containing this Rect *area; /* We're looking for a use containing this
* area, in root coords. * area, in root coords.
*/ */
{ {
@ -305,20 +276,20 @@ cmdEditEnumFunc(
#define OPTION_FLAGS 3 #define OPTION_FLAGS 3
void void
CmdElement( CmdElement(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
int option, type; int option, type;
const char * const *msg; char **msg;
Rect area; Rect area;
int style; int style;
CellDef *def; CellDef *def;
CellUse *use; CellUse *use;
bool getopt; bool getopt;
static const char * const cmdElementOption[] = { static char *cmdElementOption[] = {
"add create a new element", "add create a new element",
"delete delete an existing element", "delete delete an existing element",
"configure configure or query an existing element", "configure configure or query an existing element",
@ -328,14 +299,14 @@ CmdElement(
NULL NULL
}; };
static const char * const cmdElementType[] = { static char *cmdElementType[] = {
"line name style x1 y1 x2 y2", "line name style x1 y1 x2 y2",
"rectangle name style llx lly urx ury", "rectangle name style llx lly urx ury",
"text name style cx cy label", "text name style cx cy label",
NULL NULL
}; };
static const char * const cmdConfigureType[] = { static char *cmdConfigureType[] = {
"text get (or) replace <string>", "text get (or) replace <string>",
"style get (or) add <style> (or) remove <style>", "style get (or) add <style> (or) remove <style>",
"position get (or) <point> (or) <rect>", "position get (or) <point> (or) <rect>",
@ -390,8 +361,10 @@ CmdElement(
return; return;
} }
} }
area.r_xbot = cmdParseCoord(w, cmd->tx_argv[5], FALSE, TRUE); if (!StrIsInt(cmd->tx_argv[5])) goto badusage;
area.r_ybot = cmdParseCoord(w, cmd->tx_argv[6], FALSE, FALSE); area.r_xbot = atoi(cmd->tx_argv[5]);
if (!StrIsInt(cmd->tx_argv[6])) goto badusage;
area.r_ybot = atoi(cmd->tx_argv[6]);
switch (type) switch (type)
{ {
@ -402,8 +375,10 @@ CmdElement(
cmdElementType[ELEMENT_LINE]); cmdElementType[ELEMENT_LINE]);
return; return;
} }
area.r_xtop = cmdParseCoord(w, cmd->tx_argv[7], FALSE, TRUE); if (!StrIsInt(cmd->tx_argv[7])) goto badusage;
area.r_ytop = cmdParseCoord(w, cmd->tx_argv[8], FALSE, FALSE); area.r_xtop = atoi(cmd->tx_argv[7]);
if (!StrIsInt(cmd->tx_argv[8])) goto badusage;
area.r_ytop = atoi(cmd->tx_argv[8]);
DBWElementAddLine(w, cmd->tx_argv[3], &area, def, style); DBWElementAddLine(w, cmd->tx_argv[3], &area, def, style);
break; break;
case ELEMENT_RECT: case ELEMENT_RECT:
@ -413,8 +388,10 @@ CmdElement(
cmdElementType[ELEMENT_RECT]); cmdElementType[ELEMENT_RECT]);
return; return;
} }
area.r_xtop = cmdParseCoord(w, cmd->tx_argv[7], FALSE, TRUE); if (!StrIsInt(cmd->tx_argv[7])) goto badusage;
area.r_ytop = cmdParseCoord(w, cmd->tx_argv[8], FALSE, FALSE); area.r_xtop = atoi(cmd->tx_argv[7]);
if (!StrIsInt(cmd->tx_argv[8])) goto badusage;
area.r_ytop = atoi(cmd->tx_argv[8]);
DBWElementAddRect(w, cmd->tx_argv[3], &area, def, style); DBWElementAddRect(w, cmd->tx_argv[3], &area, def, style);
break; break;
case ELEMENT_TEXT: case ELEMENT_TEXT:
@ -528,19 +505,21 @@ CmdElement(
if (cmd->tx_argc >= 6) if (cmd->tx_argc >= 6)
{ {
crect.r_xbot = cmdParseCoord(w, cmd->tx_argv[4], if (!StrIsInt(cmd->tx_argv[4]) ||
FALSE, TRUE); !StrIsInt(cmd->tx_argv[5]))
crect.r_ybot = cmdParseCoord(w, cmd->tx_argv[5], goto badrect;
FALSE, FALSE); crect.r_xbot = atoi(cmd->tx_argv[4]);
crect.r_ybot = atoi(cmd->tx_argv[5]);
crect.r_xtop = crect.r_xbot; /* placeholder */ crect.r_xtop = crect.r_xbot; /* placeholder */
crect.r_ytop = crect.r_ybot; /* placeholder */ crect.r_ytop = crect.r_ybot; /* placeholder */
} }
if (cmd->tx_argc == 8) if (cmd->tx_argc == 8)
{ {
crect.r_xtop = cmdParseCoord(w, cmd->tx_argv[6], if (!StrIsInt(cmd->tx_argv[6]) ||
FALSE, TRUE); !StrIsInt(cmd->tx_argv[7]))
crect.r_ytop = cmdParseCoord(w, cmd->tx_argv[7], goto badrect;
FALSE, FALSE); crect.r_xtop = atoi(cmd->tx_argv[6]);
crect.r_ytop = atoi(cmd->tx_argv[7]);
} }
if (cmd->tx_argc == 6 || cmd->tx_argc == 8) if (cmd->tx_argc == 6 || cmd->tx_argc == 8)
@ -606,7 +585,7 @@ badusage:
* EditCellUse->cu_def. * EditCellUse->cu_def.
* *
* Usage: * Usage:
* erase [layers | cursor | pick x y] * erase [layers | cursor]
* *
* Results: * Results:
* None. * None.
@ -627,39 +606,24 @@ static CellUse *cmdEraseCells[MAXCELLS];
static int cmdEraseCount; static int cmdEraseCount;
void void
CmdErase( CmdErase(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
Rect editRect, areaReturn; Rect editRect, areaReturn;
TileTypeBitMask mask, errorLayersForErasure, activeLayersForErasure; TileTypeBitMask mask, errorLayersForErasure, activeLayersForErasure;
extern int cmdEraseCellsFunc(SearchContext *scx, ClientData cdarg); extern int cmdEraseCellsFunc();
windCheckOnlyWindow(&w, DBWclientID); windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL) return; 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) if (cmd->tx_argc > 2)
{ {
TxError("Usage: %s [<layers> | cursor | pick x y]\n", cmd->tx_argv[0]); TxError("Usage: %s [<layers> | cursor]\n", cmd->tx_argv[0]);
return; return;
} }
if (!ToolGetEditBox(&editRect)) return; if (!ToolGetEditBox(&editRect)) return;
if (EditCellUse == NULL)
{
TxError("No cell def being edited!\n");
return;
}
/* /*
* Erase with no arguments is the same as erasing * Erase with no arguments is the same as erasing
@ -671,16 +635,7 @@ CmdErase(
(void) CmdParseLayers("*,label", &mask); (void) CmdParseLayers("*,label", &mask);
else if (!strncmp(cmd->tx_argv[1], "cursor", 6)) else if (!strncmp(cmd->tx_argv[1], "cursor", 6))
{ {
Point editPoint, rootPoint; CmdPaintEraseButton(w, &cmd->tx_p, FALSE);
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; return;
} }
else if (!CmdParseLayers(cmd->tx_argv[1], &mask)) else if (!CmdParseLayers(cmd->tx_argv[1], &mask))
@ -759,9 +714,9 @@ CmdErase(
} }
int int
cmdEraseCellsFunc( cmdEraseCellsFunc(scx, cdarg)
SearchContext *scx, /* Indicates cell found. */ SearchContext *scx; /* Indicates cell found. */
ClientData cdarg) /* Not used. */ ClientData cdarg; /* Not used. */
{ {
/* All this procedure does is to remember cells that are /* All this procedure does is to remember cells that are
* found, up to MAXCELLS of them. * found, up to MAXCELLS of them.
@ -781,82 +736,39 @@ cmdEraseCellsFunc(
* Implement the "expand" command. * Implement the "expand" command.
* *
* Usage: * Usage:
* expand [selection|surround|overlap|all] [toggle] * expand
* * expand toggle
* "selection" expands cells in the selection. All other options
* expand cells in the layout. "all" expands all cells in the
* layout. "surround" expands cells which the cursor box
* surrounds completely, and "overlap" expands cells which the
* cursor box overlaps.
*
* If "toggle" is specified, flips the expanded/unexpanded status.
* Cells which were expanded are unexpanded, and cells which were
* unexpanded are expanded.
*
* For backwards compatibility:
* "expand" alone implements "expand overlap".
* "expand toggle" implements "expand selection toggle".
*
* Also see: CmdUnexpand
* *
* Results: * Results:
* None. * None.
* *
* Side effects: * Side effects:
* Expansion state of cells is changed. May read cells in from * If "toggle" is specified, flips the expanded/unexpanded status
* disk, and update bounding boxes that have changed. * of all selected cells. Otherwise, aren't any unexpanded cells
* left under the box. May read cells in from disk, and updates
* bounding boxes that have changed.
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#define EXPAND_SELECTION 0
#define EXPAND_SURROUND 1
#define EXPAND_OVERLAP 2
#define EXPAND_ALL 3
#define EXPAND_HELP 4
void void
CmdExpand( CmdExpand(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
int windowMask, boxMask, d, option; int windowMask, boxMask, d;
bool doToggle = FALSE;
const char * const *msg;
Rect rootRect; Rect rootRect;
CellUse *rootBoxUse; CellUse *rootBoxUse;
CellDef *rootBoxDef; 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)))
static const char * const cmdExpandOption[] = {
"selection expand cell instances in the selection",
"surround expand cell instances which the cursor box surrounds",
"overlap expand cell instances which the cursor box overlaps",
"all expand all cell instances",
NULL
};
if (cmd->tx_argc > 1)
{ {
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle", TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
strlen(cmd->tx_argv[cmd->tx_argc - 1]))) return;
{
doToggle = TRUE;
cmd->tx_argc--;
}
} }
if (cmd->tx_argc > 1)
{
option = Lookup(cmd->tx_argv[1], cmdExpandOption);
if (option < 0) option = EXPAND_HELP;
}
else
option = EXPAND_OVERLAP;
if (option == EXPAND_HELP) goto badusage;
windCheckOnlyWindow(&w, DBWclientID); windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL) if (w == (MagWindow *) NULL)
{ {
@ -887,95 +799,23 @@ CmdExpand(
WindScale(d, 1); WindScale(d, 1);
TxPrintf("expand: rescaled by %d\n", d); TxPrintf("expand: rescaled by %d\n", d);
d = DBLambda[1]; d = DBLambda[1];
if (doToggle) break; /* Don't toggle twice */ if (cmd->tx_argc == 2) break; /* Don't toggle twice */
} }
(void) ToolGetBoxWindow(&rootRect, &boxMask); (void) ToolGetBoxWindow(&rootRect, &boxMask);
if (option != EXPAND_SELECTION) if (cmd->tx_argc == 2)
SelectExpand(windowMask);
else
{ {
if ((boxMask & windowMask) != windowMask) if ((boxMask & windowMask) != windowMask)
{ {
TxError("The box isn't in the same window as the cursor.\n"); TxError("The box isn't in the same window as the cursor.\n");
return; return;
} }
} DBExpandAll(rootBoxUse, &rootRect, windowMask,
TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
switch (option)
{
case EXPAND_SELECTION:
SelectExpand(windowMask,
(doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND,
(Rect *)NULL);
break;
case EXPAND_OVERLAP:
if (doToggle)
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
&rootRect);
}
else
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
&rootRect);
}
break;
case EXPAND_SURROUND:
if (doToggle)
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
&rootRect);
}
else
{
DBExpandAll(rootBoxUse, &rootRect, windowMask,
DB_EXPAND | DB_EXPAND_SURROUND,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_SURROUND,
&rootRect);
}
break;
case EXPAND_ALL:
if (doToggle)
{
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
(Rect *)NULL);
}
else
{
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
cmdExpandFunc, (ClientData)(pointertype)windowMask);
SelectExpand(windowMask,
DB_EXPAND | DB_EXPAND_OVERLAP,
(Rect *)NULL);
}
break;
} }
} while (d != DBLambda[1]); } while (d != DBLambda[1]);
return;
badusage:
for (msg = &(cmdExpandOption[0]); *msg != NULL; msg++)
TxPrintf(" %s\n", *msg);
TxPrintf(" toggle Toggle the visibility of cell instances.\n");
} }
/* This function is called for each cell whose expansion status changed. /* This function is called for each cell whose expansion status changed.
@ -984,9 +824,9 @@ badusage:
*/ */
int int
cmdExpandFunc( cmdExpandFunc(use, windowMask)
CellUse *use, /* Use that was just expanded. */ CellUse *use; /* Use that was just expanded. */
int windowMask) /* Window where it was expanded. */ int windowMask; /* Window where it was expanded. */
{ {
if (use->cu_parent == NULL) return 0; if (use->cu_parent == NULL) return 0;
DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask, DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask,
@ -1019,17 +859,14 @@ cmdExpandFunc(
#define EXTALL 0 #define EXTALL 0
#define EXTCELL 1 #define EXTCELL 1
#define EXTDO 2 #define EXTDO 2
#define EXTHALO 3 #define EXTHELP 3
#define EXTHELP 4 #define EXTLENGTH 4
#define EXTLENGTH 5 #define EXTNO 5
#define EXTNO 6 #define EXTPARENTS 6
#define EXTPARENTS 7 #define EXTSHOWPARENTS 7
#define EXTPATH 8 #define EXTSTYLE 8
#define EXTSHOWPARENTS 9 #define EXTUNIQUE 9
#define EXTSTEPSIZE 10 #define EXTWARN 10
#define EXTSTYLE 11
#define EXTUNIQUE 12
#define EXTWARN 13
#define WARNALL 0 #define WARNALL 0
#define WARNDUP 1 #define WARNDUP 1
@ -1040,14 +877,9 @@ cmdExpandFunc(
#define DOALL 1 #define DOALL 1
#define DOCAPACITANCE 2 #define DOCAPACITANCE 2
#define DOCOUPLING 3 #define DOCOUPLING 3
#define DOEXTRESIST 4 #define DOLENGTH 4
#define DOLENGTH 5 #define DOLOCAL 5
#define DOLOCAL 6 #define DORESISTANCE 6
#define DORESISTANCE 7
#define DOLABELCHECK 8
#define DOALIASES 9
#define DOUNIQUE 10
#define DOEXTRESIST2 11
#define LENCLEAR 0 #define LENCLEAR 0
#define LENDRIVER 1 #define LENDRIVER 1
@ -1056,17 +888,14 @@ cmdExpandFunc(
#define UNIQALL 0 #define UNIQALL 0
#define UNIQTAGGED 1 #define UNIQTAGGED 1
#define UNIQNOPORTS 2 #define UNIQNOPORTS 2
#define UNIQNOTOPPORTS 3
void void
CmdExtract( CmdExtract(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
const char * const *msg; char **msg, *namep, *arg;
char *namep, *arg;
int option, warn, len, n, all; int option, warn, len, n, all;
int dist;
bool no; bool no;
CellUse *selectedUse; CellUse *selectedUse;
CellDef *selectedDef; CellDef *selectedDef;
@ -1076,7 +905,7 @@ CmdExtract(
int argc = cmd->tx_argc; int argc = cmd->tx_argc;
char **argv = cmd->tx_argv; char **argv = cmd->tx_argv;
static const char * const cmdExtWarn[] = static char *cmdExtWarn[] =
{ {
"all enable all warnings", "all enable all warnings",
"dup warn when different nodes have the same name", "dup warn when different nodes have the same name",
@ -1084,57 +913,45 @@ CmdExtract(
"labels warn when subcell nodes are unlabelled", "labels warn when subcell nodes are unlabelled",
NULL NULL
}; };
static const char * const cmdExtOption[] = static char *cmdExtOption[] =
{ {
"adjust compensate R and C hierarchically", "adjust compensate R and C hierarchically",
"all all options", "all all options",
"capacitance extract substrate capacitance", "capacitance extract substrate capacitance",
"coupling extract coupling capacitance", "coupling extract coupling capacitance",
"extresist extract resistance",
"length compute driver-receiver pathlengths", "length compute driver-receiver pathlengths",
"local put all generated files in the current directory", "local put all generated files in the current directory",
"lumped estimate lumped resistance", "resistance estimate resistance",
"labelcheck check for connections through sticky labels",
"aliases output all net name aliases",
"unique [notopports] ensure unique node names during extraction",
"resistance extract resistance (same as \"do extresist\")",
NULL NULL
}; };
static const char * const cmdExtLength[] = static char *cmdExtLength[] =
{ {
"clear clear the driver and receiver tables", "clear clear the driver and receiver tables",
"driver termName(s) identify a driving (output) terminal", "driver termName(s) identify a driving (output) terminal",
"receiver termName(s) identify a receiving (input) terminal", "receiver termName(s) identify a receiving (input) terminal",
NULL NULL
}; };
static char *cmdExtUniq[] =
/* These must match definitions EXT_UNIQ_* in extract/extract.h: */
static const char * const cmdExtUniq[] =
{ {
"all extract matching labels as unique nodes", "all extract matching labels as unique nodes",
"# extract tagged labels as unique nodes", "# extract tagged labels as unique nodes",
"noports ignore ports when making labels unique", "noports ignore ports when making labels unique",
"notopports ignore top-level ports when making labels unique",
NULL NULL
}; };
static const char * const cmdExtCmd[] = static char *cmdExtCmd[] =
{ {
"all extract root cell and all its children", "all extract root cell and all its children",
"cell name extract selected cell into file \"name\"", "cell name extract selected cell into file \"name\"",
"do [option] enable extractor option", "do [option] enable extractor option",
"halo [value] print or set the sidewall halo distance",
"help print this help information", "help print this help information",
"length [option] control pathlength extraction information", "length [option] control pathlength extraction information",
"no [option] disable extractor option", "no [option] disable extractor option",
"parents extract selected cell and all its parents", "parents extract selected cell and all its parents",
"path [path] if set, extract into the indicated path",
"showparents show all parents of selected cell", "showparents show all parents of selected cell",
"stepsize [value] print or set the extraction step size",
"style [stylename] set current extraction parameter style", "style [stylename] set current extraction parameter style",
"unique [option] generate unique names when different nodes\n\ "unique [option] generate unique names when different nodes\n\
have the same name", have the same name",
"warn [ [no] option] enable/disable reporting of non-serious errors", "warn [ [no] option] enable/disable reporting of non-fatal errors",
NULL NULL
}; };
@ -1181,10 +998,7 @@ CmdExtract(
if (argc == 1) if (argc == 1)
{ {
if (!strcmp(selectedUse->cu_def->cd_name, UNNAMED)) ExtIncremental(selectedUse);
TxError("Please name the cell before extracting.\n");
else
ExtIncremental(selectedUse);
return; return;
} }
} }
@ -1215,10 +1029,7 @@ CmdExtract(
break; break;
case EXTALL: case EXTALL:
if (!strcmp(selectedUse->cu_def->cd_name, UNNAMED)) ExtAll(selectedUse);
TxError("Please name the cell before extracting.\n");
else
ExtAll(selectedUse);
return; return;
case EXTCELL: case EXTCELL:
@ -1230,70 +1041,9 @@ CmdExtract(
TxError("No cell selected\n"); TxError("No cell selected\n");
return; return;
} }
ExtractOneCell(selectedUse->cu_def, namep, FALSE); ExtCell(selectedUse->cu_def, namep, FALSE);
return; return;
case EXTHALO:
if (ExtCurStyle == NULL)
{
TxError("No extraction style set.\n");
return;
}
else if (argc == 2)
{
char *halodisp;
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
#else
TxPrintf("Side overlap halo is %s\n", halodisp);
#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)
{
char *stepdisp;
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
#else
TxPrintf("Extraction step size is %s\n", stepdisp);
#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: case EXTPARENTS:
selectedUse = CmdGetSelectedCell((Transform *) NULL); selectedUse = CmdGetSelectedCell((Transform *) NULL);
if (selectedUse == NULL) if (selectedUse == NULL)
@ -1301,10 +1051,7 @@ CmdExtract(
TxError("No cell selected\n"); TxError("No cell selected\n");
return; return;
} }
if (!strcmp(selectedUse->cu_def->cd_name, UNNAMED)) ExtParents(selectedUse);
TxError("Please name the cell before extracting.\n");
else
ExtParents(selectedUse);
return; return;
case EXTSHOWPARENTS: case EXTSHOWPARENTS:
@ -1317,13 +1064,6 @@ CmdExtract(
ExtShowParents(selectedUse); ExtShowParents(selectedUse);
return; return;
case EXTPATH:
if (argc == 2)
ExtPrintPath(dolist);
else
ExtSetPath(argv[2]);
return;
case EXTSTYLE: case EXTSTYLE:
if (argc == 2) if (argc == 2)
ExtPrintStyle(dolist, doforall, !doforall); ExtPrintStyle(dolist, doforall, !doforall);
@ -1399,12 +1139,8 @@ CmdExtract(
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE)); TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING)); TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH)); TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
TxPrintf("%s lumped R\n", OPTSET(EXT_DORESISTANCE)); TxPrintf("%s local\n", OPTSET(EXT_DOLOCAL));
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK)); TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
TxPrintf("%s unique notopports\n", OPTSET(EXT_DOUNIQNOTOPPORTS));
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
return; return;
#undef OPTSET #undef OPTSET
} }
@ -1431,32 +1167,8 @@ CmdExtract(
case DOCAPACITANCE: option = EXT_DOCAPACITANCE; break; case DOCAPACITANCE: option = EXT_DOCAPACITANCE; break;
case DOCOUPLING: option = EXT_DOCOUPLING; break; case DOCOUPLING: option = EXT_DOCOUPLING; break;
case DOLENGTH: option = EXT_DOLENGTH; break; case DOLENGTH: option = EXT_DOLENGTH; break;
case DOLOCAL: option = EXT_DOLOCAL; break;
case DORESISTANCE: option = EXT_DORESISTANCE; break; case DORESISTANCE: option = EXT_DORESISTANCE; break;
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
case DOALIASES: option = EXT_DOALIASES; break;
case DOEXTRESIST:
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
case DOUNIQUE:
if (argc == 4)
{
if (!strncmp(argv[3], "notop", 5))
option = EXT_DOUNIQNOTOPPORTS | EXT_DOUNIQUE;
else
TxError("Usage: extract do unique [notopports]\n");
}
else
option = EXT_DOUNIQUE;
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; if (no) ExtOptions &= ~option;
else ExtOptions |= option; else ExtOptions |= option;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
@ -52,9 +52,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
/* Forward declarations */ /* Forward declarations */
extern char *cmdCheckNewName(CellDef *def, char *newName, bool tryRename, bool noninteractive); extern char *cmdCheckNewName();
extern int cmdSaveWindSet(MagWindow *window, CellDef *def); extern int cmdSaveWindSet();
extern void CmdSetWindCaption(CellUse *newEditUse, CellDef *rootDef); extern void CmdSetWindCaption();
TileTypeBitMask CmdYMLabel; TileTypeBitMask CmdYMLabel;
TileTypeBitMask CmdYMCell; TileTypeBitMask CmdYMCell;
@ -73,22 +73,9 @@ TileTypeBitMask CmdYMAllButSpace;
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric * lambda, a suffix of "g" indicates the user grid, and a suffix in metric
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid * notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um. * units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
* Traditional (backwards-compatible) behavior: Units without any suffix * Units without any suffix are assumed to be in lambda if "snap"
* are assumed to be in lambda if "snap" (DBWSnapToGrid) is set to lambda, * (DBWSnapToGrid) is set to lambda, grid units if "snap" is set to the
* grid units if "snap" is set to the user grid, and internal units otherwise. * user grid, and internal units otherwise.
* Current behavior: Use of the "units" command to set the units to
* any value other than "default" causes cmdScaleCoord() to parse any
* units provided without an identifying suffix as the units indicted by
* the "units" command. Once the "units" command has been issued, the
* values are dependent on DBWUnits and not on DBWSnapToGrid.
*
* Additional behavior from magic version 8.3.596: A single command
* option can use simple expressions using '+', '-', '*', and '/'. These
* can be passed as a single token, without spaces, or within a string
* token deliniated by quotes or braces, per usual Tcl syntax. Unlike
* the Tcl "expr" command, this can solve arithmetic expressions of
* suffixed values, evaluated independently such that different suffixes
* may be used (e.g., "1g + 3um" meaning 1 grid pitch plus 3 microns).
* *
* MagWindow argument w is used only with grid-based snapping, to find * MagWindow argument w is used only with grid-based snapping, to find
* the value of the grid for the given window. In this case, because the * the value of the grid for the given window. In this case, because the
@ -112,212 +99,110 @@ TileTypeBitMask CmdYMAllButSpace;
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#define PARSEOP_NONE 0
#define PARSEOP_ADD 1
#define PARSEOP_SUB 2
#define PARSEOP_MUL 3
#define PARSEOP_DIV 4
#define PARSEOP_END 5
int int
cmdScaleCoord( cmdScaleCoord(w, arg, is_relative, is_x, scale)
MagWindow *w, MagWindow *w;
char *arg, char *arg;
bool is_relative, bool is_relative, is_x;
bool is_x, int scale;
int scale)
{ {
char *endptr; char *endptr;
double dval = 0; double dval = 0;
int mscale = 1, curunits; int mscale = 1;
int retval, curval, parseop;
DBWclientRec *crec; DBWclientRec *crec;
if (*arg == '{' || *arg == '"') arg++; if (*arg == '{') arg++;
while (isspace(*arg) && (*arg != '\0')) arg++; while (isspace(*arg)) arg++;
parseop = PARSEOP_NONE; dval = strtod(arg, &endptr);
retval = 0; dval *= (double)scale;
while (*arg != '\0')
if (endptr == arg)
{ {
dval = strtod(arg, &endptr); /* strtod() error condition */
dval *= (double)scale; TxError("Coordinate value cannot be parsed: assuming 0\n");
mscale = -1; return 0;
}
if (endptr == arg) else if ((*endptr == 'l')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
{
/* lambda or default units */
dval *= (double)DBLambda[1];
dval /= (double)DBLambda[0];
return round(dval);
}
else if ((*endptr == 'i')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
{
/* internal units */
return round(dval);
}
else if ((*endptr == 'g')
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
{
/* grid units */
if (w == (MagWindow *)NULL)
{ {
/* strtod() error condition */ windCheckOnlyWindow(&w, DBWclientID);
TxError("Coordinate value cannot be parsed: assuming 0\n");
curval = 0;
break;
}
/* Original behavior was to accept un-suffixed values according to the
* "snap" setting. This behavior remains in effect until the "units"
* command is used, in which case units follow the selected units
* value indepedendently of the snap setting.
*
* Updated 12/24/2026 to handle space-separated values (in which
* *endptr may be a space as well as NULL).
*/
if (DBWUnits == DBW_UNITS_DEFAULT)
curunits = DBWSnapToGrid;
else
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
if ((*endptr == 'l')
|| (((*endptr == '\0') || isspace(*endptr))
&& (curunits == DBW_UNITS_LAMBDA)))
{
/* lambda or default units */
dval *= (double)DBLambda[1];
dval /= (double)DBLambda[0];
}
else if ((*endptr == 'i')
|| (((*endptr == '\0') || isspace(*endptr))
&& (curunits == DBW_UNITS_INTERNAL)))
{
/* internal units */
}
else if ((*endptr == 'g')
|| (((*endptr == '\0') || isspace(*endptr))
&& (curunits == DBW_UNITS_USER)))
{
/* grid units */
if (w == (MagWindow *)NULL) if (w == (MagWindow *)NULL)
{ return round(dval); /* Default, if window is unknown */
windCheckOnlyWindow(&w, DBWclientID); }
if (w == (MagWindow *)NULL) crec = (DBWclientRec *) w->w_clientData;
{ if (is_x)
curval = round(dval); /* Default, if window is unknown */ {
break; dval *= (double)(crec->dbw_gridRect.r_xtop
}
}
crec = (DBWclientRec *) w->w_clientData;
if (is_x)
{
dval *= (double)(crec->dbw_gridRect.r_xtop
- crec->dbw_gridRect.r_xbot); - crec->dbw_gridRect.r_xbot);
if (!is_relative) if (!is_relative)
dval += (double)crec->dbw_gridRect.r_xbot; dval += (double)crec->dbw_gridRect.r_xbot;
} }
else else
{ {
dval *= (double)(crec->dbw_gridRect.r_ytop dval *= (double)(crec->dbw_gridRect.r_ytop
- crec->dbw_gridRect.r_ybot); - crec->dbw_gridRect.r_ybot);
if (!is_relative) if (!is_relative)
dval += (double)crec->dbw_gridRect.r_ybot; dval += (double)crec->dbw_gridRect.r_ybot;
}
} }
else if (((*endptr == '\0') || isspace(*endptr)) return round(dval);
&& (curunits == DBW_UNITS_MICRONS)) }
{ else
mscale = 1000; {
} /* natural units referred to the current cifoutput style */
else if (*endptr != '\0') if (*(endptr + 1) == 'm')
{
/* natural units referred to the current cifoutput style */
if (*(endptr + 1) == 'm')
{
switch (*endptr)
{
case 'n':
mscale = 1;
break;
case 'u':
mscale = 1000;
break;
case 'm':
mscale = 1000000;
break;
case 'c':
mscale = 10000000;
break;
default:
TxError("Unknown metric prefix \"%cm\"; assuming "
"internal units\n", *endptr);
mscale = -1;
}
}
else if ((*endptr == 'u') && !isalnum(*(endptr + 1)))
/* Maybe "u" is too ambiguous but it is very commonly used as
* an abbreviation for "micron".
*/
mscale = 1000;
else if (!strncmp(endptr, "micron", 6))
mscale = 1000;
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
mscale = 10;
else if (!isspace(*endptr) && (*endptr != '+') && (*endptr != '-') &&
(*endptr != '*') && (*endptr != '/'))
{
TxError("Unknown coordinate type at \"%s\"; assuming internal units\n",
endptr);
mscale = -1;
}
}
if (mscale != -1)
dval /= CIFGetOutputScale(mscale);
curval = round(dval);
switch (parseop)
{
case PARSEOP_NONE:
retval = curval;
break;
case PARSEOP_ADD:
retval += curval;
break;
case PARSEOP_SUB:
retval -= curval;
break;
case PARSEOP_MUL:
retval *= curval;
break;
case PARSEOP_DIV:
retval /= curval;
break;
}
parseop = PARSEOP_NONE;
while (*endptr != '\0')
{ {
switch (*endptr) switch (*endptr)
{ {
case '}': case 'n':
case '"': mscale = 1;
parseop = PARSEOP_END;
break; break;
case '+': case 'u':
parseop = PARSEOP_ADD; mscale = 1000;
endptr++;
break; break;
case '-': case 'm':
parseop = PARSEOP_SUB; mscale = 1000000;
endptr++;
break; break;
case '*': case 'c':
parseop = PARSEOP_MUL; mscale = 10000000;
endptr++;
break;
case '/':
parseop = PARSEOP_DIV;
endptr++;
break;
case ' ':
case '\t':
endptr++;
break; break;
default: default:
/* Should this flag an error? */ TxError("Unknown metric prefix \"%cm\"; assuming internal units\n",
return retval; *endptr);
return round(dval);
} }
if (parseop != PARSEOP_NONE) break;
} }
arg = endptr; else if (!strncmp(endptr, "micron", 6))
while (isspace(*arg) && (*arg != '\0')) arg++; mscale = 1000;
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
mscale = 10;
else if (!isspace(*endptr))
{
TxError("Unknown coordinate type \"%s\"; assuming internal units\n",
endptr);
return round(dval);
}
} }
return retval; dval /= CIFGetOutputScale(mscale);
return round(dval);
} }
/* /*
@ -339,11 +224,10 @@ cmdScaleCoord(
*/ */
int int
cmdParseCoord( cmdParseCoord(w, arg, is_relative, is_x)
MagWindow *w, MagWindow *w;
char *arg, char *arg;
bool is_relative, bool is_relative, is_x;
bool is_x)
{ {
return cmdScaleCoord(w, arg, is_relative, is_x, 1); return cmdScaleCoord(w, arg, is_relative, is_x, 1);
} }
@ -367,7 +251,7 @@ cmdParseCoord(
*/ */
void void
CmdInit(void) CmdInit()
{ {
TTMaskZero(&CmdYMLabel); TTMaskZero(&CmdYMLabel);
TTMaskSetType(&CmdYMLabel, L_LABEL); TTMaskSetType(&CmdYMLabel, L_LABEL);
@ -401,13 +285,11 @@ CmdInit(void)
*/ */
void void
cmdFlushCell( cmdFlushCell(def)
CellDef *def, CellDef *def;
bool force_deref)
{ {
CellUse *parentUse; CellUse *parentUse;
bool dereference;
if (def == NULL) return;
/* Disallow flushing a cell that contains the edit cell as a child */ /* Disallow flushing a cell that contains the edit cell as a child */
if (EditCellUse && (EditCellUse->cu_parent == def)) if (EditCellUse && (EditCellUse->cu_parent == def))
@ -418,15 +300,6 @@ cmdFlushCell(
} }
UndoFlush(); UndoFlush();
if (force_deref)
{
/* Force dereferencing */
def->cd_flags |= CDDEREFERENCE;
freeMagic(def->cd_file);
def->cd_file = NULL;
}
DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS, DBWAreaChanged(def, &def->cd_bbox, DBW_ALLWINDOWS,
(TileTypeBitMask *) NULL); (TileTypeBitMask *) NULL);
for (parentUse = def->cd_parents; parentUse != NULL; for (parentUse = def->cd_parents; parentUse != NULL;
@ -438,7 +311,8 @@ cmdFlushCell(
} }
DBCellClearDef(def); DBCellClearDef(def);
DBCellClearAvail(def); DBCellClearAvail(def);
(void) DBCellRead(def, TRUE, TRUE, NULL); dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
DBCellSetAvail(def); DBCellSetAvail(def);
DBReComputeBbox(def); DBReComputeBbox(def);
DBCellSetModified(def, FALSE); DBCellSetModified(def, FALSE);
@ -483,9 +357,9 @@ cmdFlushCell(
*/ */
bool bool
CmdParseLayers( CmdParseLayers(s, mask)
char *s, char *s;
TileTypeBitMask *mask) TileTypeBitMask *mask;
{ {
TileTypeBitMask newmask, tempmask; TileTypeBitMask newmask, tempmask;
char *dp, c; char *dp, c;
@ -504,23 +378,23 @@ CmdParseLayers(
#define LN_CONNECT 5 #define LN_CONNECT 5
static struct static struct
{ {
const char *layer_name; char *layer_name;
int layer_value; int layer_value;
} }
const special[] = special[] =
{ {
{"$", LN_DOLLAR}, "$", LN_DOLLAR,
{"*", LN_ALL}, "*", LN_ALL,
{"errors", LN_ERRORS}, "errors", LN_ERRORS,
{"labels", LN_LABELS}, "labels", LN_LABELS,
{"subcell", LN_CELL}, "subcell", LN_CELL,
{"connect", LN_CONNECT}, "connect", LN_CONNECT,
{0}, 0,
}; };
TTMaskZero(mask); TTMaskZero(mask);
while ((c = *s++)) while (c = *s++)
{ {
switch (c) switch (c)
{ {
@ -547,7 +421,7 @@ CmdParseLayers(
type = DBTechNameTypes(name, &newmask); type = DBTechNameTypes(name, &newmask);
if (type == -2) if (type == -2)
{ {
which = LookupStruct(name, (const LookupTable *) special, sizeof special[0]); which = LookupStruct(name, (LookupTable *) special, sizeof special[0]);
if (which >= 0) if (which >= 0)
{ {
switch (special[which].layer_value) switch (special[which].layer_value)
@ -657,8 +531,8 @@ printTypes:
*/ */
TileType TileType
cmdMaskToType( cmdMaskToType(mask)
TileTypeBitMask *mask) TileTypeBitMask *mask;
{ {
TileType type, t; TileType type, t;
@ -703,16 +577,16 @@ cmdMaskToType(
*/ */
void void
cmdSaveCell( cmdSaveCell(cellDef, newName, noninteractive, tryRename)
CellDef *cellDef, /* Pointer to def of cell to be saved */ CellDef *cellDef; /* Pointer to def of cell to be saved */
char *newName, /* Pointer to name of file in which cell is to be char *newName; /* Pointer to name of file in which cell is to be
* saved. May be NULL, in which case the name from * saved. May be NULL, in which case the name from
* the CellDef is taken. * 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. * 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. * place where it was saved.
*/ */
{ {
@ -751,7 +625,7 @@ cmdSaveCell(
} }
} }
DBUpdateStamps(cellDef); DBUpdateStamps();
if (!DBCellWrite(cellDef, fileName)) if (!DBCellWrite(cellDef, fileName))
{ {
TxError("Could not write file. Cell not written.\n"); TxError("Could not write file. Cell not written.\n");
@ -761,16 +635,13 @@ cmdSaveCell(
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0)) if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
goto cleanup; goto cleanup;
/* Rename the cell, unless fileName is a .tcl file (scripted output) */ /* Rename the cell */
if ((strlen(fileName) <= 4) || strcmp(fileName + strlen(fileName) - 4, ".tcl")) if (!DBCellRenameDef(cellDef, fileName))
{ {
if (!DBCellRenameDef(cellDef, fileName)) /* This should never happen */
{ TxError("Magic error: there is already a cell named \"%s\"\n",
/* This should never happen */
TxError("Magic error: there is already a cell named \"%s\"\n",
fileName); fileName);
goto cleanup; goto cleanup;
}
} }
if (EditCellUse && (cellDef == EditCellUse->cu_def)) if (EditCellUse && (cellDef == EditCellUse->cu_def))
@ -825,13 +696,13 @@ cleanup:
*/ */
char * char *
cmdCheckNewName( cmdCheckNewName(def, newName, tryRename, noninteractive)
CellDef *def, CellDef *def;
char *newName, char *newName;
bool tryRename, bool tryRename;
bool noninteractive) bool noninteractive;
{ {
static const char * const yesno[] = { "no", "yes", 0 }; static char *yesno[] = { "no", "yes", 0 };
char *filename; char *filename;
char *prompt; char *prompt;
char *returnname; char *returnname;
@ -863,13 +734,12 @@ again:
} }
/* Remove any ".mag" file extension from the name */ /* Remove any ".mag" file extension from the name */
if (strlen(returnname) > 4) if (!strcmp(returnname + strlen(returnname) - 4, ".mag"))
if (!strcmp(returnname + strlen(returnname) - 4, ".mag")) *(returnname + strlen(returnname) - 4) = '\0';
*(returnname + strlen(returnname) - 4) = '\0';
if (strcmp(returnname, def->cd_name) != 0) 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); (void) fclose(f);
if (noninteractive) { if (noninteractive) {
@ -904,37 +774,6 @@ again:
return (returnname); return (returnname);
} }
/*
* ----------------------------------------------------------------------------
*
* nameEllipsis ---
*
* Truncate a string an append an ellipsis ("...") to the end if the string
* will overflow a fixed array length.
*
* ----------------------------------------------------------------------------
*/
static char *
nameEllipsis(
char *name,
int maxlen,
char **prefix)
{
int l = strlen(name);
if (l < maxlen)
{
*prefix = "";
return name;
}
else
{
*prefix = "...";
return &name[l - maxlen + 3];
}
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -959,20 +798,18 @@ nameEllipsis(
*/ */
int int
cmdSaveWindSet( cmdSaveWindSet(window, def)
MagWindow *window, MagWindow *window;
CellDef *def) CellDef *def;
{ {
char caption[200]; char caption[200];
CellDef *rootDef; CellDef *rootDef;
char *name, *name_pfx;
rootDef = ((CellUse *) window->w_surfaceID)->cu_def; rootDef = ((CellUse *) window->w_surfaceID)->cu_def;
if (rootDef != def) if (rootDef != def)
return 0; return 0;
name = nameEllipsis(def->cd_name, 175, &name_pfx); (void) sprintf(caption, "%s [NOT BEING EDITED]", def->cd_name);
(void) snprintf(caption, sizeof(caption), "%s%s [NOT BEING EDITED]", name_pfx, name);
(void) StrDup(&window->w_iconname, def->cd_name); (void) StrDup(&window->w_iconname, def->cd_name);
WindCaption(window, caption); WindCaption(window, caption);
return 0; return 0;
@ -1013,13 +850,13 @@ static CellDef *newRootDef; /* Pointer to root def of window in which
*/ */
void void
CmdSetWindCaption( CmdSetWindCaption(newEditUse, rootDef)
CellUse *newEditUse, /* Pointer to new edit cell use */ CellUse *newEditUse; /* Pointer to new edit cell use */
CellDef *rootDef) /* Root cell def of the window in which the CellDef *rootDef; /* Root cell def of the window in which the
* edit cell was selected. * edit cell was selected.
*/ */
{ {
int cmdWindSet(MagWindow *window, ClientData clientData); /* UNUSED */ int cmdWindSet();
newEditDef = (newEditUse) ? newEditUse->cu_def : NULL; newEditDef = (newEditUse) ? newEditUse->cu_def : NULL;
newRootDef = rootDef; newRootDef = rootDef;
@ -1053,30 +890,19 @@ CmdSetWindCaption(
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*ARGSUSED*/
int int
cmdWindSet( cmdWindSet(window)
MagWindow *window, MagWindow *window;
ClientData clientData) /* UNUSED */
{ {
char caption[200]; char caption[200];
CellDef *wDef; CellDef *wDef;
char *name[2], *name_pfx[2];
wDef = ((CellUse *) window->w_surfaceID)->cu_def; wDef = ((CellUse *) window->w_surfaceID)->cu_def;
if (wDef != newRootDef)
(void) sprintf(caption, "%s [NOT BEING EDITED]", wDef->cd_name);
else {
if (wDef != newRootDef) { (void) sprintf(caption, "%s EDITING %s", wDef->cd_name,
name[0] = nameEllipsis(wDef->cd_name, 175, &name_pfx[0]); newEditDef->cd_name);
(void) snprintf(caption, sizeof(caption), "%s%s [NOT BEING EDITED]",
name_pfx[0], name[0]);
} else {
name[0] = nameEllipsis(wDef->cd_name, 90, &name_pfx[0]);
name[1] = nameEllipsis(newEditDef->cd_name, 90, &name_pfx[1]);
(void) snprintf(caption, sizeof(caption), "%s%s EDITING %s%s",
name_pfx[0], name[0], name_pfx[1], name[1]);
#ifdef SCHEME_INTERPRETER #ifdef SCHEME_INTERPRETER
/* Add a binding to scheme variable "edit-cell" */ /* Add a binding to scheme variable "edit-cell" */
LispSetEdit (newEditDef->cd_name); LispSetEdit (newEditDef->cd_name);
@ -1113,9 +939,9 @@ cmdWindSet(
*/ */
MagWindow * MagWindow *
CmdGetRootPoint( CmdGetRootPoint(point, rect)
Point *point, Point *point;
Rect *rect) Rect *rect;
{ {
MagWindow *window; MagWindow *window;
@ -1148,9 +974,9 @@ CmdGetRootPoint(
*/ */
MagWindow * MagWindow *
CmdGetEditPoint( CmdGetEditPoint(point, rect)
Point *point, Point *point;
Rect *rect) Rect *rect;
{ {
MagWindow *window; MagWindow *window;
Rect rootRect; Rect rootRect;
@ -1185,11 +1011,11 @@ CmdGetEditPoint(
*/ */
bool bool
CmdWarnWrite(void) CmdWarnWrite()
{ {
int count, code; int count, code;
int cmdWarnWriteFunc(CellDef *cellDef, int *pcount); int cmdWarnWriteFunc();
static const char * const yesno[] = { "no", "yes", 0 }; static char *yesno[] = { "no", "yes", 0 };
char *prompt; char *prompt;
count = 0; count = 0;
@ -1207,9 +1033,9 @@ CmdWarnWrite(void)
} }
int int
cmdWarnWriteFunc( cmdWarnWriteFunc(cellDef, pcount)
CellDef *cellDef, CellDef *cellDef;
int *pcount) int *pcount;
{ {
if ((cellDef->cd_flags & CDINTERNAL) == 0) if ((cellDef->cd_flags & CDINTERNAL) == 0)
(*pcount)++; (*pcount)++;
@ -1233,27 +1059,27 @@ cmdWarnWriteFunc(
*/ */
void void
cmdExpandOneLevel( cmdExpandOneLevel(cu, bitmask, expand)
CellUse *cu, CellUse *cu;
int bitmask, int bitmask;
bool expand) bool expand;
{ {
extern int cmdExpand1func(CellUse *cu, ClientData bitmask); extern int cmdExpand1func();
/* first, expand this cell use */ /* first, expand this cell use */
DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND); DBExpand(cu, bitmask, expand);
/* now, unexpand its direct children (ONE LEVEL ONLY) */ /* now, unexpand its direct children (ONE LEVEL ONLY) */
if (expand) if (expand)
(void) DBCellEnum(cu->cu_def, cmdExpand1func, INT2CD(bitmask)); (void) DBCellEnum(cu->cu_def, cmdExpand1func, (ClientData) bitmask);
} }
int int
cmdExpand1func( cmdExpand1func(cu, bitmask)
CellUse *cu, CellUse *cu;
ClientData bitmask) ClientData bitmask;
{ {
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND); DBExpand(cu, (int) bitmask, FALSE);
return 0; return 0;
} }
@ -1281,13 +1107,13 @@ Transform *cmdSelTrans; /* Shared between CmdGetSelectedCell and
*/ */
CellUse * CellUse *
CmdGetSelectedCell( CmdGetSelectedCell(pTrans)
Transform *pTrans) /* If non-NULL, transform from selected Transform *pTrans; /* If non-NULL, transform from selected
* cell to root coords is stored here. * cell to root coords is stored here.
*/ */
{ {
CellUse *result = NULL; CellUse *result = NULL;
int cmdGetSelFunc(CellUse *selUse, CellUse *realUse, Transform *transform, CellUse **pResult); /* Forward declaration. */ int cmdGetSelFunc(); /* Forward declaration. */
cmdSelTrans = pTrans; cmdSelTrans = pTrans;
(void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL, (void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL,
@ -1297,11 +1123,11 @@ CmdGetSelectedCell(
/* ARGSUSED */ /* ARGSUSED */
int int
cmdGetSelFunc( cmdGetSelFunc(selUse, realUse, transform, pResult)
CellUse *selUse, /* Not used. */ CellUse *selUse; /* Not used. */
CellUse *realUse, /* The first selected use. */ CellUse *realUse; /* The first selected use. */
Transform *transform, /* Transform from coords of realUse to root. */ Transform *transform; /* Transform from coords of realUse to root. */
CellUse **pResult) /* Store realUse here. */ CellUse **pResult; /* Store realUse here. */
{ {
*pResult = realUse; *pResult = realUse;
if (cmdSelTrans != NULL) if (cmdSelTrans != NULL)
@ -1309,17 +1135,6 @@ cmdGetSelFunc(
return 1; /* Skip any other selected cells. */ 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;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -1340,10 +1155,10 @@ magic_isascii(int c)
*/ */
bool bool
CmdIllegalChars( CmdIllegalChars(string, illegal, msg)
char *string, /* String to check for illegal chars. */ char *string; /* String to check for illegal chars. */
char *illegal, /* String containing illegal chars. */ char *illegal; /* String containing illegal chars. */
char *msg) /* String identifying what string is char *msg; /* String identifying what string is
* supposed to represent, for ease in * supposed to represent, for ease in
* printing error messages. * printing error messages.
*/ */
@ -1352,7 +1167,7 @@ CmdIllegalChars(
for (p = string; *p != 0; p++) for (p = string; *p != 0; p++)
{ {
if (!magic_isascii(*p)) goto error; if (!isascii(*p)) goto error;
if (iscntrl(*p)) goto error; if (iscntrl(*p)) goto error;
for (bad = illegal; *bad != 0; bad++) for (bad = illegal; *bad != 0; bad++)
{ {
@ -1361,7 +1176,7 @@ CmdIllegalChars(
continue; continue;
error: error:
if (!magic_isascii(*p) || iscntrl(*p)) if (!isascii(*p) || iscntrl(*p))
{ {
TxError("%s contains illegal control character 0x%x\n", TxError("%s contains illegal control character 0x%x\n",
msg, *p); msg, *p);

File diff suppressed because it is too large Load Diff

View File

@ -20,11 +20,10 @@
*/ */
#ifndef lint #ifndef lint
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 $"; 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 $";
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
@ -47,16 +46,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "utils/utils.h" #include "utils/utils.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"
/* For diagnostics */
#include "cif/CIFint.h"
#include "database/databaseInt.h"
/* C99 compat */
#include "extract/extract.h"
/* Forward declarations */ /* Forward declarations */
extern void cmdPsearchStats(char *str, struct tms *tl, struct tms *td, int count); extern void cmdPsearchStats();
void cmdStatsHier(CellDef *, int, CellDef *); void cmdStatsHier(CellDef *, int, CellDef *);
@ -83,9 +75,9 @@ void cmdStatsHier(CellDef *, int, CellDef *);
*/ */
void void
CmdCoord( CmdCoord(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
MagWindow *pointW = (MagWindow *) NULL; MagWindow *pointW = (MagWindow *) NULL;
Rect editRect, rootRect; Rect editRect, rootRect;
@ -185,242 +177,14 @@ CmdCoord(
#ifndef NO_EXT #ifndef NO_EXT
void void
CmdExtractTest( CmdExtractTest(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
ExtractTest(w, cmd); ExtractTest(w, cmd);
} }
#endif #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);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
@ -444,9 +208,9 @@ CmdShowmem(
*/ */
void void
showTech( showTech(outf, verbose)
FILE *outf, /* File to which information is to be output */ FILE *outf; /* File to which information is to be output */
bool verbose) /* If TRUE, output detailed erase table */ bool verbose; /* If TRUE, output detailed erase table */
{ {
int i, j; int i, j;
int pNum; int pNum;
@ -464,7 +228,7 @@ showTech(
fprintf(outf, "\n"); fprintf(outf, "\n");
fprintf(outf, "Types:\n"); fprintf(outf, "Types:\n");
for (i = 0; i < DBNumTypes; i++) { for (i = 0; i < DBNumTypes; i++) {
int pl ; const char *spl ; int pl ; char *spl ;
pl = DBPlane(i); pl = DBPlane(i);
spl = ( pl <= 0 || pl > DBNumPlanes ) ? "??" : DBPlaneLongName(pl); spl = ( pl <= 0 || pl > DBNumPlanes ) ? "??" : DBPlaneLongName(pl);
@ -591,9 +355,9 @@ showTech(
} }
void void
CmdShowtech( CmdShowtech(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
FILE *outf; FILE *outf;
bool verbose; bool verbose;
@ -659,16 +423,16 @@ CmdShowtech(
*/ */
void void
CmdTilestats( CmdTilestats(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
CellUse *selectedUse; CellUse *selectedUse;
FILE *outf = stdout; FILE *outf = stdout;
bool allDefs = FALSE; bool allDefs = FALSE;
char **av = cmd->tx_argv + 1; char **av = cmd->tx_argv + 1;
int ac = cmd->tx_argc - 1; int ac = cmd->tx_argc - 1;
int cmdStatsFunc(CellDef *def, FILE *outf); int cmdStatsFunc();
if (ac > 2) if (ac > 2)
{ {
@ -743,12 +507,11 @@ int totalTiles[TT_MAXTYPES];
*/ */
int int
cmdStatsFunc( cmdStatsFunc(def, outf)
CellDef *def, CellDef *def;
FILE *outf) FILE *outf;
{ {
int cmdStatsCount(CellDef *def, struct countClient *cc); int cmdStatsCount(), cmdStatsOutput();
int cmdStatsOutput(CellDef *def, struct countClient *cc);
struct countClient cc; struct countClient cc;
int total; int total;
TileType t; TileType t;
@ -797,17 +560,15 @@ cmdStatsFunc(
*/ */
int int
cmdStatsCount( cmdStatsCount(def, cc)
CellDef *def, CellDef *def;
struct countClient *cc) struct countClient *cc;
{ {
int cmdStatsCountTile();
int pNum; int pNum;
struct cellInfo *ci; struct cellInfo *ci;
TileType t; TileType t;
/* Forward declaration */
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
if (def->cd_client) if (def->cd_client)
return (1); return (1);
@ -830,10 +591,9 @@ cmdStatsCount(
} }
int int
cmdStatsCountTile( cmdStatsCountTile(tile, ci)
Tile *tile, Tile *tile;
TileType dinfo, /* (unused) */ struct cellInfo *ci;
struct cellInfo *ci)
{ {
TileType type = TiGetType(tile); TileType type = TiGetType(tile);
@ -874,10 +634,9 @@ cmdStatsCountTile(
*/ */
void void
cmdStatsHier( cmdStatsHier(parent, nuses, child)
CellDef *parent, CellDef *parent, *child;
int nuses, int nuses;
CellDef *child)
{ {
struct cellInfo *pi, *ci; struct cellInfo *pi, *ci;
TileType t; TileType t;
@ -922,9 +681,9 @@ cmdStatsHier(
*/ */
int int
cmdStatsOutput( cmdStatsOutput(def, cc)
CellDef *def, CellDef *def;
struct countClient *cc) struct countClient *cc;
{ {
TileType t; TileType t;
struct cellInfo *ci; struct cellInfo *ci;
@ -987,11 +746,11 @@ cmdStatsOutput(
*/ */
void void
CmdPsearch( CmdPsearch(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
char *RunStats(int flags, struct tms *lastt, struct tms *deltat); char *RunStats();
static struct tms tlast, tdelta; static struct tms tlast, tdelta;
Point p; Point p;
Plane *plane; Plane *plane;
@ -1053,13 +812,12 @@ CmdPsearch(
} }
void void
cmdPsearchStats( cmdPsearchStats(str, tl, td, count)
char *str, char *str;
struct tms *tl, struct tms *tl, *td;
struct tms *td, int count;
int count)
{ {
char *RunStats(int flags, struct tms *lastt, struct tms *deltat); char *RunStats();
char *rstatp; char *rstatp;
int us, ups; int us, ups;
@ -1099,22 +857,20 @@ int numTilesFound;
bool cmdTsearchDebug = FALSE; bool cmdTsearchDebug = FALSE;
void void
CmdTsearch( CmdTsearch(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
char *rstatp; int cmdTsrFunc();
char *RunStats(), *rstatp;
static TileTypeBitMask mask; static TileTypeBitMask mask;
static struct tms tlast, tdelta; static struct tms tlast, tdelta;
Rect rtool, rsearch; Rect rtool, rsearch;
/**** Rect *ebox; ****/
Plane *plane; Plane *plane;
int i, pNum, count; int i, pNum, count;
int usPerSearch, usPerTile, usPerL2, us, boxarea; 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) if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
{ {
TxError("Usage: tsearch plane count [mask [new|mayo]]\n"); TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
@ -1213,13 +969,11 @@ CmdTsearch(
} }
int int
cmdTsrFunc( cmdTsrFunc(tp)
Tile *tp, Tile *tp;
TileType dinfo, /* (unused) */
ClientData clientdata) /* (unused) */
{ {
if (cmdTsearchDebug) if (cmdTsearchDebug)
TxPrintf("%lx\n", (intptr_t) tp); TxPrintf("%x\n", tp);
numTilesFound++; numTilesFound++;
return 0; return 0;
} }
@ -1242,9 +996,9 @@ cmdTsrFunc(
*/ */
void void
CmdWatch( CmdWatch(w, cmd)
MagWindow *w, MagWindow *w;
TxCommand *cmd) TxCommand *cmd;
{ {
DBWclientRec *crec; DBWclientRec *crec;
int pNum; int pNum;
@ -1285,7 +1039,7 @@ CmdWatch(
pNum = DBTechNamePlane(cmd->tx_argv[1]); pNum = DBTechNamePlane(cmd->tx_argv[1]);
if (pNum < 0) if (pNum < 0)
{ {
const char *cp; char *cp;
TxError("Unrecognized plane: %s. Legal names are:\n", TxError("Unrecognized plane: %s. Legal names are:\n",
cmd->tx_argv[1]); cmd->tx_argv[1]);
for(pNum=0; pNum < PL_MAXTYPES; pNum++) { for(pNum=0; pNum < PL_MAXTYPES; pNum++) {
@ -1295,16 +1049,8 @@ CmdWatch(
}; };
return; return;
} }
if (EditCellUse != NULL) crec->dbw_watchDef = EditCellUse->cu_def;
{ crec->dbw_watchTrans = EditToRootTransform;
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; crec->dbw_watchPlane = pNum;

View File

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

View File

@ -20,12 +20,11 @@
* rcsid $Header: /usr/cvsroot/magic-8.0/commands/commands.h,v 1.3 2009/01/19 15:43:03 tim Exp $ * rcsid $Header: /usr/cvsroot/magic-8.0/commands/commands.h,v 1.3 2009/01/19 15:43:03 tim Exp $
*/ */
#ifndef _MAGIC__COMMANDS__COMMANDS_H #ifndef _COMMANDS_H
#define _MAGIC__COMMANDS__COMMANDS_H #define _COMMANDS_H
#include "windows/windows.h" #include "windows/windows.h"
#include "database/database.h" #include "database/database.h"
#include "textio/txcommands.h" /* TxCommand */
/* /*
* Name of default yank buffer * Name of default yank buffer
@ -51,28 +50,18 @@ extern TileTypeBitMask CmdYMAllButSpace;
/* --------------------- Global procedure headers --------------------- */ /* --------------------- Global procedure headers --------------------- */
extern MagWindow *CmdGetEditPoint(Point *point, Rect *rect); extern MagWindow *CmdGetRootBox();
extern MagWindow *CmdGetRootPoint(Point *point, Rect *rect); extern MagWindow *CmdGetEditPoint();
extern bool CmdWarnWrite(void); extern MagWindow *CmdGetRootPoint();
extern bool CmdParseLayers(char *s, TileTypeBitMask *mask); extern bool CmdWarnWrite();
extern void CmdLabelProc(char *text, int font, int size, int rotate, int offx, int offy, extern bool CmdParseLayers();
int pos, bool sticky, TileType type); extern void CmdAddSlop();
extern void CmdSetWindCaption(CellUse *newEditUse, CellDef *rootDef); extern void CmdLabelProc();
extern CellUse *CmdGetSelectedCell(Transform *pTrans); extern void CmdSetWindCaption();
extern bool CmdIllegalChars(char *string, char *illegal, char *msg); extern CellUse *CmdGetSelectedCell();
extern TileType CmdFindNetProc(char *nodename, CellUse *use, Rect *rect, bool warn_not_found, bool *isvalid); extern bool CmdIllegalChars();
extern bool CmdCheckForPaintFunc(void); extern void CmdDoMacro();
extern TileType CmdFindNetProc();
extern bool CmdCheckForPaintFunc();
/* C99 compat */ #endif /* _COMMANDS_H */
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(CellDef *def, MagWindow *w, TxCommand *cmd, int argstart);
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
#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 # script itself. It also sets up CFLAGS without the default optimizer
# flag (-O2). # flag (-O2).
( CFLAGS=${CFLAGS:-"-g"}; export CFLAGS; cd scripts ; ./configure "$@" ) ( CFLAGS="-g"; export CFLAGS; cd scripts ; ./configure "$@" )

View File

@ -30,33 +30,20 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
typedef struct dbcellboundstruct typedef struct dbcellboundstruct
{ {
Rect *area; Rect *area;
Rect *extended; bool extended;
bool found; bool found;
} DBCellBoundStruct; } 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 int
DBBoundCellPlane( DBBoundCellPlane(def, extended, rect)
CellDef *def, CellDef *def;
Rect *extended, bool extended;
Rect *rect) Rect *rect;
{ {
TreeFilter filter; TreeFilter filter;
DBCellBoundStruct cbs; DBCellBoundStruct cbs;
@ -79,23 +66,29 @@ DBBoundCellPlane(
} }
int int
dbCellBoundFunc( dbCellBoundFunc(use, fp)
CellUse *use, CellUse *use;
TreeFilter *fp) TreeFilter *fp;
{ {
Rect *bbox;
DBCellBoundStruct *cbs; DBCellBoundStruct *cbs;
cbs = (DBCellBoundStruct *)fp->tf_arg; cbs = (DBCellBoundStruct *)fp->tf_arg;
bbox = &use->cu_bbox;
if (cbs->found) if (cbs->found)
{ {
GeoInclude(&use->cu_extended, cbs->extended); if (cbs->extended)
GeoInclude(&use->cu_bbox, cbs->area); GeoInclude(&use->cu_extended, cbs->area);
else
GeoInclude(&use->cu_bbox, cbs->area);
} }
else else
{ {
*cbs->extended = use->cu_extended; if (cbs->extended)
*cbs->area = use->cu_bbox; *cbs->area = use->cu_extended;
else
*cbs->area = use->cu_bbox;
cbs->found = TRUE; cbs->found = TRUE;
} }
return 0; return 0;
@ -124,9 +117,9 @@ dbCellBoundFunc(
*/ */
bool bool
DBBoundPlane( DBBoundPlane(plane, rect)
Plane *plane, Plane *plane;
Rect *rect) Rect *rect;
{ {
Tile *left, *right, *top, *bottom, *tp; Tile *left, *right, *top, *bottom, *tp;
@ -205,9 +198,9 @@ DBBoundPlane(
*/ */
bool bool
DBBoundPlaneVert( DBBoundPlaneVert(plane, rect)
Plane *plane, Plane *plane;
Rect *rect) Rect *rect;
{ {
Tile *left, *right, *top, *bottom, *tp; Tile *left, *right, *top, *bottom, *tp;

View File

@ -106,57 +106,8 @@ DBCellFindDup(use, parent)
BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL, BPEnumInit(&bpe, parent->cd_cellPlane, &use->cu_bbox, BPE_EQUAL,
"DBCellFindDup"); "DBCellFindDup");
while ((dupUse = BPEnumNext(&bpe))) while (dupUse = BPEnumNext(&bpe))
if (dupUse->cu_def == use->cu_def) if (dupUse->cu_def == use->cu_def) break;
{
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); BPEnumTerm(&bpe);
return dupUse; return dupUse;
@ -167,7 +118,6 @@ DBCellFindDup(use, parent)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* DBPlaceCell -- * DBPlaceCell --
* DBPlaceCellNoModify --
* *
* Add a CellUse to the subcell tile plane of a CellDef. * Add a CellUse to the subcell tile plane of a CellDef.
* Assumes prior check that the new CellUse is not an exact duplicate * Assumes prior check that the new CellUse is not an exact duplicate
@ -212,47 +162,11 @@ DBPlaceCell (use, def)
SigEnableInterrupts(); SigEnableInterrupts();
} }
/* Like DBPlaceCell(), but don't change the flags of the parent cell. */
/* This is needed by the bounding box recalculation routine, which may */
/* cause the cell to be deleted and replaced for the purpose of */
/* capturing the bounding box information in the BPlane structure, but */
/* this does not mean that anything in the parent cell has changed. */
void
DBPlaceCellNoModify (use, def)
CellUse * use; /* new celluse to add to subcell tile plane */
CellDef * def; /* parent cell's definition */
{
Rect rect; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
BPlane *bplane; /* argument to DBSrCellPlaneArea(), placeCellFunc() */
struct searchArg arg; /* argument to placeCellFunc() */
ASSERT(use != (CellUse *) NULL, "DBPlaceCell");
ASSERT(def, "DBPlaceCell");
/* To do: Check non-duplicate placement, check non-duplicate ID */
use->cu_parent = def;
/* Be careful not to permit interrupts during this, or the
* database could be left in a trashed state.
*/
SigDisableInterrupts();
BPAdd(def->cd_cellPlane, use);
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_PLACE);
SigEnableInterrupts();
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* DBDeleteCell -- * DBDeleteCell --
* *
* Remove a CellUse from the subcell tile plane of a CellDef. * Remove a CellUse from the subcell tile plane of a CellDef.
* If "nomodify" is TRUE, then don't set the parent cell's CDMODIFIED flag.
* This is needed when recomputing the bounding box, which should not by
* itself change the modified state.
* *
* Results: * Results:
* None. * None.
@ -283,39 +197,3 @@ DBDeleteCell (use)
SigEnableInterrupts(); SigEnableInterrupts();
} }
/*
* ----------------------------------------------------------------------------
* DBDeleteCellNoModify --
*
* Remove a CellUse from the subcell tile plane of a CellDef, as above,
* but don't set the parent cell's CDMODIFIED flag. This is needed when
* recomputing the bounding box, which should not by itself change the
* modified state.
*
* Results:
* None.
*
* Side effects:
* Modifies the subcell tile plane of the CellDef, sets the
* parent pointer of the deleted CellUse to NULL.
* ----------------------------------------------------------------------------
*/
void
DBDeleteCellNoModify (use)
CellUse * use;
{
ASSERT(use != (CellUse *) NULL, "DBDeleteCell");
/* It's important that this code run with interrupts disabled,
* or else we could leave the subcell tile plane in a weird
* state.
*/
SigDisableInterrupts();
dbInstanceUnplace(use);
if (UndoIsEnabled())
DBUndoCellUse(use, UNDO_CELL_DELETE);
use->cu_parent = (CellDef *) NULL;
SigEnableInterrupts();
}

View File

@ -59,15 +59,15 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/ */
char * char *
DBPrintUseId( DBPrintUseId(scx, name, size, display_only)
SearchContext *scx, /* Pointer to current search context, specifying a SearchContext *scx; /* Pointer to current search context, specifying a
* cell use and X,Y array indices. * 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. * print name of this instance.
*/ */
int size, /* Maximum number of characters to copy into string. */ int size; /* Maximum number of characters to copy into string. */
bool display_only) /* TRUE if called for displaying only */ bool display_only; /* TRUE if called for displaying only */
{ {
CellUse *use = scx->scx_use; CellUse *use = scx->scx_use;
char *sp, *id, *ep; char *sp, *id, *ep;
@ -619,9 +619,8 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
/* /*
* Include area of subcells separately * Include area of subcells separately
*/ */
if (!((foundAny = DBBoundCellPlane(cellDef, &extended, &rect)) > 0)) if ((foundAny = DBBoundCellPlane(cellDef, TRUE, &rect)) > 0)
extended = GeoNullRect; area = rect;
area = rect;
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
if (pNum != PL_DRC_CHECK) if (pNum != PL_DRC_CHECK)
@ -635,7 +634,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
} }
/* /*
* Include the area of label anchors, too. * Include the area of labels, too.
*/ */
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next) for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
{ {
@ -657,11 +656,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
} }
} }
/* Make sure the extended bounding box includes the area of all extended = area;
* paint material just found, then include the area of all text
* in the current cell.
*/
GeoInclude(&area, &extended);
if (foundAny) if (foundAny)
{ {
for (label = cellDef->cd_labels; label != NULL; label = label->lab_next) for (label = cellDef->cd_labels; label != NULL; label = label->lab_next)
@ -678,7 +673,6 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
degenerate = TRUE; degenerate = TRUE;
area.r_xbot = area.r_ybot = 0; area.r_xbot = area.r_ybot = 0;
area.r_xtop = area.r_ytop = 1; area.r_xtop = area.r_ytop = 1;
extended = area;
} }
else degenerate = FALSE; else degenerate = FALSE;
@ -693,11 +687,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
if (area.r_ybot == area.r_ytop) if (area.r_ybot == area.r_ytop)
area.r_ytop = area.r_ybot + 1; area.r_ytop = area.r_ybot + 1;
if (extended.r_xbot == extended.r_xtop) if (degenerate) extended = area;
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 /* Did the bounding box change? If not then there's no need to
* recompute the parents. If the cell has no material, then * recompute the parents. If the cell has no material, then
@ -733,7 +723,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
*/ */
parent = use->cu_parent; parent = use->cu_parent;
DBDeleteCellNoModify(use); DBDeleteCell(use);
use->cu_parent = parent; use->cu_parent = parent;
} }
@ -761,7 +751,7 @@ dbReComputeBboxFunc(cellDef, boundProc, recurseProc)
if ((parent = use->cu_parent) != (CellDef *) NULL) if ((parent = use->cu_parent) != (CellDef *) NULL)
{ {
parent->cd_flags |= CDBOXESCHANGED; parent->cd_flags |= CDBOXESCHANGED;
DBPlaceCellNoModify(use, parent); DBPlaceCell(use, parent);
if (last != parent) if (last != parent)
{ {
if (last != NULL) (*recurseProc)(last); if (last != NULL) (*recurseProc)(last);

File diff suppressed because it is too large Load Diff

View File

@ -21,9 +21,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* for qsort() */
#include <string.h> #include <string.h>
#include <ctype.h>
#include "tcltk/tclmagic.h" #include "tcltk/tclmagic.h"
#include "utils/magic.h" #include "utils/magic.h"
@ -77,10 +75,7 @@ extern void DBSetUseIdHash();
* *
* Rename a cell. This differs from the "save" command in that the * Rename a cell. This differs from the "save" command in that the
* cell is not immediately written to disk. However, the cell is * cell is not immediately written to disk. However, the cell is
* marked as modified. If "doforce" is TRUE, then allow renaming * marked as modified.
* of vendor (read-only) cells. Because vendor cells are tied to
* a GDS file, then the vendor status gets revoked and the pointer
* to the GDS file gets removed.
* *
* Results: * Results:
* Return TRUE if the cell was successfully renamed. Return FALSE * Return TRUE if the cell was successfully renamed. Return FALSE
@ -92,10 +87,9 @@ extern void DBSetUseIdHash();
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
bool bool
DBCellRename(cellname, newname, doforce) DBCellRename(cellname, newname)
char *cellname; char *cellname;
char *newname; char *newname;
bool doforce;
{ {
HashEntry *entry; HashEntry *entry;
CellDef *celldef; CellDef *celldef;
@ -117,30 +111,14 @@ DBCellRename(cellname, newname, doforce)
return FALSE; 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, */ /* Disallow renaming if the cell has the READONLY flag set, */
/* because the cellname must match the name in the GDS */ /* because the cellname must match the name in the GDS */
/* file referenced. */ /* file referenced. */
if ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS) if ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS)
{ {
if (doforce) TxError("Error: Attempt to rename read-only cell \"%s\"\n", cellname);
{ return FALSE;
TxPrintf("Warning: Renaming read-only cell \"%s\"\n", cellname);
TxPrintf("Read-only status will be revoked and GDS file pointer removed.\n");
}
else
{
TxError("Error: Attempt to rename read-only cell \"%s\"\n", cellname);
return FALSE;
}
} }
/* Good to go! */ /* Good to go! */
@ -149,21 +127,6 @@ DBCellRename(cellname, newname, doforce)
result = DBCellRenameDef(celldef, newname); result = DBCellRenameDef(celldef, newname);
DBWAreaChanged(celldef, &celldef->cd_bbox, DBW_ALLWINDOWS, DBWAreaChanged(celldef, &celldef->cd_bbox, DBW_ALLWINDOWS,
(TileTypeBitMask *) NULL); (TileTypeBitMask *) NULL);
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
{
bool isReadOnly;
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
DBPropGet(celldef, "GDS_START", &isReadOnly);
if (isReadOnly) DBPropPut(celldef, "GDS_START", NULL);
DBPropGet(celldef, "GDS_END", &isReadOnly);
if (isReadOnly) DBPropPut(celldef, "GDS_END", NULL);
}
UndoEnable(); UndoEnable();
return result; return result;
} }
@ -231,7 +194,7 @@ DBCellDelete(cellname, force)
{ {
HashEntry *entry; HashEntry *entry;
CellDef *celldef; CellDef *celldef;
CellUse *celluse, *lastuse; CellUse *celluse;
bool result; bool result;
entry = HashLookOnly(&dbCellDefTable, cellname); entry = HashLookOnly(&dbCellDefTable, cellname);
@ -266,36 +229,13 @@ DBCellDelete(cellname, force)
return FALSE; 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. */ /* Cleared to delete. . . now prompt user if the cell has changes. */
/* Last chance to save! */ /* Last chance to save! */
if ((force == FALSE) && if ((force == FALSE) &&
(celldef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED))) (celldef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED)))
{ {
static const char *yesno[] = { "no", "yes", 0 }; static char *yesno[] = { "no", "yes", 0 };
int code; int code;
char *prompt = TxPrintString("Cell %s has been modified.\n Do you" char *prompt = TxPrintString("Cell %s has been modified.\n Do you"
" want to delete it and lose all changes? ", " want to delete it and lose all changes? ",
@ -313,13 +253,12 @@ DBCellDelete(cellname, force)
/* so that WindUnload() will create a new one. */ /* so that WindUnload() will create a new one. */
if (!strcmp(cellname, UNNAMED)) if (!strcmp(cellname, UNNAMED))
DBCellRename(cellname, "__UNNAMED__", FALSE); DBCellRename(cellname, "__UNNAMED__");
/* For all top-level cell uses, check if any windows have this */ /* For all top-level cell uses, check if any windows have this */
/* use. If so, load the window with (UNNAMED). */ /* use. If so, load the window with (UNNAMED). */
UndoDisable(); UndoDisable();
free_magic1_t mm1 = freeMagic1_init();
for (celluse = celldef->cd_parents; celluse != (CellUse *) NULL; for (celluse = celldef->cd_parents; celluse != (CellUse *) NULL;
celluse = celluse->cu_nextuse) celluse = celluse->cu_nextuse)
{ {
@ -328,12 +267,10 @@ DBCellDelete(cellname, force)
WindUnload(celluse); WindUnload(celluse);
freeMagic(celluse->cu_id); freeMagic(celluse->cu_id);
} }
freeMagic1(&mm1, (char *)celluse); freeMagic((char *)celluse);
} }
freeMagic1_end(&mm1);
celldef->cd_parents = (CellUse *)NULL; celldef->cd_parents = (CellUse *)NULL;
DBWResetBox(celldef);
result = DBCellDeleteDef(celldef); result = DBCellDeleteDef(celldef);
if (result == FALSE) if (result == FALSE)
@ -343,6 +280,8 @@ DBCellDelete(cellname, force)
return result; return result;
} }
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -400,12 +339,6 @@ dbGetUseName(celluse)
ybuf[0] = '\0'; ybuf[0] = '\0';
useID = celluse->cu_id; useID = celluse->cu_id;
if (useID == NULL)
{
newID = (char *)mallocMagic(7);
sprintf(newID, "(null)");
return (newID);
}
newsize = strlen(useID) + 1; newsize = strlen(useID) + 1;
if (isx || isy) if (isx || isy)
{ {
@ -665,70 +598,6 @@ DBTopPrint(mw, dolist)
} }
} }
/*
* ----------------------------------------------------------------------------
* Simple natural sort routine
* https://stackoverflow.com/questions/34518/natural-sorting-algorithm
* By Norman Ramsey, edited for style.
* ----------------------------------------------------------------------------
*/
int strcmpbynum(const char *s1, const char *s2)
{
/* Like strcasecmp() but compare sequences of digits numerically */
for (;;)
{
if (*s2 == '\0')
return *s1 != '\0';
else if (*s1 == '\0')
return 1;
else if (!(isdigit(*s1) && isdigit(*s2)))
{
char c1, c2;
c1 = tolower(*s1);
c2 = tolower(*s2);
if (c1 != c2)
return (int)c1 - (int)c2;
else
{
++s1;
++s2;
}
}
else
{
char *lim1, *lim2;
unsigned long n1 = strtoul(s1, &lim1, 10);
unsigned long n2 = strtoul(s2, &lim2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
s1 = lim1;
s2 = lim2;
}
}
}
/*
* ----------------------------------------------------------------------------
* Sort routine for qsort() to be used by DBCellPrint(). Sorts in alphabetical
* order using the natural sort routine above. List is reverse sorted since
* the code below prints from the end to the beginning of the list.
* ----------------------------------------------------------------------------
*/
int
qcompare(const void *one, const void *two)
{
int cval;
char *s1 = *((char **)one);
char *s2 = *((char **)two);
cval = strcmpbynum(s1, s2);
return -cval;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -756,12 +625,11 @@ DBCellPrint(CellName, who, dolist)
int who; int who;
bool dolist; bool dolist;
{ {
int found, numcells; int found;
HashSearch hs; HashSearch hs;
HashEntry *entry; HashEntry *entry;
CellDef *celldef; CellDef *celldef;
CellUse *celluse; CellUse *celluse;
char **celllist;
if (!dolist) if (!dolist)
{ {
@ -789,11 +657,6 @@ DBCellPrint(CellName, who, dolist)
* CDMODIFIED flag set. * CDMODIFIED flag set.
*/ */
numcells = dbCellDefTable.ht_nEntries;
if (numcells == 0) numcells = 1;
celllist = (char **)mallocMagic(numcells * sizeof(char *));
numcells = 0;
HashStartSearch(&hs); HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL) while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{ {
@ -803,39 +666,28 @@ DBCellPrint(CellName, who, dolist)
if (((celldef->cd_flags & CDINTERNAL) != CDINTERNAL) && if (((celldef->cd_flags & CDINTERNAL) != CDINTERNAL) &&
((who != MODIFIED) || ((who != MODIFIED) ||
(celldef->cd_flags & CDMODIFIED))) (celldef->cd_flags & CDMODIFIED)))
{
if (celldef->cd_name != NULL) if (celldef->cd_name != NULL)
celllist[numcells++] = celldef->cd_name; {
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celldef->cd_name);
#else
TxPrintf("%s ", celldef->cd_name);
#endif
else
TxPrintf(" %s\n", celldef->cd_name);
}
}
} }
} }
qsort(celllist, numcells, sizeof(char *), qcompare);
while (--numcells >= 0)
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celllist[numcells]);
#else
TxPrintf("%s ", celllist[numcells]);
#endif
else
TxPrintf(" %s\n", celllist[numcells]);
}
freeMagic(celllist);
break; break;
case TOPCELLS: case TOPCELLS:
/* /*
* Print the name of all the 'top' cells. Sort alphabetically. * Print the name of all the 'top' cells.
*/ */
numcells = dbCellDefTable.ht_nEntries;
if (numcells == 0) numcells = 1;
celllist = (char **)mallocMagic(numcells * sizeof(char *));
numcells = 0;
HashStartSearch(&hs); HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL) while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{ {
@ -860,25 +712,19 @@ DBCellPrint(CellName, who, dolist)
} }
} }
if ( (found == 0) && (celldef->cd_name != NULL) ) if ( (found == 0) && (celldef->cd_name != NULL) )
celllist[numcells++] = celldef->cd_name; {
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celldef->cd_name);
#else
TxPrintf("%s ", celldef->cd_name);
#endif
else
TxPrintf(" %s\n", celldef->cd_name);
}
} }
} }
} }
qsort(celllist, numcells, sizeof(char *), qcompare);
while (--numcells >= 0)
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celllist[numcells]);
#else
TxPrintf("%s ", celllist[numcells]);
#endif
else
TxPrintf(" %s\n", celllist[numcells]);
}
freeMagic(celllist);
break; break;
default: default:
@ -912,17 +758,8 @@ DBCellPrint(CellName, who, dolist)
} }
if (found == 0) if (found == 0)
{ {
if (EditRootDef == NULL) if (!dolist)
{ TxPrintf("No cells selected.\n");
if (!dolist)
TxPrintf("No cells selected.\n");
}
else
{
dbCellPrintInfo(EditRootDef, who, dolist);
found = 1;
break;
}
} }
} }
else else
@ -1159,13 +996,11 @@ DBUsePrint(CellName, who, dolist)
celldef = DBCellLookDef(CellName); celldef = DBCellLookDef(CellName);
*lasthier = '/'; *lasthier = '/';
} }
else if (EditCellUse != NULL) else
{ {
/* Referenced cellDef is the current edit def */ /* Referenced cellDef is the current edit def */
celldef = EditCellUse->cu_def; celldef = EditCellUse->cu_def;
} }
else
return;
switch (who) switch (who)
{ {
@ -1319,7 +1154,7 @@ DBLockUse(UseName, bval)
CellDef *celldef; CellDef *celldef;
CellUse *celluse; CellUse *celluse;
int dbLockUseFunc(); int dbUseLockFunc();
/* /*
* *
@ -1347,7 +1182,7 @@ DBLockUse(UseName, bval)
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL) while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{ {
celldef = (CellDef *) HashGetValue(entry); celldef = (CellDef *) HashGetValue(entry);
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL)) if (celldef != (CellDef *) NULL)
{ {
celluse = celldef->cd_parents; /* only need one */ celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) { if (celluse != (CellUse *)NULL) {
@ -1364,329 +1199,6 @@ DBLockUse(UseName, bval)
} }
} }
/*
* ----------------------------------------------------------------------------
*
* DBOrientUse --
*
* This routine reports a cell instance's orientation.
* UseName is the name of a specific CellUse. If NULL, then the
* operation applies to all selected cell uses.
*
* Results:
* None.
*
* Side effects:
* In the Tcl/Tk implementation, the result is set in the interpreter.
*
* Notes:
* This routine only reports orientation. Setting orientation must
* be done through the selection interface (i.e., commands "sideways",
* "upsidedown", "clockwise" ("rotate"), or "orient" (added 10/30/2020)).
*
* ----------------------------------------------------------------------------
*/
void
DBOrientUse(UseName, dodef)
char *UseName;
bool dodef;
{
int found;
HashSearch hs;
HashEntry *entry;
CellDef *celldef;
CellUse *celluse;
int dbOrientUseFunc();
/*
*
* Check to see if a cell name was specified. If not, then search
* for selected cells.
*
*/
if (UseName == NULL)
{
if (EditCellUse == NULL)
TxError("Cannot set orientation of a non-edit cell!\n");
else
SelEnumCells(TRUE, (int *)NULL, (SearchContext *)NULL,
dbOrientUseFunc, (ClientData)&dodef);
}
else
{
SearchContext scx;
bzero(&scx, sizeof(SearchContext));
found = 0;
HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL))
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
DBTreeFindUse(UseName, celluse, &scx);
if (scx.scx_use != NULL) break;
}
}
}
if (scx.scx_use == NULL)
TxError("Cell %s is not currently loaded.\n", UseName);
else
dbOrientUseFunc(NULL, scx.scx_use, NULL, (ClientData)&dodef);
}
}
/*
* dbOrientUseFunc()
*/
/* For corresponding enumerations, see GeoTransOrient() */
enum def_orient {ORIENT_NORTH, ORIENT_SOUTH, ORIENT_EAST, ORIENT_WEST,
ORIENT_FLIPPED_NORTH, ORIENT_FLIPPED_SOUTH, ORIENT_FLIPPED_EAST,
ORIENT_FLIPPED_WEST};
int
dbOrientUseFunc(selUse, use, transform, data)
CellUse *selUse; /* Use from selection cell */
CellUse *use; /* Use from layout corresponding to selection */
Transform *transform;
ClientData data;
{
bool *dodef = (bool *)data;
int orient;
if (EditCellUse && !DBIsChild(use, EditCellUse))
{
TxError("Cell %s (%s) isn't a child of the edit cell.\n",
use->cu_id, use->cu_def->cd_name);
return 0;
}
orient = -1;
if (selUse != NULL)
orient = GeoTransOrient(&selUse->cu_transform);
else if (use != NULL)
orient = GeoTransOrient(&use->cu_transform);
if (orient != -1)
{
switch (orient) {
#ifdef MAGIC_WRAPPER
case ORIENT_NORTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "N" : "0");
break;
case ORIENT_EAST:
Tcl_AppendElement(magicinterp, (*dodef) ? "E" : "90");
break;
case ORIENT_SOUTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "S" : "180");
break;
case ORIENT_WEST:
Tcl_AppendElement(magicinterp, (*dodef) ? "W" : "270");
break;
case ORIENT_FLIPPED_NORTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "FN" : "0h");
break;
case ORIENT_FLIPPED_EAST:
Tcl_AppendElement(magicinterp, (*dodef) ? "FE" : "90h");
break;
case ORIENT_FLIPPED_SOUTH:
Tcl_AppendElement(magicinterp, (*dodef) ? "FS" : "180h");
break;
case ORIENT_FLIPPED_WEST:
Tcl_AppendElement(magicinterp, (*dodef) ? "FW" : "270h");
break;
#else
case ORIENT_NORTH:
TxPrintf((*dodef) ? "N" : "0");
break;
case ORIENT_EAST:
TxPrintf((*dodef) ? "E" : "90");
break;
case ORIENT_SOUTH:
TxPrintf((*dodef) ? "S" : "180");
break;
case ORIENT_WEST:
TxPrintf((*dodef) ? "W" : "270");
break;
case ORIENT_FLIPPED_NORTH:
TxPrintf((*dodef) ? "FN" : "0h");
break;
case ORIENT_FLIPPED_EAST:
TxPrintf((*dodef) ? "FE" : "90h");
break;
case ORIENT_FLIPPED_SOUTH:
TxPrintf((*dodef) ? "FS" : "180h");
break;
case ORIENT_FLIPPED_WEST:
TxPrintf((*dodef) ? "FW" : "270h");
break;
#endif
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* DBAbutmentUse --
*
* This routine reports the cell instance's abutment box in the
* coordinate system of the parent (edit) cell.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
DBAbutmentUse(UseName, dolist)
char *UseName;
bool dolist;
{
int found;
HashSearch hs;
HashEntry *entry;
CellDef *celldef;
CellUse *celluse;
int dbAbutmentUseFunc();
/*
*
* Check to see if a cell name was specified. If not, then search
* for selected cells.
*
*/
if (UseName == NULL)
{
SelEnumCells(TRUE, (int *)NULL, (SearchContext *)NULL,
dbAbutmentUseFunc, (ClientData)&dolist);
}
else
{
SearchContext scx;
bzero(&scx, sizeof(SearchContext));
found = 0;
HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
celldef = (CellDef *) HashGetValue(entry);
if ((celldef != (CellDef *)NULL) && !(celldef->cd_flags & CDINTERNAL))
{
celluse = celldef->cd_parents; /* only need one */
if (celluse != (CellUse *)NULL) {
DBTreeFindUse(UseName, celluse, &scx);
if (scx.scx_use != NULL) break;
}
}
}
if (scx.scx_use == NULL)
TxError("Cell %s is not currently loaded.\n", UseName);
else
dbAbutmentUseFunc(NULL, scx.scx_use, NULL, (ClientData)&dolist);
}
}
/*
* dbAbutmentUseFunc()
*/
int
dbAbutmentUseFunc(selUse, use, transform, data)
CellUse *selUse; /* Use from selection cell */
CellUse *use; /* Use from layout corresponding to selection */
Transform *transform;
ClientData data;
{
Rect bbox, refbox;
Transform *trans;
PropertyRecord *proprec;
char *propvalue;
char *refllx, *reflly, *refurx, *refury;
bool found;
bool *dolist = (bool *)data;
#ifdef MAGIC_WRAPPER
Tcl_Obj *pobj;
#endif
if (EditCellUse && !DBIsChild(use, EditCellUse))
{
TxError("Cell %s (%s) isn't a child of the edit cell.\n",
use->cu_id, use->cu_def->cd_name);
return 0;
}
if (use == NULL)
{
TxError("No instance in selection!\n");
return 0;
}
trans = &use->cu_transform;
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
if (!found)
bbox = use->cu_def->cd_bbox;
else
{
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
(proprec->prop_len == 4))
{
bbox.r_xbot = proprec->prop_value.prop_integer[0];
bbox.r_ybot = proprec->prop_value.prop_integer[1];
bbox.r_xtop = proprec->prop_value.prop_integer[2];
bbox.r_ytop = proprec->prop_value.prop_integer[3];
}
else
{
TxError("Unable to parse the cell's FIXED_BBOX property; using "
"the instance bounding box instead.\n");
bbox = use->cu_def->cd_bbox;
}
}
GeoTransRect(trans, &bbox, &refbox);
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
refllx = DBWPrintValue(refbox.r_xbot, (MagWindow *)NULL, TRUE);
reflly = DBWPrintValue(refbox.r_ybot, (MagWindow *)NULL, FALSE);
refurx = DBWPrintValue(refbox.r_xtop, (MagWindow *)NULL, TRUE);
refury = DBWPrintValue(refbox.r_ytop, (MagWindow *)NULL, FALSE);
#ifdef MAGIC_WRAPPER
if (*dolist)
{
pobj = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refllx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(reflly, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refurx, -1));
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refury, -1));
Tcl_SetObjResult(magicinterp, pobj);
}
else
#endif
TxPrintf("Abutment box: %s %s %s %s\n", refllx, reflly, refurx, refury);
return 0;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -1709,9 +1221,8 @@ DBCellLookDef(cellName)
{ {
HashEntry *entry; HashEntry *entry;
entry = HashLookOnly(&dbCellDefTable, cellName); entry = HashFind(&dbCellDefTable, cellName);
if (entry == (HashEntry *)NULL) return (CellDef *)NULL; return ((CellDef *) HashGetValue(entry));
return (CellDef *)HashGetValue(entry);
} }
@ -1755,7 +1266,7 @@ DBCellNewDef(cellName)
cellName = UNNAMED; cellName = UNNAMED;
entry = HashFind(&dbCellDefTable, cellName); entry = HashFind(&dbCellDefTable, cellName);
if (HashGetValue(entry) != NULL) if (HashGetValue(entry) != (ClientData) NULL)
return ((CellDef *) NULL); return ((CellDef *) NULL);
cellDef = DBCellDefAlloc(); cellDef = DBCellDefAlloc();
@ -1916,7 +1427,7 @@ DBCellRenameDef(cellDef, newName)
ASSERT(HashGetValue(oldEntry) == (ClientData) cellDef, "DBCellRenameDef"); ASSERT(HashGetValue(oldEntry) == (ClientData) cellDef, "DBCellRenameDef");
newEntry = HashFind(&dbCellDefTable, newName); newEntry = HashFind(&dbCellDefTable, newName);
if (HashGetValue(newEntry) != NULL) if (HashGetValue(newEntry) != (ClientData) NULL)
return (FALSE); return (FALSE);
HashSetValue(oldEntry, (ClientData) NULL); HashSetValue(oldEntry, (ClientData) NULL);
@ -1962,7 +1473,6 @@ DBCellDeleteDef(cellDef)
entry = HashFind(&dbCellDefTable, cellDef->cd_name); entry = HashFind(&dbCellDefTable, cellDef->cd_name);
ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef"); ASSERT(HashGetValue(entry) == (ClientData) cellDef, "DBCellDeleteDef");
HashSetValue(entry, (ClientData) NULL); HashSetValue(entry, (ClientData) NULL);
HashRemove(&dbCellDefTable, cellDef->cd_name);
if (cellDef->cd_props) if (cellDef->cd_props)
DBPropClearAll(cellDef); DBPropClearAll(cellDef);
@ -2024,10 +1534,8 @@ DBCellDefFree(cellDef)
cellDef->cd_planes[pNum] = (Plane *) NULL; cellDef->cd_planes[pNum] = (Plane *) NULL;
} }
free_magic1_t mm1 = freeMagic1_init();
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next) for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
freeMagic1(&mm1, (char *) lab); freeMagic((char *) lab);
freeMagic1_end(&mm1);
SigEnableInterrupts(); SigEnableInterrupts();
HashKill(&cellDef->cd_idHash); HashKill(&cellDef->cd_idHash);
@ -2161,14 +1669,6 @@ DBCellSrDefs(pattern, func, cdata)
* This operation is not recorded on the undo list, as it always accompanies * This operation is not recorded on the undo list, as it always accompanies
* the creation of a new cell use. * the creation of a new cell use.
* *
* *** ANOTHER WARNING ***
*
* Do NOT pass a NULL cu_id to this routine when doing bulk cell copies,
* because an entire hash table of entries for the parent def will be created
* and searched for every cell being linked, making the routine run-time
* exponential with the number of links. It is better to run
* DBGenerateUniqueIDs() instead.
*
* Results: * Results:
* TRUE if the CellUse is unique within the parent CellDef, FALSE * TRUE if the CellUse is unique within the parent CellDef, FALSE
* if there would be a name conflict. If the cu_id of the CellUse * if there would be a name conflict. If the cu_id of the CellUse
@ -2354,14 +1854,8 @@ DBFindUse(id, parentDef)
he = HashLookOnly(&parentDef->cd_idHash, id); he = HashLookOnly(&parentDef->cd_idHash, id);
if (delimit != NULL) *delimit = '['; if (delimit != NULL) *delimit = '[';
if (he == NULL) 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); return (CellUse *) HashGetValue(he);
} }
@ -2409,50 +1903,6 @@ DBGenerateUniqueIds(def, warn)
HashKill(&dbUniqueNameTable); 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);
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -2484,9 +1934,8 @@ dbFindNamesFunc(use, parentDef)
he = HashFind(&dbUniqueNameTable, use->cu_id); he = HashFind(&dbUniqueNameTable, use->cu_id);
if (HashGetValue(he)) if (HashGetValue(he))
{ {
if (dbWarnUniqueIds) TxError("Duplicate instance-id for cell %s (%s) will be renamed\n",
TxError("Duplicate instance-id for cell %s (%s) will be renamed\n", use->cu_def->cd_name, use->cu_id);
use->cu_def->cd_name, use->cu_id);
DBUnLinkCell(use, parentDef); DBUnLinkCell(use, parentDef);
freeMagic(use->cu_id); freeMagic(use->cu_id);
use->cu_id = (char *) NULL; use->cu_id = (char *) NULL;
@ -2611,7 +2060,7 @@ DBUnLinkCell(use, parentDef)
{ {
HashEntry *he; HashEntry *he;
if ((he = HashLookOnly(&parentDef->cd_idHash, use->cu_id))) if (he = HashLookOnly(&parentDef->cd_idHash, use->cu_id))
HashSetValue(he, (ClientData) NULL); HashSetValue(he, (ClientData) NULL);
} }
@ -2629,7 +2078,7 @@ DBUnLinkCell(use, parentDef)
* Side effects: * Side effects:
* Fills in *pydef with a newly created CellDef by that name, and * Fills in *pydef with a newly created CellDef by that name, and
* *pyuse with a newly created CellUse pointing to the new def. * *pyuse with a newly created CellUse pointing to the new def.
* The CellDef pointed to by *pydef has the CDINTERNAL flag * The CellDef pointed to by *pydef has the CD_INTERNAL flag
* set, and is marked as being available. * set, and is marked as being available.
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------

View File

@ -21,8 +21,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/malloc.h" #include "utils/malloc.h"
@ -76,25 +74,19 @@ struct seeTypesArg
* Returns 1 if the func() returns 1; otherwise returns 0 to keep the * Returns 1 if the func() returns 1; otherwise returns 0 to keep the
* search alive. * search alive.
* *
* NOTE: struct BPEnum has an array size 10000, causing this routine to
* take up a half megabyte of stack space if the variable is declared
* inside the local frame. Use mallocMagic() instead.
*----------------------------------------------------------------------------- *-----------------------------------------------------------------------------
*/ */
int int
DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg) DBSrCellPlaneArea(BPlane *plane, Rect *rect, int (*func)(), ClientData arg)
{ {
BPEnum sbpe; BPEnum bpe;
BPEnum *bpe;
CellUse *use; CellUse *use;
int rval = 0; int rval = 0;
/* bpe = (BPEnum *)mallocMagic(sizeof(BPEnum)); */ BPEnumInit(&bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
bpe = &sbpe;
BPEnumInit(bpe, plane, rect, BPE_OVERLAP, "DBSrCellPlaneArea");
while ((use = BPEnumNext(bpe))) while (use = BPEnumNext(&bpe))
{ {
if ((*func)(use, arg)) if ((*func)(use, arg))
{ {
@ -103,8 +95,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
} }
} }
BPEnumTerm(bpe); BPEnumTerm(&bpe);
/* freeMagic(bpe); */
return rval; return rval;
} }
@ -120,7 +111,6 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
* int * int
* func(tile, cxp) * func(tile, cxp)
* Tile *tile; * Tile *tile;
* TileType dinfo;
* TreeContext *cxp; * TreeContext *cxp;
* { * {
* } * }
@ -245,8 +235,10 @@ dbCellPlaneSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0; return 0;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, TRUE, TRUE, NULL)) {
return 0; bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
context.tc_scx = scx; context.tc_scx = scx;
context.tc_filter = fp; context.tc_filter = fp;
@ -365,8 +357,10 @@ dbCellUniqueTileSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0; return 0;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, TRUE, TRUE, NULL)) {
return 0; bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
context.tc_scx = scx; context.tc_scx = scx;
context.tc_filter = fp; context.tc_filter = fp;
@ -417,7 +411,6 @@ dbCellUniqueTileSrFunc(scx, fp)
* int * int
* func(tile, cxp) * func(tile, cxp)
* Tile *tile; * Tile *tile;
* TileType dinfo;
* TreeContext *cxp; * TreeContext *cxp;
* { * {
* } * }
@ -476,8 +469,10 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg)
return 0; return 0;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, TRUE, TRUE, NULL)) {
return 0; bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
filter.tf_func = func; filter.tf_func = func;
filter.tf_arg = cdarg; filter.tf_arg = cdarg;
@ -585,26 +580,9 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels"); ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels");
if (!DBDescendSubcell(cellUse, xMask)) return 0; if (!DBDescendSubcell(cellUse, xMask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, TRUE, TRUE, NULL))
return 0;
if (flags & TF_LABEL_REVERSE_SEARCH)
{ {
/* Search children first */ bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
filter.tf_func = func; if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
filter.tf_arg = cdarg;
filter.tf_mask = mask;
filter.tf_xmask = xMask;
filter.tf_tpath = tpath;
filter.tf_flags = flags;
scx2 = *scx;
if (scx2.scx_area.r_xbot > TiPlaneRect.r_xbot) scx2.scx_area.r_xbot -= 1;
if (scx2.scx_area.r_ybot > TiPlaneRect.r_ybot) scx2.scx_area.r_ybot -= 1;
if (scx2.scx_area.r_xtop < TiPlaneRect.r_xtop) scx2.scx_area.r_xtop += 1;
if (scx2.scx_area.r_ytop < TiPlaneRect.r_ytop) scx2.scx_area.r_ytop += 1;
if (DBCellSrArea(&scx2, dbCellLabelSrFunc, (ClientData) &filter))
return 1;
} }
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)
@ -642,8 +620,8 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
r1.r_ybot = r->r_ytop; r1.r_ybot = r->r_ytop;
r2.r_xbot = r->r_xtop; r2.r_xbot = r->r_xtop;
} }
is_touching = GEO_TOUCH(&lab->lab_rect, &r1) || is_touching = GEO_TOUCH(&lab->lab_bbox, &r1) ||
GEO_TOUCH(&lab->lab_rect, &r2); GEO_TOUCH(&lab->lab_bbox, &r2);
} }
else else
is_touching = GEO_TOUCH(&lab->lab_rect, r); is_touching = GEO_TOUCH(&lab->lab_rect, r);
@ -659,8 +637,6 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
return (1); return (1);
} }
if (flags & TF_LABEL_REVERSE_SEARCH) return 0; /* children already searched */
filter.tf_func = func; filter.tf_func = func;
filter.tf_arg = cdarg; filter.tf_arg = cdarg;
filter.tf_mask = mask; filter.tf_mask = mask;
@ -702,7 +678,7 @@ dbCellLabelSrFunc(scx, fp)
{ {
Label *lab; Label *lab;
Rect *r = &scx->scx_area; Rect *r = &scx->scx_area;
const TileTypeBitMask *mask = fp->tf_mask; TileTypeBitMask *mask = fp->tf_mask;
CellDef *def = scx->scx_use->cu_def; CellDef *def = scx->scx_use->cu_def;
char *tnext; char *tnext;
int result; int result;
@ -711,36 +687,24 @@ dbCellLabelSrFunc(scx, fp)
ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc"); ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc");
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 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))
{ {
if (fp->tf_tpath != (TerminalPath *) NULL) bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
{ if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
TerminalPath *tp = fp->tf_tpath;
tnext = tp->tp_next;
tp->tp_next = DBPrintUseId(scx, tp->tp_next, tp->tp_last-tp->tp_next,
FALSE);
if (tp->tp_next < tp->tp_last)
{
*(tp->tp_next++) = '/';
*(tp->tp_next) = '\0';
}
}
} }
/* If fp->tf_flags has TF_LABEL_REVERSE_SEARCH, then search child if (fp->tf_tpath != (TerminalPath *) NULL)
* uses first, then the parent. This is for display, so that if {
* a child cell and parent cell have overlapping labels, the parent TerminalPath *tp = fp->tf_tpath;
* label is the one on top.
*/
if (fp->tf_flags & TF_LABEL_REVERSE_SEARCH) tnext = tp->tp_next;
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp)) tp->tp_next = DBPrintUseId(scx, tp->tp_next, tp->tp_last-tp->tp_next,
result = 1; FALSE);
if (tp->tp_next < tp->tp_last)
{
*(tp->tp_next++) = '/';
*(tp->tp_next) = '\0';
}
}
/* Apply the function first to any of the labels in this def. */ /* Apply the function first to any of the labels in this def. */
@ -763,11 +727,9 @@ dbCellLabelSrFunc(scx, fp)
} }
} }
/* Now visit each child use recursively, if not doing a reverse search */ /* Now visit each child use recursively */
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH)) result = 1;
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
result = 1;
cleanup: cleanup:
/* Remove the trailing pathname component from the TerminalPath */ /* Remove the trailing pathname component from the TerminalPath */
@ -805,9 +767,6 @@ cleanup:
* remaining elements of the current array are skipped, but the * remaining elements of the current array are skipped, but the
* search is not aborted. * search is not aborted.
* *
* NOTE: Unlike DBTreeSrTiles and DBTreeSrLabels, the function is not
* applied to the top level cell, only to descendents.
*
* Each element of an array is returned separately. * Each element of an array is returned separately.
* *
* Results: * Results:
@ -845,8 +804,11 @@ DBTreeSrCells(scx, xMask, func, cdarg)
if (!DBDescendSubcell(cellUse, xMask)) if (!DBDescendSubcell(cellUse, xMask))
return 0; return 0;
if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0) if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(cellUse->cu_def, TRUE, TRUE, NULL)) {
bool dereference = (cellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0; return 0;
}
context.tc_scx = scx; context.tc_scx = scx;
context.tc_filter = &filter; context.tc_filter = &filter;
@ -885,22 +847,20 @@ dbTreeCellSrFunc(scx, fp)
if ((fp->tf_xmask == CU_DESCEND_NO_LOCK) && (use->cu_flags & CU_LOCKED)) if ((fp->tf_xmask == CU_DESCEND_NO_LOCK) && (use->cu_flags & CU_LOCKED))
return 2; return 2;
else if (!DBDescendSubcell(use, fp->tf_xmask)) else if ((!DBDescendSubcell(use, fp->tf_xmask)) ||
return (*fp->tf_func)(scx, fp->tf_arg); (fp->tf_xmask == CU_DESCEND_ALL))
result = (*fp->tf_func)(scx, fp->tf_arg);
else else
{ {
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(use->cu_def, TRUE, TRUE, NULL)) {
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0; return 0;
}
result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
} }
if (fp->tf_xmask == CU_DESCEND_ALL) return result;
{
result = (*fp->tf_func)(scx, fp->tf_arg);
if (result != 0) return result;
}
/* Run recursively on children in search area */
return DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
} }
/* /*
@ -949,9 +909,8 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
*/ */
int int
dbSeeTypesAllSrFunc(tile, dinfo, cxp) dbSeeTypesAllSrFunc(tile, cxp)
Tile *tile; Tile *tile;
TileType dinfo;
TreeContext *cxp; TreeContext *cxp;
{ {
Rect tileRect; Rect tileRect;
@ -962,7 +921,7 @@ dbSeeTypesAllSrFunc(tile, dinfo, cxp)
if (GEO_OVERLAP((&tileRect), area)) if (GEO_OVERLAP((&tileRect), area))
{ {
if (IsSplit(tile)) if (IsSplit(tile))
TTMaskSetType(mask, (dinfo & TT_SIDE) ? TTMaskSetType(mask, SplitSide(tile) ?
SplitRightType(tile) : SplitLeftType(tile)); SplitRightType(tile) : SplitLeftType(tile));
else else
TTMaskSetType(mask, TiGetType(tile)); TTMaskSetType(mask, TiGetType(tile));
@ -1148,8 +1107,12 @@ DBCellSrArea(scx, func, cdarg)
context.tc_scx = scx; context.tc_scx = scx;
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(scx->scx_use->cu_def, TRUE, TRUE, NULL)) {
bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0; return 0;
}
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane, if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
&scx->scx_area, dbCellSrFunc, (ClientData) &context)) &scx->scx_area, dbCellSrFunc, (ClientData) &context))
@ -1271,9 +1234,10 @@ DBCellEnum(cellDef, func, cdarg)
filter.tf_func = func; filter.tf_func = func;
filter.tf_arg = cdarg; filter.tf_arg = cdarg;
if ((cellDef->cd_flags & CDAVAILABLE) == 0) if ((cellDef->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(cellDef, TRUE, TRUE, NULL)) {
return 0; bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (DBSrCellPlaneArea(cellDef->cd_cellPlane, if (DBSrCellPlaneArea(cellDef->cd_cellPlane,
&TiPlaneRect, dbEnumFunc, (ClientData) &filter)) &TiPlaneRect, dbEnumFunc, (ClientData) &filter))
return 1; return 1;
@ -1537,6 +1501,8 @@ DBScaleEverything(scalen, scaled)
int dbCellDefEnumFunc(); int dbCellDefEnumFunc();
LinkedCellDef *lhead, *lcd; LinkedCellDef *lhead, *lcd;
// DBUpdateStamps();
SigDisableInterrupts(); SigDisableInterrupts();
lhead = NULL; lhead = NULL;
@ -1552,22 +1518,19 @@ DBScaleEverything(scalen, scaled)
} }
/* Free the linked CellDef list */ /* Free the linked CellDef list */
free_magic1_t mm1 = freeMagic1_init();
lcd = lhead; lcd = lhead;
while (lcd != NULL) while (lcd != NULL)
{ {
freeMagic1(&mm1, (char *)lcd); freeMagic((char *)lcd);
lcd = lcd->cd_next; lcd = lcd->cd_next;
} }
freeMagic1_end(&mm1);
/* Scale all elements */ /* Scale all elements */
DBWScaleElements(scalen, scaled); DBWScaleElements(scalen, scaled);
#ifdef ROUTE_MODULE
/* Recovery of global plane pointers */ /* Recovery of global plane pointers */
MZAttachHintPlanes(); MZAttachHintPlanes();
#endif
/* Modify root box */ /* Modify root box */
ToolScaleBox(scalen, scaled); ToolScaleBox(scalen, scaled);
@ -1643,9 +1606,8 @@ dbScalePlane(oldplane, newplane, pnum, scalen, scaled, doCIF)
*/ */
int int
dbTileScaleFunc(tile, dinfo, scvals) dbTileScaleFunc(tile, scvals)
Tile *tile; Tile *tile;
TileType dinfo;
struct scaleArg *scvals; struct scaleArg *scvals;
{ {
TileType type; TileType type;
@ -1663,20 +1625,17 @@ dbTileScaleFunc(tile, dinfo, scvals)
if ((targetRect.r_xtop - targetRect.r_xbot == 0) || if ((targetRect.r_xtop - targetRect.r_xbot == 0) ||
(targetRect.r_ytop - targetRect.r_ybot == 0)) (targetRect.r_ytop - targetRect.r_ybot == 0))
{ {
TxPrintf("Tile %p at (%d, %d) has zero area after scaling: Removed.\n", TxPrintf("Tile 0x%x at (%d, %d) has zero area after scaling: Removed.\n",
(void *) tile, targetRect.r_xbot, targetRect.r_ybot); tile, targetRect.r_xbot, targetRect.r_ybot);
return 0; return 0;
} }
type = TiGetTypeExact(tile) | dinfo; type = TiGetTypeExact(tile);
exact = type; exact = type;
if (IsSplit(tile)) if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(scvals->ptarget, exact, &targetRect, DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
( ((scvals->doCIF) ? CIFPaintTable :
#ifdef CIF_MODULE
(scvals->doCIF) ? CIFPaintTable :
#endif
DBStdPaintTbl(type, scvals->pnum)), DBStdPaintTbl(type, scvals->pnum)),
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);
return 0; return 0;
@ -1726,9 +1685,8 @@ dbMovePlane(oldplane, newplane, pnum, origx, origy)
*/ */
int int
dbTileMoveFunc(tile, dinfo, mvvals) dbTileMoveFunc(tile, mvvals)
Tile *tile; Tile *tile;
TileType dinfo;
struct moveArg *mvvals; struct moveArg *mvvals;
{ {
TileType type; TileType type;
@ -1741,12 +1699,12 @@ dbTileMoveFunc(tile, dinfo, mvvals)
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy); DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy); DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
type = TiGetTypeExact(tile) | dinfo; type = TiGetTypeExact(tile);
exact = type; exact = type;
if (IsSplit(tile)) if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect, DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum), DBStdPaintTbl(type, mvvals->pnum),
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);
return 0; return 0;
} }
@ -1808,139 +1766,15 @@ DBSrCellUses(cellDef, func, arg)
} }
/* Free this linked cellUse structure */ /* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead; lu = luhead;
while (lu != NULL) while (lu != NULL)
{ {
freeMagic1(&mm1, (char *)lu); freeMagic((char *)lu);
lu = lu->cu_next; lu = lu->cu_next;
} }
freeMagic1_end(&mm1);
return retval; return retval;
} }
/* Structure used by dbScaleProp() and dbMoveProp() */
typedef struct _cellpropstruct {
Point cps_point;
CellDef *cps_def;
} CellPropStruct;
/*
* ----------------------------------------------------------------------------
*
* dbScaleProp --
*
* Callback function for dbScaleCell. Finds properties that represent
* 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.
*
* ----------------------------------------------------------------------------
*/
int dbScaleProp(name, proprec, cps)
char *name;
PropertyRecord *proprec;
CellPropStruct *cps;
{
int i, scalen, scaled;
Point p;
/* Only "dimension" and "plane" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData)TT_SPACE);
DBClearPaintPlane(newplane);
/* Plane index is unused; arbitrarily substitute -1 */
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
scalen, scaled, TRUE);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
/* Scale numerator held in point X value, */
/* scale denominator held in point Y value */
scalen = cps->cps_point.p_x;
scaled = cps->cps_point.p_y;
for (i = 0; i < proprec->prop_len; i += 2)
{
if ((i + 1) >= proprec->prop_len) break;
p.p_x = proprec->prop_value.prop_integer[i];
p.p_y = proprec->prop_value.prop_integer[i + 1];
DBScalePoint(&p, scalen, scaled);
proprec->prop_value.prop_integer[i] = p.p_x;
proprec->prop_value.prop_integer[i + 1] = p.p_y;
}
return 0; /* Keep enumerating through properties */
}
/*
* ----------------------------------------------------------------------------
*
* dbMoveProp --
*
* Callback function for ??. Finds properties that represent
* internal geometry (*_BBOX and MASKHINTS_*) and modifies the values
* by the X, Y values passed as a pointer to a Point structure in ClientData.
*
* ----------------------------------------------------------------------------
*/
int dbMoveProp(name, proprec, cps)
char *name;
PropertyRecord *proprec;
CellPropStruct *cps;
{
int i, origx, origy;
char *newvalue;
Point p;
/* Only "dimension" and "plane" type properties get scaled */
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
{
Plane *newplane;
newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane);
/* Use plane index -1 to indicate use of CIFPaintTable */
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
DBFreePaintPlane(proprec->prop_value.prop_plane);
TiFreePlane(proprec->prop_value.prop_plane);
proprec->prop_value.prop_plane = newplane;
return 0;
}
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
origx = cps->cps_point.p_x;
origy = cps->cps_point.p_y;
for (i = 0; i < proprec->prop_len; i += 2)
{
if ((i + 1) >= proprec->prop_len) break;
p.p_x = proprec->prop_value.prop_integer[i];
p.p_y = proprec->prop_value.prop_integer[i + 1];
DBMovePoint(&p, origx, origy);
proprec->prop_value.prop_integer[i] = p.p_x;
proprec->prop_value.prop_integer[i + 1] = p.p_y;
}
return 0; /* Keep enumerating through properties */
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -1965,7 +1799,6 @@ dbScaleCell(cellDef, scalen, scaled)
LinkedCellUse *luhead, *lu; LinkedCellUse *luhead, *lu;
Plane *newplane; Plane *newplane;
BPlane *cellPlane, *cellPlaneOrig; BPlane *cellPlane, *cellPlaneOrig;
CellPropStruct cps;
/* DBCellEnum() attempts to read unavailable celldefs. We don't */ /* DBCellEnum() attempts to read unavailable celldefs. We don't */
/* want to do that here, so check CDAVAILABLE flag first. */ /* want to do that here, so check CDAVAILABLE flag first. */
@ -2021,14 +1854,12 @@ dbScaleCell(cellDef, scalen, scaled)
BPFree(cellPlaneOrig); BPFree(cellPlaneOrig);
/* Free this linked cellUse structure */ /* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead; lu = luhead;
while (lu != NULL) while (lu != NULL)
{ {
freeMagic1(&mm1, (char *)lu); freeMagic((char *)lu);
lu = lu->cu_next; lu = lu->cu_next;
} }
freeMagic1_end(&mm1);
/* Scale all of the paint tiles in this cell by creating a new plane */ /* 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. */ /* and copying all tiles into the new plane at scaled dimensions. */
@ -2080,21 +1911,31 @@ donecell:
DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled); DBScalePoint(&cellDef->cd_extended.r_ll, scalen, scaled);
DBScalePoint(&cellDef->cd_extended.r_ur, scalen, scaled); DBScalePoint(&cellDef->cd_extended.r_ur, scalen, scaled);
/* Check all properties for ones with keys beginning with "MASKHINTS_" /* If the cell is an abstract view with a fixed bounding box, then */
* or ending with "_BBOX", and scale them by the same amount as all /* adjust the bounding box property to match the new scale. */
* 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; if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
cps.cps_point.p_y = scaled; {
cps.cps_def = cellDef; Rect r;
DBPropEnum(cellDef, dbScaleProp, &cps); 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);
}
}
}
return 0; return 0;
} }
@ -2182,7 +2023,6 @@ DBMoveCell(cellDef, origx, origy)
LinkedCellUse *luhead, *lu; LinkedCellUse *luhead, *lu;
Plane *newplane; Plane *newplane;
BPlane *cellPlane, *cellPlaneOrig; BPlane *cellPlane, *cellPlaneOrig;
CellPropStruct cps;
/* Unlike dbScaleCell(), this routine is only run on valid edit defs */ /* Unlike dbScaleCell(), this routine is only run on valid edit defs */
@ -2231,14 +2071,12 @@ DBMoveCell(cellDef, origx, origy)
BPFree(cellPlaneOrig); BPFree(cellPlaneOrig);
/* Free this linked cellUse structure */ /* Free this linked cellUse structure */
free_magic1_t mm1 = freeMagic1_init();
lu = luhead; lu = luhead;
while (lu != NULL) while (lu != NULL)
{ {
freeMagic1(&mm1, (char *)lu); freeMagic((char *)lu);
lu = lu->cu_next; lu = lu->cu_next;
} }
freeMagic1_end(&mm1);
/* Move all of the paint tiles in this cell by creating a new plane */ /* 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. */ /* and copying all tiles into the new plane at the new position. */
@ -2249,7 +2087,7 @@ DBMoveCell(cellDef, origx, origy)
newplane = DBNewPlane((ClientData) TT_SPACE); newplane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(newplane); DBClearPaintPlane(newplane);
if (dbMovePlane(cellDef->cd_planes[pNum], newplane, pNum, if (dbMovePlane(cellDef->cd_planes[pNum], newplane, pNum,
origx, origy)) origx, origy, FALSE))
cellDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP); cellDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
DBFreePaintPlane(cellDef->cd_planes[pNum]); DBFreePaintPlane(cellDef->cd_planes[pNum]);
TiFreePlane(cellDef->cd_planes[pNum]); TiFreePlane(cellDef->cd_planes[pNum]);
@ -2282,15 +2120,31 @@ donecell:
DBMovePoint(&cellDef->cd_extended.r_ll, origx, origy); DBMovePoint(&cellDef->cd_extended.r_ll, origx, origy);
DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy); DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy);
/* Check all properties for ones with keys beginning with "MASKHINTS_" /* If the cell is an abstract view with a fixed bounding box, then */
* or ending with "_BBOX", and move them by the same amount as all /* adjust the bounding box property to match the new scale. */
* the geometry.
*/
cps.cps_point.p_x = origx; if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
cps.cps_point.p_y = origy; {
cps.cps_def = cellDef; Rect r;
DBPropEnum(cellDef, dbMoveProp, &cps); 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)
{
DBMovePoint(&r.r_ll, origx, origy);
DBMovePoint(&r.r_ur, origx, origy);
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);
}
}
}
return 0; return 0;
} }

View File

@ -64,8 +64,6 @@ DBDescendSubcell(use, xMask)
CellUse *use; CellUse *use;
unsigned int xMask; unsigned int xMask;
{ {
bool propfound;
/* Check single bit (window ID) or zero */ /* Check single bit (window ID) or zero */
if (((xMask - 1) & xMask) == 0) if (((xMask - 1) & xMask) == 0)
return ((use->cu_expandMask & xMask) == xMask); return ((use->cu_expandMask & xMask) == xMask);
@ -76,9 +74,12 @@ DBDescendSubcell(use, xMask)
case CU_DESCEND_NO_SUBCKT: case CU_DESCEND_NO_SUBCKT:
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(use->cu_def, TRUE, TRUE, NULL)) {
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return FALSE; return FALSE;
}
return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE; return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE;
case CU_DESCEND_NO_LOCK: case CU_DESCEND_NO_LOCK:
@ -90,16 +91,6 @@ DBDescendSubcell(use, xMask)
case CU_DESCEND_NO_VENDOR: case CU_DESCEND_NO_VENDOR:
return (use->cu_def->cd_flags & CDVENDORGDS) ? FALSE : TRUE; return (use->cu_def->cd_flags & CDVENDORGDS) ? FALSE : TRUE;
case CU_DESCEND_PROP_FLAT:
if (use->cu_expandMask == CU_DESCEND_SPECIAL)
return TRUE;
else
{
/* Descend only into cells marked with property "flatten" */
DBPropGet(use->cu_def, "flatten", &propfound);
return (propfound) ? TRUE : FALSE;
}
case CU_DESCEND_NONE: case CU_DESCEND_NONE:
return FALSE; return FALSE;
} }
@ -113,7 +104,7 @@ DBDescendSubcell(use, xMask)
* *
* Copies the contents of the CellDef pointed to by sourceDef into the * Copies the contents of the CellDef pointed to by sourceDef into the
* CellDef pointed to by destDef. Only the planes, labels, flags, * CellDef pointed to by destDef. Only the planes, labels, flags,
* cell plane, use-id hash table, and bounding box are copied. * use-id hash table, and bounding box are copied.
* *
* Results: * Results:
* None. * None.
@ -140,8 +131,6 @@ DBCellCopyDefBody(sourceDef, destDef)
for (i = 0; i < MAXPLANES; i++) for (i = 0; i < MAXPLANES; i++)
destDef->cd_planes[i] = sourceDef->cd_planes[i]; destDef->cd_planes[i] = sourceDef->cd_planes[i];
destDef->cd_cellPlane = sourceDef->cd_cellPlane;
/* Be careful to update parent pointers in the children of dest. /* Be careful to update parent pointers in the children of dest.
* Don't allow interrupts to wreck this. * Don't allow interrupts to wreck this.
*/ */
@ -218,10 +207,8 @@ DBCellClearDef(cellDef)
cellDef->cd_bbox.r_xtop = cellDef->cd_bbox.r_ytop = 1; 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_xbot = cellDef->cd_extended.r_ybot = 0;
cellDef->cd_extended.r_xtop = cellDef->cd_extended.r_ytop = 1; 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) for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
freeMagic1(&mm1, (char *) lab); freeMagic((char *) lab);
freeMagic1_end(&mm1);
cellDef->cd_labels = (Label *) NULL; cellDef->cd_labels = (Label *) NULL;
cellDef->cd_lastLabel = (Label *) NULL; cellDef->cd_lastLabel = (Label *) NULL;
@ -264,7 +251,7 @@ DBClearPaintPlane(plane)
/* Allocate a new central space tile */ /* Allocate a new central space tile */
newCenterTile = TiAlloc(); newCenterTile = TiAlloc();
PlaneSetHint(plane, newCenterTile); plane->pl_hint = newCenterTile;
TiSetBody(newCenterTile, TT_SPACE); TiSetBody(newCenterTile, TT_SPACE);
dbSetPlaneTile(plane, newCenterTile); dbSetPlaneTile(plane, newCenterTile);
} }

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -39,7 +39,6 @@ struct expandArg
{ {
bool ea_deref; /* TRUE if root def dereference flag is set */ bool ea_deref; /* TRUE if root def dereference flag is set */
int ea_xmask; /* Expand mask. */ int ea_xmask; /* Expand mask. */
int ea_type; /* Expand, unexpand, or toggle */
int (*ea_func)(); /* Function to call for each cell whose int (*ea_func)(); /* Function to call for each cell whose
* status is changed. * status is changed.
*/ */
@ -68,29 +67,23 @@ struct expandArg
*/ */
void void
DBExpand(cellUse, expandMask, expandType) DBExpand(cellUse, expandMask, expandFlag)
CellUse *cellUse; CellUse *cellUse;
int expandMask; int expandMask;
int expandType; bool expandFlag;
{ {
CellDef *def; CellDef *def;
bool expandFlag, expandTest;
if (DBDescendSubcell(cellUse, expandMask) == expandFlag)
expandTest = DBDescendSubcell(cellUse, expandMask); return;
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE)
expandFlag = expandTest;
else
{
expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE;
if (expandFlag == expandTest) return;
}
if (expandFlag) if (expandFlag)
{ {
def = cellUse->cu_def; def = cellUse->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
{ {
if (!DBCellRead(def, TRUE, TRUE, NULL)) bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
return; return;
/* Note: we don't have to recompute the bbox here, because /* Note: we don't have to recompute the bbox here, because
* if it changed, then a timestamp violation must have occurred * if it changed, then a timestamp violation must have occurred
@ -138,44 +131,51 @@ DBExpand(cellUse, expandMask, expandType)
*/ */
void void
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg) DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
CellUse *rootUse; /* Root cell use from which search begins */ CellUse *rootUse; /* Root cell use from which search begins */
Rect *rootRect; /* Area to be expanded, in root coordinates */ Rect *rootRect; /* Area to be expanded, in root coordinates */
int expandMask; /* Window mask in which cell is to be expanded */ int expandMask; /* Window mask in which cell is to be expanded */
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */ bool expandFlag; /* TRUE => expand, FALSE => unexpand */
int (*func)(); /* Function to call for each cell whose expansion int (*func)(); /* Function to call for each cell whose expansion
* status is modified. NULL means don't call anyone. * status is modified. NULL means don't call anyone.
*/ */
ClientData cdarg; /* Argument to pass to func. */ ClientData cdarg; /* Argument to pass to func. */
{ {
int dbExpandFunc(); int dbExpandFunc(), dbUnexpandFunc();
SearchContext scontext; SearchContext scontext;
struct expandArg arg; struct expandArg arg;
bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0) if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0)
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL); {
(void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, dereference, NULL);
}
/* /*
* Walk through the area and set the expansion state appropriately. * Walk through the area and set the expansion state
* appropriately.
*/ */
arg.ea_xmask = expandMask; arg.ea_xmask = expandMask;
arg.ea_func = func; arg.ea_func = func;
arg.ea_arg = cdarg; arg.ea_arg = cdarg;
arg.ea_type = expandType; arg.ea_deref = dereference;
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
scontext.scx_use = rootUse; scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform; scontext.scx_trans = GeoIdentityTransform;
scontext.scx_area = *rootRect; scontext.scx_area = *rootRect;
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg); if (expandFlag)
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
else
DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg);
} }
/* /*
* dbExpandFunc -- * dbExpandFunc --
* *
* Filter function called by DBCellSrArea on behalf of DBExpandAll above * Filter function called by DBCellSrArea on behalf of DBExpandAll above
* when cells are being expanded, unexpanded, or toggled. * when cells are being expanded.
*/ */
int int
@ -189,55 +189,64 @@ dbExpandFunc(scx, arg)
{ {
CellUse *childUse = scx->scx_use; CellUse *childUse = scx->scx_use;
int n = DBLambda[1]; int n = DBLambda[1];
int expandTest;
int expandType = (arg->ea_type & DB_EXPAND_MASK);
int expandSurround = (arg->ea_type & DB_EXPAND_SURROUND_MASK);
bool surround;
expandTest = DBDescendSubcell(childUse, arg->ea_xmask);
/* /*
* Change the expansion status of this cell if necessary. Call the * Change the expansion status of this cell if necessary. Call the
* client's function if the expansion status has changed. * client's function if the expansion status has changed.
*/ */
if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE))) if (!DBDescendSubcell(childUse, arg->ea_xmask))
{ {
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) /* If the cell is unavailable, then don't expand it.
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox)); */
if (surround || (expandSurround == DB_EXPAND_OVERLAP)) if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
{ if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, arg->ea_deref, NULL))
/* If the cell is unavailable, then don't expand it.
*/
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
{ {
/* If the parent is dereferenced, then the child should be, too */ TxError("Cell %s is unavailable. It could not be expanded.\n",
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE; childUse->cu_def->cd_name);
if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL)) return 2;
{
TxError("Cell %s is unavailable. It could not be expanded.\n",
childUse->cu_def->cd_name);
return 2;
}
} }
childUse->cu_expandMask |= arg->ea_xmask; childUse->cu_expandMask |= arg->ea_xmask;
expandTest = TRUE; if (arg->ea_func != NULL)
if (arg->ea_func != NULL) {
{ if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
}
} }
} }
else if (expandTest && ((expandType == DB_UNEXPAND) ||
(expandType == DB_EXPAND_TOGGLE))) if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
return 1;
return 2;
}
/*
* dbUnexpandFunc --
*
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
* when cells are being unexpanded.
*/
int
dbUnexpandFunc(scx, arg)
SearchContext *scx; /* Pointer to search context containing
* child use, search area in coor-
* dinates of the child use, and
* transform back to "root".
*/
struct expandArg *arg; /* Client data from caller */
{
CellUse *childUse = scx->scx_use;
/*
* Change the expansion status of this cell if necessary.
*/
if (DBDescendSubcell(childUse, arg->ea_xmask))
{ {
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox)); || GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox))
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
{ {
childUse->cu_expandMask &= ~arg->ea_xmask; childUse->cu_expandMask &= ~arg->ea_xmask;
expandTest = FALSE;
/* Call the client's function, if there is one. */ /* Call the client's function, if there is one. */
@ -248,7 +257,11 @@ dbExpandFunc(scx, arg)
} }
} }
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg)) /* Don't recursively search things that aren't already expanded. */
else return 2;
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
return 1; return 1;
return 2; return 2;
} }
@ -262,8 +275,7 @@ dbExpandFunc(scx, arg)
* the given rectangle. * the given rectangle.
* *
* Results: * Results:
* If "halt_on_error" is TRUE, then return a pointer to the first * None.
* subcell that could not be read. Otherwise, return NULL.
* *
* Side effects: * Side effects:
* May make new cells known to the database. Sets the CDAVAILABLE * May make new cells known to the database. Sets the CDAVAILABLE
@ -272,61 +284,41 @@ dbExpandFunc(scx, arg)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
CellDef * void
DBCellReadArea(rootUse, rootRect, halt_on_error) DBCellReadArea(rootUse, rootRect)
CellUse *rootUse; /* Root cell use from which search begins */ CellUse *rootUse; /* Root cell use from which search begins */
Rect *rootRect; /* Area to be read, in root coordinates */ Rect *rootRect; /* Area to be read, in root coordinates */
bool halt_on_error; /* If TRUE, failure to find a cell causes a halt */
{ {
int dbReadAreaFunc(); int dbReadAreaFunc();
SearchContext scontext; SearchContext scontext;
CellDef *err_def = NULL;
scontext.scx_use = rootUse; scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform; scontext.scx_trans = GeoIdentityTransform;
scontext.scx_area = *rootRect; scontext.scx_area = *rootRect;
if (dbReadAreaFunc(&scontext, ((halt_on_error == TRUE) ? &err_def : NULL)) == 1) (void) dbReadAreaFunc(&scontext);
return err_def;
return NULL;
} }
int int
dbReadAreaFunc(scx, err_ptr) dbReadAreaFunc(scx)
SearchContext *scx; /* Pointer to context specifying SearchContext *scx; /* Pointer to context specifying
* the cell use to be read in, and * the cell use to be read in, and
* an area to be recursively read in * an area to be recursively read in
* coordinates of the cell use's def. * coordinates of the cell use's def.
*/ */
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; CellDef *def = scx->scx_use->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0) if ((def->cd_flags & CDAVAILABLE) == 0)
{ {
if (DBCellRead(def, TRUE, TRUE, NULL) == FALSE) bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
{ (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
if (err_ptr != NULL) {
*err_ptr = def;
return 1;
}
else
return 0;
}
/* Note: we don't have to invoke DBReComputeBbox here because /* Note: we don't have to invoke DBReComputeBbox here because
* if the bbox changed then there was a timestamp mismatch and * if the bbox changed then there was a timestamp mismatch and
* the timestamp code will take care of the bounding box later. * the timestamp code will take care of the bounding box later.
*/ */
} }
if (DBCellSrArea(scx, dbReadAreaFunc, (ClientData)err_ptr)) (void) DBCellSrArea(scx, dbReadAreaFunc, (ClientData) NULL);
return 1;
/* Be clever about handling arrays: if the search area covers this /* Be clever about handling arrays: if the search area covers this
* whole definition, then there's no need to look at any other * whole definition, then there's no need to look at any other
@ -336,6 +328,5 @@ dbReadAreaFunc(scx, err_ptr)
if (GEO_SURROUND(&scx->scx_area, &scx->scx_use->cu_def->cd_bbox)) if (GEO_SURROUND(&scx->scx_area, &scx->scx_use->cu_def->cd_bbox))
return 2; return 2;
return 0; return 0;
} }

File diff suppressed because it is too large Load Diff

View File

@ -24,9 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include <math.h> /* For sin(), cos(), and round() functions */ #include <math.h> /* For sin(), cos(), and round() functions */
#include <ctype.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/malloc.h" #include "utils/malloc.h"
@ -37,13 +35,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h" #include "database/database.h"
#include "database/fonts.h" #include "database/fonts.h"
#include "database/databaseInt.h" #include "database/databaseInt.h"
#include "extract/extractInt.h" /* for ExtCurStyle */
#include "windows/windows.h" #include "windows/windows.h"
#include "dbwind/dbwind.h" #include "dbwind/dbwind.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "textio/textio.h" #include "textio/textio.h"
static TileType DBPickLabelLayer(/* CellDef *def, Label *lab, bool doCalma */); static TileType DBPickLabelLayer(/* CellDef *def, Label *lab, int noreconnect */);
/* Globally-accessible font information */ /* Globally-accessible font information */
@ -94,18 +91,17 @@ DBIsSubcircuit(cellDef)
*/ */
Label * Label *
DBPutLabel(cellDef, rect, align, text, type, flags, port) DBPutLabel(cellDef, rect, align, text, type, flags)
CellDef *cellDef; CellDef *cellDef;
Rect *rect; Rect *rect;
int align; int align;
char *text; char *text;
TileType type; TileType type;
unsigned short flags; int flags;
unsigned int port;
{ {
/* Draw text in a standard X11 font */ /* Draw text in a standard X11 font */
return DBPutFontLabel(cellDef, rect, -1, 0, 0, &GeoOrigin, return DBPutFontLabel(cellDef, rect, -1, 0, 0, &GeoOrigin,
align, text, type, flags, port); align, text, type, flags);
} }
/* /*
@ -132,7 +128,7 @@ DBPutLabel(cellDef, rect, align, text, type, flags, port)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
Label * Label *
DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags, port) DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags)
CellDef *cellDef; /* Cell in which label is placed */ CellDef *cellDef; /* Cell in which label is placed */
Rect *rect; /* Location of label; see above for description */ Rect *rect; /* Location of label; see above for description */
int font; /* A vector outline font to use, or -1 for X11 font */ int font; /* A vector outline font to use, or -1 for X11 font */
@ -145,8 +141,7 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags,
*/ */
char *text; /* Pointer to actual text of label */ char *text; /* Pointer to actual text of label */
TileType type; /* Type of tile to be labelled */ TileType type; /* Type of tile to be labelled */
unsigned short flags; /* Label flags */ int flags; /* Label flags */
unsigned int port; /* Port index (if label is a port, per the flags) */
{ {
Label *lab; Label *lab;
int len, x1, x2, y1, y2, tmp, labx, laby; int len, x1, x2, y1, y2, tmp, labx, laby;
@ -213,7 +208,6 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags,
} }
lab->lab_type = type; lab->lab_type = type;
lab->lab_flags = flags; lab->lab_flags = flags;
lab->lab_port = port;
lab->lab_rect = *rect; lab->lab_rect = *rect;
lab->lab_next = NULL; lab->lab_next = NULL;
if (cellDef->cd_labels == NULL) if (cellDef->cd_labels == NULL)
@ -234,7 +228,7 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags,
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* DBEraseGlobLabel -- * DBEraseLabel --
* *
* Delete labels attached to tiles of the indicated types that * Delete labels attached to tiles of the indicated types that
* are in the given area (as determined by the macro GEO_LABEL_IN_AREA). * are in the given area (as determined by the macro GEO_LABEL_IN_AREA).
@ -256,98 +250,7 @@ DBPutFontLabel(cellDef, rect, font, size, rot, offset, align, text, type, flags,
* still enough material to keep them around. The rect pointed to * still enough material to keep them around. The rect pointed to
* by areaReturn is filled with the area affected by removing the * by areaReturn is filled with the area affected by removing the
* label, for purposes of redrawing the necessary portions of the * label, for purposes of redrawing the necessary portions of the
* screen. * screen.
*
* ----------------------------------------------------------------------------
*/
bool
DBEraseGlobLabel(cellDef, area, mask, areaReturn, globmatch)
CellDef *cellDef; /* Cell being modified */
Rect *area; /* Area from which labels are to be erased.
* This may be a point; any labels touching
* or overlapping it are erased.
*/
TileTypeBitMask *mask; /* Mask of types from which labels are to
* be erased.
*/
Rect *areaReturn; /* Expand this with label bounding box */
char *globmatch; /* If non-NULL, do glob-style matching of
* any label against this string.
*/
{
Label *lab, *labPrev;
bool erasedAny = FALSE;
TileType newType;
free_magic1_t mm1 = freeMagic1_init();
labPrev = NULL;
lab = cellDef->cd_labels;
while (lab != NULL)
{
if (!GEO_LABEL_IN_AREA(&lab->lab_rect, area)) goto nextLab;
if (!TTMaskHasType(mask, L_LABEL))
{
if (!TTMaskHasType(mask, lab->lab_type)) goto nextLab;
/* Labels on space always get deleted at this point, since
* there's no reasonable new layer to put them on.
*/
if (!(lab->lab_type == TT_SPACE))
{
newType = DBPickLabelLayer(cellDef, lab, FALSE);
if (DBConnectsTo(newType, lab->lab_type)) goto nextLab;
}
}
if (globmatch != NULL)
{
if (!Match(globmatch, lab->lab_text)) goto nextLab;
}
DBWLabelChanged(cellDef, lab, DBW_ALLWINDOWS);
if (labPrev == NULL)
cellDef->cd_labels = lab->lab_next;
else labPrev->lab_next = lab->lab_next;
if (cellDef->cd_lastLabel == lab)
cellDef->cd_lastLabel = labPrev;
DBUndoEraseLabel(cellDef, lab);
if ((lab->lab_font >= 0) && areaReturn)
GeoInclude(&lab->lab_bbox, areaReturn);
freeMagic1(&mm1, (char *) lab);
lab = lab->lab_next;
erasedAny = TRUE;
continue;
nextLab: labPrev = lab;
lab = lab->lab_next;
}
freeMagic1_end(&mm1);
if (erasedAny)
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
return (erasedAny);
}
#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \
&& (r1)->r_ybot == (r2)->r_ybot \
&& (r1)->r_xtop == (r2)->r_xtop \
&& (r1)->r_ytop == (r2)->r_ytop)
/*
* ----------------------------------------------------------------------------
*
* DBEraseLabel ---
*
* Wrapper around DBEraseGlobLabel() with globmatch set to NULL so
* that labels are erased verbatim rather that being matched against
* a glob-style string.
*
* Results:
* Passes back the result of DBEraseGlobLabel()
*
* Side effects:
* See DBEraseGlobLabel()
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -364,9 +267,58 @@ DBEraseLabel(cellDef, area, mask, areaReturn)
*/ */
Rect *areaReturn; /* Expand this with label bounding box */ Rect *areaReturn; /* Expand this with label bounding box */
{ {
return DBEraseGlobLabel(cellDef, area, mask, areaReturn, NULL); Label *lab, *labPrev;
bool erasedAny = FALSE;
TileType newType;
labPrev = NULL;
lab = cellDef->cd_labels;
while (lab != NULL)
{
if (!GEO_LABEL_IN_AREA(&lab->lab_rect, area)) goto nextLab;
if (!TTMaskHasType(mask, L_LABEL))
{
if (!TTMaskHasType(mask, lab->lab_type)) goto nextLab;
/* Labels on space always get deleted at this point, since
* there's no reasonable new layer to put them on.
*/
if (!(lab->lab_type == TT_SPACE))
{
newType = DBPickLabelLayer(cellDef, lab, 0);
if (DBConnectsTo(newType, lab->lab_type)) goto nextLab;
}
}
DBWLabelChanged(cellDef, lab, DBW_ALLWINDOWS);
if (labPrev == NULL)
cellDef->cd_labels = lab->lab_next;
else labPrev->lab_next = lab->lab_next;
if (cellDef->cd_lastLabel == lab)
cellDef->cd_lastLabel = labPrev;
DBUndoEraseLabel(cellDef, lab);
if ((lab->lab_font >= 0) && areaReturn)
GeoInclude(&lab->lab_bbox, areaReturn);
freeMagic((char *) lab);
lab = lab->lab_next;
erasedAny = TRUE;
continue;
nextLab: labPrev = lab;
lab = lab->lab_next;
}
if (erasedAny)
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
return (erasedAny);
} }
#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \
&& (r1)->r_ybot == (r2)->r_ybot \
&& (r1)->r_xtop == (r2)->r_xtop \
&& (r1)->r_ytop == (r2)->r_ytop)
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -444,7 +396,6 @@ DBEraseLabelsByContent(def, rect, type, text)
{ {
Label *lab, *labPrev; Label *lab, *labPrev;
free_magic1_t mm1 = freeMagic1_init();
for (labPrev = NULL, lab = def->cd_labels; for (labPrev = NULL, lab = def->cd_labels;
lab != NULL; lab != NULL;
labPrev = lab, lab = lab->lab_next) labPrev = lab, lab = lab->lab_next)
@ -460,7 +411,7 @@ DBEraseLabelsByContent(def, rect, type, text)
else labPrev->lab_next = lab->lab_next; else labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab) if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev; def->cd_lastLabel = labPrev;
freeMagic1(&mm1, (char *) lab); freeMagic((char *) lab);
/* Don't iterate through loop, since this will skip a label: /* Don't iterate through loop, since this will skip a label:
* just go back to top. This is tricky! * just go back to top. This is tricky!
@ -470,15 +421,14 @@ DBEraseLabelsByContent(def, rect, type, text)
if (lab == NULL) break; if (lab == NULL) break;
else goto nextCheck; else goto nextCheck;
} }
freeMagic1_end(&mm1);
} }
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
* DBRemoveLabel -- * DBEraseLabelsByFunction --
* *
* Erase a labels by reference. * Erase any labels found on the label list for which the function returns
* TRUE. * TRUE.
* *
* Results: * Results:
@ -493,19 +443,28 @@ DBEraseLabelsByContent(def, rect, type, text)
*/ */
void void
DBRemoveLabel(def, refLab) DBEraseLabelsByFunction(def, func)
CellDef *def; /* Where to look for label to delete. */ CellDef *def; /* Where to look for label to delete. */
Label *refLab; bool (*func)(); /* Function to call for each label. If it
* returns TRUE, we delete the label.
*
* Function should be of the form:
*
* bool func(lab)
* Label *lab;
* {
* return XXX;
* }
*/
{ {
Label *lab, *labPrev; Label *lab, *labPrev;
free_magic1_t mm1 = freeMagic1_init();
for (labPrev = NULL, lab = def->cd_labels; for (labPrev = NULL, lab = def->cd_labels;
lab != NULL; lab != NULL;
labPrev = lab, lab = lab->lab_next) labPrev = lab, lab = lab->lab_next)
{ {
nextCheck: nextCheck:
if (lab != refLab) continue; if (!(*func)(lab)) continue;
DBUndoEraseLabel(def, lab); DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS); DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
if (labPrev == NULL) if (labPrev == NULL)
@ -513,7 +472,7 @@ DBRemoveLabel(def, refLab)
else labPrev->lab_next = lab->lab_next; else labPrev->lab_next = lab->lab_next;
if (def->cd_lastLabel == lab) if (def->cd_lastLabel == lab)
def->cd_lastLabel = labPrev; def->cd_lastLabel = labPrev;
freeMagic1(&mm1, (char *) lab); freeMagic((char *) lab);
/* Don't iterate through loop, since this will skip a label: /* Don't iterate through loop, since this will skip a label:
* just go back to top. This is tricky! * just go back to top. This is tricky!
@ -523,7 +482,6 @@ DBRemoveLabel(def, refLab)
if (lab == NULL) break; if (lab == NULL) break;
else goto nextCheck; else goto nextCheck;
} }
freeMagic1_end(&mm1);
} }
/* /*
@ -568,63 +526,6 @@ 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 label area adjusted to leave
* out that amount.
*
* 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;
}
/*
* ----------------------------------------------------------------------------
*
* dbLabelNotEmpty ---
*
* Callback function used by DBAdjustLabels. Finds any material under a
* label that is the label type, and returns 1 to stop the search.
*
* ----------------------------------------------------------------------------
*/
int
dbLabelNotEmpty(tile, dinfo, clientData)
Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information (unused) */
ClientData clientData; /* (unused) */
{
return 1;
}
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -654,7 +555,7 @@ DBAdjustLabels(def, area)
{ {
Label *lab; Label *lab;
TileType newType; TileType newType;
bool modified = FALSE, adjusted = FALSE; bool modified = FALSE;
/* First, find each label that crosses the area we're /* First, find each label that crosses the area we're
* interested in. * interested in.
@ -663,72 +564,18 @@ DBAdjustLabels(def, area)
for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next) for (lab = def->cd_labels; lab != NULL; lab = lab->lab_next)
{ {
if (!GEO_TOUCH(&lab->lab_rect, area)) continue; if (!GEO_TOUCH(&lab->lab_rect, area)) continue;
newType = DBPickLabelLayer(def, lab, FALSE); newType = DBPickLabelLayer(def, lab, 0);
if (newType == lab->lab_type) continue; if (newType == lab->lab_type) continue;
if (lab->lab_flags & LABEL_STICKY) continue; if (lab->lab_flags & LABEL_STICKY) continue;
if (DBVerbose && ((def->cd_flags & CDINTERNAL) == 0)) {
/* New behavior (5/2024) (idea from Philipp Guhring)---If the new TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
* type is space, then instead of immediately casting the label off lab->lab_text, DBTypeLongName(lab->lab_type),
* of its material, find the amount of the label that is still DBTypeLongName(newType), def->cd_name);
* covered by the material. If the material covers more than half };
* the label area, then adjust the label area to match the material. DBUndoEraseLabel(def, lab);
*/ lab->lab_type = newType;
DBUndoPutLabel(def, lab);
adjusted = FALSE; modified = TRUE;
if (newType == TT_SPACE)
{
Rect r;
TileTypeBitMask lmask;
TTMaskSetOnlyType(&lmask, lab->lab_type);
/* To do: Add compatible types (contact, residue) */
/* If there is no material left inside the label area, then
* the label gets reassigned to space.
*/
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)],
&lab->lab_rect, &lmask, dbLabelNotEmpty, (ClientData)NULL) == 1)
{
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); if (modified) DBCellSetModified(def, TRUE);
@ -736,32 +583,16 @@ 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 void
DBAdjustLabelsNew(def, area) DBAdjustLabelsNew(def, area, noreconnect)
CellDef *def; /* Cell whose paint was changed. */ CellDef *def; /* Cell whose paint was changed. */
Rect *area; /* Area where paint was modified. */ 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; Label *lab, *labPrev;
TileType newType; TileType newType;
@ -775,59 +606,46 @@ DBAdjustLabelsNew(def, area)
lab = def->cd_labels; lab = def->cd_labels;
while (lab != NULL) while (lab != NULL)
{ {
bool doCalma = TRUE; int locnoreconnect = noreconnect;
if (!GEO_TOUCH(&lab->lab_rect, area)) goto nextLab; if (!GEO_TOUCH(&lab->lab_rect, area)) {
if (lab->lab_type == TT_SPACE) doCalma = FALSE; goto nextLab;
newType = DBPickLabelLayer(def, lab, doCalma); }
if (newType == lab->lab_type) if (lab->lab_type == TT_SPACE) locnoreconnect = FALSE;
goto nextLab; 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);
if (((newType < 0) || (newType == TT_SPACE)) && !(lab->lab_flags & LABEL_STICKY)) if (labPrev == NULL)
{ def->cd_labels = lab->lab_next;
if (lab->lab_type == TT_SPACE) else
{ labPrev->lab_next = lab->lab_next;
TxPrintf("Deleting unattached label \"%s\" in cell %s.\n", if (def->cd_lastLabel == lab)
lab->lab_text, def->cd_name); def->cd_lastLabel = labPrev;
DBUndoEraseLabel(def, lab);
if (labPrev == NULL) DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
def->cd_labels = lab->lab_next; freeMagic((char *) lab);
else lab = lab->lab_next;
labPrev->lab_next = lab->lab_next; modified = TRUE;
if (def->cd_lastLabel == lab) continue;
def->cd_lastLabel = labPrev; } else if (!(lab->lab_flags & LABEL_STICKY)) {
DBUndoEraseLabel(def, lab); if (DBVerbose && ((def->cd_flags & CDINTERNAL) == 0)) {
DBWLabelChanged(def, lab, DBW_ALLWINDOWS); TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
free_magic1_t mm1 = freeMagic1_init(); lab->lab_text, DBTypeLongName(lab->lab_type),
freeMagic1(&mm1, (char *) lab); DBTypeLongName(newType), def->cd_name);
lab = lab->lab_next; }
freeMagic1_end(&mm1); DBUndoEraseLabel(def, lab);
modified = TRUE; lab->lab_type = newType;
continue; DBUndoPutLabel(def, lab);
modified = TRUE;
} }
else nextLab:
{ labPrev = lab;
TxPrintf("Making label \"%s\" on type %s in cell %s sticky.\n", lab = lab->lab_next;
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); if (modified) DBCellSetModified(def, TRUE);
@ -863,10 +681,10 @@ TileTypeBitMask *dbAdjustPlaneTypes; /* Mask of all types in current
* plane being searched. * plane being searched.
*/ */
TileType TileType
DBPickLabelLayer(def, lab, doCalma) DBPickLabelLayer(def, lab, noreconnect)
CellDef *def; /* Cell definition containing label. */ CellDef *def; /* Cell definition containing label. */
Label *lab; /* Label for which a home must be found. */ Label *lab; /* Label for which a home must be found. */
bool doCalma; /* if TRUE, use rules for GDS and LEF */ int noreconnect; /* if 1, return -1 if rule 5 or 6 would succeed */
{ {
TileTypeBitMask types[3], types2[3]; TileTypeBitMask types[3], types2[3];
Rect check1, check2; Rect check1, check2;
@ -967,147 +785,112 @@ DBPickLabelLayer(def, lab, doCalma)
} }
/* If the label's layer covers the label's area, use it. /* If the label's layer covers the label's area, use it.
* Otherwise, look for a layer in the following order * Otherwise, look for a layer in the following order:
* (Note: "covers" means covers the area of the label if the * 1. A layer on the same plane as the original layer and that
* label has area or touches the entire label if it doesn't.): * covers the label and connects to its original layer.
* * 2. A layer on the same plane as the original layer and that
* If "doCalma" is TRUE, then: * is a component of material that covers the label and
* 1. A layer on the same plane as the original layer and that * connects to its original layer.
* covers the label and is not a device type. * 3. A layer that covers the label and connects to the
* 2. A layer on the same plane as the original layer and that * old layer.
* covers the label. * 4. A layer that is a component of material that covers
* 3. A layer on the same plane as the original layer and that * the label and connects to the old layer.
* is a component of material that covers the label. * 5. A layer that covers the label.
* 4. -1 * 6. A layer that is a component of material that covers the label.
* * 7. Space.
* 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 * All searches are done from the lowest to highest plane, so that
* the label connects to material on the highest plane that matches * the label connects to material on the highest plane that matches
* the criteria above. This avoids weirdnesses caused by declaring * the criteria above. This avoids weirdnesses caused by declaring
* types out of order in the techfile. * 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; if (TTMaskHasType(&types[0], lab->lab_type)) return lab->lab_type;
plane = DBPlane(lab->lab_type); plane = DBPlane(lab->lab_type);
choice1 = choice2 = choice3 = choice4 = choice5 = choice6 = TT_SPACE;
if (doCalma) for (j = PL_SELECTBASE; j < DBNumPlanes; j++)
{ {
choice1 = choice2 = choice3 = -1;
for (i = TT_SELECTBASE; i < DBNumUserLayers; i += 1) for (i = TT_SELECTBASE; i < DBNumUserLayers; i += 1)
{ {
if (!TTMaskHasType(&DBPlaneTypes[plane], i)) continue; if (!TTMaskHasType(&DBPlaneTypes[j], i)) continue;
if (TTMaskHasType(&types[0], i) && (ExtCurStyle != NULL)) if (DBConnectsTo(i, lab->lab_type))
{ {
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, i)) if (DBPlane(i) == plane)
choice2 = i; {
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;
else else
choice1 = i; {
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; continue;
} }
else if (TTMaskHasType(&types[1], i)) else if (TTMaskHasType(&types[1], i))
{ {
choice3 = i; choice6 = i;
continue; continue;
} }
} }
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++) if (choice1 != TT_SPACE) return choice1;
{ else if (choice2 != TT_SPACE) return choice2;
for (i = TT_SELECTBASE; i < DBNumUserLayers; i += 1) else if (choice3 != TT_SPACE) return choice3;
{ else if (choice4 != TT_SPACE) return choice4;
if (!TTMaskHasType(&DBPlaneTypes[j], i)) continue; else if (noreconnect) {
#ifdef notdef
if (DBConnectsTo(i, lab->lab_type)) TxPrintf("DBPickLabelLayer \"%s\" (on %s at %d,%d) choice4=%s choice5=%s choice6=%s.\n",
{ lab->lab_text,
if (DBPlane(i) == plane) DBTypeLongName(lab->lab_type),
{ lab->lab_rect.r_xbot,
if (TTMaskHasType(&types[0], i)) lab->lab_rect.r_ytop,
{ DBTypeLongName(choice4),
choice1 = i; DBTypeLongName(choice5),
continue; DBTypeLongName(choice6));
} #endif
else if (TTMaskHasType(&types[1], i)) /* 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 */
choice2 = i; if(choice5 == TT_SPACE && choice6 == TT_SPACE)
continue; return TT_SPACE;
} else
} return -1;
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 /* Search function for DBPickLabelLayer: just OR in the type of
@ -1116,15 +899,14 @@ DBPickLabelLayer(def, lab, doCalma)
*/ */
int int
dbPickFunc1(tile, dinfo, mask) dbPickFunc1(tile, mask)
Tile *tile; /* Tile found. */ Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information */
TileTypeBitMask *mask; /* Mask to be modified. */ TileTypeBitMask *mask; /* Mask to be modified. */
{ {
TileType type; TileType type;
if (IsSplit(tile)) if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
else else
type = TiGetType(tile); type = TiGetType(tile);
@ -1143,16 +925,15 @@ dbPickFunc1(tile, dinfo, mask)
*/ */
int int
dbPickFunc2(tile, dinfo, mask) dbPickFunc2(tile, mask)
Tile *tile; /* Tile found. */ Tile *tile; /* Tile found. */
TileType dinfo; /* Split tile information */
TileTypeBitMask *mask; /* Mask to be modified. */ TileTypeBitMask *mask; /* Mask to be modified. */
{ {
TileType type; TileType type;
TileTypeBitMask tmp, *rMask; TileTypeBitMask tmp, *rMask;
if (IsSplit(tile)) if (IsSplit(tile))
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
else else
type = TiGetType(tile); type = TiGetType(tile);
@ -1590,7 +1371,7 @@ DBLoadFont(fontfile, scale)
float scale; float scale;
{ {
FILE *ff; FILE *ff;
const char * const ascii_names[] = { char *ascii_names[] = {
"space", "exclam", "quotedbl", "numbersign", "dollar", "space", "exclam", "quotedbl", "numbersign", "dollar",
"percent", "ampersand", "quoteright", "parenleft", "parenright", "percent", "ampersand", "quoteright", "parenleft", "parenright",
"asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
@ -1695,7 +1476,7 @@ DBLoadFont(fontfile, scale)
{ {
if (psname != NULL) if (psname != NULL)
{ {
asciiidx = LookupStructFull(psname, ascii_names, sizeof(const char *)); asciiidx = LookupStructFull(psname, ascii_names, sizeof(char *));
if (asciiidx >= 0) if (asciiidx >= 0)
chardef = 2; chardef = 2;
} }
@ -1785,10 +1566,8 @@ DBLoadFont(fontfile, scale)
} }
/* Remove the pointlist */ /* Remove the pointlist */
free_magic1_t mm1 = freeMagic1_init();
for (newPath = pathStart; newPath != NULL; newPath = newPath->fp_next) for (newPath = pathStart; newPath != NULL; newPath = newPath->fp_next)
freeMagic1(&mm1, newPath); freeMagic(newPath);
freeMagic1_end(&mm1);
pathStart = NULL; pathStart = NULL;
} }
else else

View File

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

View File

@ -19,7 +19,7 @@
* ********************************************************************* * *********************************************************************
*/ */
/* #define PAINTDEBUG */ /* For debugging */ /* #define PAINTDEBUG /* For debugging */
#ifndef lint #ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBpaint.c,v 1.15 2010/09/24 19:53:19 tim Exp $"; static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/database/DBpaint.c,v 1.15 2010/09/24 19:53:19 tim Exp $";
@ -59,8 +59,6 @@ Tile *TiNMMergeRight();
Tile *TiNMMergeLeft(); Tile *TiNMMergeLeft();
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
void dbPaintShowTile(Tile *tile, PaintUndoInfo *undo, char *str);
int dbPaintDebug = 0; int dbPaintDebug = 0;
#endif /* PAINTDEBUG */ #endif /* PAINTDEBUG */
@ -217,7 +215,7 @@ dbJoinUndo(tile, splitx, undo)
* 'undo' can be NULL. * 'undo' can be NULL.
* *
* Results: * Results:
* Always return 0. * None.
* *
* Side effects: * Side effects:
* Modifies the database plane that contains the given tile. * Modifies the database plane that contains the given tile.
@ -238,11 +236,11 @@ dbJoinUndo(tile, splitx, undo)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
int void
DBPaintPlane0(plane, area, resultTbl, undo, method) DBPaintPlane0(plane, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */ Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */ Rect *area; /* Area to be changed */
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to * present in the plane, giving the type to
* which the existing tile must change as a * which the existing tile must change as a
* result of this paint operation. * result of this paint operation.
@ -264,7 +262,7 @@ DBPaintPlane0(plane, area, resultTbl, undo, method)
bool haschanged; bool haschanged;
if (area->r_xtop <= area->r_xbot || area->r_ytop <= area->r_ybot) if (area->r_xtop <= area->r_xbot || area->r_ytop <= area->r_ybot)
return 0; return;
/* /*
* The following is a modified version of the area enumeration * The following is a modified version of the area enumeration
@ -273,10 +271,9 @@ DBPaintPlane0(plane, area, resultTbl, undo, method)
* search. * search.
*/ */
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */ /* Each iteration visits another tile on the LHS of the search area */
@ -313,11 +310,6 @@ enumerate:
* Set up the directions in which we will have to * Set up the directions in which we will have to
* merge initially. Clipping can cause some of these * merge initially. Clipping can cause some of these
* to be turned off. * 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; mergeFlags = MRG_TOP | MRG_LEFT;
if (RIGHT(tile) >= area->r_xtop) mergeFlags |= MRG_RIGHT; if (RIGHT(tile) >= area->r_xtop) mergeFlags |= MRG_RIGHT;
@ -347,7 +339,6 @@ enumerate:
* Merging is only necessary if we clip to the left or to * Merging is only necessary if we clip to the left or to
* the right, and then only to the top or the bottom. * the right, and then only to the top or the bottom.
* We do the merge in-line for efficiency. * We do the merge in-line for efficiency.
* Clipping of split tiles is more complicated.
*/ */
/* Clip up */ /* Clip up */
@ -362,17 +353,13 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ? newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType]; *resultTbl : resultTbl[oldType];
if (mergeFlags & MRG_LEFT) tile = TiNMMergeLeft(tile, plane);
tile = TiNMMergeLeft(tile, plane); TiNMMergeRight(TR(newtile), plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(newtile) == 1)
TiNMMergeRight(TR(newtile), plane);
} }
else else
{ {
if (mergeFlags & MRG_LEFT) TiNMMergeLeft(newtile, plane);
TiNMMergeLeft(newtile, plane); TiNMMergeRight(TR(tile), plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(tile) == 1)
TiNMMergeRight(TR(tile), plane);
} }
} }
else else
@ -401,17 +388,13 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ? newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType]; *resultTbl : resultTbl[oldType];
if (mergeFlags & MRG_LEFT) tile = TiNMMergeLeft(tile, plane);
tile = TiNMMergeLeft(tile, plane); TiNMMergeRight(TR(newtile), plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(newtile) == 0)
TiNMMergeRight(TR(newtile), plane);
} }
else else
{ {
if (mergeFlags & MRG_LEFT) TiNMMergeLeft(newtile, plane);
TiNMMergeLeft(newtile, plane); TiNMMergeRight(TR(tile), plane);
if ((mergeFlags & MRG_RIGHT) || SplitDirection(tile) == 0)
TiNMMergeRight(TR(tile), plane);
} }
} }
else else
@ -440,17 +423,13 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ? newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType]; *resultTbl : resultTbl[oldType];
if (mergeFlags & MRG_LEFT) tile = TiNMMergeLeft(tile, plane);
tile = TiNMMergeLeft(tile, plane); TiNMMergeRight(LB(newtile), plane);
if (mergeFlags & MRG_RIGHT)
TiNMMergeRight(LB(newtile), plane);
} }
else else
{ {
if (mergeFlags & MRG_LEFT) TiNMMergeRight(newtile, plane);
TiNMMergeRight(newtile, plane); TiNMMergeLeft(LB(tile), plane);
if (mergeFlags & MRG_RIGHT)
TiNMMergeLeft(LB(tile), plane);
} }
} }
else else
@ -460,11 +439,11 @@ enumerate:
/* Merge the outside tile to its top */ /* Merge the outside tile to its top */
tp = RT(newtile); tp = RT(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane); if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
/* Merge the outside tile to its bottom */ /* Merge the outside tile to its bottom */
tp = LB(newtile); tp = LB(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane); if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
} }
mergeFlags &= ~MRG_RIGHT; mergeFlags &= ~MRG_RIGHT;
} }
@ -487,13 +466,13 @@ enumerate:
newType = (method == (unsigned char)PAINT_XOR) ? newType = (method == (unsigned char)PAINT_XOR) ?
*resultTbl : resultTbl[oldType]; *resultTbl : resultTbl[oldType];
if (mergeFlags & MRG_LEFT) // tile = TiNMMergeRight(tile, plane);
TiNMMergeLeft(LB(newtile), plane); TiNMMergeLeft(LB(newtile), plane);
} }
else else
{ {
if (mergeFlags & MRG_LEFT) TiNMMergeLeft(newtile, plane);
TiNMMergeLeft(newtile, plane); // TiNMMergeRight(LB(tile), plane);
} }
} }
else else
@ -504,11 +483,11 @@ enumerate:
/* Merge the outside tile to its top */ /* Merge the outside tile to its top */
tp = RT(newtile); tp = RT(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane); if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
/* Merge the outside tile to its bottom */ /* Merge the outside tile to its bottom */
tp = LB(newtile); tp = LB(newtile);
if (CANMERGE_Y(newtile, tp)) TiJoinY1(&delayed, newtile, tp, plane); if (CANMERGE_Y(newtile, tp)) TiJoinY(newtile, tp, plane);
} }
mergeFlags &= ~MRG_LEFT; mergeFlags &= ~MRG_LEFT;
} }
@ -600,7 +579,7 @@ clipdone:
if (mergeFlags & MRG_TOP) if (mergeFlags & MRG_TOP)
{ {
tp = RT(tile); tp = RT(tile);
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged up (CHEAP)"); dbPaintShowTile(tile, undo, "merged up (CHEAP)");
@ -609,7 +588,7 @@ clipdone:
if (mergeFlags & MRG_BOTTOM) if (mergeFlags & MRG_BOTTOM)
{ {
tp = LB(tile); tp = LB(tile);
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged down (CHEAP)"); dbPaintShowTile(tile, undo, "merged down (CHEAP)");
@ -669,7 +648,7 @@ done:
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
while (TOP(tile) > area->r_ybot) while (TOP(tile) > area->r_ybot)
@ -717,9 +696,7 @@ enum2:
} }
done2: done2:
PlaneSetHint(plane, tile); plane->pl_hint = tile;
TiFreeIf(delayed);
return 0;
} }
/* /*
@ -741,7 +718,7 @@ DBSplitTile(plane, point, splitx)
int splitx; int splitx;
{ {
Tile *tile, *newtile, *tp; Tile *tile, *newtile, *tp;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, point); GOTOPOINT(tile, point);
if (IsSplit(tile)) /* This should always be true */ if (IsSplit(tile)) /* This should always be true */
@ -788,7 +765,7 @@ void
DBFracturePlane(plane, area, resultTbl, undo) DBFracturePlane(plane, area, resultTbl, undo)
Plane *plane; /* Plane whose paint is to be modified */ Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */ Rect *area; /* Area to be changed */
const PaintResultType *resultTbl; /* Paint table, to pinpoint those tiles PaintResultType *resultTbl; /* Paint table, to pinpoint those tiles
* that interact with the paint type. * that interact with the paint type.
*/ */
PaintUndoInfo *undo; /* Record containing everything needed to PaintUndoInfo *undo; /* Record containing everything needed to
@ -815,7 +792,7 @@ DBFracturePlane(plane, area, resultTbl, undo)
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */ /* Each iteration visits another tile on the LHS of the search area */
@ -1012,7 +989,7 @@ paintdone:
} }
done: done:
PlaneSetHint(plane, tile); plane->pl_hint = tile;
} }
/* /*
@ -1054,12 +1031,11 @@ DBMergeNMTiles0(plane, area, undo, mergeOnce)
int clipTop; int clipTop;
Tile *tile, *tp, *tp2, *newtile, *tpnew; Tile *tile, *tp, *tp2, *newtile, *tpnew;
int aspecta, aspectb; int aspecta, aspectb;
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype, ltype, rtype; TileType ttype, ltype, rtype;
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */ /* Each iteration visits another tile on the LHS of the search area */
@ -1144,23 +1120,23 @@ nmenum:
newtile = TiSplitY(tp2, TOP(tile)); newtile = TiSplitY(tp2, TOP(tile));
TiSetBody(newtile, ltype); TiSetBody(newtile, ltype);
if (CANMERGE_X(newtile, BL(newtile))) if (CANMERGE_X(newtile, BL(newtile)))
TiJoinX1(&delayed, newtile, BL(newtile), plane); TiJoinX(newtile, BL(newtile), plane);
if (CANMERGE_X(newtile, TR(newtile))) if (CANMERGE_X(newtile, TR(newtile)))
TiJoinX1(&delayed, newtile, TR(newtile), plane); TiJoinX(newtile, TR(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile))) if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY1(&delayed, newtile, RT(newtile), plane); TiJoinY(newtile, RT(newtile), plane);
} }
if (LEFT(tp2) < LEFT(tp)) if (LEFT(tp2) < LEFT(tp))
{ {
newtile = TiSplitX(tp2, LEFT(tp)); newtile = TiSplitX(tp2, LEFT(tp));
TiSetBody(newtile, ltype); TiSetBody(newtile, ltype);
if (CANMERGE_Y(tp2, LB(tp2))) if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY1(&delayed, tp2, LB(tp2), plane); TiJoinY(tp2, LB(tp2), plane);
if (CANMERGE_Y(tp2, RT(tp2))) if (CANMERGE_Y(tp2, RT(tp2)))
TiJoinY1(&delayed, tp2, RT(tp2), plane); TiJoinY(tp2, RT(tp2), plane);
tp2 = newtile; tp2 = newtile;
} }
TiJoinY1(&delayed, tp2, tp, plane); TiJoinY(tp2, tp, plane);
tp = tp2; tp = tp2;
tp2 = RT(tp2); tp2 = RT(tp2);
} }
@ -1174,11 +1150,11 @@ nmenum:
newtile = TiSplitY(tp2, BOTTOM(tp)); newtile = TiSplitY(tp2, BOTTOM(tp));
TiSetBody(newtile, rtype); TiSetBody(newtile, rtype);
if (CANMERGE_X(tp2, BL(tp2))) if (CANMERGE_X(tp2, BL(tp2)))
TiJoinX1(&delayed, tp2, BL(tp2), plane); TiJoinX(tp2, BL(tp2), plane);
if (CANMERGE_X(tp2, TR(tp2))) if (CANMERGE_X(tp2, TR(tp2)))
TiJoinX1(&delayed, tp2, TR(tp2), plane); TiJoinX(tp2, TR(tp2), plane);
if (CANMERGE_Y(tp2, LB(tp2))) if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY1(&delayed, tp2, LB(tp2), plane); TiJoinY(tp2, LB(tp2), plane);
tp2 = newtile; tp2 = newtile;
} }
if (RIGHT(tp2) > RIGHT(tile)) if (RIGHT(tp2) > RIGHT(tile))
@ -1186,16 +1162,16 @@ nmenum:
newtile = TiSplitX(tp2, RIGHT(tile)); newtile = TiSplitX(tp2, RIGHT(tile));
TiSetBody(newtile, rtype); TiSetBody(newtile, rtype);
if (CANMERGE_Y(newtile, LB(newtile))) if (CANMERGE_Y(newtile, LB(newtile)))
TiJoinY1(&delayed, newtile, LB(newtile), plane); TiJoinY(newtile, LB(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile))) if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY1(&delayed, newtile, RT(newtile), plane); TiJoinY(newtile, RT(newtile), plane);
} }
TiJoinY1(&delayed, tp2, tile, plane); TiJoinY(tp2, tile, plane);
tile = tp2; tile = tp2;
tp2 = LB(tp2); tp2 = LB(tp2);
} }
/* Merge tp and tile */ /* Merge tp and tile */
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
TiSetBody(tile, ttype); TiSetBody(tile, ttype);
} }
else /* split direction 1 */ else /* split direction 1 */
@ -1236,11 +1212,11 @@ nmenum:
newtile = TiSplitY(tp2, BOTTOM(tp)); newtile = TiSplitY(tp2, BOTTOM(tp));
TiSetBody(newtile, ltype); TiSetBody(newtile, ltype);
if (CANMERGE_X(tp2, BL(tp2))) if (CANMERGE_X(tp2, BL(tp2)))
TiJoinX1(&delayed, tp2, BL(tp2), plane); TiJoinX(tp2, BL(tp2), plane);
if (CANMERGE_X(tp2, TR(tp2))) if (CANMERGE_X(tp2, TR(tp2)))
TiJoinX1(&delayed, tp2, TR(tp2), plane); TiJoinX(tp2, TR(tp2), plane);
if (CANMERGE_Y(tp2, LB(tp2))) if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY1(&delayed, tp2, LB(tp2), plane); TiJoinY(tp2, LB(tp2), plane);
tp2 = newtile; tp2 = newtile;
} }
if (LEFT(tp2) < LEFT(tile)) if (LEFT(tp2) < LEFT(tile))
@ -1248,12 +1224,12 @@ nmenum:
newtile = TiSplitX(tp2, LEFT(tile)); newtile = TiSplitX(tp2, LEFT(tile));
TiSetBody(newtile, ltype); TiSetBody(newtile, ltype);
if (CANMERGE_Y(tp2, LB(tp2))) if (CANMERGE_Y(tp2, LB(tp2)))
TiJoinY1(&delayed, tp2, LB(tp2), plane); TiJoinY(tp2, LB(tp2), plane);
if (CANMERGE_Y(tp2, RT(tp2))) if (CANMERGE_Y(tp2, RT(tp2)))
TiJoinY1(&delayed, tp2, RT(tp2), plane); TiJoinY(tp2, RT(tp2), plane);
tp2 = newtile; tp2 = newtile;
} }
TiJoinY1(&delayed, tp2, tile, plane); TiJoinY(tp2, tile, plane);
tile = tp2; tile = tp2;
tp2 = LB(tp2); tp2 = LB(tp2);
} }
@ -1268,27 +1244,27 @@ nmenum:
newtile = TiSplitY(tp2, TOP(tile)); newtile = TiSplitY(tp2, TOP(tile));
TiSetBody(newtile, rtype); TiSetBody(newtile, rtype);
if (CANMERGE_X(newtile, BL(newtile))) if (CANMERGE_X(newtile, BL(newtile)))
TiJoinX1(&delayed, newtile, BL(newtile), plane); TiJoinX(newtile, BL(newtile), plane);
if (CANMERGE_X(newtile, TR(newtile))) if (CANMERGE_X(newtile, TR(newtile)))
TiJoinX1(&delayed, newtile, TR(newtile), plane); TiJoinX(newtile, TR(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile))) if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY1(&delayed, newtile, RT(newtile), plane); TiJoinY(newtile, RT(newtile), plane);
} }
if (RIGHT(tp2) > RIGHT(tp)) if (RIGHT(tp2) > RIGHT(tp))
{ {
newtile = TiSplitX(tp2, RIGHT(tp)); newtile = TiSplitX(tp2, RIGHT(tp));
TiSetBody(newtile, rtype); TiSetBody(newtile, rtype);
if (CANMERGE_Y(newtile, LB(newtile))) if (CANMERGE_Y(newtile, LB(newtile)))
TiJoinY1(&delayed, newtile, LB(newtile), plane); TiJoinY(newtile, LB(newtile), plane);
if (CANMERGE_Y(newtile, RT(newtile))) if (CANMERGE_Y(newtile, RT(newtile)))
TiJoinY1(&delayed, newtile, RT(newtile), plane); TiJoinY(newtile, RT(newtile), plane);
} }
TiJoinY1(&delayed, tp2, tp, plane); TiJoinY(tp2, tp, plane);
tp = tp2; tp = tp2;
tp2 = RT(tp2); tp2 = RT(tp2);
} }
/* Merge tp and tile */ /* Merge tp and tile */
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
TiSetBody(tile, ttype); TiSetBody(tile, ttype);
} }
/* Now repeat until no more merging is possible */ /* Now repeat until no more merging is possible */
@ -1329,8 +1305,7 @@ nmenum:
} }
nmdone: nmdone:
PlaneSetHint(plane, tile); plane->pl_hint = tile;
TiFreeIf(delayed);
return 0; return 0;
} }
@ -1339,7 +1314,7 @@ nmdone:
* DBDiagonalProc(type) -- * DBDiagonalProc(type) --
* *
* Return the result type of a diagonal tile painted on oldtype; * Return the result type of a diagonal tile painted on oldtype;
* Argument "dinfo", gives direction and side of diagonal, and the * Argument "cdata", gives direction and side of diagonal, and the
* paint result table for the given diagonal side. * paint result table for the given diagonal side.
* *
* If the result cannot be described with a single tile, then * If the result cannot be described with a single tile, then
@ -1357,14 +1332,15 @@ nmdone:
*/ */
int int
DBDiagonalProc(oldtype, dinfo) DBDiagonalProc(oldtype, cdata)
TileType oldtype; TileType oldtype;
DiagInfo *dinfo; ClientData cdata;
{ {
TileType old_n, old_s, old_e, old_w; TileType old_n, old_s, old_e, old_w;
TileType new_n, new_s, new_e, new_w; TileType new_n, new_s, new_e, new_w;
TileType newtype; TileType newtype;
const PaintResultType *resultTbl = dinfo->resultTbl; DiagInfo *dinfo = (DiagInfo *)cdata;
PaintResultType *resultTbl = dinfo->resultTbl;
/* Disassemble old and new types into four quadrants, find the */ /* Disassemble old and new types into four quadrants, find the */
/* paint result for each quadrant, then reassemble the result. */ /* paint result for each quadrant, then reassemble the result. */
@ -1435,6 +1411,10 @@ DBDiagonalProc(oldtype, dinfo)
else else
return -1; return -1;
/* For purposes of "undo" recording, record which side we just painted */
if (dinfo->side)
newtype |= TT_SIDE;
return newtype; return newtype;
} }
@ -1462,7 +1442,7 @@ typedef struct
* paint quadrangular (clipped triangle) areas. * paint quadrangular (clipped triangle) areas.
* *
* Results: * Results:
* 0 on success, 1 on error splitting a non-manhattan tile * None.
* *
* Side Effects: * Side Effects:
* Plane is painted with a diagonal. The plane may be hacked up * Plane is painted with a diagonal. The plane may be hacked up
@ -1472,12 +1452,12 @@ typedef struct
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
int void
DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method) DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
Plane *plane; /* Plane whose paint is to be modified */ Plane *plane; /* Plane whose paint is to be modified */
TileType exacttype; /* diagonal info for tile to be changed */ TileType exacttype; /* diagonal info for tile to be changed */
Rect *area; /* Area to be changed */ Rect *area; /* Area to be changed */
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to * present in the plane, giving the type to
* which the existing tile must change as a * which the existing tile must change as a
* result of this paint operation. * result of this paint operation.
@ -1498,7 +1478,6 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
int xc, yc, width, height; int xc, yc, width, height;
dlong xref, yref; /* xref, yref can easily exceed 32 bits */ dlong xref, yref; /* xref, yref can easily exceed 32 bits */
int resstate; int resstate;
int result = 0;
if (exacttype & TT_DIAGONAL) if (exacttype & TT_DIAGONAL)
{ {
@ -1519,7 +1498,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
/* linked list out of them. */ /* linked list out of them. */
lhead = NULL; lhead = NULL;
DBSrPaintArea(PlaneGetHint(plane), plane, area, &DBAllTypeBits, DBSrPaintArea(plane->pl_hint, plane, area, &DBAllTypeBits,
dbNMEnumFunc, (ClientData) &lhead); dbNMEnumFunc, (ClientData) &lhead);
/*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/
@ -1539,7 +1518,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
GeoClip(&lhead->r_r, area); GeoClip(&lhead->r_r, area);
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Ignore tiles that don't interact. This has */ /* Ignore tiles that don't interact. This has */
@ -1553,7 +1532,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (resultTbl[oldType] == oldType) if (resultTbl[oldType] == oldType)
{ {
freeMagic((char *) lr); freeMagic((char *) lr);
return 0; return;
} }
} }
@ -1565,7 +1544,7 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (newType == oldType) if (newType == oldType)
{ {
freeMagic((char *) lr); freeMagic((char *) lr);
return 0; return;
} }
/* Watch for the worst-case scenario of attempting to */ /* Watch for the worst-case scenario of attempting to */
@ -1581,9 +1560,9 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
{ {
if ((width == 1) || (height == 1)) if ((width == 1) || (height == 1))
{ {
result = DBPaintPlane(plane, &(lr->r_r), resultTbl, undo); DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
freeMagic((char *) lr); freeMagic((char *) lr);
return 1; /* Flag the error by returning 1 */ return;
} }
/* lr->r_r is drawn & quartered */ /* lr->r_r is drawn & quartered */
@ -1626,9 +1605,9 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
if (newType & TT_DIAGONAL) if (newType & TT_DIAGONAL)
{ {
result = DBPaintPlane(plane, &(lr->r_r), DBSpecialPaintTbl, DBPaintPlane(plane, &(lr->r_r), DBSpecialPaintTbl,
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &(lr->r_r.r_ll)); GOTOPOINT(tile, &(lr->r_r.r_ll));
if (undo && UndoIsEnabled()) if (undo && UndoIsEnabled())
{ {
@ -1641,14 +1620,14 @@ DBNMPaintPlane0(plane, exacttype, area, resultTbl, undo, method)
{ {
PaintResultType tempTbl; PaintResultType tempTbl;
tempTbl = newType; tempTbl = newType;
result = DBPaintPlane0(plane, &(lr->r_r), &tempTbl, DBPaintPlane0(plane, &(lr->r_r), &tempTbl, undo, method);
undo, method);
} }
else else
result = DBPaintPlane(plane, &(lr->r_r), resultTbl, undo); DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
freeMagic((char *) lr); freeMagic((char *) lr);
return result; /* goto nmmerge; */
return;
} }
} }
@ -1776,32 +1755,27 @@ paintrect:
if (resstate == RES_DIAG) if (resstate == RES_DIAG)
{ {
/* Recursive call to self on sub-area */ /* Recursive call to self on sub-area */
result |= DBNMPaintPlane0(plane, exacttype, &(lr->r_r), resultTbl, DBNMPaintPlane0(plane, exacttype, &(lr->r_r), resultTbl, undo, method);
undo, method);
} }
else if ((resstate == RES_LEFT && !dinfo.side) || else if ((resstate == RES_LEFT && !dinfo.side) ||
(resstate == RES_RIGHT && dinfo.side)) { (resstate == RES_RIGHT && dinfo.side)) {
result |= DBPaintPlane(plane, &(lr->r_r), resultTbl, undo); DBPaintPlane(plane, &(lr->r_r), resultTbl, undo);
} }
/* else: Rectangle does not contain type and should be ignored. */ /* else: Rectangle does not contain type and should be ignored. */
nextrect: nextrect:
lr = lr->r_next; lr = lr->r_next;
} }
free_magic1_t mm1 = freeMagic1_init();
lr = lhead; lr = lhead;
while (lr != NULL) while (lr != NULL)
{ {
freeMagic1(&mm1, (char *) lr); freeMagic((char *) lr);
lr = lr->r_next; lr = lr->r_next;
} }
freeMagic1_end(&mm1);
} }
else else
result = DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ? DBPaintPlane0(plane, area, resultTbl, undo, (method == PAINT_MARK) ?
method : PAINT_NORMAL); method : PAINT_NORMAL);
return result;
} }
/* /*
@ -1816,15 +1790,14 @@ nextrect:
*/ */
int int
dbNMEnumFunc(tile, dinfo, arg) dbNMEnumFunc(tile, arg)
Tile *tile; Tile *tile;
TileType dinfo;
LinkedRect **arg; LinkedRect **arg;
{ {
LinkedRect *lr; LinkedRect *lr;
/* Ignore the second call to any diagonal---only count once! */ /* Ignore the second call to any diagonal---only count once! */
if (IsSplit(tile) && (dinfo & TT_SIDE)) return 0; if (IsSplit(tile) && SplitSide(tile)) return 0;
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect)); lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
TiToRect(tile, &lr->r_r); TiToRect(tile, &lr->r_r);
@ -1908,7 +1881,6 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
PaintUndoInfo *undo; /* See DBPaintPlane() above */ PaintUndoInfo *undo; /* See DBPaintPlane() above */
bool mark; /* Mark tiles that were processed */ bool mark; /* Mark tiles that were processed */
{ {
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast; Tile *tp, *tpLast;
int ysplit; int ysplit;
@ -2015,7 +1987,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mark) dbMarkClient(tile, area); if (mark) dbMarkClient(tile, area);
} }
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile)); if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left"); dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -2031,7 +2003,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mark) dbMarkClient(tile, area); if (mark) dbMarkClient(tile, area);
} }
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile)); if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right"); dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
@ -2040,7 +2012,7 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mergeFlags&MRG_TOP) if (mergeFlags&MRG_TOP)
{ {
tp = RT(tile); tp = RT(tile);
if (CANMERGE_Y(tp, tile)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tp, tile)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up"); dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2049,14 +2021,13 @@ dbPaintMerge(tile, newType, area, plane, mergeFlags, undo, mark)
if (mergeFlags&MRG_BOTTOM) if (mergeFlags&MRG_BOTTOM)
{ {
tp = LB(tile); tp = LB(tile);
if (CANMERGE_Y(tp, tile)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tp, tile)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down"); dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
#endif /* PAINTDEBUG */ #endif /* PAINTDEBUG */
} }
TiFreeIf(delayed);
return (tile); return (tile);
} }
@ -2089,7 +2060,7 @@ void
DBPaintType(plane, area, resultTbl, client, undo, tileMask) DBPaintType(plane, area, resultTbl, client, undo, tileMask)
Plane *plane; /* Plane whose paint is to be modified */ Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */ Rect *area; /* Area to be changed */
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to * present in the plane, giving the type to
* which the existing tile must change as a * which the existing tile must change as a
* result of this paint operation. * result of this paint operation.
@ -2119,10 +2090,9 @@ DBPaintType(plane, area, resultTbl, client, undo, tileMask)
* search. * search.
*/ */
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */ /* Each iteration visits another tile on the LHS of the search area */
@ -2212,14 +2182,14 @@ enumerate:
if (CANMERGE_Y(newtile, tp) && if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) || ( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) ) ( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY1(&delayed, newtile, tp, plane); TiJoinY(newtile, tp, plane);
/* Merge the outside tile to its bottom */ /* Merge the outside tile to its bottom */
tp = LB(newtile); tp = LB(newtile);
if (CANMERGE_Y(newtile, tp) && if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) || ( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) ) ( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY1(&delayed, newtile, tp, plane); TiJoinY(newtile, tp, plane);
} }
/* Clip left */ /* Clip left */
@ -2236,14 +2206,14 @@ enumerate:
if (CANMERGE_Y(newtile, tp) && if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) || ( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) ) ( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY1(&delayed, newtile, tp, plane); TiJoinY(newtile, tp, plane);
/* Merge the outside tile to its bottom */ /* Merge the outside tile to its bottom */
tp = LB(newtile); tp = LB(newtile);
if (CANMERGE_Y(newtile, tp) && if (CANMERGE_Y(newtile, tp) &&
( (TiGetClient(tp) == TiGetClient(newtile)) || ( (TiGetClient(tp) == TiGetClient(newtile)) ||
( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) ) ( ! TTMaskHasType(tileMask, TiGetTypeExact(tp)) ) ) )
TiJoinY1(&delayed, newtile, tp, plane); TiJoinY(newtile, tp, plane);
} }
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
@ -2302,7 +2272,7 @@ enumerate:
{ {
tp = RT(tile); tp = RT(tile);
if (CANMERGE_Y(tile, tp) && (tp->ti_client == client)) if (CANMERGE_Y(tile, tp) && (tp->ti_client == client))
TiJoinY1(&delayed, tile, tp, plane); TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged up (CHEAP)"); dbPaintShowTile(tile, undo, "merged up (CHEAP)");
@ -2312,7 +2282,7 @@ enumerate:
{ {
tp = LB(tile); tp = LB(tile);
if (CANMERGE_Y(tile, tp) && (tp->ti_client == client)) if (CANMERGE_Y(tile, tp) && (tp->ti_client == client))
TiJoinY1(&delayed, tile, tp, plane); TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged down (CHEAP)"); dbPaintShowTile(tile, undo, "merged down (CHEAP)");
@ -2359,8 +2329,7 @@ paintdone:
} }
done: done:
PlaneSetHint(plane, tile); plane->pl_hint = tile;
TiFreeIf(delayed);
} }
/* /*
@ -2407,7 +2376,6 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
PaintUndoInfo *undo; /* See DBPaintPlane() above */ PaintUndoInfo *undo; /* See DBPaintPlane() above */
ClientData client; ClientData client;
{ {
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast; Tile *tp, *tpLast;
int ysplit; int ysplit;
@ -2509,7 +2477,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
TiSetClient(tpLast, client); TiSetClient(tpLast, client);
} }
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile)); if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left"); dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -2525,7 +2493,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
TiSetClient(tpLast, client); TiSetClient(tpLast, client);
} }
if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile)); if (BOTTOM(tp) < BOTTOM(tile)) tp = TiSplitY(tp, BOTTOM(tile));
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right"); dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
@ -2534,7 +2502,7 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
if (mergeFlags&MRG_TOP) if (mergeFlags&MRG_TOP)
{ {
tp = RT(tile); tp = RT(tile);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up"); dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2543,14 +2511,13 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
if (mergeFlags&MRG_BOTTOM) if (mergeFlags&MRG_BOTTOM)
{ {
tp = LB(tile); tp = LB(tile);
if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tp, tile) && (tp->ti_client == client)) TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down"); dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
#endif /* PAINTDEBUG */ #endif /* PAINTDEBUG */
} }
TiFreeIf(delayed);
return (tile); return (tile);
} }
@ -2580,11 +2547,11 @@ dbMergeType(tile, newType, plane, mergeFlags, undo, client)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
int void
DBPaintPlaneVert(plane, area, resultTbl, undo) DBPaintPlaneVert(plane, area, resultTbl, undo)
Plane *plane; /* Plane whose paint is to be modified */ Plane *plane; /* Plane whose paint is to be modified */
Rect *area; /* Area to be changed */ Rect *area; /* Area to be changed */
const PaintResultType *resultTbl; /* Table, indexed by the type of tile already PaintResultType *resultTbl; /* Table, indexed by the type of tile already
* present in the plane, giving the type to * present in the plane, giving the type to
* which the existing tile must change as a * which the existing tile must change as a
* result of this paint operation. * result of this paint operation.
@ -2601,7 +2568,7 @@ DBPaintPlaneVert(plane, area, resultTbl, undo)
Tile *newtile, *tp; /* Used for paint */ Tile *newtile, *tp; /* Used for paint */
if (area->r_xtop <= area->r_xbot || area->r_ytop <= area->r_ybot) if (area->r_xtop <= area->r_xbot || area->r_ytop <= area->r_ybot)
return 0; return;
/* /*
* The following is a modified version of the area enumeration * The following is a modified version of the area enumeration
@ -2610,10 +2577,9 @@ DBPaintPlaneVert(plane, area, resultTbl, undo)
* search. * search.
*/ */
Tile *delayed = NULL; /* delayed free to extend lifetime */
start.p_x = area->r_xbot; start.p_x = area->r_xbot;
start.p_y = area->r_ytop - 1; start.p_y = area->r_ytop - 1;
tile = PlaneGetHint(plane); tile = plane->pl_hint;
GOTOPOINT(tile, &start); GOTOPOINT(tile, &start);
/* Each iteration visits another tile on the LHS of the search area */ /* Each iteration visits another tile on the LHS of the search area */
@ -2692,11 +2658,11 @@ enumerate:
/* Merge the outside tile to its left */ /* Merge the outside tile to its left */
tp = BL(newtile); tp = BL(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane); if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
/* Merge the outside tile to its right */ /* Merge the outside tile to its right */
tp = TR(newtile); tp = TR(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane); if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
} }
/* Clip down */ /* Clip down */
@ -2708,11 +2674,11 @@ enumerate:
/* Merge the outside tile to its left */ /* Merge the outside tile to its left */
tp = BL(newtile); tp = BL(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane); if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
/* Merge the outside tile to its right */ /* Merge the outside tile to its right */
tp = TR(newtile); tp = TR(newtile);
if (CANMERGE_X(newtile, tp)) TiJoinX1(&delayed, newtile, tp, plane); if (CANMERGE_X(newtile, tp)) TiJoinX(newtile, tp, plane);
} }
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
@ -2770,7 +2736,7 @@ enumerate:
if (mergeFlags & MRG_LEFT) if (mergeFlags & MRG_LEFT)
{ {
tp = BL(tile); tp = BL(tile);
if (CANMERGE_X(tile, tp)) TiJoinX1(&delayed, tile, tp, plane); if (CANMERGE_X(tile, tp)) TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged left (CHEAP)"); dbPaintShowTile(tile, undo, "merged left (CHEAP)");
@ -2779,7 +2745,7 @@ enumerate:
if (mergeFlags & MRG_RIGHT) if (mergeFlags & MRG_RIGHT)
{ {
tp = TR(tile); tp = TR(tile);
if (CANMERGE_X(tile, tp)) TiJoinX1(&delayed, tile, tp, plane); if (CANMERGE_X(tile, tp)) TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "merged right (CHEAP)"); dbPaintShowTile(tile, undo, "merged right (CHEAP)");
@ -2826,9 +2792,7 @@ paintdone:
} }
done: done:
PlaneSetHint(plane, tile); plane->pl_hint = tile;
TiFreeIf(delayed);
return 0;
} }
/* /*
@ -2880,7 +2844,6 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
int mergeFlags; /* Specify which directions to merge */ int mergeFlags; /* Specify which directions to merge */
PaintUndoInfo *undo; /* See DBPaintPlane() above */ PaintUndoInfo *undo; /* See DBPaintPlane() above */
{ {
Tile *delayed = NULL; /* delayed free to extend lifetime */
Tile *tp, *tpLast; Tile *tp, *tpLast;
int xsplit; int xsplit;
@ -2975,7 +2938,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile)); if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile));
if (RIGHT(tp) > RIGHT(tile)) if (RIGHT(tp) > RIGHT(tile))
tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType); tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType);
TiJoinY1(&delayed, tile, tp, plane); TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged up"); dbPaintShowTile(tile, undo, "(DBMERGE) merged up");
@ -2988,7 +2951,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile)); if (LEFT(tp) < LEFT(tile)) tp = TiSplitX(tp, LEFT(tile));
if (RIGHT(tp) > RIGHT(tile)) if (RIGHT(tp) > RIGHT(tile))
tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType); tpLast = TiSplitX(tp, RIGHT(tile)), TiSetBody(tpLast, newType);
TiJoinY1(&delayed, tile, tp, plane); TiJoinY(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged down"); dbPaintShowTile(tile, undo, "(DBMERGE) merged down");
@ -2998,7 +2961,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (mergeFlags&MRG_LEFT) if (mergeFlags&MRG_LEFT)
{ {
tp = BL(tile); tp = BL(tile);
if (CANMERGE_X(tp, tile)) TiJoinX1(&delayed, tile, tp, plane); if (CANMERGE_X(tp, tile)) TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged left"); dbPaintShowTile(tile, undo, "(DBMERGE) merged left");
@ -3007,14 +2970,13 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
if (mergeFlags&MRG_RIGHT) if (mergeFlags&MRG_RIGHT)
{ {
tp = TR(tile); tp = TR(tile);
if (CANMERGE_X(tp, tile)) TiJoinX1(&delayed, tile, tp, plane); if (CANMERGE_X(tp, tile)) TiJoinX(tile, tp, plane);
#ifdef PAINTDEBUG #ifdef PAINTDEBUG
if (dbPaintDebug) if (dbPaintDebug)
dbPaintShowTile(tile, undo, "(DBMERGE) merged right"); dbPaintShowTile(tile, undo, "(DBMERGE) merged right");
#endif /* PAINTDEBUG */ #endif /* PAINTDEBUG */
} }
TiFreeIf(delayed);
return (tile); return (tile);
} }
@ -3037,7 +2999,7 @@ dbPaintMergeVert(tile, newType, plane, mergeFlags, undo)
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#include "utils/styles.h" #include "styles.h"
void void
dbPaintShowTile(tile, undo, str) dbPaintShowTile(tile, undo, str)
@ -3060,16 +3022,6 @@ dbPaintShowTile(tile, undo, str)
TxPrintf("%s --more--", str); fflush(stdout); TxPrintf("%s --more--", str); fflush(stdout);
(void) TxGetLine(answer, sizeof answer); (void) TxGetLine(answer, sizeof answer);
DBWFeedbackClear(NULL); 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 */ #endif /* PAINTDEBUG */
@ -3359,7 +3311,6 @@ TiNMMergeRight(tile, plane)
Tile *tile; Tile *tile;
Plane *plane; Plane *plane;
{ {
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype = TiGetTypeExact(tile); TileType ttype = TiGetTypeExact(tile);
Tile *tp, *tp2, *newtile; Tile *tp, *tp2, *newtile;
@ -3391,7 +3342,7 @@ TiNMMergeRight(tile, plane)
else else
newtile = tile; newtile = tile;
// Join tp to newtile // Join tp to newtile
TiJoinX1(&delayed, newtile, tp, plane); TiJoinX(newtile, tp, plane);
} }
tp = tp2; tp = tp2;
} }
@ -3408,13 +3359,11 @@ TiNMMergeRight(tile, plane)
newtile = TiSplitY(tp, BOTTOM(tile)); newtile = TiSplitY(tp, BOTTOM(tile));
TiSetBody(newtile, ttype); TiSetBody(newtile, ttype);
// join newtile to tile // join newtile to tile
TiJoinX1(&delayed, tile, newtile, plane); TiJoinX(tile, newtile, plane);
// merge up if possible // merge up if possible
if (CANMERGE_Y(tile, RT(tile))) TiJoinY1(&delayed, tile, RT(tile), plane); if (CANMERGE_Y(tile, RT(tile))) TiJoinY(tile, RT(tile), plane);
} }
} }
TiFreeIf(delayed);
return tile; return tile;
} }
@ -3442,7 +3391,6 @@ TiNMMergeLeft(tile, plane)
Tile *tile; Tile *tile;
Plane *plane; Plane *plane;
{ {
Tile *delayed = NULL; /* delayed free to extend lifetime */
TileType ttype = TiGetTypeExact(tile); TileType ttype = TiGetTypeExact(tile);
Tile *tp, *tp2, *newtile; Tile *tp, *tp2, *newtile;
@ -3475,7 +3423,7 @@ TiNMMergeLeft(tile, plane)
else else
newtile = tile; newtile = tile;
// Join tp to tile // Join tp to tile
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
tile = newtile; tile = newtile;
} }
tp = tp2; tp = tp2;
@ -3493,16 +3441,14 @@ TiNMMergeLeft(tile, plane)
newtile = TiSplitY(tp, TOP(tile)); newtile = TiSplitY(tp, TOP(tile));
TiSetBody(newtile, ttype); TiSetBody(newtile, ttype);
// join tp to tile // join tp to tile
TiJoinX1(&delayed, tile, tp, plane); TiJoinX(tile, tp, plane);
} }
} }
else else
{ {
// Merge up if possible // Merge up if possible
if (CANMERGE_Y(tile, tp)) TiJoinY1(&delayed, tile, tp, plane); if (CANMERGE_Y(tile, tp)) TiJoinY(tile, tp, plane);
} }
TiFreeIf(delayed);
return tile; return tile;
} }

View File

@ -119,9 +119,8 @@ DBPaint (cellDef, rect, type)
*/ */
int int
dbResolveImages(tile, dinfo, cellDef) dbResolveImages(tile, cellDef)
Tile *tile; Tile *tile;
TileType dinfo;
CellDef *cellDef; CellDef *cellDef;
{ {
Rect rect; Rect rect;
@ -131,7 +130,7 @@ dbResolveImages(tile, dinfo, cellDef)
/* Recursive call back to DBPaint---this will ensure that */ /* Recursive call back to DBPaint---this will ensure that */
/* all of the planes of the image type are painted. */ /* all of the planes of the image type are painted. */
DBPaint(cellDef, &rect, TiGetTypeExact(tile) | dinfo); DBPaint(cellDef, &rect, TiGetTypeExact(tile));
return 0; return 0;
} }
@ -284,7 +283,6 @@ DBPaintValid(cellDef, rect, mask, dinfo)
for (t = TT_SELECTBASE; t < DBNumUserLayers; t++) for (t = TT_SELECTBASE; t < DBNumUserLayers; t++)
if (TTMaskHasType(&mmask, t)) if (TTMaskHasType(&mmask, t))
{
if (DBIsContact(t)) if (DBIsContact(t))
{ {
tMask = DBResidueMask(t); tMask = DBResidueMask(t);
@ -312,7 +310,6 @@ DBPaintValid(cellDef, rect, mask, dinfo)
(t << 14) : t) : t); (t << 14) : t) : t);
DBPaint(cellDef, rect, tloc); DBPaint(cellDef, rect, tloc);
} }
}
} }
/* /*
@ -385,7 +382,6 @@ DBEraseValid(cellDef, rect, mask, dinfo)
for (t = TT_SELECTBASE; t < DBNumUserLayers; t++) for (t = TT_SELECTBASE; t < DBNumUserLayers; t++)
if (TTMaskHasType(&mmask, t)) if (TTMaskHasType(&mmask, t))
{
if (DBIsContact(t)) if (DBIsContact(t))
{ {
tMask = DBResidueMask(t); tMask = DBResidueMask(t);
@ -413,5 +409,4 @@ DBEraseValid(cellDef, rect, mask, dinfo)
(t << 14) : t) : t); (t << 14) : t) : t);
DBErase(cellDef, rect, tloc); DBErase(cellDef, rect, tloc);
} }
}
} }

View File

@ -24,7 +24,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */ #endif /* not lint */
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -32,20 +31,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h" #include "database/database.h"
#include "utils/malloc.h" #include "utils/malloc.h"
/* Global variable */
bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
* .mag files as type "string" for backwards
* compatibility. If FALSE, then properties
* are saved to the .mag file along with their
* type. Regardless of the setting, properties
* which are reserved keywords are converted
* to the best internal representation on input.
*/
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* *
* DBPropPut -- *DBPropPut --
* *
* Put a property onto a celldef. * Put a property onto a celldef.
* *
@ -57,27 +46,19 @@ bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
void void
DBPropPut(cellDef, name, value) DBPropPut(cellDef, name, value)
CellDef *cellDef; /* Pointer to definition of cell. */ CellDef *cellDef; /* Pointer to definition of cell. */
char *name; /* The name of the property desired. */ char *name; /* The name of the property desired. */
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL. ClientData value; /* MUST point to a malloc'ed structure, or NULL.
* This will be freed when the CellDef is freed. * This will be freed when the CellDef is freed.
*/ */
{ {
HashTable *htab; HashTable *htab;
HashEntry *entry; HashEntry *entry;
PropertyRecord *oldvalue; char *oldvalue;
/* Honor the NOEDIT flag. Note that the caller always assumes that */ /* Honor the NOEDIT flag */
/* the value would be saved in the hash table, so if it is not */ if (cellDef->cd_flags & CDNOEDIT) return;
/* being used, then it must be freed here. */
if (cellDef->cd_flags & CDNOEDIT)
{
if (value != (ClientData)NULL)
freeMagic((char *)value);
return;
}
if (cellDef->cd_props == (ClientData) NULL) if (cellDef->cd_props == (ClientData) NULL)
{ {
@ -95,33 +76,13 @@ DBPropPut(cellDef, name, value)
cellDef->cd_flags |= CDFIXEDBBOX; cellDef->cd_flags |= CDFIXEDBBOX;
} }
/* Special handling of GDS_FILE, which uses CDVENDORGDS as a quick lookup */
if (!strcmp(name, "GDS_FILE"))
{
if (value == (ClientData)NULL)
cellDef->cd_flags &= ~CDVENDORGDS;
else
cellDef->cd_flags |= CDVENDORGDS;
}
entry = HashFind(htab, name); entry = HashFind(htab, name);
oldvalue = (PropertyRecord *)HashGetValue(entry); oldvalue = (char *)HashGetValue(entry);
/* All properties are allocated as a single block and can just be freed, if (oldvalue != NULL) freeMagic(oldvalue);
* except for plane properties, which require freeing the plane. if (value == (ClientData)NULL)
*/
if (oldvalue != NULL)
{
if (oldvalue->prop_type == PROPERTY_TYPE_PLANE)
{
DBFreePaintPlane(oldvalue->prop_value.prop_plane);
TiFreePlane(oldvalue->prop_value.prop_plane);
}
freeMagic((char *)oldvalue);
}
if (value == (PropertyRecord *)NULL)
HashRemove(htab, name); HashRemove(htab, name);
else else
HashSetValue(entry, PTR2CD(value)); HashSetValue(entry, value);
} }
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -131,13 +92,13 @@ DBPropPut(cellDef, name, value)
* Get a property from a celldef. * Get a property from a celldef.
* *
* Results: * Results:
* NULL if the property didn't exist, or if the property record was NULL. * NULL if the property didn't exist, or if the property value was NULL.
* Otherwise, returns a pointer to the property record. * Otherwise, ClientData that represents the property.
* *
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
PropertyRecord * ClientData
DBPropGet(cellDef, name, found) DBPropGet(cellDef, name, found)
CellDef *cellDef; /* Pointer to definition of cell. */ CellDef *cellDef; /* Pointer to definition of cell. */
char *name; /* The name of the property desired. */ char *name; /* The name of the property desired. */
@ -145,12 +106,12 @@ DBPropGet(cellDef, name, found)
* exists. * exists.
*/ */
{ {
PropertyRecord *result; ClientData result;
bool haveit; bool haveit;
HashTable *htab; HashTable *htab;
HashEntry *entry; HashEntry *entry;
result = (PropertyRecord *)NULL; result = (ClientData) NULL;
haveit = FALSE; haveit = FALSE;
htab = (HashTable *) cellDef->cd_props; htab = (HashTable *) cellDef->cd_props;
if (htab == (HashTable *) NULL) goto done; if (htab == (HashTable *) NULL) goto done;
@ -159,7 +120,7 @@ DBPropGet(cellDef, name, found)
if (entry != NULL) if (entry != NULL)
{ {
haveit = TRUE; haveit = TRUE;
result = (PropertyRecord *)HashGetValue(entry); result = (ClientData) HashGetValue(entry);
} }
done: done:
@ -167,109 +128,6 @@ done:
return result; return result;
} }
/* ----------------------------------------------------------------------------
*
* DBPropGetString --
*
* Get a string property from a celldef.
*
* Results:
* NULL if the property didn't exist, or if the property record was NULL.
* Otherwise, returns a pointer to the property's string record.
*
* Notes:
* This is basically the original DBPropGet(), when properties were only
* allowed to be strings.
*
* ----------------------------------------------------------------------------
*/
char *
DBPropGetString(cellDef, name, found)
CellDef *cellDef; /* Pointer to definition of cell. */
char *name; /* The name of the property desired. */
bool *found; /* If not NULL, filled in with TRUE iff the property
* exists.
*/
{
char *result = NULL;
PropertyRecord *proprec;
bool haveit;
HashTable *htab;
HashEntry *entry;
haveit = FALSE;
htab = (HashTable *) cellDef->cd_props;
if (htab == (HashTable *) NULL) goto pdone;
entry = HashLookOnly(htab, name);
if (entry != NULL)
{
proprec = (PropertyRecord *)HashGetValue(entry);
if (proprec->prop_type == PROPERTY_TYPE_STRING)
{
haveit = TRUE;
result = proprec->prop_value.prop_string;
}
}
pdone:
if (found != (bool *) NULL) *found = haveit;
return result;
}
/* ----------------------------------------------------------------------------
*
* DBPropGetDouble --
*
* Get a single double-long integer property from a celldef.
*
* Results:
* NULL if the property didn't exist, or if the property record was NULL.
* Otherwise, returns a pointer to the property's value record.
*
* ----------------------------------------------------------------------------
*/
dlong
DBPropGetDouble(cellDef, name, found)
CellDef *cellDef; /* Pointer to definition of cell. */
char *name; /* The name of the property desired. */
bool *found; /* If not NULL, filled in with TRUE iff the property
* exists.
*/
{
dlong result = 0;
PropertyRecord *proprec;
bool haveit;
HashTable *htab;
HashEntry *entry;
haveit = FALSE;
htab = (HashTable *) cellDef->cd_props;
if (htab == (HashTable *) NULL) goto ddone;
entry = HashLookOnly(htab, name);
if (entry != NULL)
{
proprec = (PropertyRecord *)HashGetValue(entry);
if (proprec->prop_type == PROPERTY_TYPE_DOUBLE)
{
haveit = TRUE;
result = proprec->prop_value.prop_double[0];
}
else if (proprec->prop_type == PROPERTY_TYPE_STRING)
{
haveit = TRUE;
sscanf(proprec->prop_value.prop_string, "%"DLONG_PREFIX"d", &result);
}
}
ddone:
if (found != (bool *) NULL) *found = haveit;
return result;
}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* *
* DBPropEnum -- * DBPropEnum --
@ -292,7 +150,7 @@ DBPropEnum(cellDef, func, cdata)
* *
* int foo(name, value, cdata) * int foo(name, value, cdata)
* char *name; * char *name;
* PropertyRecord *value; * ClientData value;
* ClientData cdata; * ClientData cdata;
* { * {
* -- return 0 to continue, * -- return 0 to continue,
@ -313,7 +171,7 @@ DBPropEnum(cellDef, func, cdata)
HashStartSearch(&hs); HashStartSearch(&hs);
while ((entry = HashNext(htab, &hs)) != NULL) while ((entry = HashNext(htab, &hs)) != NULL)
{ {
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata); res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
if (res != 0) return res; if (res != 0) return res;
} }

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