DELETED .agignore
Index: .agignore
==================================================================
--- .agignore
+++ /dev/null
@@ -1,2 +0,0 @@
-inst
-test
Index: .fossil-settings/crlf-glob
==================================================================
--- .fossil-settings/crlf-glob
+++ .fossil-settings/crlf-glob
@@ -1,12 +1,11 @@
+cc8/*.[ch]
+cc8/*.pa
+cc8/*.sb
+
examples/*.fc
src/*.[ch]
src/*.in
-src/cc8/*/*.[ch]
-src/cc8/include/*
-src/cc8/os8/*.sb
-src/cc8/os8/bldcc8.bi
-
src/PDP8/pdp8_*.[ch]
src/PDP8/pidp8i.c.in
DELETED .ignore
Index: .ignore
==================================================================
--- .ignore
+++ /dev/null
@@ -1,1 +0,0 @@
-.agignore
Index: COPYING.md
==================================================================
--- COPYING.md
+++ COPYING.md
@@ -3,11 +3,11 @@
The PiDP-8/I software distribution is an agglomeration of software from
multiple sources. Several different licenses apply to its parts. This
file guides you to those individual licenses.
-## SIMH License
+## SIMH License
Most of the files in this software distribution are released under the
terms of the SIMH license, a copy of which typically appears at the top
of each file it applies to. This includes not only SIMH proper but also
several files written by PiDP-8/I software project contributors who
@@ -18,11 +18,11 @@
included with the distribution][sl].
[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
-## PiDP-8/I Design Files
+## PiDP-8/I Design Files
The PiDP-8/I design files in [`hardware/pidp8i`][hwp] were released
under the Creative Commons [Attribution-NonCommercial-ShareAlike 4.0
International][ccl] license [on the mailing list][pdp8il] by their
author, Oscar Vermeulen.
@@ -30,76 +30,36 @@
[ccl]: https://creativecommons.org/licenses/by-nc-sa/4.0/
[hwp]: https://tangentsoft.com/pidp8i/dir?name=hardware/pdp8i&ci=trunk
[pdp8il]: https://groups.google.com/d/msg/pidp-8/bcIH9uEB_kU/zg9uho7NDAAJ
-## autosetup License
+## autosetup License
The `configure` script and the contents of the `autosetup` directory are
released under the FreeBSD license given in [`autosetup/LICENSE`][as].
[as]: https://tangentsoft.com/pidp8i/doc/trunk/autosetup/LICENSE
-## palbart License
+## palbart License
The `palbart` program and its manual page are released under the terms
-of the license given in [`src/palbart/LICENSE.md`][pl].
-
-[pl]: https://tangentsoft.com/pidp8i/doc/trunk/src/palbart/LICENSE.md
-
-
-## d8tape License
-
-The `d8tape` program is distributed under the license given in
-[`src/d8tape/LICENSE.md`][d8tl].
-
-[d8tl]: https://tangentsoft.com/pidp8i/doc/trunk/src/d8tape/LICENSE.md
-
-
-## CC8 Compiler License
-
-The license for the `src/cc8` subtree is messy as it comes to us from
-multiple authors over many years.
-
-There are two compilers here.
-
-First we have the OS/8 "native" compiler in `src/cc8/os8`, which is
-entirely Ian Schofield's work, released under the terms of the [GNU
-General Public License version 3][gpl3].
-
-Then we have the CC8 cross-compiler which is based on Ron Cain's
-[Small-C][smc], originally published in [Dr. Dobbs' Journal][ddj].
-Wikipedia describes Small-C as "copyrighted but sharable," which I take
-to mean that we cannot claim it as our exclusive property, but we can
-modify it and distribute those modifications to others, which is what
-we're doing here.
-
-Ian Schofield then took the Small-C source base and added a SABR
-back-end, `code8.c`, which is also distributed under the [GPLv3][gpl3].
-
-There is [another PDP-8 C compiler project][smsc] based on Small-C by
-Vincent Slyngstad, which uses an entirely different approach for code
-generation. Ian Schofield took some of the library routines from this
-implementation.
-
-[ddj]: https://en.wikipedia.org/wiki/Dr._Dobb%27s_Journal
-[gpl3]: https://tangentsoft.com/pidp8i/doc/trunk/src/cc8/LICENSE.txt
-[smc]: https://en.wikipedia.org/wiki/Small-C
-[smsc]: http://so-much-stuff.com/pdp8/C/C.php
-
-
-## OS/8 License
+of the license given in [`palbart/LICENSE.md`][pl].
+
+[pl]: https://tangentsoft.com/pidp8i/doc/trunk/palbart/LICENSE.md
+
+
+## OS/8 License
The OS/8 media images included with this software distribution are
released under the Digital License Agreement presented in
[`media/os8/LICENSE.md`][dla].
[dla]: https://tangentsoft.com/pidp8i/doc/trunk/media/os8/LICENSE.md
-## Other DEC Software
+## Other DEC Software
The other files in the [`media`][md] and [`examples`][ed] directories
that originate from Digital Equipment Corporation are believed to fall
under the [public domain license][pdp8pd] DEC released all their PDP-8
software under after it stopped being ecomonmically viable. Documented
@@ -106,16 +66,15 @@
releases for specific software (e.g. TSS/8) may be difficult to come by,
however.
[md]: https://tangentsoft.com/pidp8i/dir?ci=trunk&name=media
[ed]: https://tangentsoft.com/pidp8i/dir?ci=trunk&name=examples
-[pdp8pd]: http://mailman.trailing-edge.com/pipermail/simh/2017-January/016164.html
-## ETOS License
+## ETOS License
ETOS was a commercial product produced outside of DEC. No public
documented declaration of license is known to be available for it, but
we have [a third-hand report][el] that its creators are fine with ETOS
being redistributed.
[el]: http://mailman.trailing-edge.com/pipermail/simh/2017-January/016169.html
Index: ChangeLog.md
==================================================================
--- ChangeLog.md
+++ ChangeLog.md
@@ -1,59 +1,20 @@
# PiDP-8/I Changes
-## Version 2017.12.eh? — The "Languages and Custom OS/8 Disk Packs" release
+## Version 2017.10.eh? — The "Languages and Custom OS/8 Disk Packs" release
* All prior versions were shipping `os8.rk05`, a "Field Service
Diagnostic" OS/8 disk pack image with uncertain provenance,
configuration, and modification history. We have replaced that with
a script run at build time that programmatically assembles a set of
- clean OS/8 RK05 disk images from curated, pristine, tested sources
- based on the user's chosen configuration options.
+ clean OS/8 RK05 disk images from original DEC binary distribution
+ DECtapes, other primary source media, and the user's chosen
+ configuration options.
This provides the following features and benefits as compared to the
old `os8.rk05`:
- - The PiDP-8/I software build process now builds up to three RK05
- disk images:
-
- - `os8v3d-bin.rk05` is a bootable OS/8 V3D disk configured
- according to your chosen configuration options, which are
- described below and in [`README.md`][tlrm]. It is made from
- the pristine DECtape images shipped by DEC for OS/8 V3D plus
- several third-party tapes curated for and built by the
- project's maintainers. See [the OS/8 media `README.md`
- file][os8rm] for more details.
-
- - `os8v3d-patched.rk05` is a copy of the `bin` disk with
- [most][os8p] of the patches DEC published over the years for
- OS/8 V3D applied. That set of patches was chosen and tested
- for applicability to our modern PiDP-8/I world and for
- mutual compatibility.
-
- This is the boot disk used for the IF=0 and IF=7 cases
- unless you give `--disable-os8-patches` to the `configure`
- script, in which case these boot options use the `bin` disk.
-
- - `os8v3d-src.rk05` is a non-bootable disk containing the
- contents of the OS/8 V3D source code tapes plus the source
- code for the extensions to OS/8 V3D. The *ten* TU56 tape
- images used as input to this process are also included among
- the PiDP-8/I software — see `media/os8/al-*-sa-*.tu56` — but
- we find it much more convenient to explore the sources on a
- single RK05 disk than to repeatedly attach and detach the
- TU56 tapes.
-
- You can suppress building this with `--disable-os8-src`.
-
- Default versions of these disk images are also now published on
- the project's home page for the benefit of those not running our
- PiDP-8/I software. There are quite a few OS/8 RK05 disk images
- floating around on the Internet these days, and many of them
- have bugs and breakage in them that we've fixed. It would
- completely fail to break our hearts if these images were used by
- many people outside the PiDP-8/I project.
-
- U/W FOCAL V4E is installed on SYS: by default. Start with our
[U/W FOCAL Manual Supplement for the PiDP-8/I][uwfs], then
follow links from there to further information.
The primary linked source is the [U/W FOCAL Manual][uwfm] by Jim
@@ -62,26 +23,15 @@
on the web.
This is a fascinating programming language, well worth studying!
- Ian Schofield's CC8 OS/8 C compiler is installed on `SYS:` by
- default, and its examples and other files are on `DSK:`. We
- have also merged in his `cc8` host-side cross-compiler. See
- [the CC8 `README`][cc8rm] for details.
-
- This is an improved version of the compiler relative to what was
- distributed on the mailing list in August 2017. Ian has been
- working within the project since that initial public release,
- making improvements to his compiler within our project, so that
- there will be a single canonical version. We thank him for
- trusting us to host and distribute his project.
-
- - The MACREL v2 macro assembler and its associated FUTIL V8B tool
- are installed by default. Not only is this new functionality
- relative to prior releases of the PiDP-8/I software, it is a
- considerable upgrade over to the original MACREL and FUTIL V7
- that are more commonly found on the net.
+ default. Also merged in his `cc8` cross-compiler and his
+ hand-rolled OS/8 distribution, `media/os8/cc8.rk05`. See [the
+ CC8 `README`][cc8rm] for details.
+
+ - MACREL macro assembler is installed by default.
- DCP disassembler is installed by default.
- John Comeau's CHECKMO-II chess program is installed by default.
@@ -88,49 +38,69 @@
- By default, SIMH no longer folds lowercase input and output to
uppercase. Instead, we apply patches to OS/8's command
processor and its BASIC implementation to up-case input, since
neither OS/8 nor BASIC can cope with lowercase input.
- All other programs are left to fend for themselves, which
- often works out fine. U/W FOCAL, Adventure, and TECO all handle
- lowercase input to some extent, for example, and all three can
- emit lowercase text if given it. With the prior SIMH setting,
- you could not use lowercase in these programs at all.
-
- This default can be overridden. See the documentation for the
- new `--lowercase` configuration option in `README.md`.
+ All other programs are left to fend for themselves, which often
+ works out fine. U/W FOCAL, Adventure, TECO, etc. all handle
+ lowercase input to some extent, and all can emit lowercase text
+ if given it. With the prior SIMH settting, you could not use
+ lowercase at all.
+
+ This change has been slightly controversial, so we have two
+ alternative modes that can be selected at `configure` time:
+
+ - No patches and no case-folding in SIMH. Lowercase I/O is
+ allowed, but neither SIMH nor OS/8 nor its programs will
+ second-guess your input, even if that means some programs
+ will fail when given lowercase input. If you need to engage
+ CAPS LOCK to make the program do the right thing, you are
+ expected to be aware enough to do this.
+
+ The argument in favor of this approach is that this is what
+ a real PDP-8 system running this software would have done if
+ sent lowercase input.
+
+ - Revert to the prior releases' behavior: no patches, and SIMH
+ does automatic case-folding for you, so you only get
+ uppercase, even when you type lowercase text. Programs that
+ emit lowercase text (e.g. Adventure) appear to be sending
+ uppercase instead.
+
+ This option is in fact historically accurate. Essentially,
+ this configuration makes SIMH pretend that your terminal is
+ only capable of uppercase text, which was very common in the
+ PDP-8's day: the uppercase-only Teletype Model 33 ASR was
+ the most common terminal type on PDP-8s.
+
+ Our new default is historically inaccurate, but we think it the
+ new behavior is the least likely to unpleasantly surprise end
+ users. Pick your poison.
- The `INIT.TX` message displayed by default on OS/8 boot is now
more informative than the old `FIELD SERVICE PDP-8 DIAGNOSTIC
- SYSTEM` message. It also now uses lowercase unless you built
- the simulator to force uppercase with `--lowercase=upper`.
-
- Those that do not want any boot message can disable it at
- configuration time with the `--disable-os8-init` flag.
-
- The message can be modified by editing `media/os8/init.tx.in`
- and saying `make`, which will rebuild the OS/8 media.
+ SYSTEM` message. Those that do not want any boot message can
+ disable it at configuration time.
- All of the above features can be disabled if not wanted, as can
several features present on the old `os8.rk05` disk: Adventure,
FORTRAN IV, FORTRAN II, Kermit-12, and the BASIC game and demo
programs.
- You can disable each feature above with a `--disable-os8-*`
- option to the `configure` script, or you can disable all of them
- collectively with the `--os8-minimal` option, which gets you a
- nearly bare-bones OS/8 installation with lots of spare disk
- space with which you can do what *you* want.
+ You can disable these features individually or you can disable
+ all of them with the new `configure --os8-minimal` feature,
+ which gets you a nearly bare-bones OS/8 installation with lots
+ of spare disk space with which you can do what *you* want.
- Replaced the mismatched FORTRAN compiler and runtime with
matched versions from the distribution DECtapes, and ensured that
Adventure runs under this version of the FORTRAN Run Time System
(FRTS). At various points in the past, either FORTRAN or
Adventure has been broken.
- - Repaired several broken BASIC programs on `RKB0:` by going back
- to primary sources. Either the `os8.rk05` disk image was corrupted
+ - Repaired several broken BASIC programs on RKB0: by going back to
+ primary sources. Either the `os8.rk05` disk image was corrupted
at some point or it is an image of a real RK05 disk pack that
was corrupted, causing several of these BASIC programs to not
run properly.
- The `*.MU` and music player files are left off of `RKB0:` by
@@ -141,10 +111,16 @@
- No longer installing the `VTEDIT` macros for TECO by default.
Although some may enjoy this alternative way of running TECO, it
was decided that we should offer stock TECO by default for its
historical value. If you want VTEDIT back, it can be re-enabled
with a `configure` script option.
+
+ - Added configure-time options to disable all of the above new
+ features and most of the features that were present on the
+ original `os8.rk05` disk as well. You can create a completely
+ stripped-down OS/8 disk image, one with all features enabled, or
+ anything in between.
- In the old `os8.rk05` disk image, both `SYS:` and `DSK:` were
set to `RKA0:`, which meant that to address anything on `RKB0:`, you
had to specify the device path explicitly or manually change the
default in OS/8 with an `ASSIGN RKB0 DSK` command or similar.
@@ -191,10 +167,14 @@
The difference in the `RESORC` output between the versions is:
Old: RKA0,RKB0,RKA1,RKB1, RXA0,RXA1,DTA0,DTA1,TTY,LPT,PTP,PTR
New: RKA0,RKB0,RKA1,RKB1,RKA2,RKB2,RXA0, DTA0,DTA1,TTY,LPT,PTP,PTR
+
+ - TODO: Added the `os8` script to add and remove features from the
+ built OS/8 binary disk image after it is initially built. In a
+ primitive sort of way, this is "[apt][apt] for OS/8."
This automatic OS/8 media build feature was suggested by Jonathan
Trites who wrote the initial version of the script that is now
called `libexec/mkos8`. That script was then extended and factored
into its current form by Bill Cattey and Warren Young.
@@ -207,76 +187,35 @@
See the [the top-level `README`][tlrm] for information on modifying
the default OS/8 configuration. Pretty much everything above can be
disabled if it's enabled by default, and vice versa.
-* Added Bill Cattey's `txt2ptp` program which converts plain ASCII
- text files files to the paper tape format used by SIMH, which eases
- transfer of text data into the simulator. That program is also
- linked to `ptp2txt`, which makes it perform the inverse function:
- given a SIMH paper tape image file, produce an ASCII text file on
- the host machine with its contents.
-
- This program was written to ease the movement of FOCAL program text
- between SIMH and its host OS, but they should prove useful for other
- similar tasks.
-
-* Integrated Robert Krten's `d8tape` PDP-8 host-side disassembler.
- This is distinct from the OS/8 DCP disassembler, which runs inside
- the simulator. It is intended as a companion to `palbart`, which we
- integrated last year.
-
-* Added a new "blinkenlights" demo program called `bin/teco-pi-demo`
- which drives SIMH from the outside, running a TECO macro under OS/8
- to calculate *pi* to 248 digits at a very slow rate, producing a
- display that manages to land somewhere between the random default
- display of [Deeper Thought][dt2vk] and the clear, boring patterns of
- our preexisting IF=5 demo script.
-
- Why 248 digits? Because at 249, TECO8 runs out of memory, aborting
- the demo early. At the default execution rate, it would take over
- 17 years to complete this demo, making it a good choice to run on
- PiDP-8/I units primarily being used as *objets d'art*. The demo has
- a finite run time, but your Raspberry Pi is likely to die before it
- completes. `;)`
-
- This script is also included as a demonstration of how the end user
- can reuse the technology that we developed to automatically build
- the custom OS/8 disk images described above to achieve different
- ends. Perhaps you have some other program you'd like to run within
- SIMH in an automated fashion? This shows one way how, and
- demonstrates a pre-built and tested set of tools for achieving it.
-
- We have also written [a tutorial][csd] explaining how
- `bin/teco-pi-demo` works and how to reuse the components it is built
- atop for your own ends.
-
- This demo also has a benchmark mode (command line option `-b`) which
- has two purposes:
-
- 1. It lets you see how much faster your host system runs PDP-8 code
- than a Raspberry Pi Model B+ running the PiDP-8/I simulator.
-
- 2. Given that information, the benchmark overrides a hardcoded
- timing value in the source code as distributed which prevents
- programs like `teco-pi-demo` from spamming the OS/8 terminal
- input handler. The default is for the slowest host we support
- this software on, that same Model B+ referred to above, but if
- we know you're running on a faster host, we can shorten this
- delay and remain reliable.
-
- If you run the demo in benchmark mode twice, you'll notice that the
- TECO script is input nearly instantaneously the second time, whereas
- you can see the demo "type" the script in very quickly the first
- time. (Remove `lib/pidp8i/ips.py`, say `make reconfig` and run the
- demo again to see the difference.)
-
-* The `DF` + `SING_STEP` feature for automatically attaching binary
- media images to the simulator from files on USB sticks now looks
- at all directories under `/media`, not just `usb0` through `usb7`
- so that it works with several other common Linux USB automounting
- schemes, such as the one Raspbian Desktop uses.
+* We now build an OS/8 RK05 source code disk image containing the
+ contents of the OS/8 source distribution DECtapes for the
+ convenience of those who would like to work with the OS/8 source
+ code in a more convenient fashion than attaching and detaching the
+ *ten* TU56 tape image files.
+
+ files between SIMH paper tape format and plain POSIX ASCII text
+ files. This program was written to ease the movement of FOCAL
+ program text between SIMH and its host OS, but they should prove
+ useful for other similar tasks.
+
+* Added a new "blinkenlights" demo program that drives SIMH from the
+ outside, running a TECO macro under OS/8 which calculates *pi* to
+ about 20 digits at a very slow rate, producing a display that
+ manages to land somewhere between the random default display of
+ [Deeper Thought][dt2vk] and the clear, boring patterns of our
+ preexisting IF=5 demo script.
+
+ This script, called `bin/teco-pi-demo`, is also included as a
+ demonstration of how an end-user program can reuse the technology
+ that we developed to automatically build the custom OS/8 disk images
+ described above to achieve different ends. Perhaps you have some
+ other program you'd like to run within SIMH in an automated fashion?
+ This shows one way how, and demonstrates a pre-built and tested set
+ of tools for achieving it.
* Fixed the order of initialization in the GPIO setup code for the
James L-W serial mod case. Fix by Dylan McNamee.
* The helper program that selects which boot script to run when the
@@ -291,47 +230,29 @@
on start, so relative paths given to SIMH commands (e.g. `ATTACH`)
are more likely to do what you want. In prior releases, you
generally had to give absolute paths to attach media and such
because CWD would be set somewhere unhelpful.
-* The Fetch LED is no longer lit when in STOP or single-step mode. In
- real hardware, it can be either on or off in this mode, depending
- on various conditions, but it is most often off, so while it is not
- perfectly correct now, it is less wrong. Most of the investigation
- into this issue is by Bill Cattey, with the current partial fix by
- me. A more precise fix may come later. (See ticket [347ae45403] if
- you care to know the details.)
-
-* The Pause LED state was over-counted in the LED sub-sampling scheme
- so that it would tend to be brighter than it should have been.
- Problem noticed by Ian Schofield.
-
-* The MB row's state was not showing the right thing. The problem was
- noticed in comparison to real PDP-8/I hardware by Vincent Slyngstad
- and verified by William Cattey. Ian Schofield suggested the current
- fix.
-
-* Updated for Raspbian Stretch, released in September 2017. It should
+* Updated for Raspbian Squeeze, released in September 2017. It should
still run on Raspbian Jessie, however.
-* Assorted portability, build system, and documentation improvements.
+* Assorted portability improvements.
* **TODO**
- - Create udev script replacement for usbmount so that `DF` +
- `SING_STEP` works on Stretch.
-
- - Do a `simh-update` pass, document the diffs, test for breakage.
-
- - Merge Steve Bennett's idea for combined autosetup/mkos8 option
- handling.
+ * Write `PEP001.FC` and wiki article explaining it
+ * Write `PEP001.F4` and wiki article explaining it
+ * Write `PEP001.F2` and wiki article explaining it
+ * Write `PEP001.C` and wiki article explaining it
+ * Write a doc explaining how `teco-pi-demo` works, and by
+ extension, how to use `class simh`.
+ * Fix all Immediate, High, and Medium priority [Bugs](/bugs)
+ * Implement all Immediate and High priority [Features](/features)
[apt]: https://linux.die.net/man/8/apt
-[cc8rm]: https://tangentsoft.com/pidp8i/doc/trunk/src/cc8/README.md
-[csd]: https://tangentsoft.com/pidp8i/doc/trunk/doc/class-simh.md
+[cc8rm]: https://tangentsoft.com/pidp8i/doc/trunk/cc8/README.md
[dt2vk]: https://github.com/VentureKing/Deeper-Thought-2
-[os8p]: https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-patching.md
[os8rm]: https://tangentsoft.com/pidp8i/doc/trunk/media/os8/README.md
[uwfm]: https://tangentsoft.com/pidp8i/doc/trunk/doc/uwfocal-manual.md
[uwfs]: https://tangentsoft.com/pidp8i/doc/trunk/doc/uwfocal-manual-supp.md
@@ -1143,11 +1064,11 @@
currently misbehaves if the PiDP-8/I panel is not present. Fixing
this is on the radar.)
* Fixed a bunch of bugs!
-[tlrm]: https://tangentsoft.com/pidp8i/doc/trunk/README.md
+[tlrm]: https://tangentsoft.com/pidp8i/doc/trunk/README.md
[dupatch]: https://groups.google.com/forum/#!topic/pidp-8/fmjt7AD1gIA
[dudis]: https://tangentsoft.com/pidp8i/tktview?name=e06f8ae936
[wiki]: https://tangentsoft.com/pidp8i/wcontent
[ex]: https://tangentsoft.com/pidp8i/doc/trunk/examples/README.md
[art]: https://tangentsoft.com/pidp8i/dir?c=trunk&name=labels
Index: HACKERS.md
==================================================================
--- HACKERS.md
+++ HACKERS.md
@@ -44,16 +44,16 @@
Fossil is also available for all common desktop platforms. One of [the
official binaries][fbin] may work on your system. If you're getting
binaries from a third party, be sure it is Fossil 2.1 or higher.
-[fbin]: https://fossil-scm.org/index.html/uv/download.html
-[dvcs]: https://en.wikipedia.org/wiki/Distributed_revision_control
-[fbook]: https://www.fossil-scm.org/schimpf-book/home
-[fml]: https://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-users
-[fossil]: https://fossil-scm.org/
-[fqsg]: https://fossil-scm.org/index.html/doc/trunk/www/quickstart.wiki
+[fbin]: http://fossil-scm.org/index.html/uv/download.html
+[dvcs]: http://en.wikipedia.org/wiki/Distributed_revision_control
+[fbook]: http://www.fossil-scm.org/schimpf-book/home
+[fml]: http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/fossil-users
+[fossil]: http://fossil-scm.org/
+[fqsg]: http://fossil-scm.org/index.html/doc/trunk/www/quickstart.wiki
[ggml]: https://groups.google.com/forum/#!forum/pidp-8
Fossil Anonymous Access
----
@@ -149,25 +149,18 @@
----
If you have a developer account on tangentsoft.com's Fossil instance, just
add your username to the URL like so:
- $ fossil clone https://username@tangentsoft.com/pidp8i pidp8i.fossil
-
-If you've already cloned anonymously, you don't have to clone again to
-inform Fossil about your developer account. Just do a manual sync,
-changing the URL to include the user name:
-
- $ fossil sync https://username@tangentsoft.com/pidp8i
-
-Either way, Fossil will ask you for the password for `username` on the
-remote Fossil instance, and it will offer to remember it for you. If
-you let it remember the password, operation from then on is scarcely
-different from working with an anonymous clone, except that on checkin,
-your changes will be sync'd back to the repository on tangentsoft.com if
-you're online at the time, and you'll get credit under your developer
-account name for the checkin.
+ $ fossil clone http://username@tangentsoft.com/pidp8i pidp8i.fossil
+
+Fossil will ask you for the password for `username` on the remote Fossil
+instance, and it will offer to remember it for you. If you let it
+remember the password, operation from then on is scarcely different from
+working with an anonymous clone, except that on checkin, your changes
+will be sync'd back to the repository on tangentsoft.com if you're
+online at the time.
If you're working offline, Fossil will still do the checkin locally, and
it will sync up with the central repoisitory after you get back online.
It is best to work on a branch when unable to use Fossil's autosync
feature, as you are less likely to have a sync conflict when attempting
@@ -372,11 +365,11 @@
of the current trunk. PiDP-8/I often drifts enough during development
that a patch against a stable release may not apply to the trunk cleanly
otherwise.
[osil]: https://opensource.org/licenses
-[repo]: https://tangentsoft.com/pidp8i/
+[repo]: http://tangentsoft.com/pidp8i/
[simhl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
[viral]: https://en.wikipedia.org/wiki/Viral_license
The PiDP-8/I Software Project Code Style Rules
Index: Makefile.in
==================================================================
--- Makefile.in
+++ Makefile.in
@@ -36,73 +36,39 @@
# Git commit ID of the latest version of the SIMH 4 project on GitHub
# that has been merged into this source base.
SGCID=17903827bdb294f7e60d4c7f172bd6a1a71dfbd5
-# C build flags for src/*.c and PDP8/*.c, containing the SIMH core
-# modules and the SIMH PDP-8 simulator, respectively.
-TOP_CFLAGS := @CFLAGS@ @BUILDMODE@ \
- -Wno-unused-result -Wno-parentheses \
- -DUSE_READER_THREAD -DHAVE_DLOPEN=$(subst .,,@SH_SOEXT@) -DPIDP8I \
- -DSIM_ASYNCH_IO -DHAVE_REGEX_H -DHAVE_GLOB \
- -DSIM_GIT_COMMIT_ID=$(SGCID) -D_GNU_SOURCE \
- -U__STRICT_ANSI__ \
+CFLAGS = @CFLAGS@ -Wno-unused-result -Wno-parentheses @BUILDMODE@ \
+ -DUSE_READER_THREAD -DHAVE_DLOPEN=so -DPIDP8I -DSIM_ASYNCH_IO \
+ -DHAVE_REGEX_H -DHAVE_GLOB -DSIM_GIT_COMMIT_ID=$(SGCID) \
+ -D_GNU_SOURCE -U__STRICT_ANSI__ \
-I @srcdir@/src -I @srcdir@/src/PDP8 -I src
-PDP8_CFLAGS = $(TOP_CFLAGS)
-
-# Greatly stripped-down build options for the cc8 cross-compiler
-# primarily because it's K&R C. Building under TOP_CFLAGS spews
-# pages of warnings. The only thing we share is whether to build
-# a debug or optimized version, from BUILDMODE, set by auto.def.
-CC8_CROSS_CFLAGS = -w @BUILDMODE@
-
-# Krten's d8tape doesn't need much in the way of options. It builds
-# without warnings under the supported version of Raspbian. On some
-# other OS types, it complains about one of the printf() format
-# specifiers, which we cannot fix portably, so we suppress that one.
-D8TAPE_CFLAGS = -Wno-format @BUILDMODE@
-
-# Ditto palbart.
-PALBART_CFLAGS = @BUILDMODE@
SIM = bin/pidp8i-sim
-BINS = $(SIM) @CC8_CROSS@ \
- bin/d8tape \
- bin/palbart \
- bin/pidp8i-test \
- bin/ptp2txt \
- libexec/scanswitch
-BIN_SCRIPTS = \
- bin/pidp8i \
- @srcdir@/bin/teco-pi-demo
-
-# Some *.py files are generated by Autosetup, so they need different
+BINS = bin/palbart $(SIM) bin/pidp8i-test bin/ptp2txt libexec/scanswitch @CC8_CROSS@
+
+# lib/pidp8i/dirs.py is generated by Autosetup, so it needs different
# handling than the other libraries for the out-of-tree build case.
-PIDP8I_DIRS := lib/pidp8i/dirs.py
-PIDP8I_DIN := @srcdir@/$(PIDP8I_DIRS).in
-GENNED_PY := \
- lib/pidp8i/__init__.py \
- lib/pidp8i/ips.py \
- $(PIDP8I_DIRS)
-
-SIMH_PY := lib/simh.py
-SIMH_PY_SRC := @srcdir@/$(SIMH_PY)
-
-MKOS8 := @srcdir@/libexec/mkos8
-MKOS8_LIB := @srcdir@/lib/mkos8
-MKOS8_PY := \
+PIDP8I_DIRS = lib/pidp8i/dirs.py
+PIDP8I_DIN = @srcdir@/$(PIDP8I_DIRS).in
+
+SIMH_PY_SRC = @srcdir@/lib/simh.py
+
+MKOS8 = @srcdir@/libexec/mkos8
+MKOS8_LIB = lib/mkos8
+MKOS8_PY = \
$(MKOS8_LIB)/__init__.py \
- $(MKOS8_LIB)/argparser.py \
- lib/mkos8/opts.py
-MKOS8_PY_ALL := $(GENNED_PY) $(MKOS8_PY) $(SIMH_PY_SRC)
-MKOS8_SRCS := $(MKOS8) $(MKOS8_PY_ALL) $(PIDP8I_DIN)
-
-BUILDDIRS := bin libexec obj/cc8/cross obj/d8tape obj/palbart obj/PDP8
-
-INSTDIRS := bin etc lib/mkos8 lib/pidp8i libexec share/boot share/media share/include share/man/man1
-
-SIM_OBJS := \
+ $(MKOS8_LIB)/argparser.py
+MKOS8_PY_SRC = $(addprefix @srcdir@/,$(MKOS8_PY))
+MKOS8_SRCS = $(MKOS8) $(MKOS8_PY_SRC) $(PIDP8I_DIN) $(SIMH_PY_SRC)
+
+BUILDDIRS = bin libexec obj/PDP8
+
+INSTDIRS = bin etc lib/mkos8 lib/pidp8i libexec share/boot share/media share/include share/man/man1
+
+SIM_OBJS = \
obj/gpio-common.o \
obj/PDP8/pdp8_df.o \
obj/PDP8/pdp8_cpu.o \
obj/PDP8/pdp8_clk.o \
obj/PDP8/pdp8_ct.o \
@@ -131,38 +97,25 @@
obj/sim_tape.o \
obj/sim_timer.o \
obj/sim_tmxr.o \
obj/sim_video.o
-CC8_OBJS := \
- obj/cc8/cross/code8.o \
- obj/cc8/cross/data.o \
- obj/cc8/cross/error.o \
- obj/cc8/cross/expr.o \
- obj/cc8/cross/function.o \
- obj/cc8/cross/gen.o \
- obj/cc8/cross/io.o \
- obj/cc8/cross/lex.o \
- obj/cc8/cross/main.o \
- obj/cc8/cross/preproc.o \
- obj/cc8/cross/primary.o \
- obj/cc8/cross/stmt.o \
- obj/cc8/cross/sym.o \
- obj/cc8/cross/while.o
-
-D8TAPE_OBJS := \
- obj/d8tape/dasm.o \
- obj/d8tape/flow.o \
- obj/d8tape/main.o \
- obj/d8tape/version.o
-
-MISC_OBJS := \
- obj/ptp2txt.o \
- obj/scanswitch.o \
- obj/test.o
-
-PALBART_OBJS := obj/palbart/palbart.o
+CC8_OBJS = \
+ obj/code8.o \
+ obj/data.o \
+ obj/error.o \
+ obj/expr.o \
+ obj/function.o \
+ obj/gen.o \
+ obj/io.o \
+ obj/lex.o \
+ obj/main.o \
+ obj/preproc.o \
+ obj/primary.o \
+ obj/stmt.o \
+ obj/sym.o \
+ obj/while.o
ifeq (@BUILD_DEEPER_THOUGHT@, 1)
BINS += bin/deeper
endif
@@ -185,81 +138,66 @@
boot/5.script
# List of *.in files from auto.def file, except for this present file
# (Makefile.in) which is handled separately. This list should only
# change when the list of "make-template" calls in auto.def changes.
-#
-# The MKOS8_INFILES set of files are those which, if changed, require
-# rebuilding the OS/8 media. Touching the combined set merely causes
-# a reconfig and build.
-#
-# The PRECIOUS set are those whose outfiles we want make(1) to treat as
-# "precious", meaning it won't delete files generated by a target if the
-# rule being processed to create that target fails.
-#
-# The rest have no special treatment.
-MKOS8_INFILES = \
- @srcdir@/lib/pidp8i/__init__.py.in \
- @srcdir@/lib/pidp8i/ips.py.in \
- @srcdir@/media/os8/init.tx.in \
- @srcdir@/src/PDP8/pidp8i.c.in \
- $(PIDP8I_DIN)
-PRECIOUS_INFILES = \
- @srcdir@/Makefile.in \
- @srcdir@/examples/Makefile.in \
- @srcdir@/src/Makefile.in \
- @srcdir@/src/cc8/Makefile.in \
- @srcdir@/src/PDP8/Makefile.in
+#
+# If the first file listed below changes, change the AUTOREBUILD rule
+# near the end of this file to match!
INFILES = \
@srcdir@/bin/pidp8i.in \
@srcdir@/boot/0.script.in \
@srcdir@/boot/2.script.in \
@srcdir@/boot/3.script.in \
@srcdir@/boot/4.script.in \
@srcdir@/boot/6.script.in \
@srcdir@/boot/7.script.in \
+ @srcdir@/boot/cc8.script.in \
@srcdir@/boot/run.script.in \
@srcdir@/etc/pidp8i-init.in \
@srcdir@/etc/sudoers.in \
+ @srcdir@/media/os8/init.tx.in \
@srcdir@/src/gpio-common.c.in \
+ @srcdir@/src/PDP8/pidp8i.c.in \
@srcdir@/tools/simh-update.in \
- $(MKOS8_INFILES)
-MKOS8_OUTFILES := $(subst @srcdir@/,,$(MKOS8_INFILES))
-MKOS8_OUTFILES := $(subst .in,,$(MKOS8_OUTFILES))
-PRECIOUS_OUTFILES := $(subst @srcdir@/,,$(PRECIOUS_INFILES))
-PRECIOUS_OUTFILES := $(subst .in,,$(PRECIOUS_OUTFILES))
+ $(PIDP8I_DIN)
+PRECIOUS_INFILES = \
+ @srcdir@/Makefile.in \
+ @srcdir@/cc8/Makefile.in \
+ @srcdir@/examples/Makefile.in \
+ @srcdir@/src/Makefile.in \
+ @srcdir@/src/PDP8/Makefile.in
OUTFILES := $(subst @srcdir@/,,$(INFILES))
OUTFILES := $(subst .in,,$(OUTFILES))
+PRECIOUS_OUTFILES := $(subst @srcdir@/,,$(PRECIOUS_INFILES))
+PRECIOUS_OUTFILES := $(subst .in,,$(PRECIOUS_OUTFILES))
OS8_BIN_RK05 = bin/os8v3d-bin.rk05
OS8_SRC_RK05 = @OS8_SRC_RK05@
OS8_RK05S = $(OS8_BIN_RK05) $(OS8_SRC_RK05)
CLTXT = /boot/cmdline.txt
-ADF := adrules.mk
-
.PHONY: all tags
.PRECIOUS: $(PRECIOUS_OUTFILES)
all: $(OUTFILES) $(PRECIOUS_OUTFILES) $(BUILDDIRS) $(BINS) $(BOOTSCRIPTS) $(LISTINGS) $(ASM_PTS) $(FC_EX_PTS) $(PAL_EX_PTS) $(OS8_RK05S)
clean:
@rm -f $(BINS) $(BOOTSCRIPTS) $(ASM_PTS) $(PAL_EX_PTS) $(LISTINGS) \
- $(OUTFILES) $(ADF) \
- config.log cscope.out tags \
- bin/*.pt bin/*.rk05 bin/*.save bin/txt2ptp \
- lib/*.pyc lib/*/*.pyc lib/mkos8/opts.py \
- obj/*.log obj/*.pt obj/mkos8.opts \
- src/config.h \
+ $(OUTFILES) $(OS8_RK05S) \
+ bin/*.save \
+ tags \
+ obj/*.d \
+ obj/*.o \
+ obj/*.log \
+ obj/PDP8/*.d \
@srcdir@/examples/*.err
- @find obj \( -name \*.o -o -name \*.d \) -delete
@-rmdir -p $(BUILDDIRS) 2> /dev/null || true
distclean: clean
- @rm -f \
- $(PRECIOUS_OUTFILES) \
+ @rm -f $(PRECIOUS_OUTFILES) \
config.log \
autosetup/jimsh0 \
src/config.h
ctags tags:
@@ -270,31 +208,19 @@
install: all instdirs
@echo Installing to @prefix@...
@# Install files into those dirs and set their perms
- @for f in $(BINS) ; do \
- dest=@prefix@/bin/$$(basename $$f) ; \
- echo "Installing binary $$dest..." ; \
- @INSTALL@ -m 755 -D -s $$f $$dest ; \
- done
- @for f in $(BIN_SCRIPTS) ; do \
- dest=@prefix@/bin/$$(basename $$f) ; \
- echo "Installing script $$dest..." ; \
- @INSTALL@ -m 755 -D $$f $$dest ; \
- done
- @( cd @prefix@/bin ; \
- echo "Installing txt2ptp symlink..." ; \
- ln -f ptp2txt txt2ptp ; \
- )
+ for f in $(BINS) ; do @INSTALL@ -m 755 -D -s $$f @prefix@/$$f ; done
+ ( cd @prefix@/bin ; ln -f ptp2txt txt2ptp )
+ @INSTALL@ -m 755 @srcdir@/bin/pidp8i @prefix@/bin
@(test -x /sbin/setcap && \
for f in @prefix@/bin/pidp8i-* ; do \
- echo "Setting real-time priority capabilities on $$(basename $$f)..." ; \
/sbin/setcap 'cap_sys_nice=eip' $$f ; \
done \
) || true
- @test -e @MEDIADIR@/os8/os8.rk05 || echo "Installing media..." && $(MAKE) mediainstall
+ test -e @MEDIADIR@/os8/os8.rk05 || $(MAKE) mediainstall
@# If this is a Debian-type system, install needed helper programs
@test -x /usr/bin/apt-get -a ! -h /media/usb && apt-get -y install usbmount || true
@test -x /usr/bin/apt-get -a ! -x /usr/bin/screen && apt-get -y install screen || true
@@ -301,11 +227,11 @@
@# Disable competing services if this is a Raspberry Pi
@(test -x /bin/systemctl && /bin/systemctl disable deeper || true)
@(test -x /bin/systemctl && /bin/systemctl disable pidp8 || true)
@# Install the init script if this system is systemd based.
- @@INSTALL@ -m 755 @srcdir@/etc/pidp8i-init @prefix@/etc
+ @INSTALL@ -m 755 @srcdir@/etc/pidp8i-init @prefix@/etc
@( test -w /etc/init.d -a -x /bin/systemctl && \
ln -sf @ABSPREFIX@/etc/pidp8i-init /etc/init.d/pidp8i && \
/bin/systemctl enable pidp8i \
) || true
@@ -343,39 +269,33 @@
sed -e 's/console\=[a-zA-Z0-9]+,[0-9]+ //' \
-e 's/kgdboc\=[a-zA-Z0-9]+,[0-9]+ //' -i $(CLTXT) \
) || true
@# Install CC8 stuff if built
- @test -n "@CC8_CROSS@" && \
- echo "Installing cc8 cross-compiler..." ; \
+ test -n "@CC8_CROSS@" && \
@INSTALL@ -m 755 bin/cc8 @prefix@/bin && \
- @INSTALL@ -m 644 @srcdir@/src/cc8/include/* @prefix@/share/include
+ @INSTALL@ -m 644 cc8/include/* @prefix@/share/include
@# Install palbart stuff
- @@INSTALL@ -m 755 bin/palbart @prefix@/bin
- @@INSTALL@ -m 644 @srcdir@/src/palbart/palbart.1 @prefix@/share/man/man1
+ @INSTALL@ -m 755 bin/palbart @prefix@/bin
+ @INSTALL@ -m 644 @srcdir@/palbart/palbart.1 @prefix@/share/man/man1
@# Install mkos8 and its dependencies
- @echo "Installing mkos8..."
- @@INSTALL@ -m 775 -g @INSTGRP@ $(MKOS8) @prefix@/libexec
- @( for src in $(MKOS8_PY_ALL) ; do \
- test -e $$src || src=@srcdir@/$$src ; \
- dest=@prefix@/$$(echo $$src | sed -e 's_^@srcdir@/__') ; \
- echo "Installing $$src to $$dest..." ; \
- @INSTALL@ -m 644 -g @INSTGRP@ -D $${src} $${dest} ; \
- @INSTALL@ -m 644 -g @INSTGRP@ -D $${src}c $${dest}c ; \
+ @INSTALL@ -m 775 -g @INSTGRP@ $(MKOS8) @prefix@/libexec
+ @( cd @srcdir@ ; \
+ for f in $(MKOS8_PY) ; do \
+ @INSTALL@ -m 644 -g @INSTGRP@ -D @srcdir@/$$f @prefix@/$$f ; \
+ @INSTALL@ -m 644 -g @INSTGRP@ -D @srcdir@/$${f}c @prefix@/$${f}c ; \
done \
)
- @sed -e 's#^build =.*#build = "@ABSPREFIX@"#' \
- -e 's#^media =.*#media = os.path.join (build, "share/media/")#' \
- -e 's#^os8mo =.*#os8mo = os8mi#' \
+ @sed -e 's#^build =.*$$#build = "@ABSPREFIX@"#' \
+ -e 's#^src =.*$$#src = "@ABSPREFIX@"#' \
< $(PIDP8I_DIRS) > @prefix@/$(PIDP8I_DIRS)
@chgrp @INSTGRP@ @prefix@/$(PIDP8I_DIRS)
instdirs:
- @echo "Creating installation directory tree..."
- @for d in $(INSTDIRS) ; do @INSTALL@ -m 755 -d @prefix@/$$d ; done
+ for d in $(INSTDIRS) ; do @INSTALL@ -m 755 -d @prefix@/$$d ; done
mediainstall: instdirs
@echo "[Re]installing OS and program media..."
@cd @srcdir@ ; \
find media \( \
@@ -382,28 +302,20 @@
-name \*.bin -o \
-name \*.dsk -o \
-name \*.rk05 -o \
-name \*.tu56 \
\) -exec @INSTALL@ -D -m 664 -o @INSTUSR@ -g @INSTGRP@ {} @ABSPREFIX@/share/{} \;
- @@INSTALL@ -m 644 -o @INSTUSR@ -g @INSTGRP@ bin/os8v3d-*.rk05 @ABSPREFIX@/share/media/os8
- @@INSTALL@ -m 664 -o @INSTUSR@ -g @INSTGRP@ boot/*.script @BOOTDIR@
-
-# No-dependencies versions of the bin/os8v3d-*.rk05 targets used by
-# tools/test-mkos8, because there's no point rebuilding the simulator
-# on each iteration.
-os8-bin:
- $(MKOS8)@MKOS8_OPTS@ bin
-os8-patched:
- $(MKOS8)@MKOS8_OPTS@ bin patch
+ @INSTALL@ -m 644 -o @INSTUSR@ -g @INSTGRP@ bin/os8v3d-*.rk05 @ABSPREFIX@/share/media/os8
+ @INSTALL@ -m 664 -o @INSTUSR@ -g @INSTGRP@ boot/*.script @BOOTDIR@
reconfig:
@AUTOREMAKE@
release: all
@srcdir@/tools/mkrel
-run: $(SIM)
+run: $(OS8_BIN_RK05) $(SIM)
$(SIM) boot/run.script
simh-update simh-update-f:
@@srcdir@/tools/simh-update $(subst simh-update,,$@)
@@ -425,18 +337,15 @@
# anyway!) The thing is, we only want the RK05 bin media rebuilt when
# the configure --*-os8-* options change. *That* is when we care about
# the updated init.tx file, not before. We needn't even make it an
# order-only prereq because configure and the INFILES rules above ensure
# that it always exists.
-OS8_BIN_SRCS := $(MKOS8_SRCS) \
+OS8_BIN_SRCS = $(MKOS8_SRCS) \
@srcdir@/media/os8/al-*-ba-*.tu56 \
@srcdir@/media/os8/subsys/*.tu56
-ifneq (@MKOS8_BIN_PATCHES@,)
- OS8_BIN_SRCS += @srcdir@/media/os8/patches/patch_list.txt
-endif
-$(OS8_BIN_RK05): $(OS8_BIN_SRCS) | $(SIM) $(MKOS8_OUTFILES)
- $(MKOS8)@MKOS8_OPTS@ bin @MKOS8_BIN_PATCHES@
+$(OS8_BIN_RK05): $(OS8_BIN_SRCS) | $(SIM)
+ $(MKOS8)@MKOS8_OPTS@ bin
# Also build an OS/8 source disk, as a convenience to avoid the
# need to mount up the 7 source tapes in succession.
#
# Using an order-only dependency for the simulator and the bin disk: we
@@ -443,10 +352,55 @@
# only need *a* version of each, they don't have to be recent!
OS8_SRC_SRCS = $(MKOS8_SRCS) \
@srcdir@/media/os8/al-*-sa-*.tu56
$(OS8_SRC_RK05): $(OS8_SRC_SRCS) | $(SIM) $(OS8_BIN_RK05)
$(MKOS8)@MKOS8_OPTS@ src
+
+# Rule for compiling *.c to *.o and autogenerating dependency info.
+# Explained at http://scottmcpeak.com/autodepend/autodepend.html
+#
+# Reflect any changes here into near-duplicate below!
+obj/%.o: @srcdir@/src/%.c
+ $(CC) -c $(CFLAGS) @srcdir@/src/$*.c -o obj/$*.o
+ $(CC) -MM $(CFLAGS) @srcdir@/src/$*.c > obj/$*.d
+ @mv -f obj/$*.d obj/$*.d.tmp
+ @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
+ @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \
+ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d
+ @rm -f obj/$*.d.tmp
+
+# Near-duplicate of above rule for those *.c files generated from *.c.in
+# files in the srcdir. Needed when building out-of-tree.
+obj/%.o: src/%.c
+ $(CC) -c $(CFLAGS) src/$*.c -o obj/$*.o
+ $(CC) -MM $(CFLAGS) src/$*.c > obj/$*.d
+ @mv -f obj/$*.d obj/$*.d.tmp
+ @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
+ @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \
+ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d
+ @rm -f obj/$*.d.tmp
+
+# Another near-duplicate for the PDP-8 simulator. First set above
+# doesn't catch these.
+obj/PDP8/%.o: @srcdir@/src/PDP8/%.c
+ $(CC) -c -w $(CFLAGS) @srcdir@/src/PDP8/$*.c -o obj/PDP8/$*.o
+ $(CC) -MM -w $(CFLAGS) @srcdir@/src/PDP8/$*.c > obj/PDP8/$*.d
+ @mv -f obj/$*.d obj/$*.d.tmp
+ @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
+ @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \
+ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d
+ @rm -f obj/$*.d.tmp
+
+# Another near-duplicate for CC8, since it's off in a different subdir
+obj/%.o: @srcdir@/cc8/cross/%.c
+ $(CC) -c -w $(CFLAGS) @srcdir@/cc8/cross/$*.c -o obj/$*.o
+ $(CC) -MM -w $(CFLAGS) @srcdir@/cc8/cross/$*.c > obj/$*.d
+ @mv -f obj/$*.d obj/$*.d.tmp
+ @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
+ @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \
+ sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d
+ @rm -f obj/$*.d.tmp
# Rule for building PAL assembly language programs in asm/*.pal.
obj/%.lst bin/%-pal.pt: @srcdir@/asm/%.pal bin/palbart
bin/palbart -lr $< || cat obj/$*.err
mv @srcdir@/asm/$*.lst obj
@@ -473,25 +427,23 @@
boot/1.script: boot/hs-rim-loader.script
ln -f $< $@
boot/5.script: boot/ac-mq-blinker.script
ln -f $< $@
+bin/palbart: @srcdir@/palbart/palbart.c
+ $(CC) -Wall -Wno-strict-prototypes @BUILDMODE@ $< -o $@
+ $(CC) -MM $< -o obj/palbart.d
+
$(BUILDDIRS):
mkdir -p $@
$(SIM): $(SIM_OBJS) obj/gpio-@LED_DRIVER_MODULE@ls.o
$(CC) -o $@ $^ $(LIBS)
bin/cc8: $(CC8_OBJS)
$(CC) -o $@ $^ $(LIBS)
-bin/d8tape: $(D8TAPE_OBJS)
- $(CC) -o $@ $^
-
-bin/palbart: $(PALBART_OBJS)
- $(CC) -o $@ $^
-
bin/pidp8i-test: obj/test.o obj/gpio-nls.o obj/gpio-common.o
$(CC) -o $@ $^ $(LIBS) -lncurses
bin/ptp2txt: obj/ptp2txt.o
$(CC) -o $@ $^
@@ -506,34 +458,16 @@
libexec/scanswitch: obj/scanswitch.o obj/gpio-nls.o obj/gpio-common.o
$(CC) -o $@ $^ $(LIBS)
# Reconfigure whenever one of the *.in or autosetup files changes unless
# this is "make clean".
-#
-# We purposely list only one of the OUTFILES on the left hand side
-# because to list them all is to invite Make to run N copies of the
-# configure script in parallel up to the limit of -j or the number of
-# files in INFILES, whichever is lower. Order-only prerequisites can't
-# help here (|) as that only affects the right hand side.
ifeq ($(findstring clean,$(MAKECMDGOALS)),)
media/os8/init.tx: $(INFILES) $(PRECIOUS_INFILES) @AUTODEPS@
@AUTOREMAKE@ && $(MAKE)
-
-# Also do it if the autodep tool is newer than its output, suggesting
-# that if re-run, it would generate different output.
-$(ADF): @srcdir@/tools/mkadrules
- @AUTOREMAKE@ && $(MAKE)
endif
# Rebuild simulator if the version string tool changes, since its output
# may have changed.
src/gpio-common.c: @srcdir@/tools/version
-# Pull in *.d files generated by the autodependency mechanism. See the
-# header comment of tools/mkadrules.
--include \
- $(SIM_OBJS:.o=.d) \
- $(CC8_OBJS:.o=.d) \
- $(D8TAPE_OBJS:.o=.d) \
- $(MISC_OBJS:.o=.d) \
- $(PALBART_OBJS:.o=.d)
--include $(ADF)
+-include $(SIM_OBJS:.o=.d) $(CC8_OBJS:.o=.d) obj/scanswitch.d
+
Index: README.md
==================================================================
--- README.md
+++ README.md
@@ -4,228 +4,69 @@
* A Raspberry Pi with the 40-pin GPIO connector. That rules out the
first-generation Raspberry Pi model A and B boards which had a
26-pin GPIO connector.
-* An SD card containing [a compatible OS][os].
+* An SD card containing Raspbian or something sufficiently close.
+ This software is currently tested with the Jessie Lite distribution.
+
+ Ideally, you will install a fresh OS image onto an unused SD card
+ rather than use this software to modify an existing OS installation,
+ but there is currently no known hard incompatibilty that prevents
+ you from integrating this software into an existing OS.
* This software distribution, unpacked somewhere convenient within the
- filesystem on the Raspberry Pi.
-
- We recommend that you unpack it somewhere your user has read/write
- access like `$HOME/src/pidp8i`. Since it installs as a system
- service, you might prefer `/usr/local/src` or `/opt/src`, though
- you'll have to adjust permissions for that.
-
- The [old stable 2015.12.15 release][osd] required that you unpack
- the software into `/opt/pidp8`, but we now neither require nor
- recommend that.
-
-* We require several tools and libraries that aren't always installed:
-
- * A working C compiler and other standard Linux build tools,
- such as `make(1)`.
-
- * Python's `pexpect` library
-
- * The `usbmount` tool
-
- This is provides two things:
-
- * USB stick auto-mounting on stripped-down OSes like Raspbian
- Lite so you can use the PiDP-8/I `SING_STEP` + `DF` feature
- without having to manually mount the USB stick first.
-
- * A known directory structure that allows the PiDP-8/I
- software to find the media image files on those sticks.
- (`*.pt`, `*.dt`, `*.rk`, etc.)
-
- Full-blown GUI OSes tend to have USB auto-mounting set up
- already, though they won't meet the second criteria unless they
- use the same directory layout as `usbmount`: `/media/usbN`,
- where `N` is a number from 0 to 7, depending on the order
- you attached the USB stick. Many Linuxes use `/media/LABEL`
- instead, for example, where `LABEL` is the partition's label;
- the PiDP-8/I software won't find the files on those USB sticks
- in that case.
-
- * The `ncurses` development libraries
-
- To install all of this on a Raspbian type OS, say:
-
- $ sudo apt update
- $ sudo apt install build-essential
- $ sudo apt install libncurses-dev python-pip usbmount
- $ sudo pip install pexpect
-
-[os]: https://tangentsoft.com/pidp8i/wiki?name=OS+Compatibility
-
-
-
-## Getting the Software onto Your Pi
-
-If you're reading this file within an unpacked distribution of the
-PiDP-8/I software, you should skip this section, because you have
-already achieved its aim.
-
-If you are reading this [online][this] and have not yet downloaded and
-unpacked the software source code onto your Pi, this section will get
-you going.
-
-[this]: https://tangentsoft.com/pidp8i/doc/trunk/README.md
-
-
-
-### Transferring the File to the Pi
-
-The first step is to get the tarball (`*.tar.gz` file) or Zip file onto
-the Pi. There are many options:
-
-1. **Copy the file to the SD card** you're using to boot the Pi.
- When inserted into a Mac or Windows PC, typically only the `/boot`
- partition mounts as a drive your OS can see. (There's a much
- larger partition on the SD card, but most PCs cannot see it.)
- There should be enough free space left in this small partition to
- copy the file over. When you boot the Pi up with that SD card,
- you will find the tarball or Zip file in `/boot`.
-
-2. **Pull the file down to the Pi** over the web, directly to the Pi:
-
- $ wget -O pidp8i.tar.gz https://goo.gl/JowPoC
-
- That will get you a file called `pidp8i.tar.gz` in the current
- working directory.
-
-3. **SCP the file over** to a running Pi from another machine.
- If your Pi has OpenSSH installed and running, you can use
- [WinSCP][wscp], [Cyberduck][cd], [FileZilla][fz] or another SCP
- or SFTP-compatible file transfer program to copy the file to the
- Pi over the network.
-
-[cd]: https://cyberduck.io/
-[fz]: https://filezilla-project.org/
-[wscp]: https://winscp.net/eng/
-
-4. **Clone the Fossil repository** using the instructions in the
- [`HACKERS.md` file][hack]. (Best for experts or those who wish to
- become experts.)
-
-[hack]: https://tangentsoft.com/pidp8i/doc/trunk/HACKERS.md
-
-5. **Switch to the binary OS installation images** available from the
- [top-level project page][cprj]. These are default installations of
- Raspbian Lite with the PiDP-8/I software already downloaded, built,
- and installed. These images were produced in part using option #4
- above, so you can use Fossil to update your software to the current
- version at any time, as long as the Pi is connected to the Internet.
-
-
-
-### Unpacking the Software on Your Pi
-
-Having transferred the distribution file onto your Pi, you can unpack it
-with one of the two following commands.
-
-If you grabbed the tarball:
-
- $ tar xvf /path/to/pidp8i-VERSION.tar.gz
-
-If you grabbed the Zip file instead:
-
- $ unzip /path/to/pidp8i-VERSION.zip
-
-The file name will vary somewhat, depending on when and how you
-transferred the file. After unpacking it, you will have a new
-directory beginning with `pidp8i`. `cd` into that directory, then
-proceed with the [configuration](#configuring) steps below.
-
-
-
-### If You Need More Help
-
-If the above material is not sufficient to get you started, you might
-want to look at [the documentation][rpfd] provided by the Raspberry
-Pi Foundation. In particular, we recommend their [Linux][rpfl] and
-[Raspbian][rpfr] guides. The book "[Make: Linux for Makers][lfm]"
-by Aaron Newcomb is also supposed to be good.
-
-
-[rpfd]: https://www.raspberrypi.org/documentation/
-[rpfl]: https://www.raspberrypi.org/documentation/linux/
-[rpfr]: https://www.raspberrypi.org/documentation/raspbian
-
-[lfm]: https://www.makershed.com/products/make-linux-for-makers
-
-
-
+ Raspberry Pi filesystem.
+
+ Unlike with the [upstream 2015.12.15 release][upst], this present
+ release of the software should *not* be unpacked into `/opt/pidp8`.
+ I recommend that you unpack it into `$HOME/src`, `/usr/local/src` or
+ similar, but it really doesn't matter where you put it, as long as
+ your user has full write access to that directory.
+
+* A working C compiler and other standard Linux build tools, such as
+ `make(1)`. On Debian type systems — including Raspbian — you can
+ install such tools with `sudo apt install build-essential`
+
+
+
## Configuring, Building and Installing
This software distribution builds and installs in the same way as most
other Linux/Unix software these days. The short-and-sweet is:
$ ./configure && make && sudo make install
-The `configure` step is generally needed only the first time you build
-the software in a new directory. You may want to add options after it,
-as described [below](#options).
-
-After that initial configuration, the software normally auto-reconfigures
-itself on updates using the same options you gave before, but occasionally
-we make some change that prevents this from happening. If you get a
-build error after updating to a new version of the software, try saying:
-
- $ make reconfig
-
-...and then continuing with the `make && sudo make install` steps before
-reporting a build error.
-
-If `make reconfig` also fails, you can try running the `configure`
-script again manually.
-
-
-
-### Running the Software
-
-For the most part, this is covered in the documentation linked from the
-[Learning More](/#learning) section of the project home page.
-
-The only tricky bit is that if this is the first time you have
-configured, built and installed the software as above on a given system,
-you will have to log out and back in before commands like `pidp8i` will
-be in your user's `PATH`.
-
-
-
+If you've checked out a new version of the source code and the `make`
+step fails, try redoing the `configure` step. Sometimes changes made to
+the source code invalidate prior `make` dependencies, which are
+implicitly repaired by the `configure` script.
+
+
+
### Configure Script Options
-You can change many things about the way the software is built and
+You can change a few things about the way the software is built and
installed by giving options to the `configure` script:
-
+
#### --prefix
Perhaps the most widely useful `configure` script option is `--prefix`,
-which lets you override the default installation directory, `/opt/pidp8i`.
-There are many good reasons to change where the software gets installed,
-but the default is also a good one, so unless you know for a fact that
-you want to change this default, leave it alone.
-
-For example, you might prefer that the installer put the built software
-under your home directory. This will do that:
+which lets you override the default installation directory,
+`/opt/pidp8i`. You could make it install the software under your home
+directory on the Pi with this command:
$ ./configure --prefix=$HOME/pidp8i && sudo make install
-You might think that installing to a directory your user has complete
-control over would remove the need for installing via `sudo`, but that
-is not the case, since the installation script needs root privileges to
-mark a few of the executables as having permission to run at high priority
-levels, which improves the quality of the display, particularly with the
-[incandescent lamp simulator][ils] feature enabled.
+Although this is installing to a directory your user has write access
+to, you still need to install via `sudo` because the installation
+process does other things that do require `root` access.
-
+
#### --lowercase
The American Standards Association (predecessor to ANSI) delivered the
second major version of the ASCII character encoding standard the same
year the first PDP-8 came out, 1965. The big new addition? Lowercase.
@@ -286,11 +127,11 @@
[sa]: http://homepage.cs.uiowa.edu/~jones/pdp8/faqs/#charsets
[tty]: https://tangentsoft.com/pidp8i/wiki?name=OS/8+Console+TTY+Setup
-
+
#### --no-lamp-simulator
If you build the software on a multi-core host, the PDP-8/I simulator is
normally built with the [incandescent lamp simulator][ils] feature,
which drives the LEDs in a way that mimics the incandescent lamps used
@@ -307,11 +148,11 @@
method not only uses less CPU, which may be helpful if you're trying to
run a lot of background tasks on your Pi 2 or Pi 3, it can also be
helpful when the CPU is [heavily throttled][thro].
-
+
#### --serial-mod
If you have done [Oscar's serial mod][sm1] to your PiDP-8/I PCB and the
Raspberry Pi you have connected to it, add `--serial-mod` to the
`configure` command above.
@@ -323,11 +164,11 @@
If you give this flag and your PCBs are *not* modified, most of the
hardware will work correctly, but several lights and switches will not
work correctly.
-
+
#### --alt-serial-mod
This flag is for an [alternative serial mod by James L-W][sm2]. It
doesn't require mods to the Pi, and the mods to the PiDP-8/I board are
different from Oscar's. This flag changes the GPIO code to work with
@@ -355,17 +196,17 @@
*native OS/8* C compiler. They are two different C compilers: one runs
outside the SIMH PDP-8 simulator and the other runs inside the simulator
under OS/8.
-
+
#### --disable-os8-\*
-Several default components of the [OS/8 RK05 disk image](#os8di) used by
-boot options IF=0 and IF=7 can be left out to save space and build time:
+Several default components of the OS/8 RK05 disk image used by boot
+options IF=0 and IF=7 can be left out to save space and build time:
-* **--disable-os8-advent** — Leave out the [Adventure][advent] game.
+* **--disable-os8-advent** — Leave out the Adventure game.
* **--disable-os8-ba** - Leave out the BASIC games and demos which
come from DEC's book "101 BASIC Computer Games." These are normally
installed to `RKB0:` as `*.BA`, thus the option's name.
@@ -372,18 +213,15 @@
(We considered naming it `--disable-os8-basic-games-and-demos`, but
that's too long, and it can't be `--disable-os8-basic` because that
implies that it is the OS/8 BASIC subsystem that is being left out,
which is not even currently an option.)
-* **--disable-os8-chess** — Leave out John Comeau's
- [CHECKMO-II chess implementation][chess].
+* **--disable-os8-chess** — Leave out John Comeau's CHECKMO-II chess
+ implementation.
* **--disable-os8-cc8** - Leave out Ian Schofield's native OS/8 CC8
- compiler normally installed to `SYS:`. This option is implicitly
- given if you give `--disable-os8-fortran-ii` because the output of
- the OS/8 CC8 compiler is a SABR file, and SABR is part of the
- FORTRAN II subsystem.
+ compiler normally installed to `RKA0:`
* **--disable-os8-crt** — Suppress the [console rubout behavior][tty]
enabled while building the OS/8 binary RK05 disk image. You
probably only want to do this if you have attached a real teletype
to your PiDP-8/I, and thus do not want video terminal style rubout
@@ -391,34 +229,23 @@
* **--disable-os8-focal** - Do not install any version of FOCAL on the
OS/8 system disk. This option sets `--disable-os8-uwfocal` and
overrides `--enable-os8-focal69`, both discussed below.
-* **--disable-os8-fortran-ii** - Leaves out the FORTRAN II compiler,
- SABR, the linking loader (`LOADER`), the `LIBSET` tool, and the
- `*.RL` library files.
+* **--disable-os8-fortran-ii** - Leave the FORTRAN II compiler out.
* **--disable-os8-fortran-iv** - Leave the FORTRAN IV compiler out.
-* **--disable-os8-init** - Generate `RKB0:INIT.TX` but do not display
+* **--disable-os8-init** - Generate `SYS:INIT.TX` but do not display
it on OS/8 boot. Rather than disable the default on-boot init
- message, you may want to edit `media/os8/init.tx.in` to taste
- and rebuild.
-
- (We still build the file when you give this option in case you
- later decide you want to enable the boot message, or you need to
- call up configuration information stored in `INIT.TX`.)
+ message, you may want to edit `media/os8/init.tx.in` to taste and
+ rebuild.
* **--disable-os8-k12** - Leave out the Kermit-12 implementation
normally installed to `RKA0:`
-* **--disable-os8-macrel** - Leave the MACREL v2 assembler and its
- associated FUTIL V8B tool out.
-
-* **--disable-os8-patches** - Do not apply any of the OS/8 V3D
- patches published by DEC. See the [documentation][os8p] for this
- option for more information.
+* **--disable-os8-macrel** - Leave the MACREL assembler out.
* **--disable-os8-src** - Do not build the `os8v3d-src.rk05` disk
image from the OS/8 source tapes. This is not controlled by
`--os8-minimal` because that only affects `os8v3d-bin.rk05`.
@@ -429,48 +256,40 @@
the rest of the files on `media/os8/subsys/uwfocal*.tu56`. There is
much more to explore here, but we cannot include it in the default
installation set because that would overrun OS/8's limitation on the
number of files on a volume.
-[advent]: http://www.rickmurphy.net/advent
-[chess]: https://chessprogramming.wikispaces.com/CHEKMO-II
-[os8p]: https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-patching.md
-
-
+
#### --enable-os8-\*
-There are a few file sets not normally installed to the [OS/8 RK05 disk
-image](#os8di) used by boot options IF=0 and IF=7. You can install them
-with the following options:
-
-* **--enable-os8-music** — The `*.MU` music scores and Rich Wilson's
- associated compiler (`MUSIC.PA`) and player overlay (`PLAYOV.PA`)
- are not normally installed to the built OS/8 binary RK05 disk image
- because the Raspberry Pi reportedly does not emit eufficient RFI at
- AM radio frequencies when running these programs to cause audible
- music on a typical AM radio, the very point of these demos. Until a
- way is found around this problem — what, low RFI is a *problem* now?
- — this option will default to "off".
+There are a few file sets not normally installed to the OS/8 RK05 disk
+image used by boot options IF=0 and IF=7. You can install them with the
+following options:
+
+* **--enable-os8-music** — The `*.MU` files and the player program for
+ it are not normally installed to the built OS/8 binary RK05 disk
+ image because the Raspberry Pi reportedly does not emit eufficient
+ RFI at AM radio frequencies when running these programs to cause
+ audible music on a typical AM radio, the very point of these demos.
+ Until a way is found around this problem — what, low RFI is a
+ *problem* now? — this option will default to "off".
* **--enable-os8-vtedit** — This option installs a default-run macro
pack called VTEDIT which causes the OS/8 version of TECO to run in
full-screen mode and to react to [several special keyboard
- commands][uvte] not normally recognized by TECO.
-
- This feature is disabled by default because the VTEDIT macro pack
- changes the way TECO operates, and many people want TECO to behave
- like *TECO*. VTEDIT was first created during the PDP-8's commercial
- lifetime, so enabling this option is not an anachronism, but TECO is
- much older and had a much more wide-reaching impact in history, so
- we choose to provide unvarnished TECO by default.
-
- That having been said, people don't go to a ren fair and expect to
- experience the historical ubiquity of typhoid fever, so do not feel
- guilty if you choose to try this option.
-
-[uvte]: https://tangentsoft.com/pidp8i/wiki?name=Using+VTEDIT
+ commands](/wiki?name=Using+VTEDIT) not normally recognized by TEDO.
+
+ This feature is currently disabled because it is not yet fully
+ tested by the person in charge of the OS/8 disk building process.
+
+ It may remain disabled after that because it changes the behavior of
+ the `TECO` command in OS/8, which violates the expectations of
+ people expecting a historically accurate TECO experience. On the
+ other hand, people don't go to a ren fair and expect to experience
+ the historical ubiquity of typhoid fever either, so we might change
+ our mind on this.
* **--enable-os8-focal69** — Because the default installation includes
U/W FOCAL, we have chosen to leave FOCAL 69 out by default to save
space on the O/S 8 system disk. You can give this option to install
this implementation alongside U/W FOCAL, or you can couple this
@@ -530,11 +349,11 @@
#### --help
Run `./configure --help` for more information on your options here.
-
+
## Overwriting the Local Simulator Setup
When you run `sudo make install` step on a system that already has an
existing installation, it purposely does not overwrite two classes of
files:
@@ -556,28 +375,26 @@
that the newer software you're installing contains changes that you want
to reflect into your local configuration.
You have several options here:
-1. If you just want to reflect the prior PDP-8 simulator configuration
+1. If you just want to reflect upstream PDP-8 simulator configuration
file changes into your local versions, you can hand-edit the
installed simulator configuration scripts to match the changes in
the newly-generated `boot/*.script` files under the build directory.
-2. If the change is to the binary PDP-8 media image files — including
- the [generated OS/8 disk images](#os8di) — and you're unwilling to
- overwrite your existing ones wholesale, you'll have to mount both
- versions of the media image files under the PDP-8 simulator and copy
- the changes over by hand.
-
-3. If your previously installed binary OS media images — e.g. the
- [OS/8 RK05 disk image](#os8di) that the simulator boots from by
- default — are precious but the simulator configuration scripts
- aren't precious, you can just copy the generated `boot/*.script`
- files from the build directory into the installation directory,
- `$prefix/share/boot`. (See the `--prefix` option above for the
- meaning of `$prefix`.)
+2. If the upstream change is to the binary PDP-8 media image files and
+ you're unwilling to overwrite them wholesale, you'll have to mount
+ both versions of the media image files under the PDP-8 simulator and
+ copy the changes over by hand.
+
+3. If your previously installed binary OS media images — e.g. the OS/8
+ RK05 disk image that the simulator boots from by default — are
+ precious but the simulator configuration scripts aren't precious,
+ you can just copy the generated `boot/*.script` files from the build
+ directory into the installation directory, `$prefix/share/boot`.
+ (See the `--prefix` option above for the meaning of `$prefix`.)
4. If neither your previously installed simulator configuration files
nor the binary media images are precious, you can force the
installation script to overwrite them both with a `sudo make
mediainstall` command after `sudo make install`.
@@ -585,106 +402,12 @@
Beware that this is potentially destructive! If you've made changes
to your PDP-8 operating systems or have saved files to your OS
system disks, this option will overwrite those changes!
-## OS/8 Disk Images
-
-For the first several years of the PiDP-8/I project, the OS/8 RK05 disk
-image included with the PiDP-8/I software (called `os8.rk05`) was based
-on an image of a real RK05 disk someone found in a salvaged PDP-8
-system. Parts of the image were corrupt, and not all of the pieces of
-software on the disk worked properly with the other parts. It was also
-a reflection of the time it was created and used out in the world, which
-was not always what we would wish to use today.
-
-In late 2017, several of us — see [the ChangeLog][cl] for details —
-created the `mkos8` tool, which takes the `--*-os8-*` options documented
-above and generates the `os8v3d-*.rk05` RK05 disk image files with your
-chosen configuration options.
-
-This set of disk images entirely replaces the old `os8.rk05` disk image,
-in that all features of the old disk image are still available in the
-new disk images, though the default configuration is not a strict
-superset of the old disk image. In some cases, we have made some options
-disabled by default, and in some cases, we have changed default
-behaviors. Mostly, though, the new disk images are simply more
-functional than the old ones.
-
-If you wish to know the full details of how these disk images are
-created, the best documentation so far is [the source code for the
-`mkos8` script][mkos8] and the [documentation for `class simh`][cs].
-
-The remainder of this section describes some aspects of these disk
-images which are not clear from the descriptions of the `--*-os8-*`
-configuration options above.
-
-
-### Baseline
-
-The baseline for the bootable OS/8 disk images comes from a set of
-DECtapes distributed by Digital Equipment Corporation which are now
-included with the PiDP-8/I software; see the [`media/os8/*.tu56`
-files][os8mf]. From these files and your configuration options, the
-`mkos8` script creates the baseline `os8v3d-bin.rk05` disk image.
-
-The default build creates a complete OS/8 system including `BUILD`
-support, FORTRAN IV, MACREL v2, and more.
-
-
-## Subtractions
-
-It turns out that it's pretty easy to run out of directory space on an
-OS/8 RK05 disk due to a limitation in the number of files on an OS/8
-filesystem. For this reason, the archive of device drivers and TD8E
-system are left off the system packs. They can be found in [OS/8
-Binary Distribution DECtape #2][bdt2].
-
-If you do fancy work with `BUILD`, you may need to attach that DECtape
-image and copy files in from it.
-
-
-## Default Additions
-
-The OS/8 RK05 disk image build process normally installs many software
-and data file sets to the disk image. See the [option descriptions
-above](#disable-os8): the "disable" option set effectively lists those
-packages that `mkos8` installs by default, and the following set of
-["enable" options](#enable-os8) lists those left out by default.
-
-
-## Console Enhancements
-
-The default build [enhances the console](/wiki?name=Console+TTY+Setup),
-adding support for lower case terminals where:
-
-1. The SIMH PDP-8 simulator and a few select parts of OS/8 are adjusted
- to cope with lowercase input to [varying degrees](#lowercase).
-
-2. Rubout/backspace handling is set to assume a video terminal rather
- than a teletype by default.
-
-
-## Patches
-
-After the baseline disk image is created, `mkos8` makes a copy of it as
-`os8v3d-patched.rk05` and applies a [carefully selected set of official
-DEC patches][os8p] to it unless you give the `--disable-os8-patches`
-configuration option. The IF=0 and IF=7 boot options boot from the
-patched disk unless you give that option.
-
-
-[bdt2]: https://tangentsoft.com/pidp8i/file/media/os8/al-4712c-ba-os8-v3d-2.1978.tu56
-[cl]: https://tangentsoft.com/pidp8i/doc/trunk/ChangeLog.md
-[cs]: https://tangentsoft.com/pidp8i/doc/trunk/doc/class-simh.md
-[mkos8]: https://tangentsoft.com/pidp8i/doc/trunk/libexec/mkos8
-[os8mf]: https://tangentsoft.com/pidp8i/file/media/os8
-[tlrm]: https://tangentsoft.com/pidp8i/doc/trunk/README.md
-
-
-
-## Testing Your PiDP-8/I Hardware
+
+## Testing
You can test your PiDP-8/I LED and switch functions with these commands:
$ sudo systemctl stop pidp8i
$ pidp8i-test
@@ -701,15 +424,15 @@
$ sudo systemctl start pidp8i
See [its documentation][test] for more details.
-
+
## Using the Software
-For the most part, this software distribution works like the [old stable
-2015.12.15 distribution][osd]. Its [documentation][oprj] therefore
+For the most part, this software distribution works like the upstream
+[2015.12.15 distribution][usd]. Its [documentation][prj] therefore
describes this software too, for the most part.
The largest user-visible difference between the two software
distributions is that all of the shell commands affecting the software
were renamed to include `pidp8i` in their name:
@@ -738,27 +461,28 @@
5. To shut the simulator down from the Raspbian command line:
$ sudo systemctl stop pidp8i
-There are [other major differences][mdif] between the old stable
+There are [other major differences][mdif] between the upstream
distribution and this one. See that linked wiki article for details.
## License
Copyright © 2016-2017 by Warren Young. This document is licensed under
the terms of [the SIMH license][sl].
-[cprj]: https://tangentsoft.com/pidp8i/
+[prj]: https://tangentsoft.com/pidp8i/
+[upst]: http://obsolescence.wixsite.com/obsolescence/pidp-8
[sm1]: http://obsolescence.wixsite.com/obsolescence/2016-pidp-8-building-instructions
[sm2]: https://groups.google.com/d/msg/pidp-8/-leCRMKqI1Q/Dy5RiELIFAAJ
-[osd]: http://obsolescence.wixsite.com/obsolescence/pidp-8-details
+[usd]: http://obsolescence.wixsite.com/obsolescence/pidp-8-details
[dt2]: https://github.com/VentureKing/Deeper-Thought-2
[sdoc]: https://tangentsoft.com/pidp8i/uv/doc/simh/main.pdf
-[oprj]: http://obsolescence.wixsite.com/obsolescence/pidp-8
+[prj]: http://obsolescence.wixsite.com/obsolescence/pidp-8
[test]: https://tangentsoft.com/pidp8i/doc/trunk/doc/pidp8i-test.md
[thro]: https://tangentsoft.com/pidp8i/doc/trunk/README-throttle.md
[mdif]: https://tangentsoft.com/pidp8i/wiki?name=Major+Differences
[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
[ils]: https://tangentsoft.com/pidp8i/wiki?name=Incandescent+Lamp+Simulator
Index: RELEASE-PROCESS.md
==================================================================
--- RELEASE-PROCESS.md
+++ RELEASE-PROCESS.md
@@ -1,50 +1,10 @@
# PiDP-8/I Software Release Process
This documents the process for producing release versions of the
software.
-
-## *Can* You Release Yet?
-
-Before release, you must:
-
-* Fix all Immediate, High, and Medium priority [Bugs](/bugs)
-* Implement all Immediate and High priority [Features](/features)
-
-Or reclassify them, of course.
-
-Most of the bug levels simply aid scheduling: Immediate priority bugs
-should be fixed before High, etc. Low priority bugs are "someone should
-fix this someday" type of problems, so they can move from release to
-release.
-
-The Features levels may be read as:
-
-* **Immediate**: ASAP, or sooner. :)
-* **High**: Features for this release.
-* **Medium**: Features we'll look at lifting individually to High for
- the next release.
-* **Low**: "Wouldn't it be nice if..."
-
-
-## Update SIMH
-
-If `tools/simh-update` hasn't been run recently, you might want to do
-that and re-test before publishing a new version.
-
-
-## Publish OS/8 RK05s
-
-Re-configure the software with default settings, remove `bin/*.rk05`,
-rebuild, and run `tools/publish-os8` to send the "final" OS/8 disk
-images for this version of the software up to tangentsoft.com as
-unversioned assets.
-
-Update the date stamp in the "OS/8 RK05 Media" section of the project
-home page.
-
## Update ChangeLog.md
Trawl the Fossil timeline for user-visible changes since the last
release, and write them up in user-focused form into the `ChangeLog.md`
Index: auto.def
==================================================================
--- auto.def
+++ auto.def
@@ -31,120 +31,39 @@
define defaultprefix /opt/pidp8i
use cc
use cc-lib
-use cc-shared
-
-# Canonicalize some paths which may be relative and generate others from them
-set abspfx [file-normalize [get-define prefix]]
-define ABSPREFIX $abspfx
-define BOOTDIR "$abspfx/share/boot"
-define MEDIADIR "$abspfx/share/media"
-
-# Define command line options
+
options {
alt-serial-mod => "use GPIO drive scheme suitable for James L-W's serial mod method"
cc8-cross=1 => "do not build the cc8 cross-compiler on the host"
debug-mode => "create a debug build (default is release)"
lowercase: => "select how lowercase input is to be handled"
no-lamp-simulator => "use simple LED driver instead of incandescent lamp simulator"
- os8-advent=1 => "leave Adventure off the built OS/8 RK05 image"
- os8-ba=1 => "leave *.BA BASIC games and demos off the built OS/8 RK05 image"
- os8-cc8=1 => "leave the native OS/8 CC8 compiler off the built OS/8 RK05 image"
- os8-crt=1 => "suppress CRT-style rubout processing in the built OS/8 RK05 image"
- os8-chess=1 => "leave the CHECKMO-II game of chess off the built OS/8 RK05 image"
- os8-dcp=1 => "leave the DCP disassembler off the built OS/8 RK05 image"
+ os8-advent=1 => "add the game of ADVENT to built OS/8 RK05 image"
+ os8-ba=1 => "leave *.BA BASIC games and demos off built OS/8 RK05 disk image"
+ os8-cc8=1 => "leave the native OS/8 CC8 compiler off the built OS/8 RK05 disk image"
+ os8-crt=1 => "set CRT-style rubout processing in built OS/8 KR05 image"
+ os8-chess=1 => "leave the CHECKMO-II game of chess off built OS/8 RK05 image"
+ os8-dcp=1 => "install DCP Disassembler executables to built OS/8 RK05 image"
os8-focal=1 => "leave FOCAL 69 and U/W FOCAL off the built OS/8 RK05 image"
os8-focal69 => "add FOCAL 69 to the built OS/8 RK05 image"
os8-fortran-ii=1 => "leave FORTRAN II off the built OS/8 RK05 image"
os8-fortran-iv=1 => "leave FORTRAN IV off the built OS/8 RK05 image"
- os8-init=1 => "do not show the OS/8 INIT message in the built OS/8 RK05 image"
- os8-k12=1 => "leave 12-bit Kermit off the built OS/8 RK05 image"
- os8-macrel=1 => "leave MACREL assembler off the built OS/8 RK05 image"
- os8-minimal => "set all --disable-os8-* options, giving minimal OS/8 bin disk"
- os8-music => "add *.MU files to the built OS/8 RK05 image"
- os8-patches=1 => "do not apply DEC patches to the built OS/8 RK05 bin image"
- os8-src=1 => "do not build os8v3d-src.rk05 from OS/8 source tapes"
+ os8-init=1 => "suppress the OS/8 INIT message on boot: start with a bare . prompt"
+ os8-k12=1 => "leave 12-bit Kermit off built OS/8 RK05 disk image"
+ os8-macrel=1 => "leave MACREL assembler off the build OS/8 RK05 image"
+ os8-minimal => "disable all --enable-os8-* options, giving minimal OS/8 bin disk"
+ os8-music => "add *.MU files to built OS/8 RK05 disk image"
+ os8-src=1 => "don't build os8v3d-src.rk05 from OS/8 source tapes"
os8-uwfocal=1 => "leave U/W FOCAL (only) off the built OS/8 RK05 image"
os8-vtedit => "add the TECO VTEDIT setup to built OS/8 RK05 image"
serial-mod => "use GPIO drive scheme suitable for Oscar Vermeulen's serial mod method"
throttle: => "override the throttle values in the boot scripts"
}
-# Handle meta-options first.
-if {![opt-bool os8-focal]} {
- if {[opt-bool os8-focal69]} {
- dict set $::autosetup(optset) "os8-focal69" 0
- }
- if {[opt-bool os8-uwfocal]} {
- dict set $::autosetup(optset) "os8-uwfocal" 0
- }
-}
-set os8min [opt-bool os8-minimal]
-set os8src [opt-bool os8-src]
-
-# Translate the --*-os8-* options to mkos8 command line option format
-# and build the Python option map it uses to interpret them. This
-# avoids the need to define the options by hand in both places.
-set mkos8_opts ""
-set os "# GENERATED BY auto.def; DO NOT MODIFY.\n\nopts = {\n"
-foreach opt [lsort [dict keys $::autosetup(optdefault)]] {
- # Skip meta-options handled above and non --*-os8-* options.
- if {$opt in {os8-focal os8-minimal os8-src}} { continue }
- if {[string first "os8-" $opt] != 0} { continue }
-
- # Add next line to Python output
- set od [dict get $::autosetup(optdefault) $opt]
- set oh [dict get $::autosetup(opthelpline) $opt]
- set obn [string replace $opt 0 3]
- append os "\t\"" $obn "\": \[ $od, \"" $oh "\" \],\n"
-
- # Fix grammar for upcoming msg-result calls
- if {[string first "do not " $oh] == 0} {
- set oh [string replace $oh 0 6]
- } elseif {[string first "do " $oh] == 0} {
- set oh [string replace $oh 0 2]
- }
-
- # Choose option to pass to mkos8 corresponding to this configure
- # script option. Also tell user what we're going to do; grammar
- # is inverted because the option help text says what happens when
- # you give the opposite of the option's default argument.
- set ov [opt-bool $opt]
- if {$ov == $od} {
- # Don't append a mkos8 option; the default is correct.
- msg-result "Will not $oh."
- } elseif {!$os8min && $ov} {
- append mkos8_opts " --enable-" $obn
- } else {
- append mkos8_opts " --disable-" $obn
- }
-}
-append os "}\n"
-if {![file exists "lib/mkos8"]} { file mkdir "lib/mkos8" }
-write-if-changed "lib/mkos8/opts.py" $os
-
-# Handle the OS/8 options not passed to mkos8 generically by above.
-if {$os8src} {
- msg-result "Building os8v3d-src.rk05 from OS/8 source tapes."
- define OS8_SRC_RK05 bin/os8v3d-src.rk05
-} else {
- msg-result "Will not build os8v3d-src.rk05 from OS/8 source tapes."
- define OS8_SRC_RK05 {}
-}
-if {$os8min || ![opt-bool os8-patches]} {
- msg-result "Will not patch OS/8 on the RK05 bin disk."
- define OS8_BOOT_DISK "os8v3d-bin.rk05"
- define MKOS8_BIN_PATCHES {}
-} else {
- msg-result "Will apply OS/8 V3D patches to the RK05 bin disk."
- define OS8_BOOT_DISK "os8v3d-patched.rk05"
- define MKOS8_BIN_PATCHES patch
-}
-
-# React to remaining chosen command line options
if {[opt-bool alt-serial-mod]} {
msg-result "GPIO drive adjusted for James L-W's serial mods to the PiDP-8/I PCB."
define PCB_SERIAL_MOD_JLW
define PCB_SERIAL_MOD_ANY
}
@@ -167,10 +86,12 @@
define BUILDMODE {-O0 -g}
} else {
msg-result "Creating a release build."
define BUILDMODE {-O2}
}
+
+set mkos8_opts ""
set lv [opt-val lowercase]
if {$lv == ""} { set lv "auto" }
if {$lv == "auto"} {
define SIMH_PASS_LOWERCASE
@@ -182,17 +103,87 @@
} else {
user-error "Legal values for --lowercase are {auto,pass,upper}."
}
msg-result "Lowercase handling set to '$lv' mode."
-if {[opt-bool os8-cc8] && ![opt-bool os8-fortran-ii]} {
- msg-result "Must clear --disable-os8-fortran-ii when CC8 is enabled."
- regsub -- {--disable-os8-fortran-ii } $mkos8_opts {}
+set os8min [opt-bool os8-minimal]
+if {$os8min || ![opt-bool os8-advent]} {
+ msg-result "Will not add game of ADVENT to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-advent"
+}
+if {$os8min || ![opt-bool os8-ba]} {
+ msg-result "Will not add BASIC games and demos to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-ba"
+}
+if {$os8min || ![opt-bool os8-cc8]} {
+ msg-result "Will not add CC8 to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-cc8"
+}
+if {$os8min || ![opt-bool os8-chess]} {
+ msg-result "Will not add game of CHESS to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-chess"
+}
+if {$os8min || ![opt-bool os8-crt]} {
+ msg-result "Will not add BASIC games and demos to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-crt"
+}
+if {$os8min || ![opt-bool os8-dcp]} {
+ msg-result "Will not add DCP disassembler to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-dcp"
+}
+
+if {$os8min || ![opt-bool os8-focal]} {
+ msg-result "Will not add FOCAL 69 or U/W FOCAL to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-focal"
+} elseif {[opt-bool os8-focal69] && ![opt-bool os8-uwfocal]} {
+ msg-result "Adding FOCAL 69 to the OS/8 RK05 disk image instead of U/W FOCAL."
+ append mkos8_opts " --enable-focal69 --disable-uwfocal"
+} elseif {[opt-bool os8-focal69] && [opt-bool os8-uwfocal]} {
+ msg-result "Adding both FOCAL 69 and U/W FOCAL to the OS/8 RK05 disk image."
+ append mkos8_opts " --enable-focal69" ;# default --enable-uwfocal
+} else {
+ msg-result "Adding U/W FOCAL to the OS/8 RK05 disk image instead of FOCAL 69."
+}
+
+if {$os8min || ![opt-bool os8-fortran-ii]} {
+ msg-result "Will not add FORTRAN II compiler to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-fortran-ii"
+}
+if {$os8min || ![opt-bool os8-fortran-iv]} {
+ msg-result "Will not add FORTRAN IV compiler to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-fortran-iv"
+}
+if {$os8min || ![opt-bool os8-k12]} {
+ msg-result "Will not add Kermit-12 to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-k12"
+}
+if {$os8min || ![opt-bool os8-macrel]} {
+ msg-result "Will not add MACREL assembler to the OS/8 RK05 disk image."
+ append mkos8_opts " --disable-macrel"
+}
+if {!$os8min && [opt-bool os8-music]} {
+ msg-result "Will add music files to the OS/8 RK05 disk image."
+ append mkos8_opts " --enable-music"
+} else {
+ msg-result "Will not add music files to the OS/8 RK05 disk image."
+}
+if {!$os8min && [opt-bool os8-vtedit]} {
+ msg-result "Will add VTEDIT setup to the OS/8 RK05 disk image."
+ append mkos8_opts " --enable-vtedit"
}
-# We've purposely held off exporting the mkos8 option set until now
-# because some of the configuration options can affect the option set.
+if {$os8min || ![opt-bool os8-init]} {
+ msg-result "Suppressing the INIT message on OS/8 boot."
+ append mkos8_opts " --disable-init"
+}
+if {[opt-bool os8-src]} {
+ msg-result "Building os8v3d-src.rk05 from OS/8 source tapes."
+ define OS8_SRC_RK05 bin/os8v3d-src.rk05
+} else {
+ msg-result "Will not build os8v3d-src.rk05 from OS/8 source tapes."
+ define OS8_SRC_RK05 {}
+}
define MKOS8_OPTS $mkos8_opts
# Force a rebuild of the OS/8 media if the option set changed.
if {![file exists "obj"]} { file mkdir "obj" }
write-if-changed "obj/mkos8.opts" $mkos8_opts {
@@ -300,10 +291,15 @@
}
msg-result "Found GNU install(1) program as [get-define INSTALL]."
# If we have cscope here, we'll use it in the "tags" target
define HAVE_PROG_CSCOPE [cc-check-progs cscope]
+
+# Canonicalize some paths which may be relative and generate others from them
+define ABSPREFIX [file-normalize [get-define prefix]]
+define BOOTDIR "[get-define ABSPREFIX]/share/boot"
+define MEDIADIR "[get-define ABSPREFIX]/share/media"
# Remember the name and primary group of the user who installed this, since
# we want to give that group write privileges to some files when they're
# installed, and we want them to own the screen(1) session.
set instgrp [exec id -grn]
@@ -344,11 +340,11 @@
set cmd "$srcdir/$tool"
set status [catch {exec $cmd} version]
if {$status != 0} {
# The most likely cause for tools/version to fail is that the repo
# file has become disassociated from the local checkout directory.
- set sql ".timeout 5000 ; select value from vvar where name=\"repository\""
+ set sql "select value from vvar where name=\"repository\""
set cmd "fossil sql --no-repository $srcdir/.fslckout '$sql'"
set status [catch {exec /bin/sh -c $cmd} path]
if {$status != 0} {
user-error "Fossil doesn't seem to work here. Is it installed?\nCMD: $cmd"
} elseif {[file exists $path]} {
@@ -399,24 +395,10 @@
set ls [string toupper "[get-define LED_DRIVER_MODULE]ls"]
msg-result "Found Deeper Thought; building it against $ls GPIO module"
define BUILD_DEEPER_THOUGHT 1
}
-# Generate autodependency Makefile rule sets.
-#
-# It is important to list "src" last, because GNU make takes the first
-# one that matches, and the wildcards in the generated rules for "src"
-# match all "src/*" subdirs.
-set status [catch {
- exec $srcdir/tools/mkadrules $srcdir src/cc8/cross src/d8tape src/palbart src/PDP8 src
-} result]
-if {$status == 0} {
- msg-result $result
-} else {
- user-error "Failed to generate autodependency rules: $result!"
-}
-
# Write outputs.
#
# NOTE: If you change the list of files here, change INFILES in
# Makefile.in, too.
make-config-header src/config.h \
@@ -428,21 +410,20 @@
make-template boot/2.script.in
make-template boot/3.script.in
make-template boot/4.script.in
make-template boot/6.script.in
make-template boot/7.script.in
+make-template boot/cc8.script.in
make-template boot/run.script.in
+make-template cc8/Makefile.in
make-template etc/pidp8i-init.in
make-template etc/sudoers.in
make-template examples/Makefile.in
make-template lib/pidp8i/__init__.py.in
make-template lib/pidp8i/dirs.py.in
-make-template lib/pidp8i/ips.py.in
make-template media/os8/init.tx.in
make-template src/Makefile.in
-make-template src/cc8/Makefile.in
-make-template src/cc8/os8/Makefile.in
make-template src/gpio-common.c.in
make-template src/PDP8/Makefile.in
make-template src/PDP8/pidp8i.c.in
make-template tools/simh-update.in
exec chmod +x "$builddir/tools/simh-update"
Index: autosetup/autosetup
==================================================================
--- autosetup/autosetup
+++ autosetup/autosetup
@@ -75,11 +75,10 @@
# optset is a dictionary of option values set by the user based on getopt
set autosetup(optset) {}
# optdefault is a dictionary of default values for options
set autosetup(optdefault) {}
set autosetup(optionhelp) {}
- set autosetup(opthelpline) {}
set autosetup(showhelp) 0
# Parse options
use getopt
@@ -395,11 +394,10 @@
lappend autosetup(optionhelp) $header ""
set header ""
}
# A multi-line description
lappend autosetup(optionhelp) $opthelp $desc
- dict set autosetup(opthelpline) $name $desc
incr i 2
}
}
}
DELETED bin/.agignore
Index: bin/.agignore
==================================================================
--- bin/.agignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pt
-*.rk05
DELETED bin/.ignore
Index: bin/.ignore
==================================================================
--- bin/.ignore
+++ /dev/null
@@ -1,1 +0,0 @@
-.agignore
Index: bin/teco-pi-demo
==================================================================
--- bin/teco-pi-demo
+++ bin/teco-pi-demo
@@ -34,14 +34,12 @@
# Bring in just the basics so we can bring in our local modules
import os
import sys
sys.path.insert (0, os.path.dirname (__file__) + '/../lib')
-sys.path.insert (0, os.getcwd () + '/lib')
# Other core modules we need
-from datetime import datetime
import time
# Our local modules
from pidp8i import *
from simh import *
@@ -48,54 +46,20 @@
#### main ##############################################################
def main ():
- # Check for command line flags
- benchmark = len (sys.argv) > 1 and sys.argv[1] == '-b'
-
- # Create the SIMH child instance and tell it where to send log output
- try:
- s = simh (dirs.build)
- except (RuntimeError) as e:
- print "Could not start simulator: " + e.message + '!'
- exit (1)
+ # Start TECO in the simulator
+ s = simh (dirs.build)
s.set_logfile (os.fdopen (sys.stdout.fileno (), 'w', 0))
-
- # Find and boot the built OS/8 bin disk
- rk = os.path.join (dirs.os8mo, 'os8v3d-bin.rk05')
- if not os.path.isfile (rk):
- print "Could not find " + rk + "; OS/8 media not yet built?"
- exit (1)
- print "Booting " + rk + "..."
- s.send_cmd ("att rk0 " + rk)
+ s.send_cmd ("att rk0 bin/os8v3d-bin.rk05")
s.send_cmd ("boot rk0")
-
- # Start TECO8 in the simulator under OS/8
- s.os8_send_cmd ('\\.', "R TECO")
-
- # The macro comes from http://www.iwriteiam.nl/HaPi_TECO_macro.html
- #
- # The 248 preceding "UN" in the first line of the macro is the number
- # of digits of pi to calculate. That value was reached by experiment
- # as the largest value that runs without crashing TECO with a
- #
- # ?MEM STORAGE CAPACITY EXCEEDED
- #
- # error. You can see that by increasing the value below, commenting
- # out the throttle setting below, and running the demo. On a Pi 3, it
- # should take a bit over an hour to complete, if it doesn't error out.
- #
- # With the simulator throttled, generating 248 digits takes 17 years!
- #
- # That is based on generating 1 digit every ~16 seconds on a Pi 3 when
- # running unthrottled, roughly 8 MIPS. When throttled to 59 IPS — or
- # 17ms per instruction, as below — you multiply the seconds by the
- # factor 8 MIPS / 59 IPS = ~136000, giving about 2.2 million seconds
- # per digit. Multiplying that by 248 gives ~17 years.
+ s.os8_send_cmd ('\.', "R TECO")
+
+ # The macro we'll send: http://www.iwriteiam.nl/HaPi_TECO_macro.html
macro = [
- 'GZ0J\UNQN"E 248UN \' BUH BUV HK',
+ 'GZ0J\UNQN"E 40UN \' BUH BUV HK',
'QN< J BUQ QN*10/3UI',
'QI< \+2*10+(QQ*QI)UA B L K QI*2-1UJ QA/QJUQ',
'QA-(QQ*QJ)-2\ 10@I// -1%I >',
'QQ/10UT QH+QT+48UW QW-58"E 48UW %V \' QV"N QV^T \' QWUV QQ-(QT*10)UH >',
'QV^T @^A/',
@@ -117,63 +81,16 @@
# start it running.
s.os8_send_str (last) # not os8_send_line!
s.os8_send_ctrl ('[')
s.os8_send_ctrl ('[')
- if benchmark:
- # Run demo long enough to get a good sense of the simulator's
- # execution rate while unthrottled on this host hardware. If
- # you don't run it long enough, the IPS value is untrustworthy.
- try:
- s.spin (10)
- except pexpect.TIMEOUT:
- # Find out how many IPS was executing
- s.os8_send_ctrl ('e')
- s.send_cmd ('show clocks')
- line = s.read_tail ('Execution Rate:')
- curr_ips = int (line.strip().replace(',', '').split(' ')[0])
- pf = open ('lib/pidp8i/ips.py', 'a')
- pf.write ('current = ' + str (curr_ips) + ' # ' + \
- str (datetime.today ()) + '\n')
- pf.close ()
- s.send_cmd ('quit')
- pdp_ratio = float (curr_ips) / ips.pdp8i
- rpi_ratio = float (curr_ips) / ips.raspberry_pi_b_plus
- print "\nYour system is " + format (rpi_ratio, '.1f') + \
- " times faster than a Raspberry Pi Model B+"
- print "or " + format (pdp_ratio, '.1f') + \
- " times faster than a PDP-8/I.\n"
- else:
- # Normal mode. Pop out to SIMH and throttle it down to a rate
- # suitable for a blinkenlights demo. 1/17 means SIMH runs one
- # instruction then waits for 17ms, yielding ~59 IPS.
- time.sleep (0.02) # FIXME: simulator chokes on 'cont' without this
- s.os8_send_ctrl ('e')
- s.send_cmd ('set throttle 1/17')
-
- # You can't hit Ctrl-E while running this script in the foreground
- # since pexpect takes over stdio. Therefore, if you want to be able
- # to send commands to the simulator while the demo is running,
- # uncomment the line below, which will let you send commands to the
- # simulator via telnet. From another terminal or SSH session:
- #
- # $ telnet localhost 3141
- #
- # or from a remote machine:
- #
- # $ telnet 192.168.1.2 3141
- #
- # It's disabled by default because SIMH can't be made to listen only
- # on localhost, so doing this may be a security risk. SIMH disables
- # obviously-unsafe commands like ! on the remote console, but it is
- # possible some mischief may be possible via this path anyway. It
- # could be used to exfiltrate a sensitive file via ATTACH, for one
- # thing. For another, it's a potential DoS vector.
- #s.send_cmd ('set remote telnet=3141')
-
- # Let it run. Never exits.
- s.send_cmd ('cont')
- s.spin ()
+ # Let macro run for a bit, then pop out to SIMH and throttle it down
+ # to a rate suitable for a blinkenlights demo and let it go.
+ time.sleep (0.1)
+ s.os8_send_ctrl ('e')
+ s.send_cmd ('set throttle 1/17')
+ s.send_cmd ('cont')
+ s.spin () # never exits
if __name__ == "__main__":
main()
Index: boot/0.script.in
==================================================================
--- boot/0.script.in
+++ boot/0.script.in
@@ -39,7 +39,7 @@
; wants lowercase text to be forced to uppercase. This is bidirectional,
; affecting both input to the simulated PDP-8 and output from it.
set tti ksr
@endif
-att rk0 @MEDIADIR@/os8/@OS8_BOOT_DISK@
+att rk0 @MEDIADIR@/os8/os8v3d-bin.rk05
boot rk0
ADDED boot/cc8.script.in
Index: boot/cc8.script.in
==================================================================
--- /dev/null
+++ boot/cc8.script.in
@@ -0,0 +1,16 @@
+; This script initializes a populated OS/8 environment on an
+; RK05 cartridge disk pack. That's 10 whole megabytes, so big
+; the OS requires that you split it into two partitions in order
+; to address the whole disk! These are:
+;
+; SYS: which conyains all of the OS/8 system files and CC8
+; DSK: which contains all of the user files
+;
+reset
+echo Loading the CC8 OS/8 environment from the RK05 cartridge disk...
+set tti 7b
+set cpu 32k
+set cpu noidle
+@SET_THROTTLE@
+att rk0 @MEDIADIR@/os8/cc8.rk05
+boot rk0
Index: boot/run.script.in
==================================================================
--- boot/run.script.in
+++ boot/run.script.in
@@ -13,7 +13,7 @@
set tti 7b
@else
set tti ksr
@endif
-att rk0 bin/@OS8_BOOT_DISK@
+att rk0 bin/os8v3d-bin.rk05
boot rk0
ADDED cc8/Makefile.in
Index: cc8/Makefile.in
==================================================================
--- /dev/null
+++ cc8/Makefile.in
@@ -0,0 +1,46 @@
+########################################################################
+# Makefile.in - Processed by autosetup's configure script to generate
+# an intermediate GNU make(1) file for building the PiDP-8/I software
+# from within its cc8/ subdirectory.
+#
+# The resulting Makefile will redirect simple "make" calls to the top
+# level as well as the major top-level targets (e.g. "make clean") but
+# purposefully will not redirect anything like an installation or "run
+# the system" type target. Its only purpose is to help out those who
+# are working on CC8 from within this directory. If you need to work
+# on the wider system, do it from the project's top level.
+#
+# If you are seeing this at the top of a file called Makefile and you
+# intend to make edits, do that in Makefile.in. Saying "make" will then
+# re-build Makefile from that modified Makefile.in before proceeding to
+# do the "make" operation.
+#
+# Copyright © 2017 Warren Young
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
+# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
+# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
+# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the names of the authors above
+# shall not be used in advertising or otherwise to promote the sale,
+# use or other dealings in this Software without prior written
+# authorization from those authors.
+########################################################################
+
+all clean ctags distclean tags reconfig:
+ cd @builddir@; make $@
ADDED cc8/README.md
Index: cc8/README.md
==================================================================
--- /dev/null
+++ cc8/README.md
@@ -0,0 +1,337 @@
+# A Minimal Implementation of C for the DEC PDP-8 Processor
+
+## Introduction
+
+The C language and its derivatives are now the industry standard for the
+development of operating systems and utilities. The language has evolved
+significantly since its initial specification in 1972. At this time, the
+PDP-7 was used for the initial implementation and the compiler ported to
+a number of other systems including the PDP-11. Also, the first
+glimmerings of Unix appeared following a re-write of the assembly
+language version in C and the rest is of course history. The PDP-8 was
+introduced by DEC in 1965 at the same time as the PDP-7 with the
+intention of being a small and cheap processor that could be used in a
+variety of environments. From this simple machine, the modern desktop
+device has evolved which I am using to type this document. Nonetheless,
+far from fading into obscurity, there is a very active group of
+enthusiasts who have looked to implementing the PDP-8 on modern hardware
+and the thanks to Oscar Vermuelen and others, we can all have a PDP8/I
+to play with. With this in mind, I thought it was time to have a modern
+language compiler running on the PDP-8 which as far as I can tell, the
+last native compiler developed for the PDP-8 was Pascal in 1979 by Heinz
+Stegbauer. In more recent times, one cross-compiler has been developed
+by Vince Slyngstad and updated by Paolo Maffei based on Ron Cain’s Small
+C using a VM approach. [This code][sms] is most certainly worth
+examining, and I am delighted to acknowledge this work as I have used
+some of the C library code in this project.
+
+[sms]: http://so-much-stuff.com/pdp8/C/C.php
+
+Finally, I would refer the reader to Fabrice Bellard’s OTCC. It is this
+bit of remarkable software that suggested that there may be a chance to
+implement a native PDP-8 compiler.
+
+Developing a native compiler for the PDP-8 is not an easy task as this
+processor has a very limited address space and no hardware stack. And,
+although the option exists to write the whole thing in assembly language
+as has been the case for Pascal and Algol, this project has explored the
+option of writing the compiler itself in C. To this end, 2 compilers
+have been written. Firstly, a cross-compiler based again on Ron Cain’s
+Small-C which is used to compile the native OS/8 compiler and library.
+As yet, the native compiler has rather limited functionality and will
+not compile itself. The cross-compiler will compile itself but produces
+an enormous (28K) assembler file which cannot be run on the PDP-8.
+
+
+# The Cross-Compiler
+
+The code for this is in the `cross` subdirectory, and is built along
+with the top-level PiDP-8/I software. As above, this is based upon Ron
+Cain’s Small-C compiler, and the reader is directed to the extensive
+documentation available on the web. The key file is the code generator
+section in `code8.c`. This is used to generate SABR (Symbolic Assembler
+for Binary Relocatable programmes) assembly output which is normally
+used as the second pass of the OS/8 FORTRAN II system.
+
+You use this cross-compiler to compile the 3 components of the OS/8 C
+compiler:
+
+1. `n8.c` → `n8.s`: The parser/tokeniser section of the compiler
+
+2. `p8.c` → `p8.s`: The token to SABR code converter section.
+
+3. `libc.c` → `libc.s`: The C library used by both of the above
+ via the `libc.h` include file.
+
+When you build and run this cross-compiler on a POSIX type system such
+as the Raspbian PiDP-8/I environment, the resulting `*.s` files will
+have LF-only line endings. You may need to run these files through a
+`unix2dos` type utility in order to produce the CRLF line endings that
+OS/8's SABR assembler expects, depending on how you get those `*.s`
+files into OS/8 as `*.SB`.
+
+The `*.SB` files may be assembled under OS/8:
+
+ .COMP N8.SB
+ .COMP LIBC.SB
+ .COMP P8.SB
+
+This will create the `*.RL` files for the linking loader (`LOADER.SV`).
+
+The cross-compiler has some non-standard features to enable the
+interface between the main programme and the C library. This constitutes
+a compile time linkage system to allow for standard and vararg functions
+to be called in the library. The 3 SABR files generated from the source
+files as above may then be separately downloaded, compiled, loaded and
+linked under OS/8. Each of these SABR files generates just less than 4K
+of relocatable code as `N8.RL`, `P8.RL` and `LIBC.RL`. These are linked
+in pairs under OS/8 to create the 2 native OS/8 compiler phases:
+
+Phase 1: Link `N8.RL` and `LIBC.RL` to be saved as `CC1.SV`
+
+Phase 2: Link `P8.RL` and `LIBC.RL` to be saved as `CC2.SV`
+
+The commands are as follows, with `$` being an Escape keypress:
+
+ .R LOADER
+ *N8,LIBC/I$
+ .SAVE SYS CC1
+ .R LOADER
+ P8,LIBC/I/O$
+ .SAVE SYS CC2
+
+N8 (`CC1.SV`) terminates by chaining to `CC2.SV` to complete the process
+of generating a final SABR file.
+
+Several of the C programs in this distribution reference a PAL assembly
+initialization routine `cc8/include/init.pa`, which is symlinked into
+each directory that uses it. It defines some low-level subroutines,
+initializes the environment for the programs, and calls into the LIBC
+initialization code. If you are going to compile these programs with the
+OS/8 native compiler, you will need to copy `init.pa` into the OS/8
+environment as well.
+
+The same goes for `cc8/include/libc.h`, which defines the mappings
+between the familiar C library routine names and their underlying
+implementation names.
+
+The linking loader determines the core layout of each of the pairs of
+`.RL` files as above. Typically this is as follows:
+
+**Field 0:** FOTRAN library utility functions and OS/8 I/O system
+
+**Field 1:** Reserved for the programme’s runtime stack/globals/literals.
+
+**Field 2:** Usually the primary programme ... either N8 or P8.
+
+**Field 3:** Usually the LIBC library.
+
+In all, each phase of the native OS/8 compiler will use 16K of core.
+
+
+## The Native Compiler
+
+This compiler is built and linked as above. The final two files
+generated are `CC1.SV` and `CC2.SV`. These should be on the OS/8 system
+device. (`SYS:`) The compiler expects the source file in C to be in `CC.CC`
+on the default user device. (`DSK:`) In addition, you will need to file
+`HEADER.SB` on the default user device. This is used by `CC2.SV`. I suggest
+you use the provided RK05 image as this has the `SYS:` and `DSK:` partitions
+configured as required and include a linked copy of the compiler and
+some example programs.
+
+To try it out:
+
+Boot OS/8 from the included RK05 image with:
+
+ $ bin/pidp8i-sim boot/cc8.script
+
+Note that this is a different version of OS/8 than the one currently
+distributed in the IF=0, IF=3, and IF=7 positions in the PiDP-8/I boot
+scheme. It is version V3Q (up from V3D) and it is configured to smash
+lowercase input to uppercase only in the OS/8 command processor.
+Lowercase input in the text editor will be saved as lowercase.
+
+With this special CC8 OS/8 environment running, you can enter a C
+programme in lower case via the editor.
+
+Before getting into the text editor, try building a copy of one of the
+example programs:
+
+ .COPY CC.CC)`. This does not
+ work.
+
+14. `struct` is not supported.
+
+15. Double precision `int`, `float` etc. are not supported. If you need
+ to do heavy duty maths, use Fortran.
+
+16. The stack, which includes all globals and literals, is only 4k.
+ Stack overflow is not detected.
+
+17. Recursion is implemented. See `FIB.CC`.
+
+18. Literals have to be included in the 4K limit programme area. These
+ are copied into the stack at run time. This is due to the fact that
+ ‘COMMON’ storage cannot be initialised.
+
+19. There is no option for `#include` files. The available Libc
+ functions are implicitly declared and listed in `libc.h` and `p8.c`.
+ As a result, there is no arglist checking. Examine `libc.c` for
+ details.
+
+
+## OS/8 Specifics
+
+1. I strongly suggest you limit I/O to text files.
+
+2. Don’t forget to handle form feed. See `c8.c`
+
+3. For some obscure reason, always open the input file first, then the
+ output file. I suspect a fault in `libc.c`. Examine the code!!!!
+ (Every trick in the book.)
+
+
+## Preprocessor
+
+The compiler distribution includes a pre-processor file (`c8.c` →
+`CC0.SV`). This is a stub and merely asks for a filename and calls the
+compiler chain. This file may be extended and used to process `#define`
+`#include`, etc.
+
+Compile using the cross-compiler to `c8.s`, copy to `C8.SB` under OS/8
+on your PDP-8 target system, then:
+
+ .COMP C8.SB
+ .R LOADER
+ *C8,LIBC/I/O$
+ .SAVE SYS CC0
+ .R CC0
+ > enter filename and press Return
+ .COMP CC.SB
+ .R LOADER
+ *CC,LIBC/G if no file I/O; or...
+ *CC,LIBC/I/O/G ...if using file I/O
+
+Try the examples in `*.CC` on `DSK:`. I personally like `PS.CC`,
+Pascal’s triangle. This version does not require factorials, which are a
+bit out of range for 12 bits!!
+
+Try it with:
+
+ .R CC0
+ >PS.CC
+ .COMP CC.SB
+ .R LOADER
+ *CC,LIBC/G
+
+
+## Conclusion
+
+This is a somewhat limited manual which attempts to give an outline of a
+very simple compiler for which I apologise as the source code is obscure
+and badly commented. However, the native OS/8 compiler/tokeniser
+(`n8.c`) is only 600 lines which is a nothing in the scale of things
+these days. However, I hope this project gives some insight into
+compiler design and code generation strategies to target a most
+remarkable computer. I would also like to give credit to the builders of
+OS/8 and in particular the FORTRAN II system which was never designed to
+survive the onslaught of this kind of modern software.
+
+Don’t expect too much! This compiler will not build this week’s bleeding
+edge kernel. But, it may be used to build any number of useful utility
+programs for OS/8.
+
+
+## License
+
+This document is under the [GNU GPLv3 License][gpl], copyright © May and
+June 2017 by [Ian Schofield][ian], with minor updates by [Warren
+Young][wy] in July 2017.
+
+[gpl]: https://www.gnu.org/licenses/gpl.html
+[ian]: mailto:Isysxp@gmail.com
+[wy]: https://tangentsoft.com/
ADDED cc8/cross/README.md
Index: cc8/cross/README.md
==================================================================
--- /dev/null
+++ cc8/cross/README.md
@@ -0,0 +1,16 @@
+This directory contains the sources for the CC8 cross-compiler, which is
+based on Ron Cain's Small-C system.
+
+It is built by the top-level build system as `bin/cc8` and is installed
+to `$prefix/bin/cc8`.
+
+Call it as:
+
+ cc8 myfile.c
+
+The compiler does not have any consequential command line options.
+
+The output file is `myfile.s` which is in SABR assembly code, intended
+to be assembled within the PiDP-8/I OS/8 environment. See the `test`
+subdirectory and [the top-level README][/doc/trunk/cc8/README.md] for
+further details.
ADDED cc8/cross/code8.c
Index: cc8/cross/code8.c
==================================================================
--- /dev/null
+++ cc8/cross/code8.c
@@ -0,0 +1,1057 @@
+/* File code8080.c: 2.2 (84/08/31,10:05:09) */
+/*% cc -O -c %
+ *
+ */
+
+#define unix
+
+#include
+#include "defs.h"
+#include "data.h"
+#include
+
+/* Define ASNM and LDNM to the names of the assembler and linker
+ respectively */
+
+/*
+ * Some predefinitions:
+ *
+ * INTSIZE is the size of an integer in the target machine
+ * BYTEOFF is the offset of an byte within an integer on the
+ * target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
+ * 360 = 3)
+ * This compiler assumes that an integer is the SAME length as
+ * a pointer - in fact, the compiler uses INTSIZE for both.
+ */
+#define INTSIZE 1
+#define BYTEOFF 0
+
+/*
+ * print all assembler info before any code is generated
+ *
+ */
+header ()
+{
+ outstr ("/ Small C PDP8 Coder (1.0:27/1/99)");
+ nl();
+ FEvers();
+ nl ();
+ ol ("OPDEF ANDI 0400");
+ ol ("OPDEF TADI 1400");
+ ol ("OPDEF ISZI 2400");
+ ol ("OPDEF DCAI 3400");
+ ol ("OPDEF JMSI 4400");
+ ol ("OPDEF JMPI 5400");
+ ol ("OPDEF MQL 7421");
+ ol ("OPDEF MQA 7701");
+ ol ("OPDEF MQO 7501");
+ ol ("OPDEF SWP 7521");
+ ol ("OPDEF CDF1 6211");
+ ol ("OPDEF CDF0 6201");
+ ol ("OPDEF RIF 6224");
+ ol ("OPDEF CAF0 6203");
+ ol ("OPDEF BSW 7002");
+ ol ("OPDEF CAM 7621");
+ ol ("/");
+}
+
+nl ()
+{
+ outbyte (EOL);
+/* outbyte (10); */
+}
+initmac()
+{
+ defmac("cpm\t1");
+ defmac("I8080\t1");
+ defmac("RMAC\t1");
+ defmac("smallc\t1");
+}
+
+galign(t)
+int t;
+{
+ return(t);
+}
+
+/*
+ * return size of an integer
+ */
+intsize() {
+ return(INTSIZE);
+}
+
+/*
+ * return offset of ls byte within word
+ * (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
+ */
+byteoff() {
+ return(BYTEOFF);
+}
+
+/*
+ * Output internal generated label prefix
+ */
+olprfix() {
+ ot("CC");
+}
+
+/*
+ * Output a label definition terminator
+ */
+col ()
+{
+ outbyte (',');
+}
+
+/*
+ * begin a comment line for the assembler
+ *
+ */
+comment ()
+{
+ outbyte ('/');
+}
+
+/*
+ * Emit user label prefix
+ */
+prefix ()
+{
+}
+
+/* Stkbase output stack base->literals =stkp+2 ... ie 202(8) =130(10) + sizeof(globals) */
+stkbase()
+{
+ ot("GBL");
+}
+
+/*
+ * print any assembler stuff needed after all code
+ *
+ */
+trailer ()
+{
+// ot("\tENTRY ");
+// outbyte('M');
+// printlabel (litlab);
+// nl();
+ outbyte('M');
+ printlabel (litlab);
+ col();
+ ot("\t0");
+ nl();
+ ol("\tCDF1");
+ ot("\tTAD L");
+ printlabel (litlab);
+ nl();
+ ol ("\tSNA CLA / Any literals to push?");
+ ot ("\tJMP I M");
+ printlabel (litlab);
+ nl();
+ ot("\tTAD X");
+ printlabel (litlab);
+ nl();
+ ol ("\tDCA JLC");
+ outbyte('D');
+ printlabel (litlab);
+ col();
+ ol("CDF0");
+ ot("\tTADI JLC");
+ nl();
+ ol ("\tJMSI PSH");
+ ol ("\tCLA");
+ ol ("\tISZ JLC");
+ ot("\tISZ L");
+ printlabel (litlab);
+ nl();
+ ot("\tJMP D");
+ printlabel (litlab);
+ nl();
+ ot ("\tJMP I M");
+ printlabel (litlab);
+ nl();
+ ol("CCEND,\t0");
+ ol ("END");
+}
+
+
+/*
+ * function prologue
+ */
+prologue (sym)
+char *sym;
+{
+}
+
+/*
+ * text (code) segment
+ */
+gtext ()
+{
+/* ol ("cseg"); */
+}
+
+/*
+ * data segment
+ */
+gdata ()
+{
+/* ol ("dseg"); */
+}
+
+/*
+ * Output the variable symbol at scptr as an extrn or a public
+ */
+ppubext(scptr) char *scptr; {
+ if (scptr[STORAGE] == STATIC) return 0;
+// ot (scptr[STORAGE] == EXTERN ? "extrn\t" : "public\t");
+// prefix ();
+// outstr (scptr);
+// nl();
+}
+
+/*
+ * Output the function symbol at scptr as an extrn or a public
+ */
+fpubext(scptr) char *scptr; {
+/* if (scptr[STORAGE] == STATIC) return;
+// ot (scptr[OFFSET] == FUNCTION ? "public\t" : "extrn\t");
+// prefix ();
+// outstr (scptr);
+// nl (); */
+}
+
+/*
+ * Output a decimal number to the assembler file
+ */
+onum(num) int num; {
+ outdec(num); /* pdp11 needs a "." here */
+}
+
+
+/*
+ * fetch a static memory cell into the primary register
+getmem (sym)
+char *sym;
+{
+ int adr;
+ ol ("\tCLA");
+ immd3 ();
+ adr=glint(sym)+128;
+ onum(glint(sym)+128);
+ nl();
+ ol("\tDCA JLC");
+ ol("\tTADI JLC");
+}*/
+
+getmem (sym)
+char *sym;
+{
+ int adr;
+ ol ("\tCLA");
+ immd4 ();
+ adr=glint(sym)+128;
+ onum(glint(sym)+128);
+ nl();
+}
+/*
+ * fetch a static memory cell into the primary register (pre-increment*/
+
+getincmem (sym)
+char *sym;
+{
+ int adr;
+ ol ("\tCLA");
+ adr=glint(sym)+128;
+ ot ("\tISZI (");
+ onum(adr);
+ nl();
+ immd4 ();
+ onum(adr);
+ nl();
+}
+
+
+/*
+ * fetch the address of the specified symbol into the primary register
+ *
+ */
+getloc (sym)
+char *sym;
+{
+ ol("\tCLA");
+ ol("\tTAD STKP");
+ if (sym[STORAGE] == LSTATIC) {
+ immd3 ();
+ printlabel(-1-glint(sym));
+ nl();
+ } else {
+ if (stkp-glint(sym)==0) outstr("/");
+ immd3 ();
+ outdec (stkp-glint(sym));
+ nl ();
+ }
+}
+
+/*
+ * store the primary register into the specified static memory cell
+ *
+
+putmem (sym)
+char *sym;
+{
+ ol("\tMQL");
+ immd3 ();
+ onum(glint(sym)+128);
+ nl();
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tDCAI JLC");
+ ol("\tTADI JLC");
+}
+*/
+
+putmem (sym)
+char *sym;
+{
+ ot("\tDCAI (");
+ onum(glint(sym)+128);
+ nl();
+ immd4 ();
+ onum(glint(sym)+128);
+ nl();
+}
+
+/*
+ * store the specified object type in the primary register
+ * at the address on the top of the stack
+ *
+ */
+putstk (typeobj)
+char typeobj;
+{
+ ol("\tJMSI PTSK");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * fetch the specified object type indirect through the primary
+ * register into the primary register
+ *
+ */
+indirect (typeobj)
+char typeobj;
+{
+ ol("\tDCA JLC");
+/* ol("\tCDF1"); */
+ ol("\tTADI JLC");
+}
+
+/*
+ * fetch the specified object type indirect through the primary
+ * register into the primary register (pre-increment)
+ *
+ */
+incdirect (typeobj)
+char typeobj;
+{
+ ol("\tDCA JLC");
+ ol("\tISZI JLC");
+ ol("\tTADI JLC");
+}
+
+
+/*
+ * swap the primary and secondary registers
+ *
+ */
+swap ()
+{
+ ol ("\tSWP");
+}
+/*
+* Clear primary reg
+*/
+cpri()
+{
+ ol("\tCLA");
+}
+/*
+ * print partial instruction to get an immediate value into
+ * the primary register
+ *
+ */
+immed ()
+{
+ ol ("\tCLA");
+ ot ("\tTAD (");
+}
+immd2 ()
+{
+ ol ("\tCLA");
+ ot ("\tTAD ");
+}
+immd3 ()
+{
+ ot ("\tTAD (");
+}
+
+immd4 ()
+{
+ ot("\tTADI (");
+}
+/*
+ * push the primary register onto the stack
+ *
+ */
+gpush ()
+{
+ ol ("\tJMSI PSH");
+ stkp = stkp - INTSIZE;
+}
+
+/*
+ * pop the top of the stack into the secondary register
+ *
+ */
+gpop ()
+{
+ ol ("\tJMSI POP");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * swap the primary register and the top of the stack
+ *
+ */
+swapstk ()
+{
+ ol ("\tMQL");
+ gpop();
+ ol ("\tSWP");
+ gpush();
+ ol ("\tSWP");
+}
+
+/*
+ * call the specified subroutine name
+ * varag is allowed for libc functions using a v prefix. In this case, the arg count+1 is pushed onto the stack as well.
+ * For the actual routine, the declaration should be a single arg eg printf(int args) in this case, the value of args is the count and &args-args point to the first arg in the caller's list.
+ */
+gcall (sname,nargs)
+char *sname;
+int *nargs;
+{
+ char tm[10];
+
+ if (strstr(sname,"vlibc")) {
+ immed();
+ sname++;
+ outdec(*nargs);
+ outstr("\t/ PUSH ARG COUNT");
+ nl();
+ ol("\tJMSI PSH");
+ stkp = stkp - INTSIZE;
+ (*nargs)++;
+ }
+ if (strstr(sname,"libc"))
+ {
+ strcpy(tm,sname);
+ immed();
+ outstr(tm+4);
+ nl();
+ ol("\tMQL");
+ ol("\tCALL 1,LIBC");
+ ol("\tARG STKP");
+ ol("\tCDF1"); /* Make sure DF is correct */
+ return 0;
+ }
+ ol("\tCPAGE 2");
+ ol("\tJMSI PCAL");
+ ot ("\t");
+ outstr (sname);
+ nl ();
+}
+
+stri()
+{
+ ol("\tDCAI 10");
+}
+iinit()
+{
+ ol("\tCIA;CMA");
+ ol("\tDCA 10");
+}
+
+/*
+ * return from subroutine
+ *
+ */
+gret (sym)
+char *sym;
+{
+ ol ("\tJMPI POPR");
+}
+
+/*
+ * perform subroutine call to value on top of stack
+ *
+ */
+callstk ()
+{
+ immed ();
+ outstr ("$+5");
+ nl ();
+ swapstk ();
+ ol ("pchl");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * jump to specified internal label number
+ *
+ */
+jump (label)
+int label;
+{
+ ot ("\tJMP\t");
+ printlabel (label);
+ nl ();
+}
+
+/*
+ * test the primary register and jump if false to label
+ *
+ */
+testjump (label, ft)
+int label,
+ ft;
+{
+ if (ft)
+ ol ("\tSZA");
+ else
+ ol ("\tSNA");
+ jump (label);
+}
+
+casejump()
+{
+ ol("\tTAD TMP");
+ ol("\tSNA CLA");
+}
+/*
+ * print pseudo-op to define a byte
+ *
+ */
+defbyte ()
+{
+ ot ("\t");
+}
+
+/*
+ * print pseudo-op to define storage
+ *
+ */
+defstorage ()
+{
+ ot ("COMMN\t");
+}
+
+/*
+ * print pseudo-op to define a word
+ *
+ */
+defword ()
+{
+ ot ("\t");
+}
+
+/*
+ * modify the stack pointer to the new value indicated
+ *
+ */
+modstk (newstkp)
+int newstkp;
+{
+ int k;
+
+ k = galign(stkp-newstkp);
+ if (k == 0)
+ return (newstkp);
+ if (k>0 && k<5) {
+ while (k--) ol ("\tISZ STKP");
+ return (newstkp);
+ }
+ ol ("\tMQL");
+ immd3 ();
+ outdec (k);
+ nl ();
+ ol ("\tTAD STKP");
+ ol ("\tDCA STKP");
+ swap ();
+ return (newstkp);
+}
+
+/*
+ * multiply the primary register by INTSIZE
+ */
+gaslint ()
+{
+}
+
+/*
+ * divide the primary register by INTSIZE
+ */
+gasrint()
+{
+}
+
+/*
+ * Case jump instruction
+ */
+gjcase() {
+ ol ("\tCIA");
+ ol ("\tDCA TMP");
+}
+
+/*
+ * add the primary and secondary registers
+ * if lval2 is int pointer and lval is not, scale lval
+ */
+gadd (lval,lval2) int *lval,*lval2;
+{
+/* if (lval==0) ol("\tCIA");*/
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * subtract the primary register from the secondary
+ *
+ */
+gsub ()
+{
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * multiply the primary and secondary registers
+ * (result in primary)
+ *
+ */
+gmult ()
+{
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tCALL 1,MPY");
+ ol("\tARG JLC");
+ ol("\tCDF1");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * divide the secondary register by the primary
+ * (quotient in primary, remainder in secondary)
+ *
+ */
+gdiv ()
+{
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tCALL 1,DIV");
+ ol("\tARG JLC");
+ ol("\tCDF1");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * compute the remainder (mod) of the secondary register
+ * divided by the primary register
+ * (remainder in primary, quotient in secondary)
+ *
+ */
+gmod ()
+{
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tCALL 1,DIV");
+ ol("\tARG JLC");
+ ol("\tCALL 1,IREM");
+ ol("\tARG 0");
+ ol("\tCDF1");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * inclusive 'or' the primary and secondary registers
+ *
+ */
+gor ()
+{
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * exclusive 'or' the primary and secondary registers
+ *
+ */
+gxor ()
+{
+ gpop();
+ gcall ("?xor");
+}
+
+/*
+ * 'and' the primary and secondary registers
+ *
+ */
+gand ()
+{
+ ol("\tDCA JLC");
+ ol("\tJMSI POP");
+ ol("\tMQA");
+ ol("\tAND JLC");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * arithmetic shift right the secondary register the number of
+ * times in the primary register
+ * (results in primary register)
+ *
+ */
+gasr ()
+{
+ int lbl;
+
+ lbl=getlabel();
+ ol("\tCIA");
+ ol("\tJMSI POP");
+ gnlabel(lbl);
+ ol("\tSWP");
+ ol("\tCLL RAR");
+ ol("\tSWP");
+ ol("\tIAC");
+ ol("\tSZA");
+ jump(lbl);
+ ol("\tSWP");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * arithmetic shift left the secondary register the number of
+ * times in the primary register
+ * (results in primary register)
+ *
+ */
+gasl ()
+{
+ int lbl;
+
+ lbl=getlabel();
+ ol("\tCIA");
+ ol("\tJMSI POP");
+ gnlabel(lbl);
+ ol("\tSWP");
+ ol("\tCLL RAL");
+ ol("\tSWP");
+ ol("\tIAC");
+ ol("\tSZA");
+ jump(lbl);
+ ol("\tSWP");
+ stkp = stkp + INTSIZE;
+}
+
+/*
+ * two's complement of primary register
+ *
+ */
+gneg ()
+{
+ ol("\tCIA");
+}
+
+/*
+ * logical complement of primary register
+ *
+ */
+glneg ()
+{
+ ol("\tSNA CLA");
+ ol("\tCMA");
+}
+
+/*
+ * one's complement of primary register
+ *
+ */
+gcom ()
+{
+ ol("\tCMA");
+}
+
+/*
+ * Convert primary value into logical value (0 if 0, 1 otherwise)
+ *
+ */
+gbool ()
+{
+ ol("\tSZA CLA");
+ ol("\tIAC");
+}
+
+/*
+ * increment the primary register by 1 if char, INTSIZE if
+ * int
+ */
+ginc (lval) int lval[];
+{
+ ol ("\tIAC");
+/* if (lval[2] == CINT)
+// ol ("inx\th"); */
+}
+/*
+ * Shortened INC
+*/
+
+gisz (lval)
+int *lval;
+{
+ int adr;
+ char *sym=lval[0];
+
+ if (lval[1]) {
+ ol ("\tISZI JLC");
+ return 0;
+ }
+
+ ot ("\tISZI (");
+ adr=stkp-glint(sym);
+// if (lval[STORAGE] == PUBLIC)
+ adr=glint(sym)+128;
+ onum(adr);
+ nl();
+}
+/*
+ * decrement the primary register by one if char, INTSIZE if
+ * int
+ */
+gdec (lval) int lval[];
+{
+ ol ("\tTAD (-1");
+/* if (lval[2] == CINT)
+// ol("dcx\th"); */
+}
+
+/*
+ * following are the conditional operators.
+ * they compare the secondary register against the primary register
+ * and put a literl 1 in the primary if the condition is true,
+ * otherwise they clear the primary register
+ *
+ */
+
+/*
+ * equal
+ *
+ */
+geq ()
+{
+ ol("\tCIA");
+ ol("\tTADI STKP");
+ gpop();
+ ol("\tSNA CLA");
+ ol("\tCMA");
+}
+
+/*
+ * not equal
+ *
+ */
+gne ()
+{
+ gpop();
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+}
+
+/*
+ * less than (signed)
+ *
+ */
+glt ()
+{
+ gpop();
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tAND (2048");
+}
+
+/*
+ * less than or equal (signed)
+ *
+ */
+gle ()
+{
+ gpop();
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNA");
+ ol("\tCLA CMA");
+ ol("\tAND (2048");
+}
+
+/*
+ * greater than (signed)
+ *
+ */
+ggt ()
+{
+ gpop();
+ ol("\tSWP");
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tAND (2048");
+}
+
+/*
+ * greater than or equal (signed)
+ *
+ */
+gge ()
+{
+ gpop();
+ ol("\tSWP");
+ ol("\tCIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNA");
+ ol("\tCLA CMA");
+ ol("\tAND (2048");
+}
+
+/*
+ * less than (unsigned)
+ *
+ */
+gult ()
+{
+ gpop();
+ ol("\tCLL CIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNL CLA");
+ ol("\tIAC");
+}
+
+/*
+ * less than or equal (unsigned)
+ *
+ */
+gule ()
+{
+ gpop();
+ ol("\tCLL CIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNL CLA");
+ ol("\tIAC");
+}
+
+/*
+ * greater than (unsigned)
+ *
+ */
+gugt ()
+{
+ gpop();
+ ol("\tCLL CIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNA SZL CLA");
+ ol("\tIAC");
+}
+
+/*
+ * greater than or equal (unsigned)
+ *
+ */
+guge ()
+{
+ gpop();
+ ol("\tSWP");
+ ol("\tCLL CIA");
+ ol("\tDCA JLC");
+ ol("\tMQA");
+ ol("\tTAD JLC");
+ ol("\tSNL CLA");
+ ol("\tIAC");
+}
+
+inclib() {
+#ifdef cpm
+ return("B:");
+#endif
+#ifdef unix
+ return("");
+#endif
+}
+
+/* Squirrel away argument count in a register that modstk
+ doesn't touch.
+*/
+
+gnargs(d)
+int d; {
+/* ot ("mvi\ta,");
+// onum(d);
+// nl (); */
+}
+
+assemble(s)
+char *s; {
+#ifdef ASNM
+ char buf[100];
+ strcpy(buf, ASNM);
+ strcat(buf, " ");
+ strcat(buf, s);
+ buf[strlen(buf)-1] = 's';
+ return(system(buf));
+#else
+ return(0);
+#endif
+}
+
+link() {
+#ifdef LDNM
+ fputs("I don't know how to link files yet\n", stderr);
+#else
+ return(0);
+#endif
+}
ADDED cc8/cross/ctype.h
Index: cc8/cross/ctype.h
==================================================================
--- /dev/null
+++ cc8/cross/ctype.h
@@ -0,0 +1,1 @@
+/* Nothing needed in this file */
ADDED cc8/cross/data.c
Index: cc8/cross/data.c
==================================================================
--- /dev/null
+++ cc8/cross/data.c
@@ -0,0 +1,55 @@
+/* File data.c: 2.2 (84/11/27,16:26:13) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+
+/* storage words */
+
+char symtab[SYMTBSZ];
+char *glbptr, *rglbptr, *locptr;
+int ws[WSTABSZ];
+int *wsptr;
+int swstcase[SWSTSZ];
+int swstlab[SWSTSZ];
+int swstp;
+char litq[LITABSZ];
+int litptr;
+char macq[MACQSIZE];
+int macptr;
+char line[LINESIZE];
+char mline[LINESIZE];
+int lptr, mptr, gsize;
+
+/* miscellaneous storage */
+
+int nxtlab,
+ litlab,
+ stkp,
+ argstk,
+ ncmp,
+ errcnt,
+ glbflag,
+ ctext,
+ cmode,
+ lastst,
+ inbreak;
+
+FILE *input, *input2, *output;
+FILE *inclstk[INCLSIZ];
+int inclsp;
+char fname[20];
+FILE *bfile;
+
+char quote[2];
+unsigned char *cptr;
+int *iptr;
+int fexitlab;
+int iflevel, skiplevel;
+int errfile;
+int sflag;
+int cflag;
+int errs;
+int aflag;
ADDED cc8/cross/data.h
Index: cc8/cross/data.h
==================================================================
--- /dev/null
+++ cc8/cross/data.h
@@ -0,0 +1,48 @@
+/* File data.h: 2.2 (84/11/27,16:26:11) */
+
+/* storage words */
+
+extern char symtab[];
+extern char *glbptr, *rglbptr, *locptr;
+extern int ws[];
+extern int *wsptr;
+extern int swstcase[];
+extern int swstlab[];
+extern int swstp;
+extern char litq[];
+extern int litptr;
+extern char macq[];
+extern int macptr;
+extern char line[];
+extern char mline[];
+extern int lptr, mptr, gsize;
+
+/* miscellaneous storage */
+
+extern int nxtlab,
+ litlab,
+ stkp,
+ argstk,
+ ncmp,
+ errcnt,
+ glbflag,
+ ctext,
+ cmode,
+ lastst,
+ inbreak;
+
+extern FILE *input, *input2, *output, *bfile;
+extern FILE *inclstk[];
+extern int inclsp;
+extern char fname[];
+
+extern char quote[];
+extern char *cptr;
+extern int *iptr;
+extern int fexitlab;
+extern int iflevel, skiplevel;
+extern int errfile;
+extern int sflag;
+extern int cflag;
+extern int errs;
+extern int aflag;
ADDED cc8/cross/defs.h
Index: cc8/cross/defs.h
==================================================================
--- /dev/null
+++ cc8/cross/defs.h
@@ -0,0 +1,126 @@
+/* File defs.h: 2.1 (83/03/21,02:07:20) */
+
+
+#define FOREVER for(;;)
+#define FALSE 0
+#define TRUE 1
+#define NO 0
+#define YES 1
+
+/* miscellaneous */
+
+#define EOS 0
+#define EOL 10
+#define BKSP 8
+#define CR 13
+#define FFEED 12
+#define TAB 9
+
+/* symbol table parameters */
+
+#define SYMSIZ 14
+#define SYMTBSZ 2800
+#define NUMGLBS 150
+#define STARTGLB symtab
+#define ENDGLB (STARTGLB+NUMGLBS*SYMSIZ)
+#define STARTLOC (ENDGLB+SYMSIZ)
+#define ENDLOC (symtab+SYMTBSZ-SYMSIZ)
+
+/* symbol table entry format */
+
+#define NAME 0
+#define IDENT 9
+#define TYPE 10
+#define STORAGE 11
+#define OFFSET 12
+
+/* system-wide name size (for symbols) */
+
+#define NAMESIZE 20
+#define NAMEMAX 20
+
+/* possible entries for "ident" */
+
+#define VARIABLE 1
+#define ARRAY 2
+#define POINTER 3
+#define FUNCTION 4
+
+/* possible entries for "type" */
+
+#define CCHAR 1
+#define CINT 2
+
+/* possible entries for storage */
+
+#define PUBLIC 1
+#define AUTO 2
+#define EXTERN 3
+
+#define STATIC 4
+#define LSTATIC 5
+#define DEFAUTO 6
+/* "do"/"for"/"while"/"switch" statement stack */
+
+#define WSTABSZ 100
+#define WSSIZ 7
+#define WSMAX ws+WSTABSZ-WSSIZ
+
+/* entry offsets in "do"/"for"/"while"/"switch" stack */
+
+#define WSSYM 0
+#define WSSP 1
+#define WSTYP 2
+#define WSCASEP 3
+#define WSTEST 3
+#define WSINCR 4
+#define WSDEF 4
+#define WSBODY 5
+#define WSTAB 5
+#define WSEXIT 6
+
+/* possible entries for "wstyp" */
+
+#define WSWHILE 0
+#define WSFOR 1
+#define WSDO 2
+#define WSSWITCH 3
+
+/* "switch" label stack */
+
+#define SWSTSZ 100
+
+/* literal pool */
+
+#define LITABSZ 2000
+#define LITMAX LITABSZ-1
+
+/* input line */
+
+#define LINESIZE 200
+#define LINEMAX (LINESIZE-1)
+#define MPMAX LINEMAX
+
+/* macro (define) pool */
+
+#define MACQSIZE 1000
+#define MACMAX (MACQSIZE-1)
+
+/* "include" stack */
+
+#define INCLSIZ 3
+
+/* statement types (tokens) */
+
+#define STIF 1
+#define STWHILE 2
+#define STRETURN 3
+#define STBREAK 4
+#define STCONT 5
+#define STASM 6
+#define STEXP 7
+#define STDO 8
+#define STFOR 9
+#define STSWITCH 10
+
+#define DEFLIB inclib()
ADDED cc8/cross/error.c
Index: cc8/cross/error.c
==================================================================
--- /dev/null
+++ cc8/cross/error.c
@@ -0,0 +1,43 @@
+/* File error.c: 2.1 (83/03/20,16:02:00) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+error (ptr)
+char ptr[];
+{
+ FILE *tempfile;
+
+ tempfile = output;
+ output = stdout;
+ doerror(ptr);
+ output = tempfile;
+ doerror(ptr);
+ errcnt++;
+}
+doerror(ptr) char *ptr; {
+ int k;
+ comment ();
+ outstr (line);
+ nl ();
+ comment ();
+ k = 0;
+ while (k < lptr) {
+ if (line[k] == 9)
+ tab ();
+ else
+ outbyte (' ');
+ k++;
+ }
+ outbyte ('^');
+ nl ();
+ comment ();
+ outstr ("****** ");
+ outstr (ptr);
+ outstr (" ******");
+ nl ();
+}
ADDED cc8/cross/expr.c
Index: cc8/cross/expr.c
==================================================================
--- /dev/null
+++ cc8/cross/expr.c
@@ -0,0 +1,615 @@
+/* File expr.c: 2.2 (83/06/21,11:24:26) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * lval[0] - symbol table address, else 0 for constant
+ * lval[1] - type indirect object to fetch, else 0 for static object
+ * lval[2] - type pointer or array, else 0
+ */
+
+expression (comma)
+int comma;
+{
+ int lval[3];
+
+ do {
+ if (heir1 (lval))
+ rvalue (lval);
+ if (!comma)
+ return 0;
+ } while (match (","));
+}
+
+heir1 (lval)
+int lval[];
+{
+ int k, lval2[3];
+ char fc;
+
+ k = heir1a (lval);
+ if (match ("=")) {
+ if (k == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval[1])
+ gpush ();
+ if (heir1 (lval2))
+ rvalue (lval2);
+ store (lval);
+ return (0);
+ } else
+ {
+ fc = ch();
+ if (match ("-=") ||
+ match ("+=") ||
+ match ("*=") ||
+ match ("/=") ||
+ match ("%=") ||
+ match (">>=") ||
+ match ("<<=") ||
+ match ("&=") ||
+ match ("^=") ||
+ match ("|=")) {
+ if (k == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval[1])
+ gpush ();
+ rvalue (lval);
+ gpush ();
+ if (heir1 (lval2))
+ rvalue (lval2);
+ switch (fc) {
+ case '-': {
+ if (dbltest(lval,lval2))
+ gaslint();
+ gsub();
+ result (lval, lval2);
+ break;
+ }
+ case '+': {
+ if (dbltest(lval,lval2))
+ gaslint();
+ gadd (lval,lval2);
+ result(lval,lval2);
+ break;
+ }
+ case '*': gmult (); break;
+ case '/': gdiv (); break;
+ case '%': gmod (); break;
+ case '>': gasr (); break;
+ case '<': gasl (); break;
+ case '&': gand (); break;
+ case '^': gxor (); break;
+ case '|': gor (); break;
+ }
+ store (lval);
+ return (0);
+ } else
+ return (k);
+ }
+}
+
+heir1a (lval)
+int lval[];
+{
+ int k, lval2[3], lab1, lab2;
+
+ k = heir1b (lval);
+ blanks ();
+ if (ch () != '?')
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER
+ if (match ("?")) {
+ testjump (lab1 = getlabel (), FALSE);
+ if (heir1b (lval2))
+ rvalue (lval2);
+ jump (lab2 = getlabel ());
+ printlabel (lab1);
+ col ();
+ nl ();
+ blanks ();
+ if (!match (":")) {
+ error ("missing colon");
+ return (0);
+ }
+ if (heir1b (lval2))
+ rvalue (lval2);
+ printlabel (lab2);
+ col ();
+ nl ();
+ } else
+ return (0);
+}
+
+heir1b (lval)
+int lval[];
+{
+ int k, lval2[3], lab;
+
+ k = heir1c (lval);
+ blanks ();
+ if (!sstreq ("||"))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER
+ if (match ("||")) {
+ testjump (lab = getlabel (), TRUE);
+ if (heir1c (lval2))
+ rvalue (lval2);
+ printlabel (lab);
+ col ();
+ nl ();
+ gbool();
+ } else
+ return (0);
+}
+
+heir1c (lval)
+int lval[];
+{
+ int k, lval2[3], lab;
+
+ k = heir2 (lval);
+ blanks ();
+ if (!sstreq ("&&"))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER
+ if (match ("&&")) {
+ testjump (lab = getlabel (), FALSE);
+ if (heir2 (lval2))
+ rvalue (lval2);
+ printlabel (lab);
+ col ();
+ nl ();
+ gbool();
+ } else
+ return (0);
+}
+
+heir2 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir3 (lval);
+ blanks ();
+ if ((ch() != '|') | (nch() == '|') | (nch() == '='))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if ((ch() == '|') & (nch() != '|') & (nch() != '=')) {
+ inbyte ();
+ gpush ();
+ if (heir3 (lval2))
+ rvalue (lval2);
+ gor ();
+ blanks();
+ } else
+ return (0);
+ }
+}
+
+heir3 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir4 (lval);
+ blanks ();
+ if ((ch () != '^') | (nch() == '='))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if ((ch() == '^') & (nch() != '=')){
+ inbyte ();
+ gpush ();
+ if (heir4 (lval2))
+ rvalue (lval2);
+ gxor ();
+ blanks();
+ } else
+ return (0);
+ }
+}
+
+heir4 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir5 (lval);
+ blanks ();
+ if ((ch() != '&') | (nch() == '|') | (nch() == '='))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if ((ch() == '&') & (nch() != '&') & (nch() != '=')) {
+ inbyte ();
+ gpush ();
+ if (heir5 (lval2))
+ rvalue (lval2);
+ gand ();
+ blanks();
+ } else
+ return (0);
+ }
+}
+
+heir5 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir6 (lval);
+ blanks ();
+ if (!sstreq ("==") &
+ !sstreq ("!="))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if (match ("==")) {
+ gpush ();
+ if (heir6 (lval2))
+ rvalue (lval2);
+ geq ();
+ } else if (match ("!=")) {
+ gpush ();
+ if (heir6 (lval2))
+ rvalue (lval2);
+ gne ();
+ } else
+ return (0);
+ }
+}
+
+heir6 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir7 (lval);
+ blanks ();
+ if (!sstreq ("<") &&
+ !sstreq ("<=") &&
+ !sstreq (">=") &&
+ !sstreq (">"))
+ return (k);
+ if (sstreq ("<<") || sstreq (">>"))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if (match ("<=")) {
+ gpush ();
+ if (heir7 (lval2))
+ rvalue (lval2);
+ if (lval[2] || lval2[2]) {
+ gule ();
+ continue;
+ }
+ gle ();
+ } else if (match (">=")) {
+ gpush ();
+ if (heir7 (lval2))
+ rvalue (lval2);
+ if (lval[2] || lval2[2]) {
+ guge ();
+ continue;
+ }
+ gge ();
+ } else if ((sstreq ("<")) &&
+ !sstreq ("<<")) {
+ inbyte ();
+ gpush ();
+ if (heir7 (lval2))
+ rvalue (lval2);
+ if (lval[2] || lval2[2]) {
+ gult ();
+ continue;
+ }
+ glt ();
+ } else if ((sstreq (">")) &&
+ !sstreq (">>")) {
+ inbyte ();
+ gpush ();
+ if (heir7 (lval2))
+ rvalue (lval2);
+ if (lval[2] || lval2[2]) {
+ gugt ();
+ continue;
+ }
+ ggt ();
+ } else
+ return (0);
+ blanks ();
+ }
+}
+
+heir7 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir8 (lval);
+ blanks ();
+ if (!sstreq (">>") &&
+ !sstreq ("<<") || sstreq(">>=") || sstreq("<<="))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if (sstreq(">>") && ! sstreq(">>=")) {
+ inbyte(); inbyte();
+ gpush ();
+ if (heir8 (lval2))
+ rvalue (lval2);
+ gasr ();
+ } else if (sstreq("<<") && ! sstreq("<<=")) {
+ inbyte(); inbyte();
+ gpush ();
+ if (heir8 (lval2))
+ rvalue (lval2);
+ gasl ();
+ } else
+ return (0);
+ blanks();
+ }
+}
+
+heir8 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir9 (lval);
+ blanks ();
+ if ((ch () != '+') & (ch () != '-') | nch() == '=')
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if (match ("+")) {
+ gpush ();
+ if (heir9 (lval2))
+ rvalue (lval2);
+ /* if left is pointer and right is int, scale right */
+ if (dbltest (lval, lval2))
+ gaslint ();
+ /* will scale left if right int pointer and left int */
+ gadd (lval,lval2);
+ result (lval, lval2);
+ } else if (match ("-")) {
+ gpush ();
+ if (heir9 (lval2))
+ rvalue (lval2);
+ /* if dbl, can only be: pointer - int, or
+ pointer - pointer, thus,
+ in first case, int is scaled up,
+ in second, result is scaled down. */
+ if (dbltest (lval, lval2))
+ gaslint ();
+ gsub ();
+ /* if both pointers, scale result */
+ if ((lval[2] == CINT) && (lval2[2] == CINT)) {
+ gasrint(); /* divide by intsize */
+ }
+ result (lval, lval2);
+ } else
+ return (0);
+ }
+}
+
+heir9 (lval)
+int lval[];
+{
+ int k, lval2[3];
+
+ k = heir10 (lval);
+ blanks ();
+ if (((ch () != '*') && (ch () != '/') &&
+ (ch () != '%')) || (nch() == '='))
+ return (k);
+ if (k)
+ rvalue (lval);
+ FOREVER {
+ if (match ("*")) {
+ gpush ();
+ if (heir10 (lval2))
+ rvalue (lval2);
+ gmult ();
+ } else if (match ("/")) {
+ gpush ();
+ if (heir10 (lval2))
+ rvalue (lval2);
+ gdiv ();
+ } else if (match ("%")) {
+ gpush ();
+ if (heir10 (lval2))
+ rvalue (lval2);
+ gmod ();
+ } else
+ return (0);
+ }
+}
+
+heir10 (lval)
+int lval[];
+{
+ int k;
+ unsigned char *ptr;
+
+ if (match ("++")) {
+ if ((k = heir10 (lval)) == 0) {
+ needlval ();
+ return (0);
+ }
+// if (lval[1])
+// gpush ();
+ rivalue (lval);
+// ginc (lval);
+// store (lval);
+ return (0);
+ } else if (match ("--")) {
+ if ((k = heir10 (lval)) == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval[1])
+ gpush ();
+ rvalue (lval);
+ gdec (lval);
+ store (lval);
+ return (0);
+ } else if (match ("-")) {
+ k = heir10 (lval);
+ if (k)
+ rvalue (lval);
+ gneg ();
+ return (0);
+ } else if (match ("~")) {
+ k = heir10 (lval);
+ if (k)
+ rvalue (lval);
+ gcom ();
+ return (0);
+ } else if (match ("!")) {
+ k = heir10 (lval);
+ if (k)
+ rvalue (lval);
+ glneg ();
+ return (0);
+ } else if (ch()=='*' && nch() != '=') {
+ inbyte();
+ k = heir10 (lval);
+ if (k)
+ rvalue (lval);
+ if (ptr = lval[0])
+ lval[1] = ptr[TYPE];
+ else
+ lval[1] = CINT;
+ lval[2] = 0; /* flag as not pointer or array */
+ return (1);
+ } else if (ch()=='&' && nch()!='&' && nch()!='=') {
+ inbyte();
+ k = heir10 (lval);
+ if (k == 0) {
+ error ("illegal address");
+ return (0);
+ }
+ ptr = lval[0];
+ lval[2] = ptr[TYPE];
+ if (lval[1])
+ return (0);
+ /* global and non-array */
+ immed ();
+ k=128+ptr[OFFSET]+ptr[OFFSET+1]*256;
+ onum(k);
+ ot("\t/Offset from stackbase at 128 (200(8))");
+ nl ();
+ lval[1] = ptr[TYPE];
+ return (0);
+ } else {
+ k = heir11 (lval);
+ if (match ("++")) {
+ if (k == 0) {
+ needlval ();
+ return (0);
+ }
+// if (lval[1])
+// gpush ();
+ rvalue (lval);
+ gisz (lval);
+// ginc (lval);
+// store (lval);
+// gdec (lval);
+ return (0);
+ } else if (match ("--")) {
+ if (k == 0) {
+ needlval ();
+ return (0);
+ }
+ if (lval[1])
+ gpush ();
+ rvalue (lval);
+ gdec (lval);
+ store (lval);
+ ginc (lval);
+ return (0);
+ } else
+ return (k);
+ }
+}
+
+heir11 (lval)
+int *lval;
+{
+ int k;
+ char *ptr;
+
+ k = primary (lval);
+ ptr = lval[0];
+ blanks ();
+ if ((ch () == '[') | (ch () == '('))
+ FOREVER {
+ if (match ("[")) {
+ if (ptr == 0) {
+ error ("can't subscript");
+ junk ();
+ needbrack ("]");
+ return (0);
+ } else if (ptr[IDENT] == POINTER)
+ rvalue (lval);
+ else if (ptr[IDENT] != ARRAY) {
+ error ("can't subscript");
+ k = 0;
+ }
+ gpush ();
+ expression (YES);
+ needbrack ("]");
+ if (ptr[TYPE] == CINT)
+ gaslint ();
+ gadd (NULL,NULL);
+ lval[0] = 0;
+ lval[1] = ptr[TYPE];
+ k = 1;
+ } else if (match ("(")) {
+ if (ptr == 0)
+ callfunction (0);
+ else if (ptr[IDENT] != FUNCTION) {
+ rvalue (lval);
+ callfunction (0);
+ } else
+ callfunction (ptr);
+ k = lval[0] = 0;
+ } else
+ return (k);
+ }
+ if (ptr == 0)
+ return (k);
+ if (ptr[IDENT] == FUNCTION) {
+ immed ();
+ prefix ();
+ outstr (ptr);
+ nl ();
+ return (0);
+ }
+ return (k);
+}
ADDED cc8/cross/function.c
Index: cc8/cross/function.c
==================================================================
--- /dev/null
+++ cc8/cross/function.c
@@ -0,0 +1,164 @@
+/* File function.c: 2.1 (83/03/20,16:02:04) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * begin a function
+ *
+ * called from "parse", this routine tries to make a function out
+ * of what follows
+ * modified version. p.l. woods
+ *
+ */
+int argtop;
+newfunc ()
+{
+ char n[NAMESIZE], *ptr, rtn[NAMESIZE];
+ fexitlab = getlabel();
+
+ if (!symname (n) ) {
+ error ("illegal function or declaration");
+ kill ();
+ return 0;
+ }
+ if (ptr = findglb (n)) {
+ if (ptr[IDENT] != FUNCTION)
+ multidef (n);
+ else if (ptr[OFFSET] == FUNCTION)
+ multidef (n);
+ else
+ ptr[OFFSET] = FUNCTION;
+ } else
+ addglb (n, FUNCTION, CINT, 0, PUBLIC); // Do not allocate any storage to global functions
+ if (!match ("("))
+ error ("missing open paren");
+ prefix ();
+ if (astreq(n,"main",4)) {
+ if (inbreak) {
+ ol("\tEND");
+ output=bfile;
+ }
+ outstr("xmain");
+ }
+ else outstr (n);
+ strcpy(rtn,n);
+ col ();
+// outstr("\t0");
+ nl ();
+ if (inbreak) {
+ ol("\tCLA CLL");
+ ol("\tCALL 2,PGINIT");
+ ol("\tARG STKP");
+ ol("\tARG GBL");
+ }
+ prologue (rtn);
+ locptr = STARTLOC;
+ argstk = 0;
+ while (!match (")")) {
+ if (symname (n)) {
+ if (findloc (n))
+ multidef (n);
+ else {
+ addloc (n, 0, 0, argstk, AUTO);
+ argstk = argstk + intsize();
+ }
+ } else {
+ error ("illegal argument name");
+ junk ();
+ }
+ blanks ();
+ if (!streq (line + lptr, ")")) {
+ if (!match (","))
+ error ("expected comma");
+ }
+ if (endst ())
+ break;
+ }
+ stkp = 0;
+ argtop = argstk;
+ while (argstk) {
+ if (amatch ("register", 8)) {
+ if (amatch("char", 4))
+ getarg(CCHAR);
+ else if (amatch ("int", 3))
+ getarg(CINT);
+ else
+ getarg(CINT);
+ ns();
+ } else if (amatch ("char", 4)) {
+ getarg (CCHAR);
+ ns ();
+ } else if (amatch ("int", 3)) {
+ getarg (CINT);
+ ns ();
+ } else {
+ error ("wrong number args");
+ break;
+ }
+ }
+ statement(YES);
+ printlabel(fexitlab);
+ col();
+ nl();
+ if (astreq(n,"main",4)) /* On exit from main pop literal table as well */
+ modstk(0);
+ else
+ modstk (0);
+ gret (rtn);
+ stkp = 0;
+ locptr = STARTLOC;
+}
+
+/*
+ * declare argument types
+ *
+ * called from "newfunc", this routine add an entry in the local
+ * symbol table for each named argument
+ * completely rewritten version. p.l. woods
+ *
+ */
+getarg (t)
+int t;
+{
+ int j, legalname, address;
+ char n[NAMESIZE], c, *argptr;
+
+ FOREVER {
+ if (argstk == 0)
+ return 0;
+ if (match ("*"))
+ j = POINTER;
+ else
+ j = VARIABLE;
+ if (!(legalname = symname (n)))
+ illname ();
+ if (match ("[")) {
+ while (inbyte () != ']')
+ if (endst ())
+ break;
+ j = POINTER;
+ }
+ if (legalname) {
+ if (argptr = findloc (n)) {
+ argptr[IDENT] = j;
+ argptr[TYPE] = t;
+ address = argtop - glint(argptr);
+ if (t == CCHAR && j == VARIABLE)
+ address = address + byteoff();
+ argptr[OFFSET] = (address) & 0xff;
+ argptr[OFFSET + 1] = (address >> 8) & 0xff;
+ } else
+ error ("expecting argument name");
+ }
+ argstk = argstk - intsize();
+ if (endst ())
+ return 0;
+ if (!match (","))
+ error ("expected comma");
+ }
+}
ADDED cc8/cross/gen.c
Index: cc8/cross/gen.c
==================================================================
--- /dev/null
+++ cc8/cross/gen.c
@@ -0,0 +1,159 @@
+/* File gen.c: 2.1 (83/03/20,16:02:06) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/* ToUpper routine */
+
+ ucase(ch)
+ int ch;
+ {
+ if ('a'>ch || ch>'z') return(ch);
+ return(ch-32);
+ }
+/*
+ * return next available internal label number
+ *
+ */
+getlabel ()
+{
+ return (nxtlab++);
+}
+
+/*
+ * print specified number as label
+ */
+printlabel (label)
+int label;
+{
+ olprfix ();
+ outdec (label);
+}
+
+/*
+ * glabel - generate label
+ */
+glabel (lab)
+char *lab;
+{
+ prefix ();
+ outstr (lab);
+ col ();
+ nl ();
+}
+
+/*
+ * gnlabel - generate numeric label
+ */
+gnlabel (nlab)
+int nlab;
+{
+ printlabel (nlab);
+ col ();
+ nl ();
+}
+
+outbyte (c)
+char c;
+{
+ if (c == 0)
+ return (0);
+ fputc (c, output);
+ return (c);
+}
+
+outstr (ptr)
+char ptr[];
+{
+ int k;
+
+ k = 0;
+ while (outbyte (ucase(ptr[k++])));
+}
+
+
+tab ()
+{
+ outbyte (9);
+}
+
+ol (ptr)
+char ptr[];
+{
+ ot (ptr);
+ nl ();
+}
+
+ot (ptr)
+char ptr[];
+{
+ outstr (ptr);
+}
+
+outdec (number)
+int number;
+{
+ int k, zs;
+ char c;
+
+ if (number == -32768) {
+ outstr ("-32768");
+ return 0;
+ }
+ zs = 0;
+ k = 10000;
+ if (number < 0) {
+ number = (-number);
+ outbyte ('-');
+ }
+ while (k >= 1) {
+ c = number / k + '0';
+ if ((c != '0' | (k == 1) | zs)) {
+ zs = 1;
+ outbyte (c);
+ }
+ number = number % k;
+ k = k / 10;
+ }
+}
+
+store (lval)
+int *lval;
+{
+ if (lval[1] == 0)
+ putmem (lval[0]);
+ else
+ putstk (lval[1]);
+}
+
+rvalue (lval)
+int *lval;
+{
+ if ((lval[0] != 0) & (lval[1] == 0))
+ getmem (lval[0]);
+ else
+ indirect (lval[1]);
+}
+
+rivalue (lval)
+int *lval;
+{
+ if ((lval[0] != 0) & (lval[1] == 0))
+ getincmem (lval[0]);
+ else
+ incdirect (lval[1]);
+}
+
+test (label, ft)
+int label,
+ ft;
+{
+ needbrack ("(");
+ expression (YES);
+ needbrack (")");
+ testjump (label, ft);
+}
ADDED cc8/cross/io.c
Index: cc8/cross/io.c
==================================================================
--- /dev/null
+++ cc8/cross/io.c
@@ -0,0 +1,176 @@
+/* File io.c: 2.1 (83/03/20,16:02:07) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * open input file
+ */
+openin (p) char *p;
+{
+ strcpy(fname, p);
+ fixname (fname);
+ if (!checkname (fname))
+ return (NO);
+ if ((input = fopen (fname, "r")) == NULL) {
+ pl ("Open failure\n");
+ return (NO);
+ }
+ kill ();
+ return (YES);
+}
+
+/*
+ * open output file
+ */
+openout ()
+{
+ outfname (fname);
+ if ((output = fopen (fname, "w")) == NULL) {
+ pl ("Open failure");
+ return (NO);
+ }
+ kill ();
+ return (YES);
+}
+
+/*
+ * change input filename to output filename
+ */
+outfname (s)
+char *s;
+{
+ while (*s)
+ s++;
+ *--s = 's';
+}
+
+/*
+ * remove NL from filenames
+ *
+ */
+fixname (s)
+char *s;
+{
+ while (*s && *s++ != EOL);
+ if (!*s) return 0;
+ *(--s) = 0;
+}
+
+/*
+ * check that filename is "*.c"
+ */
+checkname (s)
+char *s;
+{
+ while (*s)
+ s++;
+ if (*--s != 'c')
+ return (NO);
+ if (*--s != '.')
+ return (NO);
+ return (YES);
+}
+
+kill ()
+{
+ lptr = 0;
+ line[lptr] = 0;
+}
+
+inln ()
+{
+ int k;
+ FILE *unit;
+
+ FOREVER {
+ if (feof (input))
+ return 0;
+ if ((unit = input2) == NULL)
+ unit = input;
+ kill ();
+ while ((k = fgetc (unit)) != EOF) {
+ if ((k == EOL) | (lptr >= LINEMAX))
+ break;
+ if (k != 13) line[lptr++] = k;
+ }
+ line[lptr] = 0;
+ if (output && cmode) {
+ outstr("/\t");
+ ol(line);
+ }
+ if (k <= 0)
+ if (input2 != NULL) {
+ input2 = inclstk[--inclsp];
+ fclose (unit);
+ }
+ if (lptr) {
+ if ((ctext) & (cmode)) {
+ comment ();
+ outstr (line);
+ nl ();
+ }
+ lptr = 0;
+ return 0;
+ }
+ }
+}
+
+inbyte ()
+{
+ while (ch () == 0) {
+ if (feof (input))
+ return (0);
+ preprocess ();
+ }
+ return (gch ());
+}
+
+inchar ()
+{
+ if (ch () == 0)
+ inln ();
+ if (feof (input))
+ return (0);
+ return (gch ());
+}
+
+gch ()
+{
+ if (ch () == 0)
+ return (0);
+ else
+ return (line[lptr++] & 127);
+}
+
+nch ()
+{
+ if (ch () == 0)
+ return (0);
+ else
+ return (line[lptr + 1] & 127);
+}
+
+ch ()
+{
+ return (line[lptr] & 127);
+}
+
+/*
+ * print a carriage return and a string only to console
+ *
+ */
+pl (str)
+char *str;
+{
+ int k;
+
+ k = 0;
+ putchar (EOL);
+ while (str[k])
+ putchar (str[k++]);
+}
ADDED cc8/cross/lex.c
Index: cc8/cross/lex.c
==================================================================
--- /dev/null
+++ cc8/cross/lex.c
@@ -0,0 +1,172 @@
+/* File lex.c: 2.1 (83/03/20,16:02:09) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * semicolon enforcer
+ *
+ * called whenever syntax requires a semicolon
+ *
+ */
+ns ()
+{
+ if (!match (";"))
+ error ("missing semicolon");
+}
+
+junk ()
+{
+ if (an (inbyte ()))
+ while (an (ch ()))
+ gch ();
+ else
+ while (an (ch ())) {
+ if (ch () == 0)
+ break;
+ gch ();
+ }
+ blanks ();
+}
+
+endst ()
+{
+ blanks ();
+ return ((streq (line + lptr, ";") | (ch () == 0)));
+}
+
+needbrack (str)
+char *str;
+{
+ if (!match (str)) {
+ error ("missing bracket");
+ comment ();
+ outstr (str);
+ nl ();
+ }
+}
+
+/*
+ * test if given character is alpha
+ *
+ */
+alpha (c)
+char c;
+{
+ c = c & 127;
+ return (((c >= 'a') & (c <= 'z')) |
+ ((c >= 'A') & (c <= 'Z')) |
+ (c == '_'));
+}
+
+/*
+ * test if given character is numeric
+ *
+ */
+numeric (c)
+char c;
+{
+ c = c & 127;
+ return ((c >= '0') & (c <= '9'));
+}
+
+/*
+ * test if given character is alphanumeric
+ *
+ */
+an (c)
+char c;
+{
+ return ((alpha (c)) | (numeric (c)));
+}
+
+sstreq (str1) char *str1; {
+ return (streq(line + lptr, str1));
+}
+
+streq (str1, str2)
+char str1[], str2[];
+{
+ int k;
+
+ k = 0;
+ while (str2[k]) {
+ if ((str1[k] != str2[k]))
+ return (0);
+ k++;
+ }
+ return (k);
+}
+
+astreq (str1, str2, len)
+char str1[], str2[];
+int len;
+{
+ int k;
+
+ k = 0;
+ while (k < len) {
+ if ((str1[k] != str2[k]))
+ break;
+ if (str1[k] == 0)
+ break;
+ if (str2[k] == 0)
+ break;
+ k++;
+ }
+ if (an (str1[k]))
+ return (0);
+ if (an (str2[k]))
+ return (0);
+ return (k);
+}
+
+match (lit)
+char *lit;
+{
+ int k;
+
+ blanks ();
+ if (k = streq (line + lptr, lit)) {
+ lptr = lptr + k;
+ return (1);
+ }
+ return (0);
+}
+
+amatch (lit, len)
+char *lit;
+int len;
+{
+ int k;
+
+ blanks ();
+ if (k = astreq (line + lptr, lit, len)) {
+ lptr = lptr + k;
+ while (an (ch ()))
+ inbyte ();
+ return (1);
+ }
+ return (0);
+}
+
+blanks ()
+{
+ FOREVER {
+ while (ch () == 0) {
+ preprocess ();
+ if (feof (input))
+ break;
+ }
+ if (ch () == ' ')
+ gch ();
+ else if (ch () == 9)
+ gch ();
+ else
+ return 0;
+ }
+}
ADDED cc8/cross/main.c
Index: cc8/cross/main.c
==================================================================
--- /dev/null
+++ cc8/cross/main.c
@@ -0,0 +1,301 @@
+/* File main.c: 2.7 (84/11/28,10:14:56) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+main (argc, argv)
+int argc;
+char** argv; /* OS/8 CC8 can't cope, but bootstrapping CC8 doesn't work, either */
+{
+ char *p,*bp;
+ int smacptr;
+ macptr = 0;
+ ctext = 0;
+ argc--; argv++;
+ errs = 0;
+ aflag = 1;
+ while (p = *argv++)
+ if (*p == '-') while (*++p)
+ switch(*p) {
+ case 't': case 'T':
+ ctext = 1;
+ break;
+ case 's': case 'S':
+ sflag = 1;
+ break;
+ case 'c': case 'C':
+ cflag = 1;
+ break;
+ case 'a': case 'A':
+ aflag = 0;
+ break;
+ case 'd': case 'D':
+ bp = ++p;
+ if (!*p) usage();
+ while (*p && *p != '=') p++;
+ if (*p == '=') *p = '\t';
+ while (*p) p++;
+ p--;
+ defmac(bp);
+ break;
+ default:
+ usage();
+ }
+ else break;
+
+ smacptr = macptr;
+ if (!p)
+ usage();
+ while (p) {
+ errfile = 0;
+ if (typof(p) == 'c' || typof(p) =='C') {
+ glbptr = STARTGLB;
+ locptr = STARTLOC;
+ wsptr = ws;
+ inclsp =
+ iflevel =
+ skiplevel =
+ swstp =
+ litptr =
+ stkp =
+ errcnt =
+ ncmp =
+ lastst =
+ quote[1] =
+ gsize =
+ inbreak =
+ 0;
+ macptr = smacptr;
+ input2 = NULL;
+ quote[0] = '"';
+ cmode = 1;
+ glbflag = 1;
+ nxtlab = 0;
+ litlab = getlabel ();
+ defmac("end\tmemory");
+ rglbptr = glbptr;
+ defmac("short\tint");
+ initmac();
+ /*
+ * compiler body
+ */
+ if (!openin (p))
+ return 0;
+ if (!openout ())
+ return 0;
+ header ();
+ gtext ();
+ parse ();
+ fclose (input);
+ gdata ();
+ dumplits ();
+ dumpglbs ();
+ errorsummary ();
+ trailer ();
+ fclose (output);
+ pl ("");
+ errs = errs || errfile;
+ getchar();
+#ifndef NOASLD
+ }
+ if (!errfile && !sflag)
+ errs = errs || assemble(p);
+#else
+ } else {
+ fputs("Don't understand file ", stderr);
+ fputs(p, stderr);
+ errs = 1;
+ }
+#endif
+ p = *argv++;
+ }
+#ifndef NOASLD
+ if (!errs && !sflag && !cflag)
+ errs = errs || link();
+#endif
+ exit(errs != 0);
+ getchar();
+}
+
+FEvers()
+{
+ outstr("/\tFront End (1.0:27/1/99)");
+}
+
+usage()
+{
+ fputs("usage: sccXXXX [-tcsa] [-dSYM[=VALUE]] files\n", stderr);
+ exit(1);
+}
+
+/*
+ * process all input text
+ *
+ * at this level, only static declarations, defines, includes,
+ * and function definitions are legal.
+ *
+ */
+parse ()
+{
+ while (!feof (input)) {
+ if (amatch ("extern", 6))
+ dodcls(EXTERN);
+ else if (amatch ("static",6))
+ dodcls(STATIC);
+ else if (dodcls(PUBLIC)) ;
+ else if (match ("#asm"))
+ doasm ();
+ else if (match ("#include"))
+ doinclude ();
+ else if (match ("#define"))
+ dodefine();
+ else if (match ("#undef"))
+ doundef();
+ else
+ newfunc ();
+ blanks ();
+ }
+}
+
+/*
+ * parse top level declarations
+ */
+
+dodcls(stclass)
+int stclass; {
+ blanks();
+ if (amatch("char", 4))
+ declglb(CCHAR, stclass);
+ else if (amatch("int", 3))
+ declglb(CINT, stclass);
+ else if (stclass == PUBLIC)
+ return(0);
+ else
+ declglb(CINT, stclass);
+ ns ();
+ return(1);
+}
+
+
+/*
+ * dump the literal pool
+ */
+dumplits ()
+{
+ int j, k;
+
+/* A loc containing the size */
+ ol("\tLAP");
+ ot ("\tCPAGE ");
+ onum (2+litptr);
+ nl();
+ outbyte('L');
+ printlabel (litlab);
+ col();
+ ot("\t");
+ onum (-litptr);
+ nl();
+ if (litptr == 0)
+ return 0;
+/* Generate a loc containing the address of the literals */
+ outbyte('X');
+ printlabel (litlab);
+ col();
+ ot("\t");
+ printlabel (litlab);
+ nl();
+ printlabel (litlab);
+ col ();
+ k = 0;
+ while (k < litptr) {
+ defbyte ();
+ j = 8;
+ while (j--) {
+ onum (litq[k++] & 127);
+ if ((j == 0) | (k >= litptr)) {
+ nl ();
+ break;
+ }
+ outbyte (';');
+ }
+ }
+ ol("\tEAP");
+}
+
+/*
+ * dump all static variables
+ */
+dumpglbs ()
+{
+ int j;
+
+ if (!glbflag) {
+ ot("GBLS,\t0");
+ nl();
+ return 0;
+ }
+ cptr = rglbptr;
+ while (cptr < glbptr) {
+ if (cptr[IDENT] != FUNCTION) {
+ ppubext(cptr);
+ if (cptr[STORAGE] != EXTERN) {
+ //prefix ();
+ //outstr (cptr);
+ //col ();
+ //defstorage ();
+ j = glint(cptr);
+ if ((cptr[TYPE] == CINT) ||
+ (cptr[IDENT] == POINTER))
+ j = j * intsize();
+ //onum (j);
+ //nl ();
+ }
+ } else {
+ fpubext(cptr);
+ }
+ cptr = cptr + SYMSIZ;
+ }
+ ot("GBLS,\t");
+ onum(gsize+128); // Beginning of stack after globals
+ nl();
+}
+
+/*
+ * report errors
+ */
+errorsummary ()
+{
+ if (ncmp)
+ error ("missing closing bracket");
+ nl ();
+ comment ();
+ outdec (errcnt);
+ if (errcnt) errfile = YES;
+ outstr (" error(s) in compilation");
+ nl ();
+ comment();
+ ot("literal pool:");
+ outdec(litptr);
+ nl();
+ comment();
+ ot("global pool:");
+ outdec(glbptr-rglbptr);
+ nl();
+ comment();
+ ot("Macro pool:");
+ outdec(macptr);
+ nl();
+ pl (errcnt ? "Error(s)" : "No errors");
+}
+
+typof(s)
+char *s; {
+ s += strlen(s) - 2;
+ if (*s == '.')
+ return(*(s+1));
+ return(' ');
+}
ADDED cc8/cross/preproc.c
Index: cc8/cross/preproc.c
==================================================================
--- /dev/null
+++ cc8/cross/preproc.c
@@ -0,0 +1,345 @@
+/* File preproc.c: 2.3 (84/11/27,11:47:40) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * open an include file
+ */
+doinclude ()
+{
+ char *p;
+ FILE *inp2;
+
+ blanks ();
+ if (inp2 = fixiname ())
+ if (inclsp < INCLSIZ) {
+ inclstk[inclsp++] = input2;
+ input2 = inp2;
+ } else {
+ fclose (inp2);
+ error ("too many nested includes");
+ }
+ else {
+ error ("Could not open include file");
+ }
+ kill ();
+}
+
+/*
+ * fixiname - remove "brackets" around include file name
+ */
+fixiname ()
+{
+ char c1, c2, *p, *ibp;
+ char buf[20];
+ FILE *fp;
+ char buf2[100];
+
+ ibp = &buf[0];
+
+ if ((c1 = gch ()) != '"' && c1 != '<')
+ return (NULL);
+ for (p = line + lptr; *p ;)
+ *ibp++ = *p++;
+ c2 = *(--p);
+ if (c1 == '"' ? (c2 != '"') : (c2 != '>')) {
+ error ("incorrect delimiter");
+ return (NULL);
+ }
+ *(--ibp) = 0;
+ fp = NULL;
+ if (c1 == '<' || !(fp = fopen(buf, "r"))) {
+ strcpy(buf2, DEFLIB);
+ strcat(buf2, buf);
+ fp = fopen(buf2, "r");
+ }
+ return(fp);
+}
+
+/*
+ * "asm" pseudo-statement
+ *
+ * enters mode where assembly language statements are passed
+ * intact through parser
+ *
+ */
+doasm ()
+{
+ cmode = 0;
+ FOREVER {
+ inln ();
+ if (match ("#endasm")) {
+ ol("/\t#ENDASM");
+ break;
+ }
+ if (feof (input))
+ break;
+ outstr (line);
+ nl ();
+ }
+ kill ();
+ cmode = 1;
+}
+
+dodefine ()
+{
+ addmac();
+}
+
+doundef ()
+{
+ int mp;
+ char sname[NAMESIZE];
+
+ if (!symname(sname)) {
+ illname();
+ kill();
+ return 0;
+ }
+
+ if (mp = findmac(sname))
+ delmac(mp);
+ kill();
+}
+
+preprocess ()
+{
+ if (ifline()) return 0;
+ while (cpp());
+}
+
+doifdef (ifdef)
+int ifdef;
+{
+ char sname[NAMESIZE];
+ int k;
+
+ blanks();
+ ++iflevel;
+ if (skiplevel) return 0;
+ k = symname(sname) && findmac(sname);
+ if (k != ifdef) skiplevel = iflevel;
+}
+
+ifline()
+{
+ FOREVER {
+ inln();
+ if (feof(input)) return(1);
+ if (match("#ifdef")) {
+ doifdef(YES);
+ continue;
+ } else if (match("#ifndef")) {
+ doifdef(NO);
+ continue;
+ } else if (match("#else")) {
+ if (iflevel) {
+ if (skiplevel == iflevel) skiplevel = 0;
+ else if (skiplevel == 0) skiplevel = iflevel;
+ } else noiferr();
+ continue;
+ } else if (match("#endif")) {
+ if (iflevel) {
+ if (skiplevel == iflevel) skiplevel = 0;
+ --iflevel;
+ } else noiferr();
+ continue;
+ }
+ if (!skiplevel) return(0);
+ }
+}
+
+noiferr()
+{
+ error("no matching #if...");
+}
+
+
+cpp ()
+{
+ int k;
+ char c, sname[NAMESIZE];
+ int tog;
+ int cpped; /* non-zero if something expanded */
+
+ cpped = 0;
+ /* don't expand lines with preprocessor commands in them */
+ if (!cmode || line[0] == '#') return(0);
+
+ mptr = lptr = 0;
+ while (ch ()) {
+ if ((ch () == '/') & (nch () == '/')) {
+ inln();
+ }
+ if ((ch () == ' ') | (ch () == 9)) {
+ keepch (' ');
+ while ((ch () == ' ') | (ch () == 9))
+ gch ();
+ } else if (ch () == '"') {
+ keepch (ch ());
+ gch ();
+ while (ch () != '"') {
+ if (ch () == 0) {
+ error ("missing quote");
+ break;
+ }
+ if (ch() == '\\') keepch(gch());
+ keepch (gch ());
+ }
+ gch ();
+ keepch ('"');
+ } else if (ch () == 39) {
+ keepch (39);
+ gch ();
+ while (ch () != 39) {
+ if (ch () == 0) {
+ error ("missing apostrophe");
+ break;
+ }
+ if (ch() == '\\') keepch(gch());
+ keepch (gch ());
+ }
+ gch ();
+ keepch (39);
+ } else if ((ch () == '/') & (nch () == '*')) {
+ inchar ();
+ inchar ();
+ while ((((c = ch ()) == '*') & (nch () == '/')) == 0)
+ if (c == '$') {
+ inchar ();
+ tog = TRUE;
+ if (ch () == '-') {
+ tog = FALSE;
+ inchar ();
+ }
+ if (alpha (c = ch ())) {
+ inchar ();
+ toggle (c, tog);
+ }
+ } else {
+ if (ch () == 0)
+ inln ();
+ else
+ inchar ();
+ if (feof (input))
+ break;
+ }
+ inchar ();
+ inchar ();
+ } else if (an (ch ())) {
+ k = 0;
+ while (an (ch ())) {
+ if (k < NAMEMAX)
+ sname[k++] = ch ();
+ gch ();
+ }
+ sname[k] = 0;
+ if (k = findmac (sname)) {
+ cpped = 1;
+ while (c = macq[k++])
+ keepch (c);
+ } else {
+ k = 0;
+ while (c = sname[k++])
+ keepch (c);
+ }
+ } else
+ keepch (gch ());
+ }
+ keepch (0);
+ if (mptr >= MPMAX)
+ error ("line too long");
+ lptr = mptr = 0;
+ while (line[lptr++] = mline[mptr++]);
+ lptr = 0;
+ return(cpped);
+}
+
+keepch (c)
+char c;
+{
+ mline[mptr] = c;
+ if (mptr < MPMAX)
+ mptr++;
+ return (c);
+}
+
+defmac(s)
+char *s;
+{
+ kill();
+ strcpy(line, s);
+ addmac();
+}
+
+addmac ()
+{
+ char sname[NAMESIZE];
+ int k;
+ int mp;
+
+ if (!symname (sname)) {
+ illname ();
+ kill ();
+ return 0;
+ }
+ if (mp = findmac(sname)) {
+ error("Duplicate define");
+ delmac(mp);
+ }
+ k = 0;
+ while (putmac (sname[k++]));
+ while (ch () == ' ' | ch () == 9)
+ gch ();
+ while (putmac (gch ()));
+ if (macptr >= MACMAX)
+ error ("macro table full");
+}
+
+delmac(mp) int mp; {
+ --mp; --mp; /* step over previous null */
+ while (mp >= 0 && macq[mp]) macq[mp--] = '%';
+}
+
+
+putmac (c)
+char c;
+{
+ macq[macptr] = c;
+ if (macptr < MACMAX)
+ macptr++;
+ return (c);
+}
+
+findmac (sname)
+char *sname;
+{
+ int k;
+
+ k = 0;
+ while (k < macptr) {
+ if (astreq (sname, macq + k, NAMEMAX)) {
+ while (macq[k++]);
+ return (k);
+ }
+ while (macq[k++]);
+ while (macq[k++]);
+ }
+ return (0);
+}
+
+toggle (name, onoff)
+char name;
+int onoff;
+{
+ switch (name) {
+ case 'C':
+ ctext = onoff;
+ break;
+ }
+}
ADDED cc8/cross/primary.c
Index: cc8/cross/primary.c
==================================================================
--- /dev/null
+++ cc8/cross/primary.c
@@ -0,0 +1,317 @@
+/* File primary.c: 2.4 (84/11/27,16:26:07) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+primary (lval)
+int *lval;
+{
+ unsigned char *ptr, sname[NAMESIZE];
+ int num[1];
+ int k;
+
+ lval[2] = 0; /* clear pointer/array type */
+ if (match ("(")) {
+ k = heir1 (lval);
+ needbrack (")");
+ return (k);
+ }
+ if (amatch("sizeof", 6)) {
+ needbrack("(");
+ immed();
+ if (amatch("int", 3)) onum(intsize());
+ else if (amatch("char", 4)) onum(1);
+ else if (symname(sname)) {
+ if ((ptr = findloc(sname)) ||
+ (ptr = findglb(sname))) {
+ if (ptr[STORAGE] == LSTATIC)
+ error("sizeof local static");
+ k = glint(ptr);
+ if ((ptr[TYPE] == CINT) ||
+ (ptr[IDENT] == POINTER))
+ k *= intsize();
+ onum(k);
+ } else {
+ error("sizeof undeclared variable");
+ onum(0);
+ }
+ } else {
+ error("sizeof only on type or variable");
+ }
+ needbrack(")");
+ nl();
+ return(lval[0] = lval[1] = 0);
+ }
+ if (symname (sname)) {
+ if (ptr = findloc (sname)) {
+ getloc (ptr);
+ lval[0] = ptr;
+ lval[1] = ptr[TYPE];
+ if (ptr[IDENT] == POINTER) {
+ lval[1] = CINT;
+ lval[2] = ptr[TYPE];
+ }
+ if (ptr[IDENT] == ARRAY) {
+ lval[2] = ptr[TYPE];
+ lval[2] = 0;
+ return (0);
+ }
+ else
+ return (1);
+ }
+ if (ptr = findglb (sname))
+ if (ptr[IDENT] != FUNCTION) {
+ lval[0] = ptr;
+ lval[1] = 0;
+ if (ptr[IDENT] != ARRAY) {
+ if (ptr[IDENT] == POINTER)
+ lval[2] = ptr[TYPE];
+ return (1);
+ }
+ immed ();
+ onum(128+ptr[OFFSET]+ptr[OFFSET+1]*256);
+ ot("\t/Offset from stackbase at 128 (200(8))");
+ nl ();
+ lval[1] = lval[2] = ptr[TYPE];
+ lval[2] = 0;
+ return (0);
+ }
+ blanks ();
+ if (ch() != '(')
+ error("undeclared variable");
+ ptr = addglb (sname, FUNCTION, CINT, 0, PUBLIC);
+ lval[0] = ptr;
+ lval[1] = 0;
+ return (0);
+ }
+ if (constant (num))
+ return (lval[0] = lval[1] = 0);
+ else {
+ error ("invalid expression");
+ immed ();
+ onum (0);
+ nl ();
+ junk ();
+ return (0);
+ }
+}
+
+/*
+ * true if val1 -> int pointer or int array and val2 not pointer or array
+ */
+dbltest (val1, val2)
+int val1[], val2[];
+{
+ if (val1 == NULL)
+ return (FALSE);
+ if (val1[2] != CINT)
+ return (FALSE);
+ if (val2[2])
+ return (FALSE);
+ return (TRUE);
+}
+
+/*
+ * determine type of binary operation
+ */
+result (lval, lval2)
+int lval[],
+ lval2[];
+{
+ if (lval[2] && lval2[2])
+ lval[2] = 0;
+ else if (lval2[2]) {
+ lval[0] = lval2[0];
+ lval[1] = lval2[1];
+ lval[2] = lval2[2];
+ }
+}
+
+constant (val)
+int val[];
+{
+ if (number (val))
+ {
+ if (val[0]==0) {
+ ol("\t/ (0)");
+ cpri();
+ return (1);
+ }
+ immed ();
+ }
+ else if (pstr (val))
+ immed ();
+ else if (qstr (val)) {
+ immd2 ();
+ stkbase();
+ nl();
+/* outbyte ('+'); */
+ immd3 ();
+ } else
+ return (0);
+ onum (val[0]);
+ nl ();
+ return (1);
+}
+
+number (val)
+int val[];
+{
+ int k, minus, base;
+ char c;
+
+ k = minus = 1;
+ while (k) {
+ k = 0;
+ if (match ("+"))
+ k = 1;
+ if (match ("-")) {
+ minus = (-minus);
+ k = 1;
+ }
+ }
+ if (!numeric (c = ch ()))
+ return (0);
+ if (match ("0x") || match ("0X"))
+ while (numeric (c = ch ()) ||
+ (c >= 'a' && c <= 'f') ||
+ (c >= 'A' && c <= 'F')) {
+ inbyte ();
+ k = k * 16 +
+ (numeric (c) ? (c - '0') : ((c & 07) + 9));
+ }
+ else {
+ base = (c == '0') ? 8 : 10;
+ while (numeric (ch ())) {
+ c = inbyte ();
+ k = k * base + (c - '0');
+ }
+ }
+ if (minus < 0)
+ k = (-k);
+ val[0] = k;
+ return (1);
+}
+
+pstr (val)
+int val[];
+{
+ int k;
+ char c;
+
+ k = 0;
+ if (!match ("'"))
+ return (0);
+ while ((c = gch ()) != 39) {
+ c = (c == '\\') ? spechar(): c;
+ k = (k & 255) * 256 + (c & 255);
+ }
+ val[0] = k;
+ return (1);
+}
+
+qstr (val)
+int val[];
+{
+ char c;
+
+ if (!match (quote))
+ return (0);
+ val[0] = litptr;
+ while (ch () != '"') {
+ if (ch () == 0)
+ break;
+ if (litptr >= LITMAX) {
+ error ("string space exhausted");
+ while (!match (quote))
+ if (gch () == 0)
+ break;
+ return (1);
+ }
+ c = gch();
+ litq[litptr++] = (c == '\\') ? spechar(): c;
+ }
+ gch ();
+ litq[litptr++] = 0;
+ return (1);
+}
+
+/*
+ * decode special characters (preceeded by back slashes)
+ */
+spechar() {
+ char c;
+ c = ch();
+
+ if (c == 'n') c = EOL;
+ else if (c == 't') c = TAB;
+ else if (c == 'r') c = CR;
+ else if (c == 'f') c = FFEED;
+ else if (c == 'b') c = BKSP;
+ else if (c == '0') c = EOS;
+ else if (c == EOS) return 0;
+
+ gch();
+ return (c);
+}
+
+/*
+ * perform a function call
+ *
+ * called from "heir11", this routine will either call the named
+ * function, or if the supplied ptr is zero, will call the contents
+ * of HL
+ * NB Added section to load Acc with nargs for vararg calls
+ * NB have addded pseudo functions here as well
+ */
+callfunction (ptr)
+char *ptr;
+{
+ int nargs;
+
+ if (strcmp(ptr,"stri")==0) {
+ expression(NO);
+ stri();
+ needbrack(")");
+ return 0;
+ }
+ if (strcmp(ptr,"iinit")==0) {
+ expression(NO);
+ iinit();
+ needbrack(")");
+ return 0;
+ }
+
+ nargs = 0;
+ blanks ();
+ if (ptr == 0)
+ gpush ();
+ while (!streq (line + lptr, ")")) {
+ if (endst ())
+ break;
+ expression (NO);
+ if (ptr == 0)
+ swapstk ();
+ gpush ();
+ nargs = nargs + intsize();
+ if (!match (","))
+ break;
+ }
+ needbrack (")");
+ if (aflag)
+ gnargs(nargs / intsize());
+ if (ptr)
+ gcall (ptr,&nargs);
+ else
+ callstk ();
+ stkp = modstk (stkp + nargs);
+}
+
+needlval ()
+{
+ error ("must be lvalue");
+}
ADDED cc8/cross/stmt.c
Index: cc8/cross/stmt.c
==================================================================
--- /dev/null
+++ cc8/cross/stmt.c
@@ -0,0 +1,425 @@
+/* File stmt.c: 2.1 (83/03/20,16:02:17) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * statement parser
+ *
+ * called whenever syntax requires a statement. this routine
+ * performs that statement and returns a number telling which one
+ *
+ * 'func' is true if we require a "function_statement", which
+ * must be compound, and must contain "statement_list" (even if
+ * "declaration_list" is omitted)
+ */
+
+statement (func)
+int func;
+{
+ if ((ch () == 0) & feof (input))
+ return (0);
+ lastst = 0;
+ if (func)
+ if (match ("{")) {
+ compound (YES);
+ return (lastst);
+ } else
+ error ("function requires compound statement");
+ if (match ("{"))
+ compound (NO);
+ else
+ stst ();
+ return (lastst);
+}
+
+/*
+ * declaration
+ */
+stdecl ()
+{
+ if (amatch("register", 8))
+ doldcls(DEFAUTO);
+ else if (amatch("auto", 4))
+ doldcls(DEFAUTO);
+ else if (amatch("static", 6))
+ doldcls(LSTATIC);
+ else if (doldcls(AUTO)) ;
+ else
+ return (NO);
+ return (YES);
+}
+
+doldcls(stclass)
+int stclass;
+{
+ blanks();
+ if (amatch("char", 4))
+ declloc(CCHAR, stclass);
+ else if (amatch("int", 3))
+ declloc(CINT, stclass);
+ else if (stclass == LSTATIC || stclass == DEFAUTO)
+ declloc(CINT, stclass);
+ else
+ return(0);
+ ns();
+ return(1);
+}
+
+
+/*
+ * non-declaration statement
+ */
+stst ()
+{
+ if (amatch ("if", 2)) {
+ doif ();
+ lastst = STIF;
+ } else if (amatch ("while", 5)) {
+ dowhile ();
+ lastst = STWHILE;
+ } else if (amatch ("switch", 6)) {
+ doswitch ();
+ lastst = STSWITCH;
+ } else if (amatch ("do", 2)) {
+ dodo ();
+ ns ();
+ lastst = STDO;
+ } else if (amatch ("for", 3)) {
+ dofor ();
+ lastst = STFOR;
+ } else if (amatch ("return", 6)) {
+ doreturn ();
+ ns ();
+ lastst = STRETURN;
+ } else if (amatch ("break", 5)) {
+ dobreak ();
+ ns ();
+ lastst = STBREAK;
+ } else if (amatch ("continue", 8)) {
+ docont ();
+ ns ();
+ lastst = STCONT;
+ } else if (match (";"))
+ ;
+ else if (amatch ("case", 4)) {
+ docase ();
+ lastst = statement (NO);
+ } else if (amatch ("default", 7)) {
+ dodefault ();
+ lastst = statement (NO);
+ } else if (match ("#asm")) {
+ doasm ();
+ lastst = STASM;
+ } else if (match ("{"))
+ compound (NO);
+ else {
+ expression (YES);
+/* if (match (":")) {
+ dolabel ();
+ lastst = statement (NO);
+ } else {
+*/ ns ();
+ lastst = STEXP;
+/* }
+*/ }
+}
+
+/*
+ * compound statement
+ *
+ * allow any number of statements to fall between "{" and "}"
+ *
+ * 'func' is true if we are in a "function_statement", which
+ * must contain "statement_list"
+ */
+compound (func)
+int func;
+{
+ int decls;
+
+ decls = YES;
+ ncmp++;
+ while (!match ("}")) {
+ if (feof (input))
+ return 0;
+ if (decls) {
+ if (!stdecl ())
+ decls = NO;
+ } else
+ stst ();
+ }
+ ncmp--;
+}
+
+/*
+ * "if" statement
+ */
+doif ()
+{
+ int fstkp, flab1, flab2;
+ char *flev;
+
+ flev = locptr;
+ fstkp = stkp;
+ flab1 = getlabel ();
+ test (flab1, FALSE);
+ statement (NO);
+ stkp = modstk (fstkp);
+ locptr = flev;
+ if (!amatch ("else", 4)) {
+ gnlabel (flab1);
+ return 0;
+ }
+ jump (flab2 = getlabel ());
+ gnlabel (flab1);
+ statement (NO);
+ stkp = modstk (fstkp);
+ locptr = flev;
+ gnlabel (flab2);
+}
+
+/*
+ * "while" statement
+ */
+dowhile ()
+{
+ int ws[7];
+
+ ws[WSSYM] = locptr;
+ ws[WSSP] = stkp;
+ ws[WSTYP] = WSWHILE;
+ ws[WSTEST] = getlabel ();
+ ws[WSEXIT] = getlabel ();
+ addwhile (ws);
+ gnlabel (ws[WSTEST]);
+ test (ws[WSEXIT], FALSE);
+ statement (NO);
+ jump (ws[WSTEST]);
+ gnlabel (ws[WSEXIT]);
+ locptr = ws[WSSYM];
+ stkp = modstk (ws[WSSP]);
+ delwhile ();
+}
+
+/*
+ * "do" statement
+ */
+dodo ()
+{
+ int ws[7];
+
+ ws[WSSYM] = locptr;
+ ws[WSSP] = stkp;
+ ws[WSTYP] = WSDO;
+ ws[WSBODY] = getlabel ();
+ ws[WSTEST] = getlabel ();
+ ws[WSEXIT] = getlabel ();
+ addwhile (ws);
+ gnlabel (ws[WSBODY]);
+ statement (NO);
+ if (!match ("while")) {
+ error ("missing while");
+ return 0;
+ }
+ gnlabel (ws[WSTEST]);
+ test (ws[WSBODY], TRUE);
+ gnlabel (ws[WSEXIT]);
+ locptr = ws[WSSYM];
+ stkp = modstk (ws[WSSP]);
+ delwhile ();
+}
+
+/*
+ * "for" statement
+ */
+dofor ()
+{
+ int ws[7],
+ *pws;
+
+ ws[WSSYM] = locptr;
+ ws[WSSP] = stkp;
+ ws[WSTYP] = WSFOR;
+ ws[WSTEST] = getlabel ();
+ ws[WSINCR] = getlabel ();
+ ws[WSBODY] = getlabel ();
+ ws[WSEXIT] = getlabel ();
+ addwhile (ws);
+ pws = readwhile ();
+ needbrack ("(");
+ if (!match (";")) {
+ expression (YES);
+ ns ();
+ }
+ gnlabel (pws[WSTEST]);
+ if (!match (";")) {
+ expression (YES);
+ testjump (pws[WSBODY], TRUE);
+ jump (pws[WSEXIT]);
+ ns ();
+ } else
+ pws[WSTEST] = pws[WSBODY];
+ gnlabel (pws[WSINCR]);
+ if (!match (")")) {
+ expression (YES);
+ needbrack (")");
+ jump (pws[WSTEST]);
+ } else
+ pws[WSINCR] = pws[WSTEST];
+ gnlabel (pws[WSBODY]);
+ statement (NO);
+ jump (pws[WSINCR]);
+ gnlabel (pws[WSEXIT]);
+ locptr = pws[WSSYM];
+ stkp = modstk (pws[WSSP]);
+ delwhile ();
+}
+
+/*
+ * "switch" statement
+ */
+doswitch ()
+{
+ int ws[7];
+ int *ptr;
+
+ ws[WSSYM] = locptr;
+ ws[WSSP] = stkp;
+ ws[WSTYP] = WSSWITCH;
+ ws[WSCASEP] = swstp;
+ ws[WSTAB] = getlabel ();
+ ws[WSDEF] = ws[WSEXIT] = getlabel ();
+ addwhile (ws);
+// immed ();
+// printlabel (ws[WSTAB]);
+// nl ();
+// gpush ();
+ needbrack ("(");
+ expression (YES);
+ needbrack (")");
+// stkp = stkp + intsize(); /* '?case' will adjust the stack */
+ gjcase ();
+ jump (ws[WSTAB]);
+ statement (NO);
+ ptr = readswitch ();
+// if (ptr[WSDEF]!=ptr[WSEXIT]) jump (ptr[WSDEF]);
+ jump (ptr[WSEXIT]);
+ dumpsw (ptr);
+ gnlabel (ptr[WSEXIT]);
+ locptr = ptr[WSSYM];
+// stkp = modstk (ptr[WSSP]);
+ swstp = ptr[WSCASEP];
+ delwhile ();
+}
+
+/*
+ * "case" label
+ */
+docase ()
+{
+ int val;
+
+ val = 0;
+ if (readswitch ()) {
+ if (!number (&val))
+ if (!pstr (&val))
+ error ("bad case label");
+ addcase (val);
+ if (!match (":"))
+ error ("missing colon");
+ } else
+ error ("no active switch");
+}
+
+/*
+ * "default" label
+ */
+dodefault ()
+{
+ int *ptr,
+ lab;
+
+ if (ptr = readswitch ()) {
+ ptr[WSDEF] = lab = getlabel ();
+ gnlabel (lab);
+ if (!match (":"))
+ error ("missing colon");
+ } else
+ error ("no active switch");
+}
+
+/*
+ * "return" statement
+ */
+doreturn ()
+{
+ if (endst () == 0)
+ expression (YES);
+ jump(fexitlab);
+}
+
+/*
+ * "break" statement
+ */
+dobreak ()
+{
+ int *ptr;
+
+ if ((ptr = readwhile ()) == 0)
+ return 0;
+ modstk (ptr[WSSP]);
+ jump (ptr[WSEXIT]);
+}
+
+/*
+ * "continue" statement
+ */
+docont ()
+{
+ int *ptr;
+
+ if ((ptr = findwhile ()) == 0)
+ return 0;
+/* modstk (ptr[WSSP]); */
+ if (ptr[WSTYP] == WSFOR)
+ jump (ptr[WSINCR]);
+ else
+ jump (ptr[WSTEST]);
+}
+
+/*
+ * dump switch table
+ */
+dumpsw (ws)
+int ws[];
+{
+ int i,j;
+
+ gdata ();
+ gnlabel (ws[WSTAB]);
+ if (ws[WSCASEP] != swstp) {
+ j = ws[WSCASEP];
+ while (j < swstp) {
+ i = 4;
+ while (i--) {
+ immd3();
+ onum (swstcase[j]);
+ nl();
+ casejump();
+ jump (swstlab[j++]);
+ if ((i == 0) | (j >= swstp)) {
+ nl ();
+ break;
+ }
+ nl();
+ }
+ }
+ jump(ws[WSDEF]);
+ }
+ gtext ();
+}
ADDED cc8/cross/sym.c
Index: cc8/cross/sym.c
==================================================================
--- /dev/null
+++ cc8/cross/sym.c
@@ -0,0 +1,249 @@
+/* File sym.c: 2.1 (83/03/20,16:02:19) */
+/*% cc -O -c %
+ *
+ */
+
+#include
+#include "defs.h"
+#include "data.h"
+
+/*
+ * declare a static variable
+ */
+declglb (typ, stor)
+int typ,
+ stor;
+{
+ int k, j;
+ char sname[NAMESIZE];
+
+ FOREVER {
+ FOREVER {
+ if (endst ())
+ return 0;
+ k = 1;
+ if (match ("*"))
+ j = POINTER;
+ else
+ j = VARIABLE;
+ if (!symname (sname))
+ illname ();
+ if (findglb (sname))
+ multidef (sname);
+ if (match ("[")) {
+ k = needsub ();
+ if (k || stor == EXTERN)
+ j = ARRAY;
+ else
+ j = POINTER;
+ }
+ addglb (sname, j, typ, k, stor);
+ break;
+ }
+ if (!match (","))
+ return 0;
+ }
+}
+
+/*
+ * declare local variables
+ *
+ * works just like "declglb", but modifies machine stack and adds
+ * symbol table entry with appropriate stack offset to find it again
+ */
+declloc (typ, stclass)
+int typ, stclass;
+{
+ int k, j;
+ char sname[NAMESIZE];
+
+ FOREVER {
+ FOREVER {
+ if (endst ())
+ return 0;
+ if (match ("*"))
+ j = POINTER;
+ else
+ j = VARIABLE;
+ if (!symname (sname))
+ illname ();
+ if (findloc (sname))
+ multidef (sname);
+ if (match ("[")) {
+ k = needsub ();
+ if (k) {
+ j = ARRAY;
+ if (typ == CINT)
+ k = k * intsize();
+ } else {
+ j = POINTER;
+ k = intsize();
+ }
+ } else
+ if ((typ == CCHAR) & (j != POINTER))
+ k = 1;
+ else
+ k = intsize();
+ if (stclass != LSTATIC) {
+ k = galign(k);
+ stkp = modstk (stkp - k);
+ addloc (sname, j, typ, stkp+k-1, AUTO); /* Reversed stack for PDP8 */
+ } else
+ addloc( sname, j, typ, k, LSTATIC);
+ break;
+ }
+ if (!match (","))
+ return 0;
+ }
+}
+
+/*
+ * get required array size
+ */
+needsub ()
+{
+ int num[1];
+
+ if (match ("]"))
+ return (0);
+ if (!number (num)) {
+ error ("must be constant");
+ num[0] = 1;
+ }
+ if (num[0] < 0) {
+ error ("negative size illegal");
+ num[0] = (-num[0]);
+ }
+ needbrack ("]");
+ return (num[0]);
+}
+
+findglb (sname)
+char *sname;
+{
+ char *ptr;
+
+ ptr = STARTGLB;
+ while (ptr != glbptr) {
+ if (astreq (sname, ptr, NAMEMAX))
+ return (ptr);
+ ptr = ptr + SYMSIZ;
+ }
+ return (0);
+}
+
+findloc (sname)
+char *sname;
+{
+ char *ptr;
+
+ ptr = locptr;
+ while (ptr != STARTLOC) {
+ ptr = ptr - SYMSIZ;
+ if (astreq (sname, ptr, NAMEMAX))
+ return (ptr);
+ }
+ return (0);
+}
+
+addglb (sname, id, typ, value, stor)
+char *sname, id, typ;
+int value,
+ stor;
+{
+ char *ptr;
+
+ if (cptr = findglb (sname))
+ return (cptr);
+ if (glbptr >= ENDGLB) {
+ error ("global symbol table overflow");
+ return (0);
+ }
+ cptr = ptr = glbptr;
+ while (an (*ptr++ = *sname++));
+ cptr[IDENT] = id;
+ cptr[TYPE] = typ;
+ cptr[STORAGE] = stor;
+ cptr[OFFSET] = gsize & 0xff;
+ cptr[OFFSET+1] = (gsize >> 8) & 0xff;
+ gsize = gsize + value;
+ glbptr = glbptr + SYMSIZ;
+ return (cptr);
+}
+
+addloc (sname, id, typ, value, stclass)
+char *sname, id, typ;
+int value, stclass;
+{
+ char *ptr;
+ int k;
+
+ if (cptr = findloc (sname))
+ return (cptr);
+ if (locptr >= ENDLOC) {
+ error ("local symbol table overflow");
+ return (0);
+ }
+ cptr = ptr = locptr;
+ while (an (*ptr++ = *sname++));
+ cptr[IDENT] = id;
+ cptr[TYPE] = typ;
+ cptr[STORAGE] = stclass;
+ if (stclass == LSTATIC) {
+ gdata();
+ printlabel(k = getlabel());
+ col();
+ defstorage();
+ onum(value);
+ nl();
+ gtext();
+ value = k;
+ } else
+ value = galign(value);
+ cptr[OFFSET] = value & 0xff;
+ cptr[OFFSET+1] = (value >> 8) & 0xff;
+ locptr = locptr + SYMSIZ;
+ return (cptr);
+}
+
+/*
+ * test if next input string is legal symbol name
+ *
+ */
+symname (sname)
+char *sname;
+{
+ int k;
+ char c;
+
+ blanks ();
+ if (!alpha (ch ()))
+ return (0);
+ k = 0;
+ while (an (ch ()))
+ sname[k++] = gch ();
+ sname[k] = 0;
+ return (1);
+}
+
+illname ()
+{
+ error ("illegal symbol name");
+}
+
+multidef (sname)
+char *sname;
+{
+ error ("already defined");
+ comment ();
+ outstr (sname);
+ nl ();
+}
+
+glint(syment) char *syment; {
+ short l,u,r;
+ l = syment[OFFSET];
+ u = syment[OFFSET+1];
+ r = (l & 0xff) + ((u << 8) & ~0x00ff);
+ return (r);
+}
ADDED cc8/cross/test/README.md
Index: cc8/cross/test/README.md
==================================================================
--- /dev/null
+++ cc8/cross/test/README.md
@@ -0,0 +1,13 @@
+This directory contains a very simple BASIC interpreter that can be
+compiled using the CC8 cross-compiler to create a SABR file, which can
+be assembled under the PiDP-8/I OS/8 environment per the instructions in
+[the top-level README][/doc/trunk/cc8/README.md] file.
+
+With the native OS/8 compiler installed in a running OS/8 instance, this
+will assemble and run the BASIC interpreter:
+
+ .COMP BASIC.SB
+ .R LOADER
+ BASIC,LIBC/G
+
+And off you go...
ADDED cc8/cross/test/basic.c
Index: cc8/cross/test/basic.c
==================================================================
--- /dev/null
+++ cc8/cross/test/basic.c
@@ -0,0 +1,245 @@
+#include
+#include
+
+
+#define SMAX 10
+#define CMAX 256
+#define BMAX 64
+#define LMAX 32
+#define DMAX 32
+#define CBMX 1024
+#define LXMX 999
+
+
+int E [SMAX]; /* subroutine line number stack */
+int L [CMAX]; /* FOR loop beginning line number */
+int M [CMAX]; /* FOR loop maximum index value */
+int P [CMAX]; /* program variable value */
+char Lb[CBMX]; /* Line buffer of CBMX chars */
+int l,i,j;
+int *C; /* subroutine stack pointer */
+char B [BMAX]; /* command input buffer */
+char F [2]; /* temporary search string */
+char *m [LXMX]; /* pointers to lines of program. This is a real waste of space! */
+char *p,*q,*x,*y,*z,*s,*d;
+
+
+
+G( ) { /* get program line from buffer */
+ atoi(B,&l);
+ y=m[l];
+ if(y){
+ if(strstr(B," "))
+ strcpy(y,B);
+ else
+ y=m[l]=0;
+ return;
+ }
+ y=Lb;
+ while(*y)
+ y=y+DMAX;
+ strcpy(y,B);
+ m [l]=y;
+} /* end G */
+
+/* recursive descent parser for arithmetic/logical expressions */
+S( ) {
+ int o;
+
+ o=J( );
+ switch(*p++){
+ case '=': return o==S( );
+ break;
+ case '#': return o!=S( );
+ default: p--; return o;
+ }
+} /* end S */
+
+J( ) {
+ int o;
+
+ o=K( );
+ switch(*p++){
+ case '<': return o': return o>J( );
+ default: p--; return o;
+ }
+} /* end J */
+
+K( ) {
+ int o;
+
+ o=V( );
+ switch(*p++){
+ case '$': return o<=K( );
+ break;
+ case '!': return o>=K( );
+ default: p--; return o;
+ }
+} /* end K */
+
+V( ) {
+ int o;
+
+ o=W( );
+ switch(*p++){
+ case '+': return o+V( );
+ break;
+ case '-': return o-V( );
+ default: p--; return o;
+ }
+} /* end V */
+
+W( ) {
+ int o;
+
+ o=Y( );
+ switch(*p++){
+ case '*': return o*W( );
+ break;
+ case '/': return o/W( );
+ default: p--; return o;
+ }
+} /* end W */
+
+Y( ) {
+ int o;
+
+ if(*p=='-'){
+ p++;
+ return -Y();
+ }
+ q=p;
+ if(*p>='0'&&*p<='9'){
+ while(*p>='0'&&*p<='9')
+ p++;
+ atoi(q,&o);
+ return o;
+ }
+ if(*p=='('){
+ p++; o=S( ); p++;
+ return o;
+ }
+ return P [*p++];
+} /* end Y */
+
+bufclear()
+{
+ memset(m,0,LXMX);
+ memset(Lb,0,CBMX);
+}
+
+main( ) {
+ int tmp; /* temp var to fix bug 07Sep2005 Somos */
+
+ bufclear();
+ while(puts("Ok\r\n"),gets(B))
+ switch(*B){
+ case 'R': /* "RUN" command */
+ C=E;
+ l=1;
+ for(i=0; i" ) ) ) * p ++ = '#' , * p = ' ' ;
+ while ( ( p = strstr ( s , "<=" ) ) ) * p ++ = '$' , * p = ' ' ;
+ while ( ( p = strstr ( s , ">=" ) ) ) * p ++ = '!' , * p = ' ' ;
+ }
+ d=B;
+ j=0;
+ while(*s){
+ if(*s=='"') j++;
+ if(*s!=' '||(j&1)) *d++=*s;
+ s++;
+ }
+ *d=j=0;
+ d--; /* backup to last char in line */
+ if(B [1]!='='){
+ switch(*B){
+ case 'E': /* "END" */
+ l=-1;
+ break;
+ case 'R': /* "REM" */
+ if(B [2]!='M') l=*--C; /* "RETURN" */
+ break;
+ case 'I':
+ if(B [1]=='N'){ /* "INPUT" */
+ tmp=*d; /* save for bug fix next line 07Sep2005 Somos */
+ gets(p=B); P [tmp]=S( );
+ } else { /* "IF" */
+ *(tmp=strstr(B,"TH"))=0; /* "THEN" */
+ p=B+2;
+ if(S( )){
+ p=tmp+4; l=S( )-1;
+ }
+ }
+ break;
+ case 'P': /* "PRINT" */
+ tmp=',';
+ p=B+5;
+ while(tmp==','){
+ if(*p=='"'){
+ while(*++p!='"')
+ putc(*p);
+ p++;
+ } else {
+ printf("%d",S( ));
+ }
+ tmp=*p++;
+ putc(' ');
+ }
+ puts("\r\n");
+ break;
+ case 'G': /* "GOTO" */
+ p=B+4;
+ if(B [2]=='S'){ /* "GOSUB" */
+ *C++=l; p++;
+ }
+ l=S( )-1;
+ break;
+ case 'F': /* "FOR" */
+ *(tmp=strstr(B,"TO"))=0; /* "TO" */
+ p=B+5;
+ P [i=B [3]]=S( );
+ p=tmp+2;
+ M [i]=S( );
+ L [i]=l;
+ break;
+ case 'N': /* "NEXT" */
+ tmp=*d;
+ if(P [tmp]
+#include "defs.h"
+#include "data.h"
+
+addwhile (ptr)
+int ptr[];
+{
+ int k;
+
+ if (wsptr == WSMAX) {
+ error ("too many active whiles");
+ return 0;
+ }
+ k = 0;
+ while (k < WSSIZ)
+ *wsptr++ = ptr[k++];
+ return 0;
+}
+
+delwhile ()
+{
+ if (readwhile ())
+ wsptr = wsptr - WSSIZ;
+}
+
+int readwhile ()
+{
+ if (wsptr == ws) {
+ error ("no active do/for/while/switch");
+ return (0);
+ } else
+ return (wsptr-WSSIZ);
+}
+
+int *findwhile ()
+{
+ int *ptr;
+
+ for (ptr = wsptr; ptr != ws;) {
+ ptr = ptr - WSSIZ;
+ if (ptr[WSTYP] != WSSWITCH)
+ return (ptr);
+ }
+ error ("no active do/for/while");
+ return (0);
+}
+
+int *readswitch ()
+{
+ int *ptr;
+
+ if (ptr = (int *)readwhile ())
+ if (ptr[WSTYP] == WSSWITCH)
+ return (ptr);
+ return (0);
+}
+
+addcase (val)
+int val;
+{
+ int lab;
+
+ if (swstp == SWSTSZ)
+ error ("too many case labels");
+ else {
+ swstcase[swstp] = val;
+ swstlab[swstp++] = lab = getlabel ();
+ printlabel (lab);
+ col ();
+ nl ();
+ }
+}
ADDED cc8/include/init.pa
Index: cc8/include/init.pa
==================================================================
--- /dev/null
+++ cc8/include/init.pa
@@ -0,0 +1,100 @@
+#asm
+/
+/ PDP8/E Run time routines for Small c compiler
+/
+ABSYM POP 160
+ABSYM PSH 161
+ABSYM JLC 162
+ABSYM STKP 163
+ABSYM PTSK 164
+ABSYM POPR 165
+ABSYM PCAL 166
+ABSYM TMP 167
+ABSYM GBL 170
+ABSYM ZTMP 171
+/
+ DECIM
+/
+STK, COMMN 3840
+/
+/
+/
+ ENTRY MAIN
+MAIN, BLOCK 2
+ TAD GBLS
+ DCA STKP
+ TAD GBLS
+ DCA GBL
+ ISZ GBL / LOCAL LITERALS = STKP+1
+ TAD PVL
+ DCA PSH
+ TAD OVL
+ DCA POP
+ TAD MVL
+ DCA PTSK
+ TAD PVR
+ DCA POPR
+ TAD PVC
+ DCA PCAL
+ RIF
+ TAD (3201
+ DCA PCL1
+ TAD PCL1
+ DCA DCC0
+ JMS MCC0
+ CLA CMA
+ MQL
+ CALL 1,LIBC
+ ARG STKP
+ CALL 0,OPEN
+ JMSI PCAL
+ XMAIN
+ CALL 0,EXIT
+/
+PUSH, 0
+ CDF1
+ ISZ STKP
+ DCAI STKP
+ TADI STKP
+ JMPI PUSH
+PPOP, 0
+ CDF1
+ DCA TMP
+ TADI STKP
+ MQL
+ CMA
+ TAD STKP
+ DCA STKP
+ TAD TMP
+ JMPI PPOP
+PUTSTK, 0
+ JMSI POP
+ SWP
+ DCA JLC
+ SWP
+ DCAI JLC
+ TADI JLC
+ JMPI PUTSTK
+POPRET, JMSI POP
+ SWP
+ DCA ZTMP
+ SWP
+ JMPI ZTMP
+PCALL, 0
+ CLA CLL
+PCL1, 0
+ TADI PCALL
+ DCA ZTMP
+ TAD PCALL
+ IAC
+ JMSI PSH / PUSH RETURN
+ CLA
+ JMPI ZTMP
+PVL, PUSH
+OVL, PPOP
+MVL, PUTSTK
+SVL, STK
+PVR, POPRET
+PVC, PCALL
+/
+#endasm
ADDED cc8/include/libc.h
Index: cc8/include/libc.h
==================================================================
--- /dev/null
+++ cc8/include/libc.h
@@ -0,0 +1,41 @@
+/*
+
+
+ Libc header
+ Please note, no function declarations are made
+ so, make sure the arg lists are correct in the calling code
+
+*/
+
+#define itoa libc0
+#define puts libc1
+#define nl libc2
+#define getc libc3
+#define gets libc4
+#define atoi libc5
+#define sscanf vlibc6
+#define xinit libc7
+#define memcpy libc8
+#define kbhit libc9
+#define putc libc10
+#define strcpy libc11
+#define strcat libc12
+#define strstr libc13
+#define exit libc14
+#define isnum libc15
+#define isdigit libc15
+#define isalpha libc16
+#define sprintf vlibc17
+#define memset libc18
+#define fgetc libc19
+#define fopen libc20
+#define fputc libc21
+#define fclose libc22
+#define printf vlibc23
+#define isalnum libc24
+#define isspace libc25
+#define fprintf vlibc26
+#define fputs libc27
+#define strcmp libc28
+#define cupper libc29
+#define fgets libc30
ADDED cc8/os8/c8.c
Index: cc8/os8/c8.c
==================================================================
--- /dev/null
+++ cc8/os8/c8.c
@@ -0,0 +1,30 @@
+#include
+#include
+
+/* C pre-processor stub for PDP/8 c compiler 2017 */
+/* Ask for input file, copy to CC.CC and run CC1 */
+
+
+main()
+{
+ int bfr;
+ int fnm[10];
+
+ putc('>');
+ gets(fnm);
+ cupper(fnm);
+ fopen(fnm,"r");
+ fopen("CC.CC","w");
+ while (bfr=fgetc())
+ if (bfr!=12) /* Ignore form feed */
+ fputc(bfr);
+ fclose();
+#asm
+ CALL 1,CHAIN
+ ARG FNM
+ HLT
+FNM, TEXT "CC1@@@"
+#endasm
+
+
+}
ADDED cc8/os8/calc.c
Index: cc8/os8/calc.c
==================================================================
--- /dev/null
+++ cc8/os8/calc.c
@@ -0,0 +1,45 @@
+
+int main()
+{
+ int x,y,ans,i;
+ int choice;
+ int div;
+ int bfr[10];
+
+ ans=0;
+
+ while (1)
+ {
+ printf("DO YOU WISH TO CONTINUE (Y/N):");
+ ans=getc();
+ if (ans=='Y')
+ {
+ printf("ENTER ANY TWO NUMBERS:\r\n");
+
+ printf("ENTER THE FIRST NUMBER:");
+ gets(bfr);
+ sscanf(bfr,"%d",&x);
+
+ printf("ENTER THE SECOND NUMBER:");
+ gets(bfr);
+ sscanf(bfr,"%d",&y);
+
+ printf("SELECT THE OPERATION:\r\n");
+
+ printf("1: ADDITION\r\n");
+ printf("2: SUBTRACTION\r\n");
+ printf("3: MULTIPLICATION\r\n");
+ printf("4: DIVISION\r\n");
+
+ printf("CHOICE:");
+ gets(bfr);
+ sscanf(bfr,"%d",&choice);
+
+ if (choice==1) printf("Result:%d\r\n",x+y);
+ if (choice==2) printf("Result:%d\r\n",x-y);
+ if (choice==3) printf("Result:%d\r\n",x*y);
+ if (choice==4) printf("Result:%d\r\n",x/y);
+ }
+ break;
+}
+
ADDED cc8/os8/fib.c
Index: cc8/os8/fib.c
==================================================================
--- /dev/null
+++ cc8/os8/fib.c
@@ -0,0 +1,15 @@
+int fib(n)
+{
+ if (n < 2)
+ return n;
+ else
+ return fib(n-1)+fib(n-2);
+}
+
+
+int main()
+{
+ int i;
+ for (i=0;i<10;i++)
+ printf("Fib#:%d = %d\r\n",fib(i));
+}
ADDED cc8/os8/header.sb
Index: cc8/os8/header.sb
==================================================================
--- /dev/null
+++ cc8/os8/header.sb
@@ -0,0 +1,116 @@
+/ SABR DEFINITIONS
+/ FRONT END (2.0:1/4/2017)
+OPDEF ANDI 0400
+OPDEF TADI 1400
+OPDEF ISZI 2400
+OPDEF DCAI 3400
+OPDEF JMSI 4400
+OPDEF JMPI 5400
+OPDEF MQL 7421
+OPDEF MQA 7701
+OPDEF MQO 7501
+OPDEF SWP 7521
+OPDEF CDF1 6211
+OPDEF CDF0 6201
+OPDEF RIF 6224
+OPDEF CAF0 6203
+OPDEF BSW 7002
+OPDEF CAM 7621
+/
+/ PDP8/E Run time routines for Small c compiler
+/
+ABSYM POP 160
+ABSYM PSH 161
+ABSYM JLC 162
+ABSYM STKP 163
+ABSYM PTSK 164
+ABSYM POPR 165
+ABSYM PCAL 166
+ABSYM TMP 167
+ABSYM GBL 170
+ABSYM ZTMP 171
+/
+ DECIM
+/
+STK, COMMN 3840
+/
+/
+/
+ ENTRY MAIN
+MAIN, BLOCK 2
+ TAD GBLS
+ DCA STKP
+ TAD GBLS
+ DCA GBL
+ ISZ GBL / LOCAL LITERALS = STKP+1
+ TAD PVL
+ DCA PSH
+ TAD OVL
+ DCA POP
+ TAD MVL
+ DCA PTSK
+ TAD PVR
+ DCA POPR
+ TAD PVC
+ DCA PCAL
+ RIF
+ TAD (3201
+ DCA PCL1
+ TAD PCL1
+ DCA DCC0
+ JMS MCC0
+ CLA CMA
+ MQL
+ CALL 1,LIBC
+ ARG STKP
+ CALL 0,OPEN
+ JMSI PCAL
+ XMAIN
+ CALL 0,EXIT
+/
+PUSH, 0
+ CDF1
+ ISZ STKP
+ DCAI STKP
+ TADI STKP
+ JMPI PUSH
+PPOP, 0
+ CDF1
+ DCA TMP
+ TADI STKP
+ MQL
+ CMA
+ TAD STKP
+ DCA STKP
+ TAD TMP
+ JMPI PPOP
+PUTSTK, 0
+ JMSI POP
+ SWP
+ DCA JLC
+ SWP
+ DCAI JLC
+ TADI JLC
+ JMPI PUTSTK
+POPRET, JMSI POP
+ SWP
+ DCA ZTMP
+ SWP
+ JMPI ZTMP
+PCALL, 0
+ CLA CLL
+PCL1, 0
+ TADI PCALL
+ DCA ZTMP
+ TAD PCALL
+ IAC
+ JMSI PSH / PUSH RETURN
+ CLA
+ JMPI ZTMP
+PVL, PUSH
+OVL, PPOP
+MVL, PUTSTK
+SVL, STK
+PVR, POPRET
+PVC, PCALL
+/
ADDED cc8/os8/init.pa
Index: cc8/os8/init.pa
==================================================================
--- /dev/null
+++ cc8/os8/init.pa
@@ -0,0 +1,1 @@
+../include/init.pa
ADDED cc8/os8/libc.c
Index: cc8/os8/libc.c
==================================================================
--- /dev/null
+++ cc8/os8/libc.c
@@ -0,0 +1,964 @@
+#asm
+/
+/ PDP8/E lIBC routines for Small c compiler
+/ THIS IS A COMPLEX COLLECTION OF MIXED C AND ASSEMBLER
+/ SOME FUNCTIONS HAVE BEEN SUBSTANTIALLY SHORTENED TO SAVE SPACE
+/ EVENTUALLY, MOST WILL NEED TO BE WRITTEN IN ASSEMBLER AND HAND OPTIMISED EG ATOI
+/
+ABSYM POP 147
+ABSYM PSH 150
+ABSYM JLC 151
+ABSYM STKP 152
+ABSYM PTSK 153
+ABSYM POPR 154
+ABSYM PCAL 155
+ABSYM TMP 156
+ABSYM GBL 157
+ABSYM ZTMP 146
+ABSYM ZPTR 145
+ABSYM ZCTR 144
+ABSYM FPTR 160
+/
+ DECIM
+/
+/
+/
+/
+ DUMMY ARGST
+ DUMMY ARGNM
+ARGST, BLOCK 2
+ARGNM, BLOCK 2
+/
+ ENTRY LIBC
+LIBC, BLOCK 2
+ CLA CLL
+ TAD I LIBC
+ DCA ARGST
+ INC LIBC#
+ TAD I LIBC
+ DCA ARGST#
+ INC LIBC#
+ TAD I ARGST
+ DCA STKP
+ IAC
+ TAD LCALL / INIT ? LCALL==-1
+ SZA CLA
+ JMP LB1
+ TAD STKP
+ DCA GBL / SET LOCAL GBL(LITPTR)
+ ISZ GBL
+ TAD PVL
+ DCA PSH
+ TAD OVL
+ DCA POP
+ TAD MVL
+ DCA PTSK
+ TAD PVR
+ DCA POPR
+ TAD PVC
+ DCA PCAL
+ RIF
+ TAD (3201
+ DCA PCL1
+ TAD PCL1
+ DCA DCC0
+ JMS MCC0
+ TAD STKP
+ DCA I ARGST / UPDATE MASTER STKP
+ DCA ZPTR / INIT PRINTF FLAG
+ DCA FPTR / INIT FPRINTF FLAG
+LB1, MQA / CALL INDEX IN MQ
+ SPA
+ JMP LRET
+ TAD CPNT
+ DCA LCALL
+ TAD I LCALL
+ DCA LCALL
+ JMSI PCAL
+LCALL, -1
+ RETRN LIBC
+LRET, CLA MQL
+ DCA LCALL / INIT OK
+ RETRN LIBC
+/
+PUSH, 0
+ CDF1
+ ISZ STKP
+ DCAI STKP
+ TADI STKP
+ JMPI PUSH
+PPOP, 0
+ CDF1
+ DCA TMP
+ TADI STKP
+ MQL
+ CMA
+ TAD STKP
+ DCA STKP
+ TAD TMP
+ JMPI PPOP
+PUTSTK, 0
+ JMSI POP
+ SWP
+ DCA JLC
+ SWP
+ DCAI JLC
+ TADI JLC
+ JMPI PUTSTK
+POPRET, JMSI POP
+ SWP
+ DCA ZTMP
+ TAD STKP
+ DCA I ARGST / UPDATE MASTER STKP
+ SWP
+ CDF1
+ JMPI ZTMP
+PCALL, 0
+ CLA CLL
+PCL1, 0
+ TADI PCALL
+ DCA ZTMP
+ TAD PCALL
+ IAC
+ JMSI PSH / PUSH RETURN
+ CLA
+ TAD STKP
+ DCA I ARGST / UPDATE MASTER STKP
+ CDF1
+ JMPI ZTMP
+PVL, PUSH
+OVL, PPOP
+MVL, PUTSTK
+PVR, POPRET
+PVC, PCALL
+/
+CPNT, CLIST
+ CPAGE 24
+/
+/ THIS IS THE DISPATCH LIST FOR THIS LIBRARY
+/ MAKE SURE LIBC.H MATCHES
+/
+CLIST, ITOA
+ PUTS
+ DISPXY
+ GETC
+ GETS
+ ATOI
+ SSCANF
+ XINIT
+ MEMCPY
+ KBHIT
+ PUTC
+ STRCPY
+ STRCAT
+ STRSTR
+ EXIT
+ ISNUM
+ ISALPHA
+ SPRINTF
+ MEMSET
+ FGETC
+ FOPEN
+ FPUTC
+ FCLOSE
+ PRINTF
+ ISALNUM
+ ISSPACE
+ FPRINTF
+ FPUTS
+ STRCMP
+ CUPPER
+ FGETS
+#endasm
+
+#define stdout 0
+#define NULL 0
+#define isdigit isnum
+
+
+
+fgetc()
+{
+#asm
+
+ CLA CLL
+ CALL 2,CHRIO
+ ARG (-4
+ ARG FRSL
+ TAD FRSL
+ TAD (-26 /^Z
+ SNA CLA
+ DCA FRSL
+ TAD FRSL
+ CDF1
+ JMPI POPR
+FRSL,BLOCK 2
+
+// CHRIO - CHARACTER I/O.
+/
+/ CALL CHRIO(IDEVN,ICHAR)
+/
+/ IDEV = FORT II DEVICE NUMBER.
+/
+/ ICHAR = 7 OR 8 BIT CHARACTER.
+/
+/ IF IDEV IS POSITIVE, THE CHAR IS OUTPUTTED.
+/
+/ IF IDEV IS NEGATIVE, THE NEXT CHAR IS
+/ READ FROM THE DEVICE, AND PUT IN ICHAR.
+/
+//
+ ENTRY CHRIO
+CHRIO, BLOCK 2
+ JMS GETP
+ SPA /WHAT IS DEVICE SIGN?
+ JMP RCHAR /NEG DEV. MEANS READ.
+ JMS SETDEV /POS DEV. MEANS WRITE.
+ 0000
+ JMS GETP
+ DCA ICHAR
+ JMS CHSUB
+ JMP XIT
+
+IDEV, 0
+ICHAR, 0
+ADDR, 0
+
+RCHAR, CIA /READ A CHAR.
+ JMS SETDEV
+ 1024 /SET BIT FOR READ. (8 UNITS NOW!)
+ JMS GETP
+ CLA
+ TAD CDFB
+ DCA CDFCH
+ JMS CHSUB
+CDFCH, HLT
+ AND (127 / 7 BIT FOR NOW
+ DCAI ADDR
+XIT, CLA
+ RETRN CHRIO
+
+SETDEV, 0
+ TAD (-1
+ AND (7
+ CLL RAR;RTR;RTR
+ TAD I SETDEV
+ INC SETDEV
+ DCA IDEV
+ JMP I SETDEV
+
+CHSUB, 0
+ TAD ICHAR
+ AND (255
+ TAD IDEV
+ CALL 0,GENIO
+ JMP I CHSUB
+
+GETP, 0
+ TAD CHRIO
+ DCA CDFA
+CDFA, HLT
+ TADI CHRIO#
+ DCA CDFB
+ INC CHRIO#
+ TADI CHRIO#
+ DCA ADDR
+ INC CHRIO#
+CDFB, HLT
+ TADI ADDR
+ JMP I GETP
+#endasm
+}
+
+fputc(ch)
+int ch;
+{
+ ch;
+#asm
+ DCA FRSL
+ CALL 2,CHRIO
+ ARG (4
+ ARG FRSL
+ CDF1
+ TAD FRSL
+#endasm
+}
+ sixbit(p)
+char *p;
+{
+ *p++;
+#asm
+ AND (63
+ BSW
+ MQL
+#endasm
+ *p;
+#asm
+ AND (63
+ MQO
+#endasm
+}
+
+fputs(p)
+int *p;
+{
+ while (*p++)
+#asm
+ DCA FRSL
+ CALL 2,CHRIO
+ ARG (4
+ ARG FRSL
+ CDF1
+#endasm
+}
+
+
+fopen (fnm,flg)
+char *fnm;
+int flg;
+{
+ char *p;
+ p=fnm;
+ p=strstr(fnm,".");
+ if (p==0)
+ return(-1);
+ if (*flg=='w') {
+#asm
+ CLA
+ TAD FC1#
+ DCA FBSE#
+ JMP FC3
+FC1, CALL 0,OOPEN
+FC2, CALL 0,IOPEN
+#endasm
+ }
+ if (*flg=='r') {
+#asm
+ CLA
+ TAD FC2#
+ DCA FBSE#
+FC3, CDF1
+#endasm
+ *p++=0;
+ sixbit(p);
+#asm
+ PAGE
+ / OFFSET IOPEN+81 = FILEEX
+ DCA ZTMP
+ TAD FC2# / CODE
+ AND (63
+ TAD (128
+ DCA FDCT
+ CDF0
+ TADI FDCT
+ DCA FEX1
+ TAD FDCT
+ TAD (64
+ DCA FDCT
+ TADI FDCT
+ TAD (81 / OFFSET OF EXTENSION
+ DCA FDCT
+FEX1, HLT
+ TAD ZTMP
+ DCAI FDCT
+ CDF1
+#endasm
+ fnm;
+#asm
+ DCA ZTMP / PACK 6 8BIT CHARS INTO FILENAME
+ TAD (-3
+ DCA FDCT
+ TAD FDCA
+ DCA FP4
+FP1, CAM
+ TADI ZTMP
+ SNA
+ JMP FP2
+ AND (63
+ BSW
+ MQL
+ ISZ ZTMP
+FP2, TADI ZTMP / WILL USE STACK FIELD
+ AND (63
+ SZA
+ ISZ ZTMP
+ MQO
+FP4, DCA FFNM
+ ISZ FP4
+ ISZ FDCT
+ JMP FP1
+ TAD (46
+ DCAI ZTMP / PUT . BACK INTO FNM
+ CLA CLL CMA
+ TAD STKP
+ DCA STKP
+FBSE, CALL 2,IOPEN
+ ARG FDEV
+ ARG FFNM
+ JMPI POPR
+FDCA, DCA FFNM
+FDCT, 0
+FFNM, TEXT /TM@@@@/
+FDEV, TEXT /DSK@@@/
+#endasm
+ }
+}
+
+fclose()
+{
+#asm
+ CALL 0,OCLOS
+#endasm
+}
+
+
+puts(p)
+char *p;
+ {
+ while (*p++)
+#asm
+ TLS
+XC1, TSF
+ JMP XC1
+#endasm
+ }
+
+dispxy(x,y)
+int x,y;
+{
+ x;
+#asm
+ 3115 / DIX
+#endasm
+ y;
+#asm
+ 3116 / DIY
+ 3117 / DIL
+#endasm
+}
+
+getc()
+{
+#asm
+ CLA
+GT1, KSF
+ JMP GT1
+ KRB
+ TLS
+ AND (127 /* 7 BIT! */
+#endasm
+}
+
+gets(p)
+char *p;
+{
+int q,tm;
+ tm=1;
+ q=p;
+ while (tm) {
+#asm
+XC2, CLA CLL
+ KSF
+ JMP XC2
+ KRB
+ TAD (-255
+ CLA
+ KRB
+ SNL / DO NOT ECHO BS
+ TLS
+XC3, AND (127
+ TAD (-13 / CR IS END OF STRING -> 0
+ SZA
+ TAD (13
+ DCAI STKP
+#endasm
+ if (tm!=127)
+ *p++=tm;
+ else
+ if (p-q) {
+ puts("\b \b");
+ p--;
+ }
+ }
+ putc(10); /* newline */
+ return 1;
+}
+
+
+atoi(p,rsl)
+char *p;
+int *rsl;
+{
+#asm
+ DCA ZTMP
+ DCA ZCTR
+ TAD (3584 / NOP
+ DCA XINV
+ CDF1 / Change DF back to 1 in case SABR changes it!
+#endasm
+ while (*p==' ')
+ p++;
+ if (*p=='-') {
+#asm
+ CLA
+ TAD (3617
+ DCA XINV / CIA
+ CDF1
+#endasm
+ p++;
+ }
+ while (*p++) {
+#asm
+ TAD (-48 / '0' ... SEE CODE
+ DCA JLC
+ TAD JLC
+ SPA CLA
+ JMP XRET
+ TAD (-10
+ TAD JLC
+ SMA CLA
+ JMP XRET / EXIT IF NOT NUMBER
+ TAD ZTMP
+ CLL RTL / *4
+ TAD ZTMP / *5
+ CLL RAL / *10
+ TAD JLC
+ DCA ZTMP
+ ISZ ZCTR / CHAR COUNTER
+#endasm
+ }
+#asm
+XRET, TAD ZCTR
+ MQL
+ CMA
+ TAD STKP / ->RSL
+ DCA TMP
+ TADI TMP
+ DCA TMP
+ TAD ZTMP
+XINV, NOP
+ DCAI TMP / WRITE RSL
+ MQA / RETURN LENGTH
+#endasm
+}
+
+
+xinit()
+{
+ puts("PDP-8 C Compiler V1.0:\r\n");
+}
+
+
+memcpy(dst,src,cnt)
+int dst,src,cnt;
+{
+#asm
+ CLA
+ TAD STKP
+ TAD (-4
+ DCA 12
+ CMA
+ TADI 12
+ DCA 11
+ CMA
+ TADI 12
+ DCA 10
+ TADI 12
+ CIA
+ DCA ZTMP
+CP1, TADI 10
+ DCAI 11
+ ISZ ZTMP
+ JMP CP1
+#endasm
+
+}
+
+kbhit()
+{
+#asm
+ CLA CMA
+ KSF
+ CLA
+#endasm
+}
+
+putc(p)
+char p;
+{
+ p;
+#asm
+ TLS
+MP1, TSF
+ JMP MP1
+#endasm
+}
+
+strcmp( dm , sm )
+char *dm,*sm;
+{
+ int rsl;
+
+ rsl=0;
+ while (*dm)
+ rsl+=(*sm++-*dm++);
+ return rsl;
+}
+
+strcpy( dm , sm )
+char *dm,*sm;
+{
+ while (*dm++=*sm++);
+}
+
+strcat( dm , sm )
+char *dm,*sm;
+{
+ int qm;
+ qm=dm;
+ while(*dm) dm++;
+ strcpy(dm,sm);
+ return qm;
+}
+
+strstr ( s , o )
+char *s , *o ;
+{
+char *x , *y , *z ;
+ for ( x = s ; * x ; x ++ ) {
+ for ( y = x , z = o ; * z && * y == * z ; y ++ ) z ++ ;
+ if ( z > o && ! * z ) return x ;
+ } return 0 ;
+}
+
+exit(retval)
+int retval;
+{
+#asm
+ CALL 0,EXIT
+ HLT
+#endasm
+}
+
+isalnum(vl)
+int vl;
+{
+ return (isnum(vl) + isalpha(vl));
+}
+
+isnum(vl)
+int vl;
+{
+ vl;
+#asm
+ TAD (-48
+ SPA
+ JMP XNO
+ TAD (-10
+ SMA CLA
+XNO, CLA SKP
+ IAC
+#endasm
+}
+
+isspace(vl)
+int vl;
+{
+ vl;
+#asm
+ SNA
+ JMP YNO
+ TAD (-33
+ SMA CLA
+YNO, CLA SKP
+ IAC
+#endasm
+}
+
+
+isalpha(vl)
+int vl;
+{
+ vl; /* Include '?' and '@' as alpha vars */
+#asm
+ TAD (-65
+ SPA
+ JMP ANO
+ TAD (-26
+ SPA
+ JMP BNO
+ TAD (-6
+ SPA
+ JMP ANO
+ TAD (-26
+BNO, SMA CLA
+ANO, CLA SKP
+ IAC
+#endasm
+}
+
+cupper(p) /* In place convert to uppercase */
+int p;
+{
+ p;
+#asm
+ DCA ZTMP
+CPP1, CLA
+ TADI ZTMP
+ SNA
+ JMP CPP2
+ TAD (-97
+ SPA
+ JMP CPP3
+ TAD (-26
+ SMA
+ JMP CPP3
+ TAD (91
+ DCAI ZTMP
+CPP3, ISZ ZTMP
+ JMP CPP1
+CPP2,
+#endasm
+}
+
+/* Arbitrary fgets(). Read until LF, CR/LF are retained*/
+/* EOF returns null, else strlen(*p) */
+
+fgets(p)
+char *p;
+{
+char *q;
+ q=p;
+ while(*p=fgetc()) {
+ if (*p++==10)
+ break;
+ }
+ *p=0;
+ return (p-q);
+}
+
+memset(dst, dt, sz)
+char *dst;
+int dt,sz;
+{
+ int i;
+ for (i=0;ilen) width = width - len; else width = 0;
+ if(!left) while(width--) {*obfr++=pad; ++cc;}
+ while(len--) {*obfr++=*sptr++; ++cc; }
+ if(left) while(width--) {*obfr++=pad; ++cc;}
+ }
+ *obfr=0;
+ zptr;
+#asm
+ SNA / IF ZPTR, EITHER USE PUTS OR FPUTS
+ JMP PF1
+ JMSI PSH
+ CLA
+ TAD FPTR
+ SNA CLA
+ JMP PF2
+ JMSI PCAL
+ FPUTS
+ JMP PF3
+PF2, JMSI PCAL
+ PUTS
+PF3, JMSI POP
+PF1, CLA
+ DCA ZPTR
+ DCA FPTR
+#endasm
+
+ return(cc);
+ }
+
+/*
+** itoa(n,s) - Convert n to characters in s
+*/
+itoa(n, s) char *s; int n; {
+ int sign;
+ char *ptr;
+ ptr = s;
+ if ((sign = n) < 0) n = -n;
+ do {
+ *ptr++ = n % 10 + '0';
+ } while ((n = n / 10) > 0);
+ if (sign < 0) *ptr++ = '-';
+ *ptr = '\0';
+ reverse(s);
+ }
+
+/*
+** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
+** NOTE: This is a non-standard function.
+*/
+itoab(n, s, b) int n; char *s; int b; {
+ char *ptr;
+ int lowbit;
+ ptr = s;
+ b >>= 1;
+ do {
+ lowbit = n & 1;
+ n = (n >> 1) & 4095;
+ *ptr = ((n % b) << 1) + lowbit;
+ if(*ptr < 10) *ptr += '0'; else *ptr += 55;
+ ++ptr;
+ } while(n /= b);
+ *ptr = 0;
+ reverse (s);
+ }
+
+
+strlen(p)
+char *p;
+{
+ int n;
+
+ n=0;
+ while (*p++)
+ n++;
+ return n;
+}
+
+#define EOF 0
+
+sscanf(nxtarg) int nxtarg; {
+ char *ctl;
+ int u;
+ int *narg, wast, ac, width, ch, cnv, base, ovfl, sign, *ibfr;
+ ac = 0;
+ nxtarg = &nxtarg-nxtarg;
+ ibfr = *nxtarg++;
+ ctl = *nxtarg++;
+ while(*ctl) {
+ if(*ctl++ != '%') continue;
+ narg = *nxtarg++;
+ ctl += atoi(ctl, &width);
+ if (!width)
+ width=-1;
+ if(!(cnv = *ctl++)) break;
+ switch(cnv) {
+ case 'c':
+ *narg = *ibfr++;
+ break;
+ case 's':
+ while(width--)
+ if((*narg++ = *ibfr++) == 0) break;
+ *narg = 0;
+ break;
+ default:
+ switch(cnv) {
+ case 'b': base = 2; break;
+ case 'd': base = 10; break;
+ case 'o': base = 8; break;
+ case 'x': base = 16; break;
+ default: return (ac);
+ }
+ *narg = u = 0;
+ sign = 1;
+ while(width-- && (ch=*ibfr++)>32) {
+ if(ch == '-') {sign = -1; continue;}
+ if(ch < '0') break;
+ if(ch >= 'a') ch -= 87;
+ else if(ch >= 'A') ch -= 55;
+ else ch -= '0';
+ u = u * base + ch;
+ }
+ *narg = sign * u;
+ }
+ ++ac;
+ }
+ return (ac);
+ }
+
ADDED cc8/os8/n8.c
Index: cc8/os8/n8.c
==================================================================
--- /dev/null
+++ cc8/os8/n8.c
@@ -0,0 +1,606 @@
+
+
+#include
+#include
+
+
+#define SMAX 10
+#define CMAX 256
+#define BMAX 64
+#define LMAX 32
+#define DMAX 32
+#define CBMX 1024
+#define LXMX 999
+
+int asm[CBMX];
+int ltbf[512];
+int xlt[CMAX];
+int gm[CMAX]; /* Global symbol table */
+int tkbf[LMAX];
+int *p,*q,*s,*ltpt;
+int gsym,lsym,gadr,ladr,stkp,lctr,*fptr,gsz,ctr,tm,ectr;
+int glim,*n,ccm;
+int tmp;
+int tkn[BMAX];
+int bfr[BMAX];
+int tmbf[LMAX];
+int smbf[LMAX];
+int Lb[BMAX];
+int lm[CMAX]; /* Auto symbol table */
+int fstk[BMAX]; /* Push down stack for For etc. */
+int inproc,addr,cbrk;
+int izf,ixf,idf,ieq,ssz,icd;
+
+
+getsym()
+{
+ q=tkbf;
+ while (isspace(*p))
+ p++;
+ while (isalnum(*p))
+ *q++=*p++;
+ *q=0;
+ while (isspace(*p))
+ p++;
+ return *tkbf;
+}
+
+chkpsh()
+{
+ switch (*p) {
+ case 0:
+ case ',':
+ case ')':
+ case '=':
+ case ']':
+ case ' ':
+ return;
+ }
+ stri(19);
+ stkp++;
+}
+
+/* recursive descent parser for arithmetic/logical expressions */
+
+S( ) {
+
+ J( );
+ switch(*p++){
+ case '=':
+ S();
+ stri(1);
+ stkp--;
+ break;
+ case ']':
+ case ')':
+ return 1;
+ case ',':
+ break;
+ default:
+ p--;
+ }
+ if (ieq) {
+ ieq=0;
+ S();
+ stri(24);
+ stkp--;
+ }
+ return 0;
+} /* end S */
+
+J( ) {
+
+ K( );
+ switch(*p++){
+ case '&': J( ); stri(20); stkp--; break;
+ case '|': J( ); stri(-20); stkp--; break;
+ default: p--;
+ }
+} /* end J */
+
+K( ) {
+
+ V( );
+ switch(*p++){
+ case '<': K( ); stri(11); stkp--; break;
+ case '>': K( ); stri(-11); stkp--; break;
+ default: p--;
+ }
+} /* end K */
+
+V( ) {
+
+ W( );
+ switch(*p++){
+ case '+':
+ V();
+ stri(2);
+ stkp--;
+ break;
+ case '-': V( );
+ stri(3);
+ stkp--;
+ break;
+ default: p--;
+ }
+} /* end V */
+
+W( ) {
+
+ Y( );
+ chkpsh();
+ switch(*p++) {
+ case '*': W( ); stri(13); stkp--; break;
+ case '/': W( ); stri(14); stkp--; break;
+ default: p--;
+ }
+} /* end W */
+
+
+Y( ) {
+ int o,ctx;
+ int txbf[10];
+
+ while (*p==' ')
+ p++;
+ if (!*p)
+ return;
+
+ if (*p=='"') {
+ stri(10);
+ stri(ltpt-ltbf);
+ while (*++p!='"') {
+ if (*p=='\\')
+ switch (*++p) {
+ case 'r':
+ *p=13;
+ break;
+ case 'n':
+ *p=10;
+ }
+ *ltpt++=*p;
+ }
+ *ltpt++=0;
+ p++;
+ return;
+ }
+ n=q=p;
+ if (*p=='-')
+ p++;
+ if(isdigit(*p)) {
+ while(isdigit(*p))
+ p++;
+ stri(4);
+ atoi(q,&tmp);
+ stri(tmp);
+ return;
+ }
+ if (*p==39) {
+ stri(4);
+ stri(*++p);
+ p+=2;
+ return;
+ }
+ ixf=izf=idf=ieq=icd=0;
+ if (!getsym()) {
+ switch (*p++) {
+ case '&':
+ getsym();
+ stri(21);
+ stri(fndlcl(tkbf));
+ return;
+ case '*':
+ getsym();
+ ixf++;
+ break;
+ case '!':
+ Y();
+ stri(26);
+ return;
+ case '(':
+ S();
+ return;
+ case ')':
+ icd=1;
+ return;
+ }
+ }
+ if(*p=='('){
+ strcpy(txbf,tkbf);
+ ctx=o=0;p++;
+ while (*p && !o) {
+ o=S( );
+ if (icd)
+ break;
+ stkp++;
+ stri(19);
+ ctx++; /* arg count */
+ }
+ stri(9);
+ stri(ctx);
+ stkp-=ctx;
+ if ((o=strstr(gm,txbf))){
+ stri(o-gm);
+ }
+ else {
+ stri(gsz);
+ strpad(txbf);
+ strcat(gm,smbf);
+ gsz+=9;
+ }
+ return;
+ }
+ /* Digraphs */
+
+ q=p+1;
+ if (tmp=*q==*p)
+ switch (*p) {
+ case '+':
+ izf=-tmp;
+ p+=2;
+ break;
+ case '-':
+ idf=-tmp;
+ p+=2;
+ break;
+ case '=':
+ ieq=-tmp;
+ p=q+1;
+ break;
+ }
+
+ o=fndlcl(tkbf);
+ tmp=-17;
+ if (ssz>1) {
+ if (*p=='[') {
+ stri(21);
+ stri(o);
+ stri(19);
+ stkp++;
+ p++;S();
+ stri(2);
+ if (*p=='=')
+ stri(19);
+ else {
+ stri(22);
+ stkp--;
+ }
+ return;
+ }
+ stri(21);
+ stri(o);
+ return;
+ }
+ switch (*p) {
+ case 0:
+ case ',':
+ case ')':
+ tmp=-17;
+ break;
+ case '=':
+ tmp=8;
+ if (ixf)
+ tmp=-8;
+ ixf=0;
+ stkp++;
+ default:
+ break;
+ }
+ stri(tmp);
+ stri(o);
+ if (*n=='-')
+ stri(27);
+ if (izf)
+ stri(15);
+ if (idf)
+ stri(25);
+ if (ixf)
+ stri(22);
+ return;
+} /* end Y */
+
+procst(trm)
+char trm;
+{
+ ccm=ctr=1;
+ p=q=Lb;
+ while(1) {
+ tm=fgetc();
+ ctr-=tm=='(';
+ ctr+=tm==')';
+ ccm-=tm==',';
+ if (!ctr || tm==trm)
+ break;
+ *q++=tm;
+ }
+ *q=0;
+ if (inproc)
+ while (*p)
+ S();
+}
+
+strpad(sym)
+char *sym;
+{
+ char *a,*b;
+
+ strcpy(a=smbf," "); /* 9 spaces */
+ while (*sym)
+ *a++=*sym++;
+}
+
+addsym(sym,sz)
+char *sym;
+int sz;
+{
+ strpad(sym);
+ smbf[8]=sz;
+ if (inproc+(sz<0)) {
+ smbf[7]=stkp+1;
+ stkp+=sz;
+ strcat(lm,smbf);
+ stri(6);
+ stri(sz);
+ return;
+ }
+ smbf[7]=gadr;
+ gadr+=sz;
+ strcat(gm,smbf);
+ gsz+=9;
+}
+
+fndlcl(sym)
+char *sym;
+{
+ strpad(sym);
+ smbf[7]=0;
+ if (s=strstr(lm,smbf)) {
+ ssz=s[8];
+ s=s+7;
+ return *s-stkp;
+ }
+ if (s=strstr(gm,smbf)) {
+ ssz=s[8];
+ s=s+7;
+ return *s;
+ }
+ return 0;
+}
+
+gettk()
+{
+ char xtm;
+
+ q=tkbf;
+ while (isspace(xtm=fgetc()));
+ while (isalnum(xtm)) {
+ *q++=xtm;
+ xtm=fgetc();
+ }
+ *q=0;
+ return xtm;
+}
+
+popfr()
+{
+ while (*fptr==inproc) {
+ cbrk=*--fptr;
+ stri(23);
+ stri(*--fptr);
+ stri(5);
+ stri(*fptr+2);
+ fptr--;
+ }
+}
+
+dostt()
+{
+ p=tmbf;
+ while (tm!=';') {
+ *p++=tm;
+ tm=fgetc();
+ }
+ *p=0;
+ strcpy(Lb,tkbf);
+ strcat(Lb,tmbf);
+ p=Lb;
+ S();
+ tm=1;
+}
+
+fnbrk()
+{
+ while (tm!='(')
+ tm=fgetc();
+}
+
+next()
+{
+ char *lp;
+ int fflg;
+
+ lp=0;
+ if (*tkbf) {
+ strcat(tkbf," ");
+ lp=strstr(tkn,tkbf);
+ }
+ fflg=lctr;
+ if (lp) {
+ switch(lp-tkn) {
+ case 0:
+ while (tm!=';' && tm!='{') {
+ tm=gettk();
+ strcpy(bfr,tkbf);
+ while (isspace(tm))
+ tm=fgetc();
+ switch (tm) {
+ case '[':
+ tm=gettk();
+ atoi(tkbf,&fflg);
+ addsym(bfr,fflg);
+ tm=fgetc();
+ break;
+ case '(':
+ stri(7);
+ stri(gsz);
+ if (strstr("main",tkbf))
+ strcpy(tkbf,"XMAIN");
+ addsym(tkbf,1);
+ procst(')');
+ stkp=-(ccm+1);
+ while (*p) {
+ getsym();
+ addsym(tkbf,-1);
+ p++;
+ stkp+=2;
+ }
+ stkp=0;
+ tm=gettk();
+ cbrk=100;
+ break;
+ case ',':
+ case ';':
+ addsym(tkbf,1);
+ break;
+ } /* end whie */
+ } /* end case 0: */
+ break;
+ case 4:
+ fflg=fflg+100;
+ case 12:
+ fnbrk();
+ stri(5);
+ *++fptr=fflg;
+ stri(fflg);
+ procst(0);
+ stri(12);
+ stri(tm=*fptr+2);
+ *++fptr=cbrk;
+ if (fflg<100)
+ cbrk=tm;
+ *++fptr=inproc;
+ lctr+=3;
+ tm=0;
+ stri(99);
+ break;
+ case 7:
+ tm=0;
+ break;
+ case 18:
+ stri(23);
+ stri(cbrk);
+ break;
+ case 24:
+ procst(';');
+ stri(23);
+ stri(ectr);
+ tm=1;
+ break;
+ case 31:
+ fnbrk();
+ procst(';');
+ stri(5);
+ stri(lctr++);
+ *++fptr=lctr;
+ procst(';');
+ stri(12);
+ stri(lctr+2);
+ stri(23);
+ stri(lctr+1);
+ stri(5);
+ stri(lctr++);
+ procst(')');
+ *++fptr=cbrk;
+ *++fptr=inproc;
+ stri(23);
+ stri(lctr-2);
+ stri(5);
+ stri(lctr++);
+ lctr++;
+ tm=0;
+ break;
+ default:
+ dostt();
+ } /* End switch */
+ } else
+ switch (tm) {
+ case '{':
+ tm=1;
+ inproc++;
+ break;
+ case '}':
+ break;
+ case -1:
+ case 0:
+ stri(0);
+#asm
+ CALL 1,CHAIN
+ ARG FNM
+ HLT
+FNM, TEXT "CC2@@@"
+#endasm
+ case '/':
+ while (fgetc()!='/'); /* Skip comment */
+ tm=1;
+ break;
+ default:
+ dostt();
+ }
+ return tm;
+}
+
+
+
+main()
+{
+ char trm;
+
+ memset(ltbf,0,&ssz-ltbf);
+ fopen("CC.CC","r");
+ strcpy(tkn,"int if else while break return for ");
+ lctr = 10;
+ ectr = 900;
+ ltpt = ltbf;
+ fptr = fstk;
+ *fptr = -1;
+ gadr = 128; /* Start of globals */
+ iinit(asm);
+ tm=gettk();
+ while (1) {
+ trm=next();
+ tm=gettk();
+ switch (trm) {
+ case '{':
+ inproc++;
+ break;
+ case '}':
+ inproc--;
+ if (!inproc) {
+ stri(5);
+ stri(ectr++);
+ stri(16);
+ stri(-stkp);
+ stkp = *lm = 0;
+ break;
+ }
+ case ';':
+ case 1:
+ stri(99);
+ if (!strcmp("else",tkbf)) {
+ stri(-23);
+ stri(100+lctr+2);
+ popfr();
+ *++fptr=100+lctr++;
+ *++fptr=cbrk;
+ *++fptr=inproc;
+ }
+ else
+ popfr();
+ case 0:
+ break;
+ default:
+ procst(';');
+ }
+ }
+}
+
ADDED cc8/os8/os8.sb
Index: cc8/os8/os8.sb
==================================================================
--- /dev/null
+++ cc8/os8/os8.sb
@@ -0,0 +1,521 @@
+#asm
+/
+/ PDP8/E Run time routines for Small c compiler
+/
+ABSYM POP 160
+ABSYM PSH 161
+ABSYM JLC 162
+ABSYM STKP 163
+ABSYM PTSK 164
+ABSYM POPR 165
+ABSYM PCAL 166
+ABSYM TMP 167
+ABSYM GBL 170
+ABSYM ZTMP 171
+/
+ DECIM
+/
+STK, COMMN 3840
+/
+/
+/
+ ENTRY MAIN
+MAIN, BLOCK 2
+ TAD GBLS
+ DCA STKP
+ TAD GBLS
+ TAD (2 / ACTUAL START AFTER A NULL AND 1 WORD CALL
+ DCA GBL
+ TAD PVL
+ DCA PSH
+ TAD OVL
+ DCA POP
+ TAD MVL
+ DCA PTSK
+ TAD PVR
+ DCA POPR
+ TAD PVC
+ DCA PCAL
+ RIF
+ TAD (3201
+ DCA PCL1
+ TAD PCL1
+ DCA DCC0
+ JMSI PCAL
+ XMAIN
+ CALL 0,EXIT
+/
+PUSH, 0
+ CDF1
+ ISZ STKP
+ DCAI STKP
+ TADI STKP
+ JMPI PUSH
+PPOP, 0
+ CDF1
+ DCA TMP
+ TADI STKP
+ MQL
+ CMA
+ TAD STKP
+ DCA STKP
+ TAD TMP
+ JMPI PPOP
+PUTSTK, 0
+ JMSI POP
+ SWP
+ DCA JLC
+ SWP
+ DCAI JLC
+ TADI JLC
+ JMPI PUTSTK
+POPRET, JMSI POP
+ SWP
+ DCA ZTMP
+ SWP
+ JMPI ZTMP
+PCALL, 0
+ CLA CLL
+PCL1, 0
+ TADI PCALL
+ DCA ZTMP
+ TAD STKP
+ DCAI (163 / ADDRESS OF STKP
+ TAD PCALL
+ IAC
+ JMSI PSH / PUSH RETURN
+ CLA
+ JMPI ZTMP
+PVL, PUSH
+OVL, PPOP
+MVL, PUTSTK
+SVL, STK
+PVR, POPRET
+PVC, PCALL
+/
+#endasm
+
+/* Comparison routines */
+
+
+outdec (number)
+int number;
+{
+#asm
+ CLA CLL CMA
+ TAD STKP / STKP-1 -> ARG
+ DCA VAL#
+ CALL 2,WRITE
+ ARG (1
+ ARG FMT
+ CALL 1,IOH
+VAL, ARG 0
+ CALL 1,IOH
+ ARG 0
+ JMSI POPR
+FMT, TEXT /(I5)/
+#endasm
+}
+
+outstr(p)
+char *p;
+ {
+ while (*p++)
+#asm
+ TLS
+XC1, TSF
+ JMP XC1
+#endasm
+ }
+
+nl()
+{
+ outstr("\r\n");
+}
+
+getch()
+{
+#asm
+ CLA
+GT1, KSF
+ JMP GT1
+ KRB
+#endasm
+}
+
+instr(p)
+char *p;
+{
+int q,tm;
+ tm=1;
+ q=p;
+ while (tm) {
+#asm
+XC2, CLA MQL
+ KSF
+ JMP XC2
+ KRB
+ TLS
+XC3, AND (127
+ SWP
+ TAD STKP
+ JMSI PSH
+ MQA
+ JMSI PTSK
+#endasm
+ if (tm==13) tm=0;
+ if (tm==127) {
+ if (p-q) {
+ p--;
+ outstr("\b \b");
+ }
+ } else {
+ *p++=tm;
+ }
+ }
+ outstr("\n");
+ return 1;
+}
+
+atoi(p)
+char *p;
+{
+#asm
+ DCA ZTMP
+ TAD (3584 / NOP
+ DCA XINV
+ CDF1 / Change DF back to 1 in case SABR changes it!
+#endasm
+ while (*p==' ')
+ p++;
+ if (*p=='-') {
+#asm
+ CLA
+ TAD (3617
+ DCA XINV / CIA
+ CDF1
+#endasm
+ p++;
+ }
+ while (*p++) {
+#asm
+ TAD (-48 / '0' ... SEE CODE
+ DCA JLC
+ TAD JLC
+ SPA CLA
+ JMP XRET
+ TAD (-10
+ TAD JLC
+ SMA CLA
+ JMP XRET
+ TAD ZTMP
+ CLL RTL
+ TAD ZTMP
+ CLL RAL
+ TAD JLC
+ DCA ZTMP
+#endasm
+ }
+#asm
+XRET, TAD ZTMP
+XINV, NOP
+#endasm
+}
+
+cend()
+{
+#asm
+ CLA SKP
+CX, CCEND
+ TAD CX
+#endasm
+}
+
+xinit()
+{
+ outstr("PDP-8 C Compiler V1.0:");
+ poct(cend());
+ nl();
+}
+/* Excluded at present
+#asm
+ PAGE
+NARG, 0
+PFMT, BLOCK 20
+PXFMT, PFMT
+SCF, CALL 0,READ
+PTF, CALL 0,WRITE
+QTF, JMP PL11
+QMF, NOP
+
+SCANF, CIA
+ DCA NARG
+ TAD SCF#
+ DCA PL9#
+ TAD QMF
+ DCA PL12
+ JMP PL10
+
+PRINTF, CIA
+ DCA NARG
+ TAD PTF#
+ DCA PL9#
+ TAD QTF
+ DCA PL12
+PL10, TAD STKP
+ TAD NARG
+ DCA JLC
+ TADI JLC
+ DCA JLC
+ TAD PXFMT
+ DCA TMP
+PL1, CDF1
+ TADI JLC
+ SNA
+ JMP PL2
+ AND (63
+ CLL RTL;RTL;RTL
+ MQL
+ ISZ JLC
+ TADI JLC
+ SNA
+ JMP PL21
+ AND (63
+ MQO
+ CDF0
+ DCAI TMP
+ ISZ TMP
+ ISZ JLC
+ JMP PL1
+PL21, MQO
+PL2, CDF0
+ DCAI TMP
+PL9, CALL 2,WRITE
+ ARG (1
+ ARG PFMT
+PL4, ISZ NARG
+ SKP
+ JMP PL3
+ TAD STKP
+ TAD NARG
+PL12, NOP
+ DCA JLC
+ CDF1
+ TADI JLC
+PL11, DCA PL5#
+ CALL 1,IOH
+PL5, ARG 0
+ JMP PL4
+PL3, CALL 1,IOH
+ ARG 0
+ JMSI POPR
+#endasm
+*/
+disp(x,y)
+int x,y;
+{
+#asm
+ OCTAL
+OPDEF DISPX 6053
+OPDEF DISPY 6054
+OPDEF INTEN 6055
+SKPDF DSSKP 6052
+OPDEF DSCLR 6050
+ DECIM
+
+ TAD STKP
+ TAD (-1
+ DCA JLC
+ TADI JLC
+ DISPY
+ CLA
+ TAD STKP
+ TAD (-2
+ DCA JLC
+ TADI JLC
+ DISPX
+ CLA
+ INTEN
+DS1, DSSKP
+ JMP DS1
+ DSCLR
+#endasm
+}
+
+kbhit()
+{
+#asm
+ CLA CMA
+ KSF
+ CLA
+#endasm
+}
+
+putchar(p)
+char p;
+{
+ p;
+#asm
+ TLS
+MP1, TSF
+ JMP MP1
+#endasm
+}
+
+strcpy( dm , sm )
+char *dm,*sm;
+{
+ while (*sm)
+ *dm++=*sm++;
+ *dm=0;
+}
+
+strcat( dm , sm )
+char *dm,*sm;
+{
+ int qm;
+ qm=dm;
+ while(*dm) dm++;
+ strcpy(dm,sm);
+ return qm;
+}
+
+strstr ( s , o )
+char *s , *o ;
+{
+char *x , *y , *z ;
+ for ( x = s ; * x ; x ++ ) {
+ for ( y = x , z = o ; * z && * y == * z ; y ++ ) z ++ ;
+ if ( z > o && ! * z ) return x ;
+ } return 0 ;
+}
+
+cexit(retval)
+int retval;
+{
+#asm
+ CALL 0,EXIT
+ HLT
+#endasm
+}
+
+isnum(vl)
+int vl;
+{
+ vl;
+#asm
+ TAD (-48
+ SPA
+ JMP XNO
+ TAD (-10
+ SMA CLA
+XNO, CLA SKP
+ IAC
+#endasm
+}
+
+isalpha(vl)
+int vl;
+{
+ vl; /* Include '?' and '@' as alpha vars */
+#asm
+ TAD (-63
+ SPA
+ JMP ANO
+ TAD (-28
+ SMA CLA
+ANO, CLA SKP
+ IAC
+#endasm
+}
+
+poct(vl)
+int vl;
+{
+ vl;
+#asm
+ CLL RAL
+ DCA TMP
+ TAD (-4
+ DCA PCTR
+PWR0, TAD TMP
+ RAL
+ RTL
+ DCA TMP
+ TAD TMP
+ AND (7
+ TAD (48
+ TLS
+PRW1, TSF
+ JMP PRW1
+ CLA
+ ISZ PCTR
+ JMP PWR0
+PCTR, 0
+#endasm
+}
+
+/* Not included */
+pdec(vl)
+int vl;
+{
+ if (vl&2048) {
+ vl=-vl;
+ putchar('-');
+ }
+ vl;
+#asm
+ CPAGE 52
+ARW7, SZA
+ JMP ARW6
+ TAD (-1
+ DCA CZB
+ JMP ARW8
+ARW6, DCA VALUE
+ DCA DIGIT
+ DCA AFLG
+ TAD (-4
+ DCA CZB
+ TAD AZA
+ DCA ARW
+ SKP
+ARW4, DCA VALUE
+ CLL
+ARW2, TAD VALUE
+ARW, TAD TENPWR
+ SZL
+ ISZ DIGIT
+ SZL
+ JMP ARW4
+ CLA
+ TAD DIGIT
+ SZA CLA
+ JMP ARW5
+ TAD AFLG
+ SNA CLA
+ JMP ARW3 /SKIP LEADING ZEROES
+ARW5, ISZ AFLG
+ TAD DIGIT
+ARW8, TAD (48
+ TLS
+ARW3, TSF
+ JMP ARW3
+ CLA
+ DCA DIGIT
+ ISZ ARW
+ ISZ CZB
+ JMP ARW2
+ JMP CZB /WILL NOW BE 0
+AZA, TAD TENPWR
+TENPWR, -1000
+ -100
+ -10
+ -1
+VALUE, 0
+DIGIT, 0
+AFLG, 0
+CZB, 0
+
+#endasm
+}
+
ADDED cc8/os8/p8.c
Index: cc8/os8/p8.c
==================================================================
--- /dev/null
+++ cc8/os8/p8.c
@@ -0,0 +1,185 @@
+
+#include
+#include
+
+#define SMAX 10
+#define CMAX 256
+#define BMAX 64
+#define LMAX 32
+#define DMAX 32
+#define CBMX 1024
+#define LXMX 999
+
+int asm[CBMX];
+int ltbf[512];
+int xlt[CMAX];
+int gm[CMAX]; /* Global symbol table */
+int tkbf[LMAX];
+int *p,*q,*s,*ltpt;
+int gsym,lsym,gadr,ladr,stkp,*as,lctr,*fptr,gsz,ctr,tm,ectr;
+int glim;
+int ltsz,pflg,t;
+int tmstr[32];
+
+main()
+{
+
+ as=asm;
+ fopen("HEADER.SB","r");
+ fopen("CC.SB","w");
+ strcpy(xlt,"ITOA PUTS DISPXY GETC GETS ATOI SSCANF XINIT MEMCPY KBHIT PUTC STRCPY STRCAT STRSTR EXIT ISNUM ");
+ strcat(xlt,"ISALPH SPRINTF MEMSET FGETC FOPEN FPUTC FCLOSE PRINTF ISALNUM ISSPACE FPRINTF FPUTS STRCMP CUPPER FGETS ");
+ while (t=fgetc())
+ if (t!=12) /* Ignore form feed */
+ fputc(t);
+ cupper(gm);
+ while (*as) {
+ pflg=0;
+ *tmstr=0;
+ switch (*as++) {
+ case 99:
+ fprintf("/\r");
+ break;
+ case 1:
+ fprintf("\tJMSI PTSK\r");
+ break;
+ case 3:
+ strcpy(tmstr,"\tCIA\r");
+ case 2:
+ fprintf("%s\tTADI STKP\r\tJMSI POP\r",tmstr);
+ break;
+ case 4:
+ fprintf("\tCLA\r\tTAD (%d\r",*as++);
+ break;
+ case 5:
+ if (*as<0)
+ *as=100-*as;
+ fprintf("CC%d,\r",*as++);
+ break;
+ case 6:
+ if (*as>1)
+ fprintf("\tTAD STKP\r\tTAD (%d\r\tDCA STKP\r",*as);
+ else
+ if (*as>0)
+ fputs("\tISZ STKP\r");
+ as++;
+ break;
+ case 7:
+ p=gm+*as++;
+ while (*p-' ')
+ fputc(*p++);
+ fputs(",\r");
+ break;
+ case -8:
+ strcpy(tmstr,"\tDCA JLC\r\tTADI JLC\r");
+ case 8:
+ if (*as>0)
+ fprintf("\tCLA\r\tTAD (%d\r%s\tJMSI PSH\r",*as++,tmstr);
+ else
+ fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r%s\tJMSI PSH\r",*as++,tmstr);
+ break;
+ case 9:
+ tm=*as++;
+ p=gm+*as++;
+ strcpy(tkbf," ");
+ memcpy(tkbf,p,7);
+ if (p=strstr(xlt,tkbf)) {
+ t=(p-xlt)>>3;
+ if ((t==6) + (t==17) + (t==23))
+ fprintf("\tCLA\r\tTAD (%d\r\tJMSI PSH\r",tm++);
+ fprintf("\tCLA\r\tTAD (%d\r\tMQL\r\tCALL 1,LIBC\r\tARG STKP\r\tCDF1\r",t);
+ }
+ else
+ fprintf("\tJMSI PCAL\r\t%s\r",tkbf);
+ if (tm)
+ fprintf("\tMQL\r\tTAD (%d\r\tTAD STKP\r\tDCA STKP\r\tSWP\r",-tm);
+ break;
+ case 10:
+ fprintf("\tCLA\r\tTAD GBL\r\tTAD (%d\r",*as++);
+ break;
+ case -11:
+ fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSMA SZA CLA\r\tCMA\r");
+ break;
+ case 11:
+ fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSPA CLA\r\tCMA\r");
+ break;
+ case 12:
+ fprintf("\tSNA\r\tJMP CC%d\r",*as++);
+ break;
+ case 13:
+ fprintf("\tJMSI POP\r\tDCA JLC\r\tSWP\r\tCALL 1,MPY\r\tARG JLC\r\tCDF1\r");
+ break;
+ case 14:
+ fprintf("\tJMSI POP\r\tDCA JLC\r\tSWP\r\tCALL 1,DIV\r\tARG JLC\r\tCDF1\r");
+ break;
+ case 15:
+ fprintf("\tISZI JLC\r\tNOP\r");
+ break;
+ case 16:
+ fprintf("\tMQL\r\tTAD STKP\r\tTAD (%d\r\tDCA STKP\r\tSWP\r\tJMPI POPR\r/\r",*as++);
+ break;
+ case 17:
+ pflg++;
+ case -17:
+ if (*as>0)
+ fprintf("\tCLA\r\tTAD (%d\r\tDCA JLC\r\tTADI JLC\r",*as++);
+ else
+ fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r\tDCA JLC\r\tTADI JLC\r",*as++);
+ if (pflg==0)
+ break;
+ case 19:
+ fprintf("\tJMSI PSH\r");
+ break;
+ case 20:
+ fprintf("\tANDI STKP\r\tJMSI POP\r");
+ break;
+ case -20:
+ fprintf("\tJMSI POP\r\tMQA\r");
+ break;
+ case 21:
+ if (*as>0)
+ fprintf("\tCLA\r\tTAD (%d\r",*as++);
+ else
+ fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r",*as++);
+ break;
+ case 22:
+ fprintf("\tDCA JLC\r\tTADI JLC\r");
+ break;
+ case 23:
+ if (*as<100)
+ fprintf("\tJMP CC%d\r",*as);
+ as++;
+ break;
+ case -23:
+ fprintf("\tJMP CC%d\r",*as++);
+ break;
+ case 24:
+ fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSNA CLA\r\tCMA\r");
+ break;
+ case 25:
+ fprintf("\tMQL\r\tCMA\r\tTADI JLC\r\tDCAI JLC\r\tSWP\r");
+ break;
+ case 26:
+ fprintf("\tSNA CLA\r\tCMA\r");
+ break;
+ case 27:
+ fputs("\tCIA\r");
+ }
+ }
+ ltsz=ltpt-ltbf;
+ fprintf("\tLAP\r\tCPAGE %d\rLCC0,\t%d\rXCC0,\tCC0\rCC0,\t\r",ltsz+2,-ltsz);
+ p=ltbf;
+ while (ltsz) {
+ fprintf("%d",*p++);
+ if (ltsz>1)
+ fputs("; ");
+ if ((ltsz&7)==0)
+ fputc(13);
+ ltsz--;
+ }
+ fprintf("\r\tEAP\rGBLS,\t%d\r",gadr);
+ fprintf("\rMCC0,\t0\r\tCDF1\r\tTAD LCC0\r\tSNA CLA\r\tJMP I MCC0\r\tTAD XCC0\r\tDCA JLC\rDCC0,\tCDF0\r\tTADI JLC\r");
+ fprintf("\tJMSI PSH\r\tCLA\r\tISZ JLC\r\tISZ LCC0\r\tJMP DCC0\r\tJMP I MCC0\rCCEND,\t0\r\t\END\r");
+
+ fclose();
+}
ADDED cc8/os8/ps.c
Index: cc8/os8/ps.c
==================================================================
--- /dev/null
+++ cc8/os8/ps.c
@@ -0,0 +1,16 @@
+int main()
+{
+ int ar[20],i,j,n;
+
+ n=14;
+ for (i=1;i1;j--)
+ ar[j]=ar[j-1]+ar[j];
+ for (j=0;j<2*(n-i-1);j++)
+ putc(' ');
+ for (j=1;jCtrl-E keystroke so that you can send more SIMH commands
-after OS/8 starts up. This accomplishes that:
-
- s.os8_send_ctrl ('e')
-
-While out in the SIMH context, you *could* continue to call the
-`simh.os8_*` methods, but since SIMH can accept input as fast as your
-program can give it, it is best to use methods like `simh.send_cmd`
-which don't insert artificial delays. For many programs, this
-difference won't matter, but it results in a major speed improvement in
-a program like `mkos8` which sends many SIMH and OS/8 commands
-back-to-back!
-
-
-## Getting Back to OS/8 from SIMH
-
-There are several ways to get back to the simulated OS/8 environment
-from SIMH context, each with different tradeoffs.
-
-
-### Rebooting
-
-You saw the first one above: send a `boot rk0` command to SIMH. This
-restarts OS/8 entirely. This is good if you need a clean environment.
-If you need to save state between one run of OS/8 and the next, save it
-to the RK05 disk pack or other SIMH media, then re-load it when OS/8
-reboots.
-
-
-### Continuing
-
-The way `teco-pi-demo` does it is to send a `cont` command to SIMH.
-
-The problem with this method is that it sometimes hangs the simulator.
-The solution is to insert a small delay *before* escaping to the SIMH
-context. I'm not sure why this is sometimes necessary. My best guess is
-required to give OS/8 time to settle into an interruptible state before
-escaping to SIMH, so that on "continue," we re-enter OS/8 in a sane
-state.
-
-You can usually avoid the need for that delay by waiting for an OS/8
-command prompt before escaping to SIMH, since that is a reliable
-indicator that OS/8 is in such an interruptible state.
-
-You don't see these anomalies when using OS/8 interactively because
-humans aren't fast enough to type commands at OS/8 fast enough to cause
-the problem. That is doubtless why there this bug still exists in OS/8
-in 2017.
-
-
-### Re-Entering
-
-If your use of OS/8 is such that all required state is saved to disk
-before re-entering OS/8, you can call the `simh.os8_restart` method to
-avoid the need for a delay *or* a reboot. It re-calls OS/8's entry
-point from SIMH context, which we've found through much testing is
-entirely reliable, as compared to sending a SIMH `cont` command without
-having delayed before escaping to SIMH context.
-
-`mkos8` uses this option extensively.
-
-
-## Sending Escape Characters
-
-Several OS/8 programs expect an Escape (a.k.a. `ALTMODE`)
-keystroke to do things. Examples are `TECO` and `FRTS`. There isn't a
-specific method to do this because we can do that in terms of one we've
-just described:
-
- s.os8_send_ctrl ('[')
-
-Yes, Escape is Ctrl-\[. Now you can be the life of
-the party with that bit of trivia up your sleeve. Or maybe you go to
-better parties than I do.
-
-
-## But There's More!
-
-The above introduced you to most of the functionality of `class simh`
-used by `teco-pi-demo`, but there's more to the class than that,
-primarily because the `mkos8` script's needs are broader. Rather than
-just recapitulate the class documentation here, please read through [the
-class's source code][ssc], paying particular attention to the method
-comments. It's a pretty simple class, making it a quick read.
-
-Another useful module is [`pidp8i.dirs`][dsc] which contains paths to
-many directories in the PiDP-8/I system, which you can reuse to avoid
-having to hard-code their locations. This not only makes your script
-independent of the installation location, which is configurable at build
-time via `./configure --prefix=/some/path`, but also allows it to run
-correctly from the PiDP-8/I software's build directory, which has a
-somewhat different directory structure from the installation tree.
-
-[ssc]: https://tangentsoft.com/pidp8i/file/lib/simh.py
-[dsc]: https://tangentsoft.com/pidp8i/file/lib/pidp8i/dirs.py
-
-
-## Credits and License
-
-Written by and copyright © 2017 by Warren Young. Licensed under the
-terms of [the SIMH license][sl].
-
-[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
DELETED doc/os8-fortran-iv.md
Index: doc/os8-fortran-iv.md
==================================================================
--- doc/os8-fortran-iv.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# OS/8 FORTRAN IV
-
-OS/8 `FORTRAN IV` is extensively documented:
-
-* Chapter 8 of the [1974 OS/8 Handbook][os8h1974] (large file!).
-* Section 2 of the [OS/8 Language Reference Manual AA-H609A-TA][os8lang].
-* The [OS/8 Fortran IV Software Support Manual DEC-S8-LFSSA-A-D][os8f4suppt]
-
-This file serves more as a quick guide to what has been gathered
-to this repository as far as distribution DECtapes, and patches
-are concerned.
-
-The [1979 OS/8 Software Components Catalog][os8cat] provides an
-inventory of and part numbers for the OS/8 V3D binary and source
-distribution DECtapes. Images of these DECtapes are all found in
-media/os8/subsys as follows:
-
-| DEC Part | Filename | Description |
-| ----------- | ------------------------------- | ----------------- |
-| AL-4549D-BA | al-4549d-ba-fr4-v3d-1.1978.tu56 | Binary DECtape #1 |
-| AL-5596D-BA | al-5596d-ba-fr4-v3d-2.1978.tu56 | Binary DECtape #2 |
-| AL-4545D-SA | al-4545d-sa-fr4-v3d-1.tu56 | Source DECtape #1 |
-| AL-4546D-SA | al-4546d-sa-fr4-v3d-2.tu56 | Source DECtape #2 |
-| AL-4547D-SA | al-4547d-sa-fr4-v3d-3.tu56 | Source DECtape #3 |
-
-When with-os8-fortran-iv is enabled (which is the default), the
-contents of Binary DECtape #1 are installed on the OS/8 RK05 images
-built by `mkos8`.
-
-Binary DECtape #2 contains the `.RA` sources for the components
-of the FORTRAN IV library. Those files are already assembled
-and archived in `FORLIB.RL` and installed from Binary DECtape #1.
-
-The three source DECtapes contain the buildable source code for the
-rest of OS/8 FORTRAN IV system. Build instructions are found in
-Appendix B of the _OS/8 Fortran IV Software Support Manual_.
-
-If with-os8-patches is configured, the `os8v3d-patched.rk05` image will contain the following patches:
-
-* `F4 21.1.2 M` Fix for the `EQUIVALENCE` statement that brings
- `F4.SV` and `PASS3.SV` up to version 4B.
-* `F4 51.3.1 M` Enable recognition of `"` as an incorrect character in
- a subroutine call argument that brings `F4.SV` up to version 4C.
-* `F4 51.3.2 M` Enable recognition of syntax errors in type
- declarations.
-* `FORLIB 51.10.1 M` Updates `FORLIB.RL` to contain an corrected
- `DLOG` function that will correctly handle numbers smaller than
- `1.1-018`.
-
-There is one more patch available, `FRTS 51.3.3 O`, an optional patch
-that enables the FORTRAN IV runtime system to accommodate 2 page
-system handlers in addition to the TD8E handler. This patch has not
-yet been verified.
-
-FORTRAN IV on the system packs should work.
-
-The sources are available in the tree in the files named above.
-
-Enjoy!
-
-[os8h1974]: http://bitsavers.trailing-edge.com/pdf/dec/pdp8/os8/OS8_Handbook_Apr1974.pdf
-[os8lang]: http://bitsavers.trailing-edge.com/pdf/dec/pdp8/os8/AA-H609A-TA_OS8_Language_Reference_Manual_Mar79.pdf
-[os8f4suppt]: http://bitsavers.trailing-edge.com/pdf/dec/pdp8/os8/DEC-S8-LFSSA-A-D_F4swSupp.pdf
-[os8cat]: https://ia601002.us.archive.org/8/items/bitsavers_decpdp8sofoftwareComponentsCatalogJul79_7798622/AV-0872E-TA_PDP-8_Software_Components_Catalog_Jul79.pdf
-
-### License
-
-Copyright © 2017 by Bill Cattey. Licensed under the terms of
-[the SIMH license][sl].
-
-[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
DELETED doc/os8-macrel.md
Index: doc/os8-macrel.md
==================================================================
--- doc/os8-macrel.md
+++ /dev/null
@@ -1,86 +0,0 @@
-# OS/8 `MACREL`
-
-`MACREL`, the MAcro RELocating assembler, was a late development. It
-was an attempt to replace `PAL8` with a Macro assembler capable of
-producing relocatable modules. When `MACREL` first came on the scene,
-several companies decided to port their next major upgrade to `MACREL`
-from `PAL8`. `MACREL` was so buggy that everybody basically had to
-revert to `PAL8` and back-port all the new code originally intended
-for the new major upgrade. This situation befell ETOS Version 5.
-
-We have a binary distribution DECtape image of `MACREL` version 1, DEC
-part number `AL-5642A-BA`. Unfortunately the version numbers of the
-patches did not match what was shown in the binaries.
-
-With the `MACREL` V1 patches, I wanted to do more research before
-recommending application of the patches. In the course of that
-research, I discovered that all the archived manuals to be found online
-were for `MACREL` v2.
-
-See: [Willem van der Mark's PDP-8 Manuals archive][vandermarkman] for:
-
-* [OS/8 MACREL/LINK -- Software Support -- Version 2C -- September 1980 AA-J7073-TA][maclinkss]
-* [OS/8 MACREL/LINK -- User Manual -- Version 2D -- January 1979 AA-5664B-TA][maclinkuser]
-
-Or see the [PDP8 doc tree on ftp.dbit com][dbitdocs] for:
-
-* [maclkssm.doc -- OS/8 MACREL/LINK V2 Software Support Manual][dbitmacssm]
-* [maclnkum.doc -- OS/8 MACREL/LINK V2 User's Manual.][dbitmacuser]
-* [macrelrn.doc -- OS/8 MACREL/LINK V2 Release Notes][dbitmacrel]
-
-Version 2 was the clearly better baseline. I didn't hold out much
-hope to find binary and source distributions of `MACREL` v2. (DEC
-Part numbers `AL-5642B-BA` for the binary DECtape and the 4 source
-DECtapes, `AL-5643B-SA`, `AL-5644B-SA`, `AL-H602B-SA`, and
-`AL-H602B-SA`.)
-
-Very recently we found a complete set of `MACREL` version 2 binaries
-as part of a buildable RTS-8 Archive at [ibiblio.org ... pdp-8/rts8/v3/release][rts8rel]
-
-We found a source distribution of `MACREL` v2 in Dave Gesswein's
-[misc_floppy][dgfloppy] archive. Part one is flagged as having
-errors, but another obscure site had a mis-labeled archive of this
-same stuff so we may be ok.
-
-The `MACREL` v2 source would not build under `MACREL` v1, but now we
-have `MACREL` v2 and initial tests look promising.
-
-Baseline `MACREL` v2 will be integrated into the system packs.
-Because we didn't have `MACREL` v2, no work was done to create patch
-files, or to validate them. With both source and binary for `MACREL`
-v2 now in hand, this work can proceed. The plan is to fetch the
-patches, validate them, and install all mandatory patches that can be
-verified.
-
-The current integration of `MACREL` v2 includes a hand-applied patch
-to `FUTIL`. We want the latest version of `FUTIL` because it contains
-new code handles extended memory and certain `MACREL` data
-structures. However version 8A of `FUTIL` shipped on the `MACREL` v2
-tape had a bug that causes it to *hang* when run under `BATCH`.
-
-Patch `35.13.1M` fixes this problem and upgrades `FUTIL` to version
-8B. This patch was applied by hand tested, and grouped with what we
-integrate onto the system packs when we add `MACREL`.
-
-To reduce uncertainty around the operation of `OVRDRV.MA`, Source
-patch `41.5.1M` has been applied by hand to `OVRDRV.MA`.
-
-See also: [our documentaiton on the OS/8 Patching][os8patches]
-
-[vandermarkman]: http://vandermark.ch/pdp8/index.php?n=PDP8.Manuals
-[maclinkss]: http://vandermark.ch/pdp8/uploads/PDP8/PDP8.Manuals/AA-J073A-TA.txt
-[maclinkuser]: http://vandermark.ch/pdp8/uploads/PDP8/PDP8.Manuals/AA-5664B-TA.txt
-[dbitdocs]: ftp://ftp.dbit.com/pub/pdp8/doc/
-[dbitmacssm]: ftp://ftp.dbit.com/pub/pdp8/doc/maclkssm.doc
-[dbitmacuser]: ftp://ftp.dbit.com/pub/pdp8/doc/maclnkum.doc
-[dbitmacrel]: ftp://ftp.dbit.com/pub/pdp8/doc/macrelrn.doc
-[rts8rel]: http://www.ibiblio.org/pub/academic/computer-science/history/pdp-8/rts8/v3/release
-[dgfloppy]: http://www.pdp8online.com/images/images/misc_floppy.shtml
-[os8patches]: https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-patching.md
-
-### License
-
-Copyright © 2017 by Bill Cattey. Licensed under the terms of
-[the SIMH license][sl].
-
-[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
DELETED doc/os8-patching.md
Index: doc/os8-patching.md
==================================================================
--- doc/os8-patching.md
+++ /dev/null
@@ -1,404 +0,0 @@
-# OS/8 System Patches
-
-Between major updates to distribution media, DEC would send out
-important information and patches to customers through its publication
-_PDP-8 Digital Software News_ (_DSN_ for short).
-
-Many issues of _DSN_ can be found on bitsavers.org under
-[pdf/dec/pdp8/softwarenews][dsn].
-
-To help customers keep track of which patches to apply, _DSN_ added a
-Cumulative Index.
-
-Using the _PDP-8 DIGITAL Software News Cumulative Index_ found in the
-latest available issue of _DSN_, [October/November 1980][dsn8010], I
-created a spreadsheet of all patches relevant to the OS/8 V3D packs
-under construction. That spreadsheet enabled me to go to the
-particular issues containing the patches, and keep track of what
-action I took with them.
-
-I reviewed all the patches and came up with a list of the mandatory
-patches. Using OCR'd text from each relevant _DSN_ issue, I created a
-file per patch, which I then compared to the scanned PDF and corrected
-the OCR errors.
-
-Then I enhanced our `mkos8` script to apply the patches in an
-automated way. Most of the patches were for programs available
-in source form, so I built the programs from source, and then bench
-checked the patch against the source. In a few cases the code was too
-obscure, and I marked the patch as "plausable" rather than "verified"
-in my spreadsheet.
-
-The file [patch_list.txt][pl] lists all of the patch files in
-`media/os8/patches`. Comments in that file begin with `#` and are
-used to disable patches we have rejected for one reason or another.
-Each rejected patch also has a comment that explains why that
-particular patch was rejected from the default set. Typical reasons
-are:
-
-* The patch requires hardware our simulator doesn't have.
-* The patch conflicts with another patch we deem more important.
-* The patch changes some behavior, and we prefer that the unpatched
- behavior be the default.
-
-You may want to examine this file to see if there are any decisions you
-would reverse. After modifying that file, say "`make`" to rebuild the
-OS/8 binary RK05 disk image file with your choice of patches.
-
-You can disable all of these OS/8 patches by giving the
-`--disable-os8-patches` option to the `configure` script.
-
-[dsn]: http://bitsavers.org/pdf/dec/pdp8/softwarenews/
-[dsn8010]: http://bitsavers.org/pdf/dec/pdp8/softwarenews/198010_PDP8swNews_AA-K629A-BA.pdf
-[pl]: https://tangentsoft.com/pidp8i/doc/trunk/media/os8/patches/patch_list.txt
-
-
-## Review of Recommendations
-
-`BRTS 31.11.2O` is an optional patch which disables 8th bit parity. It
-is recommended because sometimes we may want to allow output that
-does not force the 8th bit.
-
-`BRTS 31.11.3O` is an optional patch that enables 132 column
-output. It is recommended because it is expected that wide column
-output is desirable.
-
-`TECO 31.20.1O` is an optional patch that permanently forces no case
-flagging. It is not recommended because we want to allow the option
-of case flagging.
-
-`TECO 31.20.2O` is an optional patch that turns off verbose
-errors. It was for slow terminals and experienced users who didn't
-want to wait to see the long error messages they already knew. It is
-not recommended because we expect a majority of users to be on high
-speed terminals needing the verbose errors.
-
-`TECO 31.20.3O` turns off a warning that you are using the `YANK`
-command to completely overwrite a buffer full of text. Issuing the
-command a second time succeeds. It was again to avoid experienced
-users. It is not recommended because we expect fewer advanced users
-who would be annoyed by the protection.
-
-`TECO 31.20.4O` implements rubout support specifically and uniquely
-for the `VT05` terminal in a way that breaks it for all other video
-terminals. It is not recommended because there are VERY few `VT05`
-deployments that would use it.
-
-It is at this point that I began to notice that in later years, patches
-became less carefully produced, and more prone to errors. Some are not
-correctable, even today.
-
-`BASIC.UF-31.5.1M` shows:
-
- 4044/4514 4556
-
-changing location `4044` from `4514` to `4556`. Such a change would be
-consistent with the stated purpose of the patch, to correct references
-to page zero literals that moved with the `V3D` version of `BRTS`.
-The source around location '4044' looks like this:
-
- 04043 4775 JMS I (BUFCDF /SET UP USER BUF
- 04044 1273 TAD NSAM
- 04045 7041 CIA
- 04046 3276 DCA NCTR /-#OF BOARDS TO CLAR
-
-In my judgment the `TAD NSAM` to get the subscript into the `AC`
-should be retained, and the `4556` call to `UNSFIX` to truncate the
-value of the Floating Point Accumulator should NOT be inserted. I
-modified the patch to leave out that change. It remains to be seen if
-calls to User Functions in OS/8 `BASIC` will ever be run to test this
-code. Here at least is an analysis to later explorers.
-
-`EDIT 21.17.4 M` is supposedly a mandatory patch. It fixes a problem
-with line printer output through a specific parall interface card.
-Unfortunately, the patch overwrites mandatory patch in 21.17.2 and is
-NOT recommended.
-
-`ABSLDR 21.29.1 M` is supposedly a mandatory patch that enables
-`ABSLDR` to work with `SAVE` image files. Normally `ABSLDR` only
-loads `BIN` format files. The patch sequence number, `21.29`
-identifies the patch as being for the OS/8 V3D version of `ABSLDR`.
-But the patch changes locations that are not used by `ABSLDR.SV`.
-Furthermore, the patch says it upgrades `ABSLDR` from version 6B to
-version 6C.
-
-Version 6 of `ABSLDR` was part of the OS/8 V3D Device Extensions kit.
-See [our documention on the OS/8 V3D Device Extensions][os8ext].
-Verification of this now seems within reach, with the expectation that
-it is mis-labeled, and is properly applied to the version with the
-Extensions kit. Until it is verified, applying this patch is *not*
-recommended.
-
-`PAL8-21.22.4M` is broken and doubly mis-labeled. Mis-label #1: It is
-an optional, not mandatory patch. Mis-label #2: It is for product
-sequence `35.14`, the `V13` codeline of `PAL-8` that, like `ABSLDR
-V6`, is in the Device Extensions kit. The breakage: Source listing
-quits working. *Do not apply this patch!*
-
-Patch `FRTS-51.3.3-O.patch8` is to enable 2-page system drivers like
-`RL01`. Except that the `RL01` driver is only available in the
-Extensions kit. The patch overwrites existing code that makes `FRTS`
-able to function with the `TD8E` 2-page system handler. I've read the
-code but don't fully understand it. Perhaps it generalizes the `TD8E`
-support. But if you happen to be using this setup under `TD8E` and
-`FRTS` doesn't work, then back out this patch.
-
-
-## Patch Application Order
-
-The `patch` routine in `mkos8` applies the patches in the order they
-appear in `patch_list.txt`. That list is currently in alphabetical
-order. However, there may in future emerge patches that impose an
-order.
-
-For example, if the `ABSLDR` patch actually did work, it needs the
-`FUTIL 31.21.2 M` in order to patch into the `ABSLDR` overlay bits.
-
-I was skeptical of `FUTIL 31.21.2M` because, when I
-load `ABSLDR.SV` into core with GET, the contents of memory showed by
-`ODT` are *DIFFERENT* from those shown by `FUTIL`. With deeper
-understanding of the OS/8 Device Extensions kit, I see that the patch
-was incorporated into the version 8 `FUTIL` source, and also that
-`ODT` is expected to be updated in version 3S of the Keyboard Monitor.
-
-## Then There's `MACREL`
-
-I've gone into detail on the explorations and understandings with
-regard to `MACREL` in a [sister document to this one][macreldoc].
-
-Originally I reviewed the patches for `MACREL` v1, because that's all
-we had. But the version numbers of the patches did not match the
-version numbers of the executables. A little diversion into the guess
-work surrounding patch verification:
-
-Version number mismatches sometimes do occur with patches. For
-example, `TECO 31.20.11 M` says that it upgrades `TECO` to version
-`5.06`, but got the bits wrong. Instead of changing contents from
-`0771` to `0772`, it looked to change from `0772` to `0773`. `772`
-octal is `506` decimal, and the `TECO` version number is represented
-with a 12 bit number. It's called "5.06" but it's represented as
-`0772` octal, or `506` decimal.
-
-With that TECO patch, I simply changed the version amendment line in
-that `TECO` patch, because the rest was correct. Whoever published
-the patch got the version number wrong, and nobody complained.
-
-With no `MACREL` v1 source verification was not really possible, so
-applying those patches was postponed. But then we found both binary
-and source of `MACREL` v2!
-
-In the interests of shipping out system packs in finite time, we will
-integrate `MACREL` v2 into the system packs, and verify/apply `MACREL`
-v2 patches as follow-on work.
-
-After further testing of 'MACREL' I have concluded that integrating
-the source-level patch `41.5.1M` will reduce uncertainty. So I have
-hand-integrated that patch into the `MACREL` tu56 image as well.
-
-[macreldoc]:https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-macrel.md
-
-## `FUTIL`:
-
-I was dubious of some of the `FUTIL` patches, but with finding source
-to version 8A, I gained confidence in the version 7 patches, and
-understood how seriously important the first patch was to version 8.
-
-The `MACREL` v2 tape shipped with version 8A of `FUTIL`. That was
-necessary because V2 of `MACREL` supported the latest memory expansion,
-and so the OS/8 Core Control Block needed to change.
-
-Unfortunately, the `FUTIL.SV` distributed as version 8A had the wrong
-starting address and Job Status Word settings. It *hangs* when run
-under `BATCH`. Our automated pack builder and patcher `mkos8` run
-`FUTIL` under `BATCH`.
-
-The `MACREL` v2 DECtape image we use with `mkos8` contains a
-hand-applied patch `35.13.1M` that fixes this problem.
-
-Currently if you opt in to having `MACREL` on the system packs, you
-get `FUTIL` version 8B. If not, you get `FUTIL` version 7 and `mkos8`
-applies the relevant patches. If `FUTIL` version 8 is installed, the
-automated patch applier recognizes the version 7 patches don't fit and
-fails to install them.
-
-## One-off Patches
-
-Most of the patches are parsed and applied in an automated manner
-by mkos8. However some are one-offs.
-
-See the `FUTIL` section above with regards to patch `35.13.1M`.
-
-`FORLIB 51.10.1 M` is a one line source change to `DLOG.RA`. The patch
-file provides that line. It also provides instructions on how to use
-`RALF` to assemble the source and on how to to use `LIBRA` to replace
-the old version of `DLOG` with the new one in `FORLIB.RL`. I followed
-the instructions to hand-tool a patched `FORLIB.RL` which I then put
-in the `local.tu56` DECtape image along with the other local hacks.
-The `patch` routine `mkos8` has in-line code to replace `FORLIB.RL` on
-`SYS:` if installation of FORTRAN IV is enabled.
-
-
-## Unfinished Business
-
-There remain the following patches that are still under development,
-because they are not simple binary overlays on executables that could
-be applied with simple scripts driving `ODT` or `FUTIL`. Instead they
-are either batch scripts, or are applied to source code that is
-rebuilt either with an assembler or high level language compiler.
-
-`LQP 21.49.1 M` patches a device driver `.BN` file, then using `BUILD`
-to insert it into the system. At the present time the OS/8 V3D packs
-we build do not use the `LPQ` driver. (We ran out of device ID space
-and so we don't have anywhere to put an active `LPQ` driver.)
-
-
-## The Tracking Spreadsheet
-
-Below is the latest snapshot of the tracking spreadsheet.
-
-Status column key:
-
-| **A** | Patch Applies Successfully |
-| **V** | Patch Source Verified |
-| **K** | Patch Source Probably OK. Weaker confidence than "Verified". |
-| **P** | Patch Source Plausible. Weaker confidence than "OK". |
-| **N** | Not recommended |
-| **O** | OCR Cleaned up. No other verification or application done. |
-| **D** | Does not apply. |
-| **B** | Bad patch. DO NOT APPLY. |
-
-
-### OS/8 V3D Patches
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| `HANDLER` | `CTRL/Z` and `NULL` | `01 O *` | Oct-77 | Optional. Not going to apply. | |
-| `CREF` | Bug with `FIXTAB` | `21.15.1M` | Apr/May-78 | `CREF-21.15.1-v2B.patch8` Corrects bad patch | AV |
-| | Input and output file specifications | `21.15.2M` | Feb/Mar-80 | `CREF-21.15.2-v2C.patch8` | AK |
-| `EDIT` | `EDIT` Problem with no `FORMFEED` at end of the input file | `21.17.1M` | Mar-78 | `EDIT-21.17.1M-v12B.patch8` | AV |
-| | `EDIT` `Q` command after `L` command | `21.17.2M` | Jun/Jul-79 | `EDIT-21.17.2M-v12C.patch8` | AV |
-| | `EDIT` `Q` command patch | `21.17.3M` | Jun/Jul-79 | `EDIT-21.17.3M-v12D.patch8` | AV |
-| | `EDIT.SV` `V` option will not work with `LPT DKC8-AA` | `21.17.4M` | Feb/Mar-80 | `EDIT-21.17.4M-v12C.patch8` Overwrites patch `21.12.2M` | AVB |
-| `FOTP` | Incorrect directory validation | `21.19.1M` | Jun/Jul-79 | `FOTP-21.19.1M-v9B.patch8` (Corrected from Aug/Sep 1978, Detailed in Apr/May 79) | AV |
-| `MCPIP` | `DATE-78` Patch for `MCPIP` | `21.21.1M` | Mar-78 | `MCPIP-21.21.1M-v6B.patch8` | AV |
-| `PAL8` | Incorrect core size routine | `21.22.1M` | Aug/Sep-78 | `PAL8-21.22.1M-v10B.patch8` | AV |
-| | Erroneous `LINK` generation noted on `PAGE` directive | `21.22.2M` | Aug/Sep-78 | `PAL8-21.22.2M-v10C.patch8` | AV |
-| | `EXPUNGE` patch to `PAL8` | `21.22.3M` | Feb/Mar-80 | `PAL8-21.22.3M-v10D.patch8` | AK |
-| | `TAB`s are translated incorrectly | `21.22.4M` | Oct/Nov-80 | `PAL8-21.22.4M` (Supercedes June/July 1980 (which had wrong contents of memory.)) Bad! Wrong version of `PAL8`! Breaks list output. | AB |
-| `PIP` | `PIP` `/Y` option does not work properly when transferring a system | `21.23-1M` | Aug/Sep-78 | `PIP-21.23.1M-V12B.patch8` | AK |
-| `PIP10` | `DATE-78` Patch to `PIP 10` | `21.24.1M` | Jun/Jul-79 | `PIP10-21.24.1M-V3B.patch8` (Corrected from Dec 78/Jan 79) | AV |
-| `SET` | Using `SET` with two-page system handlers | `21.26.1M` | Apr/May-78 | `SET-21.26.1M-v1C.patch8` | AV |
-| | `SCOPE` `RUBOUT`s fail in `SET` | `21.26.2M` | Apr/May-78 | `SET-21.26.2M-v1D.patch8` | AV |
-| | Parsing of `=` in `TTY WIDTH` option | `21.26.3M` | Aug/Sep-78 | `SET-21.26.3M-v1E.patch8` | AV |
-| `LPQ` | `LDP01` Handler fails to recognize `TAB`s | `21.49.1M` | Dec/Jan-80 | `LQP-21.49.1M-vB.patch8` (supercedes Mar 1978) | O |
-| `TM8E` | Write protect patch to `TM8E.PA` | `21.61.1H` | Feb/Mar-80 | New `TM8E` Source. Too hard to correct. | |
-
-
-### OS/8 Extension Kit V3D Patches
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| `SABR` | Line buffer problem in `SABR` | `21.91.1M` | Oct/Nov-79 | `SABR-21.91.1M-v18B.patch8` | AV |
-| `BASIC.UF` | `BASIC.UF` Incompatible from OS/8 V3C | `31.5.1M` | Aug/Sep-78 | `BASIC.UF-31.5.1M-V5B.patch8` Source also in _DSN_. | AV |
-| `BLOAD` | `BLOAD` Will not build `CCB` properly | `31.10.1M` | Feb/Mar-80 | `BLOAD-31.10.1M-v5B.patch8` | AV |
-| `BRTS` | `IOTABLE` Overflow | `31.11.1M` | Mar-78 | `BRTS-31.11.1-M-v5b.patch8` | AV |
-| | `BASIC` `PNT` Function | `31.11.2O` | Jun/Jul-78 | `BRTS-31.11.2-O.patch8` (superceds/corrects Mar 1978) | AV |
-| | Line size on output of `BASIC` | `31.11.3O` | Jun/Jul-78 | `BRTS-31.11.3-O.patch8` | AV |
-| | Change line printer width | `31.11.4F` | Oct/Nov-79 | Optional change of width to 132 columns | |
-| | Patch to `BRTS` for addressing `LAB 8/E` functions | `31.11.5M` | Oct/Nov-79 | `BRTS-31.11.5-x.patch8` (`BASIC.UF` patch is a prerequisite.) | AV |
-| `TECO` | Changing the default `EU` value for no `case` flagging | `31.20.1O` | Mar-78 | `TECO-31.20.01O.patch8` | AVN |
-| | Changing the default `EH` value for one line error printouts | `31.20.2O` | Mar-78 | `TECO-31.20.02O.patch8` | AVN |
-| | Removing `YANK` protection | `31.20.3O` | Mar-78 | `TECO-31.20.03O.patch8` | AVN |
-| | `SCOPE` Support for `VT05` users | `31.20.4O` | Mar-78 | `TECO-31.20.04O.patch8` | AP N |
-| | Problem with `AY` command | `31.20.5M` | Mar-78 | `TECO-31.20.05M-v5A.patch8` | AV |
-| | Conditionals inside iterations | `31.20.6M` | Mar-78 | `TECO-31.20.06M-v5B.patch8` | AV |
-| | Echoing of warning bells | `31.20.7M` | Mar-78 | `TECO-31.20.07M-v5B.patch8` | AV |
-| | `CTRL/U` Sometimes fails after `*` | `31.20.8M` | Apr/May-78 | `TECO-31.20.08M-v5.04.patch8` | AK |
-| | Multiplying by `0` in `TECO` | `31.20.10M` | Apr/May-78 | `TECO-31.20.10M-v5.05.patch8` | AV |
-| | `Q` registers don't work in 8K | `31.20.11M` | Apr/May-78 | `TECO-31.20.11M-v5.06.patch8` | AV |
-| | Can't skip over `W` | `31.20.12M` | Apr/May-78 | `TECO-31.20.12M-v5.07.patch8` | AV |
-| | Unspecified iterations after inserts | `31.20.13M` | Oct/Nov-78 | `TECO-31.20.13M-v5.08.patch8` (Corrected from Jun/Jul 78) | AV |
-| | New features in `TECO V5` | `31.20.14` N | Aug/Sep-78 | Documentation Only | |
-| `FUTIL` | `FUTIL` Patch | `31.21.1M` | Apr/May-78 | `FUTIL-31.21.1M-v7B.patch8` | AV |
-| | Fix `SHOW CCB` and mapping of `CD` modules | `31.21.2M` | Oct/Nov-78 | `FUTIL-31.21.2M-v7D.patch8` (Corrected from Aug/Sep 78) | AV |
-| | Optional: change `XS` format from `excess-240` to `excess-237`. Useful for viewing `COS` data files. | `31.21.3O` | Aug/Sep-78 | `FUTIL-31.21.3O.patch8` | AVN |
-| | `FUTIL` Patch to `MACREL`/`LINK` overlays | `31.21.4 N` | Jun/Jul-79 | Documentation Only | |
-| `MSBAT` | `DIM` Statement not working in `MSBAT` | `31.22.1M` | Dec 78/Jan-79 | `MSBAT-31.22.1M-v3B.patch8` | AV |
-| `BATCH` | `MANUAL INTERVENTION REQUIRED` Erroneously | `31.23.1M` | Aug/Sep-78 | `BATCH-31.23.1M-v7B.patch8` | AV |
-
-
-### OS/8 FORTRAN IV V3D Patches
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| `F4` | `EQUIVALENCE` Statement | `02M` / `21.1.2M` | Dec/Jan-80 | `F4-21.1.2M-v4B.patch8` (Revised, Oct 77: `F4` and `PASS3` not `FRTS` patched.) | AP |
-| | `FORTRAN` Compiler fails to recognize `"` as an error | `51.3.1M` | Jun/Jul-78 | `F4-51.3.1M-v4C.patch8` (Corrects March 1978) | AP |
-| | `FORTRAN` Compiler not recognizing syntax error | `51.3.2M` | Jun/Jul-78 | `F4-51.3.2M-v4x.patch8` | AP |
-| | `FORTRAN` runtime system 2-page handler | `51.3.3O` | Oct/Nov-78 | `FRTS-51.3.3-O.patch8` Needed for RL02. (Corrected from Aug/Sep 78) | A |
-| | Restriction with subscripted variables | `51.3.4R` | Aug/Sep-80 | Documentation: `FIV` `FORTRAN IV` will not allow subscripting to be used on both sides of an arithmetic expression. | |
-| `FORLIB` | `FORTRAN IV` `DLOG` Patch | `51.10.1M` | Feb/Mar-80 | `FORLIB-51.10.1M.patch8` (apply to `DLOG.RA`) | AV |
-
-
-### OS/8 MACREL/LINKER V1A Patches
-
-These patches are listed for completeness. The version numbers don't
-match. We lack source so we cannot verify them. we've moved on to
-`MACREL` v2 as canon.
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| `LINK` | Patch `V1D` to `LINK` | `40.2.1M` | Apr/May-78 | `LINK-40.2.1M-v1D.patch8` | O |
-| | Patch `VIE` to `LINK` | `40.2.2M` | Apr/May-78 | `LINK-40.2.2M-v1E.patch8` | O |
-| | `LINK` Corrections | `40.2.3M` | Apr/May-78 | `LINK-40.2.3M-v1F.patch8` | O |
-| `MACREL` | Patch `V1D` to `MACREL` | `40.5.1M` | Apr/May-78 | `MACREL-40.5.1M-v1D.patch8` | OD |
-| | Patch `V1E` to `MACREL` | `40.5.2M` | Apr/May-78 | `MACREL-40.5.2M-v1E.patch8` | OD |
-| `OVRDRV` | Patch `V1B` to `OVRDRV.MA` | `40.6.1M` | Apr/May-78 | `OVRDRV-40.6.1M-v1B-8srccom` | O |
-
-
-### OS/8 V3D Device Extensions December 1978 Patches
-
-**WARNING**: Do not use this kit without first consulting _DSN_ Apr/May 1979.
-See also: [Our OS/8 Device Extensions documentation][os8ext]
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| `FRTS` | `FRTS` Patch | `35.1.3M` | Apr/May-79 | | |
-| `MONITOR` | `MONITOR` `V3S` Patch | `35.2.1M` | Apr/May-79 | | |
-| `FUTIL` | `FUTIL` hangs under `BATCH` | `35.13.1M` CRITICAL! | Apr/May-79 | | AV |
-| `PAL8` | `EXPUNGE` Patch to `PAL8` | `35.14.1M` | Feb/Mar-80 | `PAL8-35.14.1M-v13B.patch8` | AN |
-| `ABSLDR` | Loader problem with `SAVE` image files | `21.29.1M` | Oct/Nov-80 | `ABSLDR-21.29.1M-v6C.patch8` (Supercedes June/July 1980) Bad: v6B was with OS/8 Device Extensions. | OB |
-| `ABSLDR` | `ABSLDR` Patch | `35.18.1M` | Apr/May-79 | | |
-| `BLOAD` | `BLOAD` Will not build `CCB` properly | `35.51.1M` | Feb/Mar-80 | `BLOAD-35.51.1M-v5C.patch8` | ON |
-
-
-### OS/8 MACREL/LINKER V2A Patches
-
-These patches have not been turned into files. Armed with newly
-discovered sources verification is possible. Work on these will begin
-soon.
-
-| Component | Issue | Sequence | Mon/Yr | Notes | Status |
-| ------ | ------ | ------ | ------ | ------ | ------ |
-| User's |`EXPUNGE` Documentation error | `41.1.1N` | Jun/Jul-79 | | |
-| Guide | `MACREL` Version numbers: `MACREL` is `V2C` not `V2D`; `LINK` is `V2A` not `V2B`. | `41.1.2N` | Jun/Jul-79 | | |
-| | Macro restriction in `MACREL` | `41.1.3N` | Aug/Sep-79 | | |
-| | Error in `.MCALL` macro example | `41.1.4N` | Feb/Mar-80 | | |
-| `KREF` | Correct printing of numeric local symbols | `41.3.1M` | Apr/May-80 | | |
-| `MACREL` | `EXPUNGE` Patch to `MACREL` | `41.4.1F` | Jun/Jul-79 | | |
-| | Inconsistencies in `MACREL` error reporting | `41.4.2N` | Aug/Sep-79 | | |
-| | Forward reference patch to `MACREL` | `41.4.3M` | Aug/Sep-79 | | |
-| | Correct macro substring problem | `41.4.4M` | Apr/May-80 | | |
-| | Correct printing of numeric local symbols | `41.4.5M` | Apr/May-80 | | |
-| `OVRDRV` | Correct `CDF` problem | `41.5.1M` | Dec/Jan-80 | Source change applied by hand. | AV |
-| `FUTIL` | `FUTIL` hangs under `BATCH` | `35.13.1M` | Apr/May-79 | Critical to proper operation of our automated builder. Applied by hand to the `MACREL` v2 integration. | AV |
-
-
-
-### License
-
-Copyright © 2017 by Bill Cattey. Licensed under the terms of
-[the SIMH license][sl].
-
-[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
-[os8ext]: https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-v3d-device-extenaions.md
-
DELETED doc/os8-v3d-device-extensions.md
Index: doc/os8-v3d-device-extensions.md
==================================================================
--- doc/os8-v3d-device-extensions.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# OS/8 V3D Device Extensions
-
-The _OS/8 V3D Device Extensions_ kit (product code `QF026`) was released
-in December 1978. It was created to support the newest PDP-8 hardware:
-
-* The `KT8A` Memory Management option which enables addressing by a
- factor of four beyond the previous maximum of 32K to a whopping
- 128K of memory. The highest memory field for a PDP-8a goes up from
- 7 to 37 (octal).
-
-* The `RL01` disk supporting 4 times the previous usual disk capacity,
- now up to nearly 5 Meg.
-
-* The `RX02` double-density floppy disks.
-
-* Device drivers `VXSY` and `VXNS` enables use of `KT8A` extended
- memory as a file oriented system or non-system device.
-
-This distribution contains software updates:
-
-* A version of `BUILD`, the system builder that could run under
- `BATCH`. The previous version would just hang.
-
-* An update to the OS/8 system including `Keybord Monitor` version
- 3S, and a version of `ODT` that works with memory fields greater
- than 7.
-
-* `ABSLDR` version 6A supports loading into memory fields greater
- than 7.
-
-* `PAL8` version 13A allows code to specify memory fields greater
- than 7.
-
-* `CCL` version 7A updates the 'MEMORY' command to recognize up
- to 128K words of memory.
-
-* `PIP` version 14A knows the sizes of the new devices, and has
- updated how it copies in the monitor system head.
-
-* `RESORC` version 5A includes new devices.
-
-* `BOOT` version 5A boots new devices.
-
-* `RXCOPY` version 4B formats and copies single and double density
- floppies.
-
-* `FUTIL` version 8A recognizes new core control block format that
- can represent extended above field 7.
-
-The _OS/8 V3D Device Extensions User's Guide_ can be found
-in [Willem van der Mark's PDP-8 doc archive][vdmdoc], under
-[OS/8 - Device Extensions - User's Guide - December 1978 AA-D319A-TA.pdf][vdmextensions].
-or on the [ftp.dbit.com pdp8 doc archive][dbitdoc] at [devextug.doc --
-OS/8 Device Extensions User's Guide][dbitug]
-
-The release notes can be found on ftp.dbit.com at [devextrn.doc OS/8
-Device Extensions Release Notes ][dbitrn].
-
-Details on how the `KT8A` Memory Extension hardware works, physically
-and programatically, can also be found at Willem van der Mark's site:
-[vandermark.ch ... Emulator.128KMemory/EK-KT08A-UG_jul78-ocr.pdf][kt8adoc].
-
-When reference is made to `PAL8` version 13, that version originally came
-from this kit.
-
-The distribution DECtape for this kit, part number `AL-H525A-BA` has
-not yet been found. The PDP-8 Software Components Catalog July 1979
-gives no part number for a Source DECtape distribution of this kit.
-There is an RK05 source distribution, part number
-`AN-H529A-SA`. However, plausable source and binary have recently been
-found!
-
-The binaries were on someone's local hard disk and not published to
-the net anywhere I could find. Sadly those binaries did not include
-the DECtape's system area, and so the updated version of the OS/8
-Keyboard Monitor, Command Decoder and `ODT` seemed lost until a tape
-could be found. It appears that the original source of these .en files
-is Johnny Billingquist's site, [ftp.update.uu.se ... dectape1][uuseext1].
-
-Then, however, a self-extracting archive called, `os8v3f.exe` was
-found on a mirror site of ibiblio.org, [rtk.mirrors.pdp-11.ru
-... fromhichols][rtknicnols]. Mainline ibiblio.org didn't have it, perhaps it was
-purged because of its `.exe` extension. The archive is also available
-directly from [ftp.update.uu.se ... fromnichols][uusenichols], but at slow speed.
-
-When that archive was extracted, the manifest of source files
-corresponds exactly to the manifest of binaries in the Extensions Kit
-file archive are present. This looks quite promising for a future
-project to upgrade to OS/8 V3D with the Device Extensions software,
-and to create system packs useful even on PDP-8a hardware with 128K
-words of memory!
-
-After comparing sources found for OS/78, and OS/278, as well as Willem
-van der Mark's locally modified sources labeled OS/8 version 4, I have
-moderate confidence that these sources will enable validation and
-integration of most, if not all the OS/8 V3D Device Extensions
-functionality.
-
-[rtknichols]: http://rtk.mirrors.pdp-11.ru/ftp.update.uu.se/pdp8/pdp-8/fromnichols/
-[uuseext1]: ftp://ftp.update.uu.se/pub/pdp8/pdp-8/os8/os8.v3d/binaries/devext/dectapes/dectape1/
-[uusenichols]: ftp://ftp.update.uu.se/pub/pdp8/pdp-8/fromnichols/
-
-## FUTIL
-
-This validation has been done with regards to `FUTIL`.
-
-The `MACREL` v2 tape shipped with version 8A of `FUTIL`. That was
-necessary because V2 of `MACREL` supported the latest memory
-expansion, and so the OS/8 Core Control Block format needed to change.
-
-`FUTIL` version 8A integrated patches for `FUTIL` version 7 into the
-source. Finding those patches in the version 8A source strongly
-increased my confidence in those patches.
-
-Unfortunately the `FUTIL.SV` verson 8A executable was saved
-incorrectly and then shipped. The Core Control Block setting and
-starting address were mis-specified. So `FUTIL` version 8A *hangs*
-when run under `BATCH`.
-
-The [April-May 1979][dsn1979apr] issue of _PDP-8 Digital Software
-News_ contained patch `35.13.1M` which fixed this problem and upgraded
-`FUTIL` to version 8B. I've confirmed both the problem and the fix.
-
-Currently if you opt in to having `MACREL` on the system packs, you
-get `MACREL` v2 and `FUTIL` version 8B. If leave `MACREL` out, you get
-`FUTIL` version 7. The automated pack builder recognizes that the
-version 7 patches won't apply to version 8, and fails to apply them.
-The research I did on the OS/8 Device Extensions kit and on
-`MACREL` increased my confidence about the `FUTIL` version 7 patches.
-
-See also [our documentation on the `MACREL` integration][macreldoc]
-and [our documentation on applying OS/8 patches][patchdoc].
-
-### License
-
-Copyright © 2017 by Bill Cattey. Licensed under the terms of
-[the SIMH license][sl].
-
-[vdmdoc]: http://vandermark.ch/pdp8/index.php?n=PDP8.Manuals
-[vdmextensions]: http://vandermark.ch/pdp8/uploads/PDP8/PDP8.Manuals/AA-D319A-TA.pdf
-[dbitdoc]: ftp://ftp.dbit.com/pub/pdp8/doc/
-[dbitug]: ftp://ftp.dbit.com/pub/pdp8/doc/devextug.doc
-[dbitrn]: ftp://ftp.dbit.com/pub/pdp8/doc/devextrn.doc
-[kt8adoc]: http://www.vandermark.ch/pdp8/uploads/Emulator/Emulator.128KMemory/EK-KT08A-UG_jul78-ocr.pdf
-[dsn1979apr]: http://bitsavers.org/pdf/dec/pdp8/softwarenews/198010_PDP8swNews_AA-K629A-BA.pdf
-[macreldoc]:https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-macrel.md
-[macreldoc]:https://tangentsoft.com/pidp8i/doc/trunk/doc/os8-patching.md
-[sl]: https://tangentsoft.com/pidp8i/doc/trunk/SIMH-LICENSE.md
-
Index: doc/pidp8i-test.md
==================================================================
--- doc/pidp8i-test.md
+++ doc/pidp8i-test.md
@@ -1,6 +1,6 @@
-# PiDP-8/I PCB Test Program
+# PCB Test Program
## Compiling and Installing
`pidp8i-test` is a simple program to test [Oscar Vermeulen's PiDP-8/I
@@ -8,40 +8,28 @@
the other software with the normal `make` process.
## Running It
-If you're running one of the [binary OS images][devhome], simply give
-these commands:
+If you are building the software on the Pi for the first time, log out
+of your user account after installing it, then back in so that the
+install script's changes to your user's `PATH` take effect.
+
+Thereafter, simply give these commands:
$ sudo systemctl stop pidp8i
- $ pidp8i-test
+ $ pidp8i-test
The first command ensures that the modified PDP-8 simulator is stopped
during the test, since only one program can be talking to the switch and
LED array at a given time. (This also applies to other programs like
[Deeper Thought 2][dt2].)
-If you built the PiDP-8/I software from source atop some other Raspberry
-Pi operating system installation, you will have to log out and back in
-after installing the software so the installer's adjustments to your
-`PATH` take effect. Then you can use the commands above.
-
## Test Procedure
-The test normally proceeds automatically forward, but you can take
-control of the test sequence with these keys:
-
-| Key | Effect
-| --------------------------------- | ------
-| ↑ or → | Skip to next test
-| ↓ or ← | Go back to previous test
-| R | Resume auto-advance behavior
-| X or Ctrl-C | Exit program
-
-Any of the arrow keypresses stop the auto-advancing behavior.
+You can at any time hit Ctrl-C to stop the test.
The test proceeds as follows:
* All On test:
@@ -104,9 +92,8 @@
This document is licensed under the same terms as the associated
[`src/test.c` program][program].
-[devhome]: https://tangentsoft.com/pidp8i/
[project]: http://obsolescence.wix.com/obsolescence#!pidp-8
[dt2]: https://github.com/VentureKing/Deeper-Thought-2
[program]: https://tangentsoft.com/pidp8i/doc/trunk/src/test.c
Index: doc/uwfocal-manual-supp.md
==================================================================
--- doc/uwfocal-manual-supp.md
+++ doc/uwfocal-manual-supp.md
@@ -71,16 +71,16 @@
modern paste-through-SSH speeds doesn't affect OS/8 itself, so we'll use
it as an intermediary:
.R PIP
*HELLO.DAWhy Did We Write This?
+------------------------------------------------------------------------
+
+## Coccyges
+
+### Why Did We Write This?
[The Manual][uwfm] is well written as far as it goes, but there are
gaps:
+
+1. It inspires questions in the reader's mind without providing an
+ answer. While that is actually a hallmark of a good book, the U/W
+ FOCAL manual sometimes does it for topics that are properly within
+ its scope and so should be answered within.
+
+1. It omits coverage for some topics we wish it would cover, though
+ they are not properly within its scope.
1. It is written somewhat generically for the whole PDP-8 family as of
late 1978, whereas the PiDP-8/I project is focused on a single model
from 1968. Those not familiar with the differences can therefore be
confused by some of its directions.
@@ -853,21 +865,15 @@
1. There are multiple versions of U/W FOCAL; the version covered by
[the Manual][uwfm] isn't the one we actually ship. Our two
[other][uwfr] primary [sources][uwfd] also do not cover exactly the
version of U/W FOCAL we ship.
-1. It inspires questions in the reader's mind without providing an
- answer. Whether this was intentional — with the author intending
- that the user answer these questions on his own — or otherwise, some
- of these questions we felt needed answering here within the PiDP-8/I
- U/W FOCAL documentation.
-
This document is our attempt to fill these gaps and to supplement those
other documents. [Extensions and corrections][hack] are welcome.
-## References
+### References
The primary sources for this supplement are:
* [U/W FOCAL Manual][uwfm], October 1978, by Jim van Zee of the
University of Washington.
@@ -878,18 +884,16 @@
* [DECUS Submission for U/W FOCAL][uwfd], also by van Zee, from August
1978.
This document describes the OS/8 version of U/W FOCAL rather than
- the paper tape version described by [the Manual][uwfm] we use as our
- primary document here within the PiDP-8/I project. We chose to
- convert the Manual to Markdown rather than this DECUS submission
- because the DECUS document's scan is terrible, resulting in nearly
- worthless OCR output; we *really* did not want to retype the whole
- thing! Additionally, we think the Manual is a better tutorial than
- the DECUS submission, though the DECUS submission is perhaps a
- better reference text.
+ the paper tape version described by the Manual. We chose to convert
+ the Manual to Markdown rather than this DECUS submission because the
+ scan is terrible, resulting in nearly worthless OCR output; we
+ *really* did not want to retype the whole thing! On balance, we
+ think the Manual is a better tutorial than the DECUS submission,
+ though the DECUS submission is perhaps a better reference text.
[df8]: http://www.ibiblio.org/pub/academic/computer-science/history/pdp-8/FOCL69%20Files/DEC-08-AJAD-D.pdf
[f71]: http://svn.so-much-stuff.com/svn/trunk/pdp8/src/decus/focal8-177/
[hack]: https://tangentsoft.com/pidp8i/doc/trunk/HACKERS.md#patches
[uwfd]: http://www.pdp8.net/pdp8cgi/query_docs/view.pl?id=191
Index: doc/uwfocal-manual.md
==================================================================
--- doc/uwfocal-manual.md
+++ doc/uwfocal-manual.md
@@ -1751,11 +1751,11 @@
'stop-on-character' capability, making it difficult for UWF to keep up
with the data once the tape has started moving. By way of an example,
the following command will read in 50 numbers from the high-speed
reader:
- O R; FOR I=1,50; ASK DATA(I); NEXT; O I,E
+ O R; FOR 1=1,50; ASK DATA(I); NEXT; O I,E
Notice that an `O I,E` command is used at the end of the loop to restore
input to the keyboard. If this command were omitted the H.S. reader
would continue to be used for input, probably causing an error to occur
since it is unlikely that the next data value on the tape would
@@ -2246,11 +2246,11 @@
Similarly, the `FMIN` function can be used to avoid typing nonexistent
values when dumping an array in a multi-column format. In this example,
`C` is the number of columns and `N` the number of data values in the
array:
- FOR I=1,C,N; FOR J=I,FMIN(N,C+I-1); TYPE Q(J); NEXT; TYPE !
+ FOR 1=1,C,N; FOR J=I,FMIN(N,C+I-1); TYPE Q(J); NEXT; TYPE !
As a final example, an entire array can be scanned for its extrema
simply by comparing each element with the previous best estimates:
SET MIN=MAX=A(1); FOR I=2,N; SET MIN=FMIN(A(I),MIN), MAX=FMAX(A(I),MAX)
Index: examples/README.md
==================================================================
--- examples/README.md
+++ examples/README.md
@@ -31,11 +31,11 @@
To use the example BASIC program, simply transcribe it into OS/8 BASIC:
.R BASIC
NEW OR OLD--NEW
- FILE NAME--PEP001.BA
+ FILE NAME--PAL001.BA
READY
10 FOR I = 1 TO 999
10 FOR I = 1 TO 999
20 A = I / 3 \ B = I / 5
@@ -49,11 +49,11 @@
SAVE
READY
RUN
- PEP001 BA 5A
+ PAL001 BA 4A
TOTAL: xxxxxxx
READY
BYE
@@ -69,22 +69,21 @@
OS/8 Handbook for a decoding guide.
## How to Use the Assembly Language Examples
-For each PAL8 assembly program in `asm/*.pal` or `examples/*.pal`, the
-build process produces several output files:
-
-| Extension | Meaning
-| --------------- | ---------------
-| `*.pal` | the PAL8 assembly source code for the program; input to the process
-| `obj/*.lst` | the human-readable assembler output
-| `bin/*-pal.pt` | the machine-readable assembler output (RIM format)
-| `boot/*.script` | a SIMH-readable version of the assembled code
-
-Each of those files has a corresponding way of getting the example
-running in the simulator:
+For each PAL8 assembly program in `asm/*.pal` or `examples/*.pal`,
+there are two additional files:
+
+| Extension | Meaning
+-----------------------------
+| `*.pal` | the PAL8 assembly source code for the program
+| `obj/*.lst` | the human-readable assembler output
+| `bin/*-pal.pt` | the machine-readable assembler output (RIM format)
+
+There are three ways to run these on your PiDP-8/I, each starting with
+one of the above three files:
1. Transcribe the assembly program text to a file within a PDP-8
operating system and assemble it inside the simulator.
2. Toggle the program in from the front panel. I can recommend this
@@ -91,17 +90,15 @@
method only for very short programs.
3. Copy the `*-pal.pt` file to a USB stick and use the PiDP-8/I's
[automatic media mounting feature][howto]. This is the fastest method.
-4. Boot SIMH with the example in core, running the program immediately.
-
I cover each of these options below, in the same order as the list
above.
-### Option 1: Transcribing the Assembly Code into an OS/8 Session
+## Option 1: Transcribing the Assembly Code into an OS/8 Session
To transcribe [`examples/add.pal`][pal] into the OS/8 simulation on a
PiDP-8/I:
.R EDIT
@@ -173,18 +170,17 @@
.R PIP
*ADD.PA 1000) {
- printf("%d + ", st);
- st = 0;
- }
- }
-
- printf("%d\n", st);
-}
DELETED examples/pep001.fc
Index: examples/pep001.fc
==================================================================
--- examples/pep001.fc
+++ /dev/null
@@ -1,7 +0,0 @@
-01.10 SET TOTAL = 0
-01.20 FOR I = 3, 999 ; DO -.3
-01.30 IF (FRAC(I / 3)) , 1.5
-01.40 IF (FRAC(I / 5)) , 1.5, 1.6
-01.50 SET TOTAL = TOTAL + I
-01.60 NEXT
-01.70 TYPE "TOTAL: ", %6, TOTAL, !
Index: lib/mkos8/argparser.py
==================================================================
--- lib/mkos8/argparser.py
+++ lib/mkos8/argparser.py
@@ -29,43 +29,63 @@
# use or other dealings in this Software without prior written
# authorization from those authors.
########################################################################
import argparse
-import opts
class ArgParser (argparse.ArgumentParser):
def __init__ (self, allowed_acts):
- # Call parent class ctor to initialize the arg parser
argparse.ArgumentParser.__init__ (self,
description = 'Build OS/8 RK05 disk images')
- # Add general-purpose args
- self.add_bool ('-d', '--debug',
- help = 'add extra debugging output, normally suppressed')
self.add_bool ('-v', '--verbose',
help = 'verbose SIMH output instead of progress messages')
-
- # Add arguments corresponding to --*-os8-* configure script options
- for obn, vals in opts.opts.iteritems():
- od = 'dis' if vals[0] else 'en'
- self.add_bool ('--' + od + 'able-' + obn, help = vals[1])
-
- # Add options that do not exactly mirror configuration options
+ self.add_bool ('--enable-music',
+ help = 'add *.MU files to binary disk')
+ self.add_bool ('--disable-ba',
+ help = 'leave BASIC games and demos off binary disk')
+ self.add_bool ('--disable-cc8',
+ help = 'leave CC8 off binary disk')
+ self.add_bool ('--disable-dcp',
+ help = 'leave DCP disassembler off binary disk')
+ self.add_bool ('--disable-focal',
+ help = 'leave FOCAL 69 and U/W FOCAL off binary disk')
+ self.add_bool ('--enable-focal69',
+ help = 'install FOCAL 69 on the binary disk')
+ self.add_bool ('--disable-uwfocal',
+ help = 'leave U/W FOCAL (only) off binary disk')
+ self.add_bool ('--disable-fortran-ii',
+ help = 'leave FORTRAN II compiler off binary disk')
+ self.add_bool ('--disable-fortran-iv',
+ help = 'leave FORTRAN IV compiler off binary disk')
+ self.add_bool ('--disable-init',
+ help = 'suppress display of the INIT message on OS/8 boot')
+ self.add_bool ('--disable-k12',
+ help = 'leave 12-bit Kermit off binary disk')
+ self.add_bool ('--disable-macrel',
+ help = 'leave MACREL assembler off binary disk')
+ self.add_bool ('--enable-vtedit',
+ help = 'install and enable TECO VTEDIT mode')
+ self.add_bool ('--disable-crt',
+ help = 'console is a printing terminal and does not use ' +
+ 'character overwrite on rubout')
self.add_bool ('--disable-lcmod',
help = 'disable the OS/8 command upcasing patch; best set ' +
'when SIMH is set to tti ksr mode')
+ self.add_bool ('--disable-advent',
+ help = 'leave game of Adventure off binary disk')
+ self.add_bool ('--disable-chess',
+ help = 'leave CHEKMO-II off binary disk')
- # Add trailing "what do do" argument
self.add_argument (
'what',
choices = allowed_acts,
help = 'select which RK05 media gets built; default is "all"',
nargs = argparse.REMAINDER)
- # Finish initializing
self.args = self.parse_args()
+
if len (self.args.what) == 0: self.args.what = [ 'all' ]
def add_bool (self, *args, **kwargs):
kwargs['action'] = 'store_true'
Index: lib/pidp8i/__init__.py.in
==================================================================
--- lib/pidp8i/__init__.py.in
+++ lib/pidp8i/__init__.py.in
@@ -32,6 +32,6 @@
# shall not be used in advertising or otherwise to promote the sale,
# use or other dealings in this Software without prior written
# authorization from those authors.
########################################################################
-__all__ = [ 'dirs', 'ips' ]
+__all__ = [ 'dirs' ]
Index: lib/pidp8i/dirs.py.in
==================================================================
--- lib/pidp8i/dirs.py.in
+++ lib/pidp8i/dirs.py.in
@@ -44,15 +44,14 @@
build = "@builddir@"
src = "@abs_top_srcdir@"
# Derived directories. Where it matters, these are the development tree
# paths, overridden or adjusted below if we're installed.
-bin = os.path.join (build, "bin/")
-log = os.path.join (build, "obj/")
-media = os.path.join (src, "media/")
-os8mi = os.path.join (media, "os8/") # mkos8 inputs
-os8mo = bin # mkos8 outputs
+bin = build + "/bin/"
+log = build + "/obj/"
+media = src + "/media/os8/"
+os8 = bin
# Adjust paths for the "installed" case
if not os.path.exists(log):
# The obj/ dir doesn't exist in the install tree
log = "/tmp/"
DELETED lib/pidp8i/ips.py.in
Index: lib/pidp8i/ips.py.in
==================================================================
--- lib/pidp8i/ips.py.in
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-########################################################################
-# ips.py.in - Defines the default instructions per second value.
-#
-# This file is a .in file purely to provide the default version of
-# ips.py which can be appended to by running bin/teco-pi-demo -b on
-# the target hardware to provide a better local IPS value.
-#
-# Copyright © 2017 by Warren Young
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-# Approximate IPS rate for a PDP-8/I based on one fact:
-#
-# 1. The core cycle time of a PDP-8/I is 1.5 µs.
-#
-# ...and one assumption:
-#
-# 2. PDP-8 systems execute instructions at varying rates from roughly 1
-# core cycle time up to many core cycle times. Most of the core
-# PDP-8 instructions not involving I/O take 1-2 cycles, with I/O
-# taking longer, so we assume that the average for typical real
-# world PDP-8 code will average to 2 cycles per instruction.
-#
-# Thus, this value is the inverted cycle time divided by 2.
-pdp8i = 333333
-
-# A Raspberry Pi B+ running pidp8i-sim unthrottled executes PDP-8 code
-# faster than a real PDP-8/I by the factor given, so that running the
-# teco-pi-demo benchmkark (-b) it shows a factor of about 1.0. This
-# gives us the lowest possible IPS value short of throttling the sim,
-# underclocking the Pi, or starving the simulator of CPU power.
-raspberry_pi_b_plus = pdp8i * 5.6
-
-# Initial value; teco-pi-demo -b appends overrides for this
-current = raspberry_pi_b_plus
-
-# Benchmark results:
Index: lib/simh.py
==================================================================
--- lib/simh.py
+++ lib/simh.py
@@ -2,12 +2,10 @@
# -*- coding: utf-8 -*-
########################################################################
# simh/__init__.py - A wrapper class around pexpect for communicating
# with an instance of the PiDP-8/I SIMH simulator running OS/8.
#
-# See ../doc/class-simh.md for a usage tutorial.
-#
# Copyright © 2017 by Jonathan Trites, William Cattey, and Warren Young.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
@@ -31,94 +29,31 @@
# shall not be used in advertising or otherwise to promote the sale,
# use or other dealings in this Software without prior written
# authorization from those authors.
########################################################################
-import os.path
import pexpect
import pkg_resources
-import subprocess
-import tempfile
import time
-import pidp8i
-
class simh:
# pexpect object instance, set by ctor
_child = None
- # Constant used by os8_kbd_delay, assembled in stages:
- #
- # 1. PDP-8 RS-232 bits per character: 7-bit ASCII plus necessary
- # start, stop, and parity bits.
- #
- # 2. The ratio of the instructions per second ratios of a PDP-8/I to
- # that of the host hardware running the simulator. The former is
- # an approximate value; see lib/pidp8i/ips.py.in for the value and
- # its defense. The latter is either the IPS rate for:
- #
- # a) a Raspberry Pi Model B+, that being the slowest host system
- # we run this simulator on; or
- #
- # b) the IPS rate of the actual host hardware if you have run the
- # "bin/teco-pi-demo -b" benchmark on it.
- #
- # 2. The fact that real PDP-8s ran OS/8 reliably at 300 bps, and have
- # been claimed to get flaky as early as 600 bps by some. (Others
- # claim to have run them up to 9,600 bps.)
- #
- # 3. The "safe BPS" value is the fastest bit per second speed actual
- # PDP-8 hardware was known to run OS/8 terminal I/O at. In this
- # case, it is the high-speed tape reader.
- #
- # TODO: We may be able to increase this.
- #
- # We have one report that OS/8 was tested with terminals up to
- # about ~600 bps before becoming unreliable.
- #
- # We have another report that OS/8 could run under ETOS with
- # 9,600 bps terminals, but we don't know if that tells us anything
- # about OS/8 running without the ETOS multitasking hardware.
- #
- # 4. Given above, calculate safe characters per second for host HW.
- #
- # 5. Invert to get seconds per character, that being the delay value.
- _bpc = 7 + 1 + 1 + 1 # [1]
- _ips_ratio = float (pidp8i.ips.current) / pidp8i.ips.pdp8i # [2]
- _pdp8i_safe_bps = 300 # [3]
- _host_safe_cps = _pdp8i_safe_bps * _ips_ratio / _bpc # [4]
- _os8_kbd_delay = 1 / _host_safe_cps # [5]
-
#### ctor ############################################################
- # The first parameter must be given as the parent of bin/pidp8i-sim.
- #
- # The second defaults to false, meaning that a failure to lock the
- # GPIO for the caller's exclusive use is a fatal error. If you pass
- # True instead, we just complain if the GPIO is already locked and
- # move on. This tolerant mode is appropriate for programs that need
- # the simulator alone, not actually the PiDP-8/I front panel display.
-
- def __init__ (self, basedir, ignore_gpio_lock = False):
+
+ def __init__ (self, basedir):
# Start the simulator instance
self._child = pexpect.spawn(basedir + '/bin/pidp8i-sim')
# Turn off pexpect's default inter-send() delay. We add our own as
# necessary. The conditional tracks an API change between 3 and 4.
pev4 = (pkg_resources.get_distribution("pexpect").parsed_version >
pkg_resources.parse_version("4.0"))
self._child.delaybeforesend = None if pev4 else 0
- # Wait for either an error or the simulator's configuration line.
- if not self.try_wait (\
- '^PiDP-8/I [a-z].*\[.*\]', \
- 'Failed to lock /dev/gpiomem', timeout = 3):
- if ignore_gpio_lock:
- print "WARNING: Failed to lock GPIO for exclusive use. Won't use front panel."
- else:
- raise RuntimeError ('GPIO locked')
-
#### back_to_cmd ######################################################
# Pause the simulation and return to the SIMH command prompt when the
# simulated software emits the given prompt string. Typically used to
# wait for OS/8 to finish running a command so we can do something
@@ -127,59 +62,32 @@
def back_to_cmd (self, prompt):
self._child.expect ("\n%s$" % prompt)
self.os8_kbd_delay ()
self._child.sendcontrol ('e')
-
- #### os8_get_file ####################################################
- # Rough inverse of os8_send_file.
- #
- # Both paths must be given and are used literally. (Contrast our
- # inverse, where the destinatinon file name is produced from the
- # source if not given.)
- #
- # When this function is called to pull a file sent by our inverse, the
- # conversion should be lossless except for the transforms done by our
- # underlying utility tools, such as the LF -> CR+LF done by txt2ptp
- # but not undone by ptp2txt.
- #
- # Entry context should be inside OS/8. Exit context is inside OS/8.
-
- def os8_get_file (self, intname, extname):
- # Attach a blank paper tape to the simulator.
- ptf = tempfile.NamedTemporaryFile (suffix = '.pt', delete = False)
- ptf.close ()
- ptn = ptf.name
- self.back_to_cmd ('\\.')
- self.send_cmd ('attach ptp ' + ptn)
-
- # Punch internal file to external paper tape image
- self.os8_restart ()
- self.os8_send_cmd ('\\.', 'PUNCH ' + intname);
- self.back_to_cmd ('\\.') # wait for transfer to finish
-
- # Convert text file from SIMH paper tape format
- tool = os.path.join (pidp8i.dirs.build, 'bin', 'ptp2txt')
- self.send_cmd ('detach ptp')
- subprocess.call (tool + ' < ' + ptn + ' > ' + extname, shell = True)
-
- # Return to OS/8, just because that's where we were on entry, so we
- # should not change that.
- self.os8_restart ()
-
#### os8_kbd_delay ###################################################
# Artificially delay the media generation process to account for the
# fact that OS/8 lacks a modern multi-character keyboard input buffer.
- # It is unsafe to send text faster than a contemporary terminal could,
- # though we can scale it based on how much faster this host is than a
- # real PDP-8. See the constants above for the calculation.
+ # It is unsafe to send text faster than a contemporary terminal could.
+ #
+ # The constant is based on advice we received that OS/8 would begin to
+ # become unreliable when run with a terminal speaking more than about
+ # 600 bps. We divide that by 7-bit ASCII plus necessary start, stop,
+ # and parity bits to get characters per second. Then we multiply that
+ # by 4, the minimum number of times faster our SIMH instance runs as
+ # compared to a real PDP-8. (Keep in mind that we initially run the
+ # simulator without any throttling.) Finally, we invert that value to
+ # get secs per character instead of characters per second. OS/8 must
+ # be able to accept input at least this fast on our simulator.
+
+ _kbd_delay = 1 / (600 / (7 + 1 + 1 + 1) * 4)
def os8_kbd_delay (self):
- time.sleep (self._os8_kbd_delay)
+ time.sleep (self._kbd_delay)
- #### os8_send_cmd ####################################################
+ #### os8_send_cmd ######################################################
# Wait for an OS/8 command prompt running within SIMH, then send the
# given line.
#
# The prompt string is passed in because OS/8 has several different
# prompt types.
@@ -187,67 +95,21 @@
def os8_send_cmd (self, prompt, line):
self._child.expect ("\n%s$" % prompt)
self.os8_send_line (line)
- #### os8_send_ctrl ###################################################
+ #### os8_send_ctrl #####################################################
# Send a control character to OS/8 corresponding to the ASCII letter
# given. We precede it with the OS/8 keyboard delay, since we're
# probably following a call to os8_send_line or os8_send_cmd.
def os8_send_ctrl (self, char):
self.os8_kbd_delay ()
self._child.sendcontrol (char[0].lower ())
- #### os8_send_file ###################################################
- # Send a copy of a local text file to OS/8. The local path may
- # contain directory components, but the remote must not, of course.
- #
- # If the destination file name is not uppercase, it will be so forced.
- #
- # If the destination file name is not given, it is taken as the
- # basename of the source file name.
- #
- # The file is sent via the SIMH paper tape device through PIP in its
- # default ASCII mode, rather than character by character for two reasons:
- #
- # 1. It's faster. It runs as fast as the simulator can process the
- # I/O instructions, without any os8_kbd_delay() hooey.
- #
- # 2. It allows lowercase input regardless of the way the simulator is
- # configured. ASCII is ASCII.
- #
- # Entry context should be inside OS/8. Exit context is inside OS/8.
-
- def os8_send_file (self, source, dest = None):
- # Create path and file names not given
- bns = os.path.basename (source)
- if dest == None: dest = bns
- dest = dest.upper ()
-
- # Convert text file to SIMH paper tape format
- bdir = pidp8i.dirs.build
- pt = os.path.join (bdir, 'obj', bns + '.pt')
- tool = os.path.join (bdir, 'bin', 'txt2ptp')
- subprocess.call (tool + ' < ' + source + ' > ' + pt, shell = True)
-
- # Paper tape created, so attach it read-only and copy it in. We're
- # relying on txt2ptp to insert the Ctrl-Z EOF marker at the end of
- # the file.
- self.back_to_cmd ('\\.')
- self.send_cmd ('attach -r ptr ' + pt)
- self.os8_restart ()
- self.os8_send_cmd ('\\.', 'R PIP')
- self.os8_send_cmd ('\*', dest + '1
-
-/
- LDX 0,0
- FLDA XRDAL
- FSTA F
- FCLA
- FSTA CUM
-DALB, FLDA F
- FMUL D16 /16 REAL PARTS
- FSUB D8 /NEED JUST 8
- ATX 1
- FLDA A0,1 /GET MULTIPLIER
- FMULM F
- FLDA LA0,1 /ADD LOG(A(K)) TO SUM
- FADDM CUM
- FLDA F
- FSUB DAL1
- JLT DALB
-/NOW F>1. USE TAYLOR SERIES
-/LOG(T)=Z-(Z^2)/2+(Z^3)/3+... WHERE Z=T-1
- FLDA F
- FSUB DAL1 /F-1.0
- FSTA F
- FMUL DT7
- FADD DT6
- FMUL F
- FADD DT5
- FMUL F
- FADD DT4
- FMUL F
- FADD DT3
- FMUL F
- FADD DT2
- FMUL F
- FADD DAL1
- FMUL F
- FSUB CUM
- FADD N
- JA DALRTN
-
Index: media/os8/patches/FORLIB-51.10.1M.patch8
==================================================================
--- media/os8/patches/FORLIB-51.10.1M.patch8
+++ media/os8/patches/FORLIB-51.10.1M.patch8
@@ -3,14 +3,13 @@
# There is a problem with DLOG where it could not handle numbers smaller than
# 1.E-018 correctly. The following patch fixes this problem.
#
# Make a source change to DLOG.RA using either EDIT or TECO. Replace
# this line:
-#
-# Published patch has a typo. There is no "EADD" function. It is "FADD".
+#
# DALA, EADD DAL1 /ADD BACK
# with :
-# DALA, FLDA% BPDAL /GET ARGUMENT BACK
+# DALA, FLDA$ BPDAL /GET ARGUMENT BACK
# .R RALF
# *DLOG.RL insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+palbart \- BART enhanced PDP8 crossassembler
+.SH SYNOPSIS
+.B palbart
+.RI [options] inputfile
+.br
+.SH DESCRIPTION
+This manual page documents briefly the
+.B palbart
+command.
+It is a cross-assembler to for PDP/8 assembly language programs.
+It will produce an output file in bin format, rim format, and using the
+appropriate pseudo-ops, a combination of rim and bin formats.
+A listing file is always produced and with an optional symbol table
+and/or a symbol cross-reference (concordance). The permanent symbol
+table can be output in a form that may be read back in so a customized
+permanent symbol table can be produced. Any detected errors are output
+to a separate file giving the filename in which they were detected
+along with the line number, column number and error message as well as
+marking the error in the listing file.
+.PP
+The following file name extensions are used:
+.PP
+ .pal source code (input)
+.PP
+ .lst assembly listing (output)
+.PP
+ .bin assembly output in DEC's bin format (output)
+.PP
+ .rim assembly output in DEC's rim format (output)
+.PP
+ .err assembly errors detected (if any) (output)
+.PP
+ .prm permanent symbol table in form suitable for reading after the EXPUNGE pseudo-op.
+
+.PP
+.SH OPTIONS
+A summary of options is included below.
+.TP
+.B \-d
+Show symbol table at end of assembly
+.TP
+.B \-h
+Display help.
+.TP
+.B \-l
+Allow generation of literals (default is no literal generation)
+Show version of program.
+.TP
+.B \-p
+Generate a file with the permanent symbols in it.
+(To get the current symbol table, assemble a file than has only
+a $ in it.)
+.TP
+.B \-r
+Produce output in rim format (default is bin format)
+.TP
+.B \-v
+Display version information.
+.TP
+.B \-x
+Generate a cross-reference (concordance) of user symbols.
+
+.SH DIAGNOSTICS
+Assembler error diagnostics are output to an error file and inserted
+in the listing file. Each line in the error file has the form
+.PP
+(:) : error: at Loc =
+.PP
+An example error message is:
+.br
+bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616
+.PP
+The error diagnostics put in the listing start with a two character
+error code (if appropriate) and a short message. A carat '^' is
+placed under the item in error if appropriate.
+An example error message is:
+.PP
+ 17 07616 3000 DCA UNDEF
+.br
+ UD undefined ^
+.br
+ 18 07617 1777 TAD I DUMMY
+.PP
+When an indirect is generated, an at character '@' is placed after the
+the instruction value in the listing as an indicator as follows:
+.PP
+ 14 03716 1777@ TAD OFFPAG
+.PP
+Undefined symbols are marked in the symbol table listing by prepending
+a '?' to the symbol. Redefined symbols are marked in the symbol table
+listing by prepending a '#' to the symbol. Examples are:
+.PP
+ #REDEF 04567
+.br
+ SWITCH 07612
+.br
+ ?UNDEF 00000
+.PP
+Refer to the code for the diagnostic messages generated.
+
+.SH BUGS
+Only a minimal effort has been made to keep the listing format
+anything like the PAL-8 listing format.
+The operation of the conditional assembly pseudo-ops may not function
+exactly as the DEC versions. I did not have any examples of these so
+the implementation is my interpretation of how they should work.
+.PP
+The RIMPUNch and BINPUNch pseudo-ops do not change the binary output
+file type that was specified on startup. This was intentional and
+and allows rim formatted data to be output prior to the actual binary
+formatted data. On UN*X style systems, the same effect can be achieved
+ing the "cat" command, but on DOS/Windows systems, doing this was
+a major chore.
+.PP
+The floating point input does not generate values exactly as the DEC
+compiler does. I worked out several examples by hand and believe that
+this implementation is slightly more accurate. If I am mistaken,
+let me know and, if possible, a better method of generating the values.
+.br
+
+.SH HISTORICAL NOTE
+This assembler was written to support the fleet of PDP-8 systems
+used by the Bay Area Rapid Transit System. As of early 1997,
+this includes about 40 PDP-8/E systems driving the train destination
+signs in passenger stations.
+
+.SH REFERENCES
+This assembler is based on the pal assember by:
+.br
+Douglas Jones and
+.br
+Rich Coon
+
+.SH DISCLAIMER
+See the symbol table for the set of pseudo-ops supported.
+.PP
+See the code for pseudo-ops that are not standard for PDP/8 assembly.
+.PP
+Refer to DEC's "Programming Languages (for the PDP/8)" for complete
+documentation of pseudo-ops.
+.PP
+Refer to DEC's "Introduction to Programming (for the PDP/8)" or a
+lower level introduction to the assembly language.
+
+.SH WARRANTY
+If you don't like it the way it works or if it doesn't work, that's
+tough. You're welcome to fix it yourself. That's what you get for
+using free software.
+
+.SH COPYRIGHT NOTICE
+This is free software. There is no fee for using it. You may make
+any changes that you wish and also give it away. If you can make
+a commercial product out of it, fine, but do not put any limits on
+the purchaser's right to do the same. If you improve it or fix any
+bugs, it would be nice if you told me and offered me a copy of the
+new version.
+Gary Messenbrink
+
+.SH VERSIONS
+ Version Date by Comments
+.br
+ v1.0 12Apr96 GAM Original
+.br
+ v1.1 18Nov96 GAM Permanent symbol table initialization error.
+.br
+ v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators.
+.br
+ v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants).
+.br
+ v1.4 29Nov96 GAM Fixed bug in checksum generation.
+.br
+ v2.1 08Dec96 GAM Added concordance processing (cross reference).
+.br
+ v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants).
+.br
+ v2.3 2Feb97 GAM Fixed paging problem in cross reference output.
+.br
+ v2.4 11Apr97 GAM Fixed problem with some labels being put in cross reference multiple times.
+
+.SH AUTHOR
+This manual page was written by Vince Mulhollon ,
+for the Debian GNU/Linux system (but may be used by others).
ADDED palbart/palbart.c
Index: palbart/palbart.c
==================================================================
--- /dev/null
+++ palbart/palbart.c
@@ -0,0 +1,4352 @@
+/******************************************************************************/
+/* */
+/* Program: PAL (BART version) */
+/* File: pal.c */
+/* Author: Gary A. Messenbrink */
+/* gam@rahul.net */
+/* */
+/* Purpose: A 2 pass PDP-8 pal-like assembler. */
+/* */
+/* PAL(1) */
+/* */
+/* NAME */
+/* pal - a PDP/8 pal-like assembler. */
+/* */
+/* SYNOPSIS: */
+/* pal [ -$ -d -h -e -l -p -r -t -v -x ] inputfile */
+/* */
+/* DESCRIPTION */
+/* This is a cross-assembler to for PDP/8 assembly language programs. */
+/* It will produce an output file in bin format, rim format, and using the */
+/* appropriate pseudo-ops, a combination of rim and bin formats. */
+/* A listing file is always produced and with an optional symbol table */
+/* and/or a symbol cross-reference (concordance). The permanent symbol */
+/* table can be output in a form that may be read back in so a customized */
+/* permanent symbol table can be produced. Any detected errors are output */
+/* to a separate file giving the filename in which they were detected */
+/* along with the line number, column number and error message as well as */
+/* marking the error in the listing file. */
+/* The following file name extensions are used: */
+/* .pal source code (input) */
+/* .lst assembly listing (output) */
+/* .bin assembly output in DEC's bin format (output) */
+/* .rim assembly output in DEC's rim format (output) */
+/* .err assembly errors detected (if any) (output) */
+/* .prm permanent symbol table in form suitable for reading after */
+/* the EXPUNGE pseudo-op. */
+/* */
+/* OPTIONS */
+/* -$ Allow files to not end with $ */
+/* -d Dump the symbol table at end of assembly */
+/* -h Show help */
+/* -e Don't allow generation of links */
+/* -l Allow generation of links (default is link generation) */
+/* -n No redefinition of permanent symbols with labels */
+/* -p Generate a file with the permanent symbols in it. */
+/* (To get the current symbol table, assemble a file than has only */
+/* a $ in it.) */
+/* -r Produce output in rim format (default is bin format) */
+/* -tN Set tab stops to N spaces (default is 8) */
+/* -v Display program version. */
+/* -x Generate a cross-reference (concordance) of user symbols. */
+/* */
+/* DIAGNOSTICS */
+/* Assembler error diagnostics are output to an error file and inserted */
+/* in the listing file. Each line in the error file has the form */
+/* */
+/* (:) : error: at Loc = */
+/* */
+/* An example error message is: */
+/* */
+/* bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616 */
+/* */
+/* The error diagnostics put in the listing start with a two character */
+/* error code (if appropriate) and a short message. A carat '^' is */
+/* placed under the item in error if appropriate. */
+/* An example error message is: */
+/* */
+/* 17 07616 3000 DCA UNDEF */
+/* UD undefined ^ */
+/* 18 07617 1777 TAD I DUMMY */
+/* */
+/* When an indirect is generated, an at character '@' is placed after the */
+/* the instruction value in the listing as an indicator as follows: */
+/* */
+/* 14 03716 1777@ TAD OFFPAG */
+/* */
+/* Undefined symbols are marked in the symbol table listing by prepending */
+/* a '?' to the symbol. Redefined symbols are marked in the symbol table */
+/* listing by prepending a '#' to the symbol. Examples are: */
+/* */
+/* #REDEF 04567 */
+/* SWITCH 07612 */
+/* ?UNDEF 00000 */
+/* */
+/* Refer to the code for the diagnostic messages generated. */
+/* */
+/* BUGS */
+/* This program will accept source that real PAL will not. To ensure */
+/* valid source assemble on real or simulated PDP-8. */
+/* Different PAL versions have different permanent symbols defined. This */
+/* program define more than and PAL version. By default redefining them */
+/* as a label is not an error. It is for normal PAL. The -n flag will */
+/* make redefining an error. */
+/* */
+/* Only a minimal effort has been made to keep the listing format */
+/* anything like the PAL-8 listing format. */
+/* The operation of the conditional assembly pseudo-ops may not function */
+/* exactly as the DEC versions. I did not have any examples of these so */
+/* the implementation is my interpretation of how they should work. */
+/* */
+/* The RIMPUNch and BINPUNch pseudo-ops do not change the binary output */
+/* file type that was specified on startup. This was intentional and */
+/* and allows rim formatted data to be output prior to the actual binary */
+/* formatted data. On UN*X style systems, the same effect can be achieved */
+/* by using the "cat" command, but on DOS/Windows systems, doing this was */
+/* a major chore. */
+/* */
+/* The floating point input does not generate values exactly as the DEC */
+/* compiler does. I worked out several examples by hand and believe that */
+/* this implementation is slightly more accurate. If I am mistaken, */
+/* let me know and, if possible, a better method of generating the values. */
+/* */
+/* CDF .-. */
+/* Generates 2201 when assembled at 5000. This looks like a bug in OS/8 */
+/* PAL */
+/* */
+/* BUILD and INSTALLATION */
+/* The current version has only been built under Linux. */
+/* Earlier versions have been built and successfully executed on: */
+/* a. Linux (80486 CPU)using gcc */
+/* b. RS/6000 (AIX 3.2.5) */
+/* c. Borland C++ version 3.1 (large memory model) */
+/* d. Borland C++ version 4.52 (large memory model) */
+/* with no modifications to the source code. */
+/* */
+/* On UNIX type systems, store the the program as the pal command */
+/* and on PC type systems, store it as pal.exe */
+/* */
+/* HISTORICAL NOTE: */
+/* This assembler was written to support the fleet of PDP-8 systems */
+/* used by the Bay Area Rapid Transit System. As of early 1997, */
+/* this includes about 40 PDP-8/E systems driving the train destination */
+/* signs in passenger stations. */
+/* */
+/* REFERENCES: */
+/* This assembler is based on the pal assembler by: */
+/* Douglas Jones and */
+/* Rich Coon */
+/* */
+/* DISCLAIMER: */
+/* See the symbol table for the set of pseudo-ops supported. */
+/* See the code for pseudo-ops that are not standard for PDP/8 assembly. */
+/* Refer to DEC's "Programming Languages (for the PDP/8)" for complete */
+/* documentation of pseudo-ops. */
+/* Refer to DEC's "Introduction to Programming (for the PDP/8)" or a */
+/* lower level introduction to the assembly language. */
+/* */
+/* WARRANTY: */
+/* If you don't like it the way it works or if it doesn't work, that's */
+/* tough. You're welcome to fix it yourself. That's what you get for */
+/* using free software. */
+/* */
+/* COPYRIGHT NOTICE: */
+/* This is free software. There is no fee for using it. You may make */
+/* any changes that you wish and also give it away. If you can make */
+/* a commercial product out of it, fine, but do not put any limits on */
+/* the purchaser's right to do the same. If you improve it or fix any */
+/* bugs, it would be nice if you told me and offered me a copy of the */
+/* new version. */
+/* */
+/* */
+/* Amendments Record: */
+/* Version Date by Comments */
+/* ------- ------- --- --------------------------------------------------- */
+/* v1.0 12Apr96 GAM Original */
+/* v1.1 18Nov96 GAM Permanent symbol table initialization error. */
+/* v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators. */
+/* v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants). */
+/* v1.4 29Nov96 GAM Fixed bug in checksum generation. */
+/* v2.1 08Dec96 GAM Added concordance processing (cross reference). */
+/* v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants). */
+/* v2.3 2Feb97 GAM Fixed paging problem in cross reference output. */
+/* DJG: I started with the 2.5 RK version but found when looking on the net */
+/* later that multiple diverging version existed. I have tried to combine */
+/* the fixed into one version. I took the version info below from the versions*/
+/* I pulled from. */
+/* http://dustyoldcomputers.com/pdp-common/reference/host/index.html */
+/* http://www.dunnington.u-net.com/public/PDP-8/palbart.c */
+/* http://sourcecodebrowser.com/palbart/2.4/palbart-2_84_8c_source.html */
+/* http://packages.qa.debian.org/p/palbart.html */
+/* v2.4 11Apr97 GAM Fixed problem with some labels being put in cross */
+/* reference multiple times. */
+/* Started with RK version, Attempted to merge */
+/* GAM V2.4 and PNT change DJG */
+/* v2.4 29Oct07 RK Added 4 character tabstop; IOTs for TA8/E. */
+/* v2.4 19Jan03 PNT Added ASCII pseudo-op, like TEXT but not packed. */
+/* v2.5 03Nov07 RK Fixed buffer overflow problem in readLine and */
+/* increased symbol table size */
+/* v2.6 14Jul03 PNT Added missing TTY symbols, and "1st TTY" symbols. */
+/* v2.7 14Jun13 DJG David Gesswein djg@pdp8online.com */
+/* Merged other changes found online giving duplicate */
+/* Versions in the history */
+/* Didn't copy over deleting -l literal flag */
+/* All fixes to make it match OS/8 PAL8 better */
+/* Fixed handling of IFDEF type conditionals */
+/* Fixed excessive redefined symbol errors */
+/* PAL8 uses 12 bit symbols and this program label */
+/* symbols are 15 bit. */
+/* Added FILENAME and DEVNAME psuedo ops */
+/* Added OPR and KCF instructions. Fixed RMF */
+/* Allowed space after = */
+/* Prevented I and D from being deleted by EXPUNGE */
+/* Allowed permanent symbols to be redefined with error*/
+/* PAL8 updates without message. Error is just warning*/
+/* Fixed certain cases of memory reference generation */
+/* Allowed unary + */
+/* Fixed " character literal at end of line */
+/* Fixed errors in reloc handling */
+/* Fixed [CDF CIF type expressions */
+/* Made title default to first line */
+/* Fixed checksum when nopunch used */
+/* Fixed FIXTAB */
+/* Probably added more subtle bugs */
+/* v2.8 15Jun13 DJG Merged versions found on net. See above */
+/* Added * to RELOC addresses in listing */
+/* Changed default to literal/links on. Added -e to */
+/* turn off */
+/* Fixed PAGE when RELOC used */
+/* Changed SPF to TFL and SPI to TSK */
+/* Make error when changing permanent symbol to label */
+/* if -e flag is used */
+/* Allow space oring in IFZERO etc */
+/* Fixed handling of page zero overflow */
+/* v2.9 23Jun13 DJG Fixed properly all pages literal handling */
+/* changing page doesn't cause loss of last literal */
+/* location used. */
+/* Fixed bin generation if no origin set */
+/* v2.9a 01Jul13 DJG Fixed Comment. Binaries not updated */
+/* v2.10 08Feb14 DJG Changed trailer to 8 bytes since pip didn't like */
+/* trailer of one 0x80 */
+/* v2.11 19Apr15 DPI Fixed incorrect link generation with impled 0200 */
+/* starting address. Patch from Doug Ingrams */
+/* v2.12 28Apr15 DJG Fixed incorrect handling of reloc, expressions with */
+/* undefined symbols. Fixed conditional assembly with */
+/* undefined symbols. Added new flag to allow file to */
+/* not end with $ */
+/* v2.13 02May15 DPI Fixed bug in readLine when removing \r from a blank */
+/* line. Changed -s to -$ in -h display. Corrected */
+/* version comment. */
+/* v2.13 03May15 DJG Moved TITLE, BANK to new additional option. */
+/* Change release variable below when you update. Send changes back to */
+/* David Gesswein, djg@pdp8online.com. */
+/******************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+
+char *release = "pal-2.13, 03 May 2015";
+
+/* Set to 1 and use -e flag to make ( and [ literals errors */
+#define LITERAL_ERROR 0
+
+#define LINELEN 132
+#define LIST_LINES_PER_PAGE 55 /* Includes 5 line page header. */
+#define NAMELEN 128
+#define SYMBOL_COLUMNS 5
+#define SYMLEN 7
+#define SYMBOL_TABLE_SIZE 4096
+#define TITLELEN 63
+#define XREF_COLUMNS 8
+
+#define ADDRESS_FIELD 00177
+#define FIELD_FIELD 070000
+#define INDIRECT_BIT 00400
+#define LAST_PAGE_LOC 00177
+#define OP_CODE 07000
+#define PAGE_BIT 00200
+
+#ifdef PAGE_SIZE
+#undef PAGE_SIZE
+#endif
+#define PAGE_SIZE 00200
+
+#define PAGE_FIELD 07600
+#define PAGE_ZERO_END 00200
+
+/* Macro to get the number of elements in an array. */
+#define DIM(a) (sizeof(a)/sizeof(a[0]))
+
+/* Macro to get the address plus one of the end of an array. */
+#define BEYOND(a) ((a) + DIM(A))
+
+#define is_blank(c) ((c==' ') || (c=='\t') || (c=='\f') || (c=='>'))
+#define isend(c) ((c=='\0')|| (c=='\n'))
+#define isdone(c) ((c=='/') || (isend(c)) || (c==';'))
+
+/* Macros for testing symbol attributes. Each macro evaluates to non-zero */
+/* (true) if the stated condition is met. */
+/* Use these to test attributes. The proper bits are extracted and then */
+/* tested. */
+#define M_CONDITIONAL(s) ((s & CONDITION) == CONDITION)
+#define M_DEFINED(s) ((s & DEFINED) == DEFINED)
+#define M_DUPLICATE(s) ((s & DUPLICATE) == DUPLICATE)
+#define M_FIXED(s) ((s & FIXED) == FIXED)
+#define M_LABEL(s) ((s & LABEL) == LABEL)
+#define M_MRI(s) ((s & MRI) == MRI)
+#define M_MRIFIX(s) ((s & MRIFIX) == MRIFIX)
+#define M_PSEUDO(s) ((s & PSEUDO) == PSEUDO)
+#define M_REDEFINED(s) ((s & REDEFINED) == REDEFINED)
+#define M_UNDEFINED(s) (!M_DEFINED(s))
+#define M_PERM_REDEFINED(s) ((s & PERM_REDEFINED) == PERM_REDEFINED)
+
+/* This macro is used to test symbols by the conditional assembly pseudo-ops. */
+#define M_DEF(s) (M_DEFINED(s))
+#define M_COND(s) (M_CONDITIONAL(s))
+#define M_DEFINED_CONDITIONALLY(t) (M_DEF(t) && ((pass==1) ||!M_COND(t)))
+
+typedef unsigned char BOOL;
+typedef unsigned char BYTE;
+typedef short int WORD16;
+typedef long int WORD32;
+
+#ifndef FALSE
+ #define FALSE 0
+ #define TRUE (!FALSE)
+#endif
+
+/* Line listing styles. Used to control listing of lines. */
+enum linestyle_t
+{
+ LINE, LINE_VAL, LINE_LOC_VAL, LOC_VAL
+};
+typedef enum linestyle_t LINESTYLE_T;
+
+/* Symbol Types. */
+/* Note that the names that have FIX as the suffix contain the FIXED bit */
+/* included in the value. */
+/* */
+/* The CONDITION bit is used when processing the conditional assembly PSEUDO- */
+/* OPs (e.g., IFDEF). During pass 1 of the assembly, the symbol is either */
+/* defined or undefined. The condition bit is set when the symbol is defined */
+/* during pass 1 and reset on pass 2 at the location the symbol was defined */
+/* during pass 1. When processing conditionals during pass 2, if the symbol */
+/* is defined and the condition bit is set, the symbol is treated as if it */
+/* were undefined. This gives consistent behavior of the conditional */
+/* pseudo-ops during both pass 1 and pass 2. */
+enum symtyp
+{
+ UNDEFINED = 0000,
+ DEFINED = 0001,
+ FIXED = 0002,
+ MRI = 0004 | DEFINED,
+ LABEL = 0010 | DEFINED,
+ REDEFINED = 0020 | DEFINED,
+ DUPLICATE = 0040 | DEFINED,
+ PSEUDO = 0100 | FIXED | DEFINED,
+ CONDITION = 0200 | DEFINED,
+ PERM_REDEFINED = 0400,
+ MRIFIX = MRI | FIXED | DEFINED,
+ DEFFIX = DEFINED | FIXED
+};
+typedef enum symtyp SYMTYP;
+
+enum pseudo_t
+{
+ BANK, BINPUNCH, DECIMAL, DUBL, EJECT, ENPUNCH, EXPUNGE, FIELD,
+ FIXMRI, FIXTAB, FLTG, IFDEF, IFNDEF, IFNZERO, IFZERO, NOPUNCH,
+ OCTAL, PAGE, PAUSE, RELOC, RIMPUNCH, SEGMNT, TEXT, TITLE,
+ XLIST, ZBLOCK, FILENAME, DEVICE, ASCII
+};
+typedef enum pseudo_t PSEUDO_T;
+
+struct sym_t
+{
+ SYMTYP type;
+ char name[SYMLEN];
+ WORD16 val;
+ int xref_index;
+ int xref_count;
+};
+typedef struct sym_t SYM_T;
+
+struct lpool_t
+{
+ WORD16 loc;
+ WORD16 last_punched;
+ WORD16 pool[PAGE_SIZE];
+};
+typedef struct lpool_t LPOOL_T;
+
+struct emsg_t
+{
+ char *list;
+ char *file;
+};
+typedef struct emsg_t EMSG_T;
+
+struct errsave_t
+{
+ char *mesg;
+ int col;
+};
+typedef struct errsave_t ERRSAVE_T;
+
+struct fltg_
+{
+ WORD16 exponent;
+ WORD32 mantissa;
+};
+typedef struct fltg_ FLTG_T;
+
+/*----------------------------------------------------------------------------*/
+
+/* Function Prototypes */
+
+int binarySearch( char *name, int start, int symbol_count );
+int compareSymbols( const void *a, const void *b );
+void conditionFalse( void );
+void conditionTrue( void );
+SYM_T *defineLexeme( int start, int term, WORD16 val, SYMTYP type );
+SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start);
+void endOfBinary( void );
+void errorLexeme( EMSG_T *mesg, int col );
+void errorMessage( EMSG_T *mesg, int col );
+void errorSymbol( EMSG_T *mesg, char *name, int col );
+SYM_T *eval( void );
+WORD32 evalDubl( WORD32 initial_value );
+FLTG_T *evalFltg( void );
+SYM_T *evalSymbol( void );
+void getArgs( int argc, char *argv[] );
+WORD32 getDublExpr( void );
+WORD32 getDublExprs( void );
+FLTG_T *getFltgExpr( void );
+FLTG_T *getFltgExprs( void );
+SYM_T *getExpr( void );
+WORD16 getExprs( void );
+WORD16 incrementClc( void );
+void inputDubl( void );
+void inputFltg( void );
+WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index );
+char *lexemeToName( char *name, int from, int term );
+void listLine( void );
+SYM_T *lookup( char *name );
+void moveToEndOfLine( void );
+void nextLexBlank( void );
+void nextLexeme( void );
+void normalizeFltg( FLTG_T *fltg );
+void onePass( void );
+void printCrossReference( void );
+void printErrorMessages( void );
+void printLine(char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle);
+void printPageBreak( void );
+void printPermanentSymbolTable( void );
+void printSymbolTable( void );
+BOOL pseudoOperators( PSEUDO_T val );
+void punchChecksum( void );
+void punchLocObject( WORD16 loc, WORD16 val );
+void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 );
+void punchOutObject( WORD16 loc, WORD16 val );
+void punchLeader( int count );
+void punchObject( WORD16 val );
+void punchOrigin( WORD16 loc );
+void readLine( void );
+void saveError( char *mesg, int cc );
+BOOL testForLiteralCollision( WORD16 loc );
+void topOfForm( char *title, char *sub_title );
+
+/*----------------------------------------------------------------------------*/
+
+/* Table of pseudo-ops (directives) which are used to setup the symbol */
+/* table on startup and when the EXPUNGE pseudo-op is executed. */
+SYM_T pseudo[] =
+{
+ { PSEUDO, "ASCII", ASCII }, /* Put 8-bit ASCII into memory (see TEXT) */
+ { PSEUDO, "BINPUN", BINPUNCH }, /* Output in Binary Loader format. */
+ { PSEUDO, "DECIMA", DECIMAL }, /* Read literal constants in base 10. */
+ { PSEUDO, "DEVICE", DEVICE }, /* Pack 6 bit device name into memory */
+ { PSEUDO, "DUBL", DUBL }, /* Ignored (unsupported). */
+ { PSEUDO, "EJECT", EJECT }, /* Eject a page in the listing. */
+ { PSEUDO, "ENPUNC", ENPUNCH }, /* Turn on object code generation. */
+ { PSEUDO, "EXPUNG", EXPUNGE }, /* Remove all symbols from symbol table. */
+ { PSEUDO, "FIELD", FIELD }, /* Set origin to memory field. */
+ { PSEUDO, "FILENA", FILENAME }, /* Pack 6 bit filename into memory. */
+ { PSEUDO, "FIXMRI", FIXMRI }, /* Like =, but creates mem ref instruction*/
+ { PSEUDO, "FIXTAB", FIXTAB }, /* Mark current symbols as permanent. */
+ { PSEUDO, "FLTG", FLTG }, /* Ignored (unsupported). */
+ { PSEUDO, "IFDEF", IFDEF }, /* Assemble if symbol is defined. */
+ { PSEUDO, "IFNDEF", IFNDEF }, /* Assemble if symbol is not defined. */
+ { PSEUDO, "IFNZER", IFNZERO }, /* Assemble if symbol value is not 0. */
+ { PSEUDO, "IFNZRO", IFNZERO }, /* Assemble if symbol value is not 0. */
+ { PSEUDO, "IFZERO", IFZERO }, /* Assemble if symbol value is 0. */
+ { PSEUDO, "NOPUNC", NOPUNCH }, /* Turn off object code generation. */
+ { PSEUDO, "OCTAL", OCTAL }, /* Read literal constants in base 8. */
+ { PSEUDO, "PAGE", PAGE }, /* Set orign to page +1 or page n (0..37).*/
+ { PSEUDO, "PAUSE", PAUSE }, /* Ignored */
+ { PSEUDO, "RELOC", RELOC }, /* Assemble to run at a different address.*/
+ { PSEUDO, "RIMPUN", RIMPUNCH }, /* Output in Read In Mode format. */
+ { PSEUDO, "SEGMNT", SEGMNT }, /* Like page, but with page size=1K words.*/
+ { PSEUDO, "TEXT", TEXT }, /* Pack 6 bit trimmed ASCII into memory. */
+ { PSEUDO, "XLIST", XLIST }, /* Toggle listing generation. */
+ { PSEUDO, "ZBLOCK", ZBLOCK }, /* Zero a block of memory. */
+ { PSEUDO, "TITLE", TITLE }, /* Use the text string as a listing title.*/
+ { PSEUDO, "BANK", BANK } /* Like field, select some 32K out of 128K*/
+};
+/* Number o extended pseudo operators to ignore unless command option specified
+ * to enable */
+#define NUMBER_ADDITIONAL_PSEUDO 2
+
+/* Symbol Table */
+/* The table is put in lexical order on startup, so symbols can be */
+/* inserted as desired into the initial table. */
+/* really_permanent_symbols aren't removed by EXPUNGE */
+SYM_T really_permanent_symbols[] =
+{
+ { MRIFIX, "I", 00400 }, /* INDIRECT ADDRESSING */
+ { MRIFIX, "Z", 00000 } /* PAGE ZERO ADDRESS */
+};
+
+SYM_T permanent_symbols[] =
+{
+ /* Memory Reference Instructions */
+ { MRIFIX, "AND", 00000 }, /* LOGICAL AND */
+ { MRIFIX, "TAD", 01000 }, /* TWO'S COMPLEMENT ADD */
+ { MRIFIX, "ISZ", 02000 }, /* INCREMENT AND SKIP IF ZERO */
+ { MRIFIX, "DCA", 03000 }, /* DEPOSIT AND CLEAR ACC */
+ { MRIFIX, "JMP", 05000 }, /* JUMP */
+ { MRIFIX, "JMS", 04000 }, /* JUMP TO SUBROUTINE */
+ /* Floating Point Interpreter Instructions */
+ { MRIFIX, "FEXT", 00000 }, /* FLOATING EXIT */
+ { MRIFIX, "FADD", 01000 }, /* FLOATING ADD */
+ { MRIFIX, "FSUB", 02000 }, /* FLOATING SUBTRACT */
+ { MRIFIX, "FMPY", 03000 }, /* FLOATING MULTIPLY */
+ { MRIFIX, "FDIV", 04000 }, /* FLOATING DIVIDE */
+ { MRIFIX, "FGET", 05000 }, /* FLOATING GET */
+ { MRIFIX, "FPUT", 06000 }, /* FLOATING PUT */
+ { FIXED, "FNOR", 07000 }, /* FLOATING NORMALIZE */
+ { FIXED, "FEXT", 00000 }, /* EXIT FROM FLOATING POINT INTERPRETER */
+ { FIXED, "SQUARE", 00001 }, /* SQUARE C(FAC) */
+ { FIXED, "SQROOT", 00002 }, /* TAKE SQUARE ROOT OF C(FAC) */
+ /* Group 1 Operate Microinstrcutions */
+ { FIXED, "OPR", 07000 }, /* NO OPERATION */
+ { FIXED, "NOP", 07000 }, /* NO OPERATION */
+ { FIXED, "IAC", 07001 }, /* INCREMENT AC */
+ { FIXED, "RAL", 07004 }, /* ROTATE AC AND LINK LEFT ONE */
+ { FIXED, "RTL", 07006 }, /* ROTATE AC AND LINK LEFT TWO */
+ { FIXED, "RAR", 07010 }, /* ROTATE AC AND LINK RIGHT ONE */
+ { FIXED, "RTR", 07012 }, /* ROTATE AC AND LINK RIGHT TWO */
+ { FIXED, "CML", 07020 }, /* COMPLEMENT LINK */
+ { FIXED, "CMA", 07040 }, /* COMPLEMEMNT AC */
+ { FIXED, "CLL", 07100 }, /* CLEAR LINK */
+ { FIXED, "CLA", 07200 }, /* CLEAR AC */
+ /* Group 2 Operate Microinstructions */
+ { FIXED, "BSW", 07002 }, /* Swap bytes in AC (PDP/8e) */
+ { FIXED, "HLT", 07402 }, /* HALT THE COMPUTER */
+ { FIXED, "OSR", 07404 }, /* INCLUSIVE OR SR WITH AC */
+ { FIXED, "SKP", 07410 }, /* SKIP UNCONDITIONALLY */
+ { FIXED, "SNL", 07420 }, /* SKIP ON NON-ZERO LINK */
+ { FIXED, "SZL", 07430 }, /* SKIP ON ZERO LINK */
+ { FIXED, "SZA", 07440 }, /* SKIP ON ZERO AC */
+ { FIXED, "SNA", 07450 }, /* SKIP ON NON=ZERO AC */
+ { FIXED, "SMA", 07500 }, /* SKIP MINUS AC */
+ { FIXED, "SPA", 07510 }, /* SKIP ON POSITIVE AC (ZERO IS POSITIVE) */
+ /* Combined Operate Microinstructions */
+ { FIXED, "CIA", 07041 }, /* COMPLEMENT AND INCREMENT AC */
+ { FIXED, "STL", 07120 }, /* SET LINK TO 1 */
+ { FIXED, "GLK", 07204 }, /* GET LINK (PUT LINK IN AC BIT 11) */
+ { FIXED, "STA", 07240 }, /* SET AC TO -1 */
+ { FIXED, "LAS", 07604 }, /* LOAD ACC WITH SR */
+ /* MQ Instructions (PDP/8e) */
+ { FIXED, "MQL", 07421 }, /* Load MQ from AC, then clear AC. */
+ { FIXED, "MQA", 07501 }, /* Inclusive OR MQ with AC */
+ { FIXED, "SWP", 07521 }, /* Swap AC and MQ */
+ { FIXED, "ACL", 07701 }, /* Load MQ into AC */
+ /* Program Interrupt */
+ { FIXED, "IOT", 06000 },
+ { FIXED, "ION", 06001 }, /* TURN INTERRUPT PROCESSOR ON */
+ { FIXED, "IOF", 06002 }, /* TURN INTERRUPT PROCESSOR OFF */
+ /* Program Interrupt, PDP-8/e */
+ { FIXED, "SKON", 06000 }, /* Skip if interrupt on and turn int off. */
+ { FIXED, "SRQ", 06003 }, /* Skip on interrupt request. */
+ { FIXED, "GTF", 06004 }, /* Get interrupt flags. */
+ { FIXED, "RTF", 06005 }, /* Restore interrupt flags. */
+ { FIXED, "SGT", 06006 }, /* Skip on greater than flag. */
+ { FIXED, "CAF", 06007 }, /* Clear all flags. */
+ /* Keyboard/Reader */
+ { FIXED, "KCF", 06030 }, /* CLEAR KEYBOAR FLAG */
+ { FIXED, "KSF", 06031 }, /* SKIP ON KEYBOARD FLAG */
+ { FIXED, "KCC", 06032 }, /* CLEAR KEYBOARD FLAG & READ CHAR */
+ { FIXED, "KRS", 06034 }, /* READ KEYBOARD BUFFER (STATIC) */
+ { FIXED, "KIE", 06035 }, /* AC11 TO KEYBD/RDR INT ENABLE F/F */
+ { FIXED, "KRB", 06036 }, /* READ KEYBOARD BUFFER & CLEAR FLAG */
+ /* Teleprinter/Punch */
+ { FIXED, "TFL", 06040 }, /* SET TELEPRINTER/PUNCH FLAG */
+ { FIXED, "TSF", 06041 }, /* SKIP ON TELEPRINTER FLAG */
+ { FIXED, "TCF", 06042 }, /* CLEAR TELEPRINTER FLAG */
+ { FIXED, "TPC", 06044 }, /* LOAD TELEPRINTER & PRINT */
+ { FIXED, "TSK", 06045 }, /* SKIP IF TELETYPE INTERRUPT */
+ { FIXED, "TLS", 06046 }, /* LOAD TELPRINTER & CLEAR FLAG */
+ /* High Speed Paper Tape Reader */
+ { FIXED, "RSF", 06011 }, /* SKIP ON READER FLAG */
+ { FIXED, "RRB", 06012 }, /* READ READER BUFFER AND CLEAR FLAG */
+ { FIXED, "RFC", 06014 }, /* READER FETCH CHARACTER */
+ /* PC8-E High Speed Paper Tape Reader & Punch */
+ { FIXED, "RPE", 06010 }, /* Set interrupt enable for reader/punch */
+ { FIXED, "PCE", 06020 }, /* Clear interrupt enable for rdr/punch */
+ { FIXED, "RCC", 06016 }, /* Read reader buffer, clear flags & buf, */
+ /* and fetch character. */
+ /* High Speed Paper Tape Punch */
+ { FIXED, "PSF", 06021 }, /* SKIP ON PUNCH FLAG */
+ { FIXED, "PCF", 06022 }, /* CLEAR ON PUNCH FLAG */
+ { FIXED, "PPC", 06024 }, /* LOAD PUNCH BUFFER AND PUNCH CHARACTER* */
+ { FIXED, "PLS", 06026 }, /* LOAD PUNCH BUFFER AND CLEAR FLAG */
+
+ /* DECassette TU60 (RK 20071008) */
+ { FIXED, "KCLR", 06700 }, /* Clear all (clear A and B) */
+ { FIXED, "KSDR", 06701 }, /* Skip if data flag set */
+ { FIXED, "KSEN", 06702 }, /* Skip if EOT/BOT, not ready, or empty */
+ { FIXED, "KSBF", 06703 }, /* Skip if ready flag set */
+ { FIXED, "KLSA", 06704 }, /* AC4-11 -> A, clear A, -(AC4-11) -> A */
+ { FIXED, "KSAF", 06705 }, /* Skip on any flag or error */
+ { FIXED, "KGOA", 06706 }, /* Assert status A and transfer data to AC*/
+ { FIXED, "KRSB", 06707 }, /* Transfer B -> AC4-11 */
+
+ /* DECtape Transport Type TU55 and DECtape Control Type TC01 */
+ { FIXED, "DTRA", 06761 }, /* Contents of status register is ORed */
+ /* into AC bits 0-9 */
+ { FIXED, "DTCA", 06762 }, /* Clear status register A, all flags */
+ /* undisturbed */
+ { FIXED, "DTXA", 06764 }, /* Status register A loaded by exclusive */
+ /* OR from AC. If AC bit 10=0, clear */
+ /* error flags; if AC bit 11=0, DECtape */
+ /* control flag is cleared. */
+ { FIXED, "DTLA", 06766 }, /* Combination of DTCA and DTXA */
+ { FIXED, "DTSF", 06771 }, /* Skip if error flag is 1 or if DECtape */
+ /* control flag is 1 */
+ { FIXED, "DTRB", 06772 }, /* Contents of status register B is */
+ /* ORed into AC */
+ { FIXED, "DTLB", 06774 }, /* Memory field portion of status */
+ /* register B loaded from AC bits 6-8 */
+ /* Disk File and Control, Type DF32 */
+ { FIXED, "DCMA", 06601 }, /* CLEAR DISK MEMORY REQUEST AND */
+ /* INTERRUPT FLAGS */
+ { FIXED, "DMAR", 06603 }, /* LOAD DISK FROM AC, CLEAR AC READ */
+ /* INTO CORE, CLEAR INTERRUPT FLAG */
+ { FIXED, "DMAW", 06605 }, /* LOAD DISK FROM AC, WRITE ONTO DISK */
+ /* FROM CORE, CLEAR INTERRUPT FLAG */
+ { FIXED, "DCEA", 06611 }, /* CLEAR DISK EXTENDED ADDRESS AND */
+ { FIXED, "DSAC", 06612 }, /* SKIP IF ADDRESS CONFIRMED FLAG = 1 */
+ /* MEMORY ADDRESS EXTENSION REGISTER */
+ { FIXED, "DEAL", 06615 }, /* CLEAR DISK EXTENDED ADDRESS AND */
+ /* MEMORY ADDRESS EXTENSION REGISTER */
+ /* AND LOAD SAME FROM AC */
+ { FIXED, "DEAC", 06616 }, /* CLEAR AC, LOAD AC FROM DISK EXTENDED */
+ /* ADDRESS REGISTER, SKIP IF ADDRESS */
+ /* CONFIRMED FLAG = 1 */
+ { FIXED, "DFSE", 06621 }, /* SKIP IF PARITY ERROR, DATA REQUEST */
+ /* LATE, OR WRITE LOCK SWITCH FLAG = 0 */
+ /* (NO ERROR) */
+ { FIXED, "DFSC", 06622 }, /* SKIP IF COMPLETION FLAG = 1 (DATA */
+ /* TRANSFER COMPLETE) */
+ { FIXED, "DMAC", 06626 }, /* CLEAR AC, LOAD AC FROM DISK MEMORY */
+ /* ADDRESS REGISTER */
+ /* Disk File and Control, Type RF08 */
+ { FIXED, "DCIM", 06611 },
+ { FIXED, "DIML", 06615 },
+ { FIXED, "DIMA", 06616 },
+ { FIXED, "DISK", 06623 },
+ { FIXED, "DCXA", 06641 },
+ { FIXED, "DXAL", 06643 },
+ { FIXED, "DXAC", 06645 },
+ { FIXED, "DMMT", 06646 },
+ /* Memory Extension Control, Type 183 */
+ { FIXED, "CDF", 06201 }, /* CHANGE DATA FIELD */
+ { FIXED, "CIF", 06202 }, /* CHANGE INSTRUCTION FIELD */
+ { FIXED, "CDI", 06203 }, /* Change data & instrution field. */
+ { FIXED, "RDF", 06214 }, /* READ DATA FIELD */
+ { FIXED, "RIF", 06224 }, /* READ INSTRUCTION FIELD */
+ { FIXED, "RIB", 06234 }, /* READ INTERRUPT BUFFER */
+ { FIXED, "RMF", 06244 }, /* RESTORE MEMORY FIELD */
+ /* Memory Parity, Type MP8/I (MP8/L) */
+ { FIXED, "SMP", 06101 }, /* SKIP IF MEMORY PARITY FLAG = 0 */
+ { FIXED, "CMP", 06104 }, /* CLEAR MEMORY PAIRTY FLAG */
+ /* Memory Parity, Type MP8-E (PDP8/e) */
+ { FIXED, "DPI", 06100 }, /* Disable parity interrupt. */
+ { FIXED, "SNP", 06101 }, /* Skip if no parity error. */
+ { FIXED, "EPI", 06103 }, /* Enable parity interrupt. */
+ { FIXED, "CNP", 06104 }, /* Clear parity error flag. */
+ { FIXED, "CEP", 06106 }, /* Check for even parity. */
+ { FIXED, "SPO", 06107 }, /* Skip on parity option. */
+ /* Data Communications Systems, Type 680I */
+ { FIXED, "TTINCR", 06401 }, /* The content of the line select */
+ /* register is incremented by one. */
+ { FIXED, "TTI", 06402 }, /* The line status word is read and */
+ /* sampled. If the line is active for */
+ /* the fourth time, the line bit is */
+ /* shifted into the character assembly */
+ /* word. If the line bit is active for */
+ /* a number of times less than four, */
+ /* the count is incremented. If the */
+ /* line is not active, the active/inac- */
+ /* tive status of the line is recorded */
+ { FIXED, "TTO", 06404 }, /* The character in the AC is shifted */
+ /* right one position, zeros are shifted */
+ /* into vacated positions, and the orig- */
+ /* inal content of AC11 is transferred */
+ /* out of the computer on the TTY line. */
+ { FIXED, "TTCL", 06411 }, /* The line select register is cleared. */
+ { FIXED, "TTSL", 06412 }, /* The line select register is loaded by */
+ /* an OR transfer from the content of */
+ /* of AC5-11, the the AC is cleared. */
+ { FIXED, "TTRL", 06414 }, /* The content of the line select regis- */
+ /* ter is read into AC5-11 by an OR */
+ /* transfer. */
+ { FIXED, "TTSKP", 06421 }, /* Skip if clock flag is a 1. */
+ { FIXED, "TTXON", 06424 }, /* Clock 1 is enabled to request a prog- */
+ /* ram interrupt and clock 1 flag is */
+ /* cleared. */
+ { FIXED, "TTXOF", 06422 }, /* Clock 1 is disabled from causing a */
+ /* program interrupt and clock 1 flag */
+ /* is cleared. */
+}; /* End-of-Symbols for Permanent Symbol Table */
+
+/* Global variables */
+SYM_T *symtab; /* Symbol Table */
+int symbol_top; /* Number of entries in symbol table. */
+
+SYM_T *fixed_symbols; /* Start of the fixed symbol table entries. */
+int number_of_fixed_symbols;
+
+/*----------------------------------------------------------------------------*/
+
+WORD16 *xreftab; /* Start of the concordance table. */
+
+ERRSAVE_T error_list[20];
+int save_error_count;
+
+#define GET_PAGE_INDEX(x) (((x) & 07600) >> 7)
+#define MAX_PAGES 32
+LPOOL_T cp[MAX_PAGES]; /* Storage for page constants. */
+int max_page_used[MAX_PAGES];
+
+char s_detected[] = "detected";
+char s_error[] = "error";
+char s_errors[] = "errors";
+char s_no[] = "No";
+char s_page[] = "Page";
+char s_symtable[] = "Symbol Table";
+char s_xref[] = "Cross Reference";
+char s_generated[] = "generated";
+char s_link[] = "link";
+char s_links[] = "links";
+
+/* Assembler diagnostic messages. */
+/* Some attempt has been made to keep continuity with the PAL-III and */
+/* MACRO-8 diagnostic messages. If a diagnostic indicator, (e.g., IC) */
+/* exists, then the indicator is put in the listing as the first two */
+/* characters of the diagnostic message. The PAL-III indicators where used */
+/* when there was a choice between using MACRO-8 and PAL-III indicators. */
+/* The character pairs and their meanings are: */
+/* DT Duplicate Tag (symbol) */
+/* IC Illegal Character */
+/* ID Illegal Redefinition of a symbol. An attempt was made to give */
+/* a symbol a new value not via =. */
+/* IE Illegal Equals An equal sign was used in the wrong context, */
+/* (e.g., A+B=C, or TAD A+=B) */
+/* II Illegal Indirect An off page reference was made, but a literal */
+/* could not be generated because the indirect bit was already set. */
+/* IR Illegal Reference (address is not on current page or page zero) */
+/* ND No $ (the program terminator) at end of file. */
+/* PE Current, Non-Zero Page Exceeded (literal table flowed into code) */
+/* RD ReDefintion of a symbol */
+/* ST Symbol Table full */
+/* UA Undefined Address (undefined symbol) */
+/* ZE Zero Page Exceeded (see above, or out of space) */
+EMSG_T duplicate_label = { "DT duplicate", "duplicate label" };
+EMSG_T illegal_blank = { "IC illegal blank", "illegal blank" };
+EMSG_T illegal_character = { "IC illegal char", "illegal character" };
+EMSG_T illegal_expression = { "IC in expression", "illegal expression" };
+EMSG_T label_syntax = { "IC label syntax", "label syntax" };
+EMSG_T not_a_number = { "IC numeric syntax", "numeric syntax of" };
+EMSG_T number_not_radix = { "IC radix", "number not in current radix"};
+EMSG_T symbol_syntax = { "IC symbol syntax", "symbol syntax" };
+EMSG_T illegal_equals = { "IE illegal =", "illegal equals" };
+EMSG_T illegal_indirect = { "II off page", "illegal indirect" };
+EMSG_T illegal_reference = { "IR off page", "illegal reference" };
+EMSG_T undefined_symbol = { "UD undefined", "undefined symbol" };
+EMSG_T redefined_symbol = { "RD redefined", "redefined symbol" };
+EMSG_T illegal_redefine = { "ID redefined", "Illegal redefine of symbol" };
+EMSG_T literal_overflow = { "PE page exceeded",
+ "current page literal capacity exceeded" };
+EMSG_T pz_literal_overflow = { "ZE page exceeded",
+ "page zero capacity exceeded" };
+EMSG_T dubl_overflow = { "dubl overflow", "DUBL value overflow" };
+EMSG_T fltg_overflow = { "fltg overflow", "FLTG value overflow" };
+EMSG_T zblock_too_small = { "expr too small", "ZBLOCK value too small" };
+EMSG_T zblock_too_large = { "expr too large", "ZBLOCK value too large" };
+EMSG_T end_of_file = { "ND no $ at EOF", "No $ at End-of-File" };
+EMSG_T no_pseudo_op = { "not implemented",
+ "not implemented pseudo-op" };
+EMSG_T illegal_field_value = { "expr out of range",
+ "field value not in range of 0 through 7" };
+EMSG_T literal_gen_off = { "literals off",
+ "literal generation is off" };
+EMSG_T no_literal_value = { "no value", "no literal value" };
+EMSG_T text_string = { "no delimiter",
+ "text string delimiters not matched" };
+EMSG_T in_rim_mode = { "not OK in rim mode"
+ "FIELD pseudo-op not valid in RIM mode" };
+EMSG_T lt_expected = { "'<' expected", "'<' expected" };
+EMSG_T symbol_table_full = { "ST Symbol Tbl Full",
+ "Symbol Table Full" };
+/*----------------------------------------------------------------------------*/
+
+FILE *errorfile;
+FILE *infile;
+FILE *listfile;
+FILE *listsave;
+FILE *objectfile;
+FILE *objectsave;
+
+char errorpathname[NAMELEN];
+char filename[NAMELEN];
+char listpathname[NAMELEN];
+char objectpathname[NAMELEN];
+char *pathname;
+char permpathname[NAMELEN];
+
+int tabstops; /* number of characters to expand a tab to */
+int list_lineno;
+int list_pageno;
+char list_title[LINELEN];
+BOOL list_title_set; /* Set if TITLE pseudo-op used. */
+char line[LINELEN]; /* Input line. */
+int lineno; /* Current line number. */
+int page_lineno; /* print line number on current page. */
+BOOL listed; /* Listed flag. */
+BOOL listedsave;
+
+int cc; /* Column Counter (char position in line). */
+WORD16 checksum; /* Generated checksum */
+BOOL binary_data_output; /* Set true when data has been output. */
+WORD16 clc; /* Location counter */
+WORD16 cplc; /* Current page literal counter. */
+char delimiter; /* Character immediately after eval'd term. */
+int errors; /* Number of errors found so far. */
+int links; /* Number of links generated so far. */
+BOOL error_in_line; /* TRUE if error on current line. */
+int errors_pass_1; /* Number of errors on pass 1. */
+WORD16 field; /* Current field */
+WORD16 fieldlc; /* location counter without field portion. */
+BOOL fltg_input; /* TRUE when doing floating point input. */
+BOOL indirect_generated; /* TRUE if an off page address generated. */
+int last_xref_lexstart; /* Column where last xref symbol was located. */
+int last_xref_lineno; /* Line where last xref symbol was located. */
+int lexstartprev; /* Where previous lexeme started. */
+int lextermprev; /* Where previous lexeme ended. */
+int lexstart; /* Index of current lexeme on line. */
+int lexterm; /* Index of character after current lexeme. */
+BOOL literals_ok; /* Generate literals, ignore ID redefine err */
+BOOL perm_redef_error; /* Make redefining perm sym with labels error */
+int maxcc; /* Current line length. */
+BOOL overflow; /* Overflow flag for math routines. */
+int pass; /* Number of current pass. */
+BOOL print_permanent_symbols;
+WORD16 pzlc; /* Page Zero literal counter. */
+WORD16 radix; /* Default number radix. */
+WORD16 reloc; /* The relocation distance. */
+BOOL rim_mode; /* Generate rim format, defaults to bin */
+BOOL dollar_not_required; /* $ not required at end of file */
+BOOL additional_enabled; /* True if extended functions over PAL8 */
+ /* enabled */
+BOOL symtab_print; /* Print symbol table flag */
+BOOL xref;
+
+FLTG_T fltg_ac; /* Value holder for evalFltg() */
+SYM_T sym_eval = { DEFINED, "", 0 }; /* Value holder for eval() */
+SYM_T sym_getexpr = { DEFINED, "", 0 }; /* Value holder for getexpr() */
+SYM_T sym_undefined = { UNDEFINED, "", 0 };/* Symbol Table Terminator */
+
+
+/******************************************************************************/
+/* */
+/* Function: main */
+/* */
+/* Synopsis: Starting point. Controls order of assembly. */
+/* */
+/******************************************************************************/
+int main( int argc, char *argv[] )
+{
+ int ix;
+ int space;
+
+ /* Set the default values for global symbols. */
+ binary_data_output = FALSE;
+ fltg_input = FALSE;
+ literals_ok = TRUE;
+ perm_redef_error = FALSE;
+ print_permanent_symbols = FALSE;
+ rim_mode = FALSE;
+ dollar_not_required = FALSE;
+ additional_enabled = FALSE;
+ symtab_print = FALSE;
+ xref = FALSE;
+ pathname = NULL;
+
+ /* Get the options and pathnames */
+ getArgs( argc, argv );
+
+ /* Setup the error file in case symbol table overflows while installing the */
+ /* permanent symbols. */
+ errorfile = fopen( errorpathname, "w" );
+ if (errorfile == NULL) {
+ fprintf( stderr, "Could not open error file %s: %s\n", errorpathname, strerror(errno));
+ exit( -1 );
+
+ }
+ errors = 0;
+ save_error_count = 0;
+ pass = 0; /* This is required for symbol table initialization. */
+ symtab = (SYM_T *) malloc( sizeof( SYM_T ) * SYMBOL_TABLE_SIZE );
+
+ if( symtab == NULL )
+ {
+ fprintf( stderr, "Could not allocate memory for symbol table.\n");
+ exit( -1 );
+ }
+
+ /* Place end marker in symbol table. */
+ symtab[0] = sym_undefined;
+ symbol_top = 0;
+ number_of_fixed_symbols = symbol_top;
+ fixed_symbols = &symtab[symbol_top - 1];
+
+ /* Enter the pseudo-ops into the symbol table */
+ for( ix = 0; ix < DIM( pseudo ) -
+ (additional_enabled ? 0 : NUMBER_ADDITIONAL_PSEUDO) ; ix++ )
+ {
+ defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 );
+ }
+
+ /* Enter the predefined symbols into the table. */
+ /* Also make them part of the permanent symbol table. */
+ for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ )
+ {
+ defineSymbol( really_permanent_symbols[ix].name,
+ really_permanent_symbols[ix].val,
+ really_permanent_symbols[ix].type | DEFFIX , 0 );
+ }
+
+ /* Enter the predefined symbols into the table. */
+ /* Also make them part of the permanent symbol table. */
+ for( ix = 0; ix < DIM( permanent_symbols ); ix++ )
+ {
+ defineSymbol( permanent_symbols[ix].name,
+ permanent_symbols[ix].val,
+ permanent_symbols[ix].type | DEFFIX , 0 );
+ }
+
+ number_of_fixed_symbols = symbol_top;
+ fixed_symbols = &symtab[symbol_top - 1];
+
+ /* Do pass one of the assembly */
+ checksum = 0;
+ pass = 1;
+ page_lineno = LIST_LINES_PER_PAGE;
+ onePass();
+ errors_pass_1 = errors;
+
+ /* Set up for pass two */
+ rewind( infile );
+ /*Opened in main errorfile = fopen( errorpathname, "w" );*/
+ objectfile = fopen( objectpathname, "wb" );
+ if (objectfile == NULL) {
+ fprintf( stderr, "Could not open object file %s: %s\n", objectpathname, strerror(errno));
+ exit( -1 );
+
+ }
+ objectsave = objectfile;
+
+ listfile = fopen( listpathname, "w" );
+ if (listfile == NULL) {
+ fprintf( stderr, "Could not open list file %s: %s\n", listpathname, strerror(errno));
+ exit( -1 );
+
+ }
+ listsave = NULL;
+
+ punchLeader( 0 );
+ checksum = 0;
+
+ /* Do pass two of the assembly */
+ errors = 0;
+ save_error_count = 0;
+ page_lineno = LIST_LINES_PER_PAGE;
+
+ if( xref )
+ {
+ /* Get the amount of space that will be required for the concordance. */
+ for( space = 0, ix = 0; ix < symbol_top; ix++ )
+ {
+ symtab[ix].xref_index = space; /* Index into concordance table. */
+ space += symtab[ix].xref_count + 1;
+ symtab[ix].xref_count = 0; /* Clear the count for pass 2. */
+
+ }
+ /* Allocate the necessary space. */
+ xreftab = (WORD16 *) malloc( sizeof( WORD16 ) * space );
+
+ /* Clear the cross reference space. */
+ for( ix = 0; ix < space; ix++ )
+ {
+ xreftab[ix] = 0;
+ }
+ }
+ pass = 2;
+ onePass();
+
+ /* Undo effects of NOPUNCH for any following checksum */
+ objectfile = objectsave;
+ punchChecksum();
+
+ /* Works great for trailer. */
+ punchLeader( 8 );
+
+ /* undo effects of XLIST for any following output to listing file. */
+ if( listfile == NULL )
+ {
+ listfile = listsave;
+ }
+
+ /* Display value of error counter. */
+ if( errors == 0 )
+ {
+ fprintf( listfile, "\n %s %s %s\n", s_no, s_detected, s_errors );
+ }
+ else
+ {
+ fprintf( errorfile, "\n %d %s %s\n", errors, s_detected,
+ ( errors == 1 ? s_error : s_errors ));
+ fprintf( listfile, "\n %d %s %s\n", errors, s_detected,
+ ( errors == 1 ? s_error : s_errors ));
+ fprintf( stderr, " %d %s %s\n", errors, s_detected,
+ ( errors == 1 ? s_error : s_errors ));
+ }
+ /* Display value of link counter. */
+ if( links == 0 )
+ {
+ fprintf( listfile, " %s %s %s\n", s_no, s_links, s_generated );
+ }
+ else
+ {
+ fprintf( errorfile, " %d %s %s\n", links,
+ ( links == 1 ? s_link : s_links ),
+ s_generated);
+ fprintf( listfile, " %d %s %s\n", links,
+ ( links == 1 ? s_link : s_links ),
+ s_generated);
+ fprintf( stderr, " %d %s %s\n", links,
+ ( links == 1 ? s_link : s_links ),
+ s_generated);
+ }
+
+ if( symtab_print )
+ {
+ printSymbolTable();
+ }
+
+ if( print_permanent_symbols )
+ {
+ printPermanentSymbolTable();
+ }
+
+ if( xref )
+ {
+ printCrossReference();
+ }
+
+ fclose( objectfile );
+ fclose( listfile );
+ fclose( errorfile );
+ if( errors == 0 && errors_pass_1 == 0 )
+ {
+ remove( errorpathname );
+ }
+
+ return( errors != 0 );
+} /* main() */
+
+/******************************************************************************/
+/* */
+/* Function: getArgs */
+/* */
+/* Synopsis: Parse command line, set flags accordingly and setup input and */
+/* output files. */
+/* */
+/******************************************************************************/
+void getArgs( int argc, char *argv[] )
+{
+ int len;
+ int ix, jx;
+
+ /* Set the defaults */
+ errorfile = NULL;
+ infile = NULL;
+ listfile = NULL;
+ listsave = NULL;
+ objectfile = NULL;
+ objectsave = NULL;
+ tabstops = 8;
+
+ for( ix = 1; ix < argc; ix++ )
+ {
+ if( argv[ix][0] == '-' )
+ {
+ for( jx = 1; argv[ix][jx] != 0; jx++ )
+ {
+ switch( argv[ix][jx] )
+ {
+ case '$':
+ dollar_not_required = TRUE;
+ break;
+
+ case 'd':
+ symtab_print = TRUE;
+ break;
+
+ case 'a':
+ additional_enabled = TRUE;
+ break;
+
+ case 'r':
+ rim_mode = TRUE;
+ break;
+
+ case 'e':
+ literals_ok = FALSE;
+ break;
+
+ case 'l':
+ literals_ok = TRUE;
+ break;
+
+ case 'n':
+ perm_redef_error = TRUE;
+ break;
+
+ case 'p':
+ print_permanent_symbols = TRUE;
+ break;
+
+ /* Added -tN; RK 20071029 */
+ /* Damn, this is ugly, we should use getopt() */
+ case 't':
+ if (argv [ix][jx + 1]) {
+ tabstops = atoi (argv [ix] + (jx + 1));
+ /* advance past numbers */
+ for (jx++; argv [ix][jx]; jx++) ;
+ jx--;
+ } else {
+ ix++;
+ if (ix >= argc) {
+ fprintf( stderr, "%s: missing argument for -t, expected number of tabsopts\n", argv[0] );
+ exit( -1 );
+ }
+ for (jx = 0; argv [ix][jx]; jx++) ;
+ jx--;
+ tabstops = atoi (argv [ix]);
+ }
+ break;
+
+ case 'x':
+ xref = TRUE;
+ break;
+
+ case 'v':
+ fprintf( stderr, "%s\n", release );
+ fflush( stderr );
+ exit( -1 );
+ break;
+
+ default:
+ fprintf( stderr, "%s: unknown flag: %s\n", argv[0], argv[ix] );
+ case 'h':
+ fprintf( stderr, " -$ -- allow file to not end with $\n" );
+ fprintf( stderr, " -a -- enable additional function not in PAL8\n" );
+ fprintf( stderr, " -d -- dump symbol table\n" );
+ fprintf( stderr, " -e -- error if link generated\n" );
+ fprintf( stderr, " -h -- show this help\n" );
+ fprintf( stderr, " -l -- generate literal/link (default)\n" );
+ fprintf( stderr, " -n -- no redefining with label permanent symbols\n" );
+ fprintf( stderr, " -p -- output permanent symbols to file\n" );
+ fprintf( stderr, " -r -- output rim format file\n" );
+ fprintf( stderr, " -t N -- set tab stops to N\n" );
+ fprintf( stderr, " -v -- display version\n" );
+ fprintf( stderr, " -x -- output cross reference to file\n" );
+ fflush( stderr );
+ exit( -1 );
+ } /* end switch */
+ } /* end for */
+ }
+ else
+ {
+ if( pathname != NULL )
+ {
+ fprintf( stderr, "%s: too many input files\n", argv[0] );
+ exit( -1 );
+ }
+ pathname = &argv[ix][0];
+ }
+ } /* end for */
+
+ if( pathname == NULL )
+ {
+ fprintf( stderr, "%s: no input file specified\n", argv[0] );
+ exit( -1 );
+ }
+
+ len = strlen( pathname );
+ if( len > NAMELEN - 5 )
+ {
+ fprintf( stderr, "%s: pathname \"%s\" too long\n", argv[0], pathname );
+ exit( -1 );
+ }
+
+ /* Now open the input file. */
+ if(( infile = fopen( pathname, "r" )) == NULL )
+ {
+ fprintf( stderr, "%s: cannot open \"%s\": %s\n", argv[0], pathname, strerror(errno) );
+ exit( -1 );
+ }
+
+ /* Now make the pathnames */
+ /* Find last '.', if it exists. */
+ jx = len - 1;
+ while( pathname[jx] != '.' && pathname[jx] != '/'
+ && pathname[jx] != '\\' && jx >= 0 )
+ {
+ jx--;
+ }
+
+ switch( pathname[jx] )
+ {
+ case '.':
+ break;
+
+ case '/':
+ case '\\':
+ jx = len;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Add the pathname extensions. */
+ strncpy( objectpathname, pathname, jx );
+ objectpathname[jx] = '\0';
+ strcat( objectpathname, rim_mode ? ".rim" : ".bin" );
+
+ strncpy( listpathname, pathname, jx );
+ listpathname[jx] = '\0';
+ strcat( listpathname, ".lst" );
+
+ strncpy( errorpathname, pathname, jx );
+ errorpathname[jx] = '\0';
+ strcat( errorpathname, ".err" );
+
+ strncpy( permpathname, pathname, jx );
+ permpathname[jx] = '\0';
+ strcat( permpathname, ".prm" );
+
+ /* Extract the filename from the path. */
+ if( isalpha( pathname[0] ) && pathname[1] == ':' && pathname[2] != '\\' )
+ {
+ pathname[1] = '\\'; /* MS-DOS style pathname */
+ }
+
+ jx = len - 1;
+ while( pathname[jx] != '/' && pathname[jx] != '\\' && jx >= 0 )
+ {
+ jx--;
+ }
+ strcpy( filename, &pathname[jx + 1] );
+
+} /* getArgs() */
+
+/******************************************************************************/
+/* */
+/* Function: clearLiteralTable */
+/* */
+/* Synopsis: Clear the cp and max_page_used data storing literal */
+/* information. */
+/* */
+/******************************************************************************/
+void clearLiteralTable()
+{
+ int i;
+
+ for (i = 0; i < DIM(cp); i++)
+ {
+ cp[i].loc = 0200; /* Points to end of page for [] operands. */
+ cp[i].last_punched = 0200; /* Points to end of page for [] operands. */
+ }
+ memset(max_page_used, 0, sizeof(max_page_used));
+}
+
+/******************************************************************************/
+/* */
+/* Function: onePass */
+/* */
+/* Synopsis: Do one assembly pass. */
+/* */
+/******************************************************************************/
+void onePass()
+{
+ char name[SYMLEN];
+ WORD16 newclc;
+ BOOL scanning_line;
+ int start;
+ SYM_T *sym;
+ int term;
+ WORD16 val;
+
+ clc = 0200; /* Default starting address is 200 octal. */
+ field = 0;
+ fieldlc = clc & 07777;
+ reloc = 0;
+ clearLiteralTable();
+ listed = TRUE;
+ lineno = 0;
+ list_pageno = 0;
+ list_lineno = 0;
+ last_xref_lexstart = 0;
+ last_xref_lineno = 0;
+ list_title_set = FALSE;
+ radix = 8; /* Initial radix is octal (base 8). */
+
+ if( !rim_mode )
+ {
+ /* Put out initial origin if not in rim mode. */
+ punchOrigin( clc );
+ }
+
+ while( TRUE )
+ {
+ readLine();
+ nextLexeme();
+
+ scanning_line = TRUE;
+ while( scanning_line )
+ {
+ if( isend( line[lexstart] ))
+ {
+ scanning_line = FALSE;
+ }
+ else
+ {
+ switch( line[lexstart] )
+ {
+ case '/':
+ scanning_line = FALSE;
+ break;
+
+ case ';':
+ nextLexeme();
+ break;
+
+ case '$':
+ endOfBinary();
+ return;
+
+ case '*':
+ nextLexeme(); /* Skip '*', (set origin symbol) */
+ newclc = ((getExpr())->val & 07777 ) | field;
+ /* Do not change Current Location Counter if an error occurred. */
+ if( !error_in_line )
+ {
+ if(( newclc & 07600 ) != ( clc & 07600 ) )
+ {
+ /* Current page has changed. */
+ punchLiteralPool( cp, 0 );
+ }
+ clc = newclc - reloc;
+ fieldlc = clc & 07777;
+
+ if( !rim_mode )
+ {
+ /* Not rim mode, put out origin. */
+ punchOrigin( clc );
+ }
+ printLine( line, 0, fieldlc, LINE_VAL );
+ }
+ break;
+
+ default:
+ switch( line[lexterm] )
+ {
+ case ',':
+ if( isalpha( line[lexstart] ))
+ {
+ /* Use lookup so symbol will not be counted as reference. */
+ sym = lookup( lexemeToName( name, lexstart, lexterm ));
+ if( M_DEFINED( sym->type ))
+ {
+ if( (sym->val & 07777) != ( ( clc+reloc ) & 07777) && pass == 2 )
+ {
+ errorSymbol( &duplicate_label, sym->name, lexstart );
+ }
+ sym->type = sym->type | DUPLICATE;
+ }
+ /* Must call define on pass 2 to generate concordance. */
+ defineLexeme( lexstart, lexterm, ( clc + reloc ), LABEL );
+ }
+ else
+ {
+ errorLexeme( &label_syntax, lexstart );
+ }
+ nextLexeme(); /* skip label */
+ nextLexeme(); /* skip comma */
+ break;
+
+ case '=':
+ if( isalpha( line[lexstart] ))
+ {
+ start = lexstart;
+ term = lexterm;
+ delimiter = line[lexterm];
+ nextLexBlank(); /* skip symbol */
+ nextLexeme(); /* skip trailing =, allow blank */
+ delimiter = line[lexterm];
+ val = getExprs();
+ defineLexeme( start, term, val, DEFINED );
+ printLine( line, 0, val, LINE_VAL );
+ }
+ else
+ {
+ errorLexeme( &symbol_syntax, lexstartprev );
+ nextLexeme(); /* skip symbol */
+ nextLexeme(); /* skip trailing = */
+ getExprs(); /* skip expression */
+ }
+ break;
+
+ default:
+ if( isalpha( line[lexstart] ))
+ {
+ sym = evalSymbol();
+ val = sym->val;
+ if( M_PSEUDO( sym->type ))
+ {
+ nextLexeme(); /* Skip symbol */
+ scanning_line = pseudoOperators( (PSEUDO_T)val & 07777 );
+ }
+ else
+ {
+ /* Identifier is not a pseudo-op, interpret as load value */
+ punchOutObject( clc, getExprs() & 07777 );
+ incrementClc();
+ }
+ }
+ else
+ {
+ /* Identifier is a value, interpret as load value */
+ punchOutObject( clc, getExprs() & 07777 );
+ incrementClc();
+ }
+ break;
+ } /* end switch */
+ break;
+ } /* end switch */
+ } /* end if */
+ } /* end while( scanning_line ) */
+ } /* end while( TRUE ) */
+} /* onePass() */
+
+
+/******************************************************************************/
+/* */
+/* Function: fixMRIInstruction */
+/* */
+/* Synopsis: Now that we have the final value figure out if page 0, current */
+/* page, or indirect needed and max final instruction */
+/* */
+/******************************************************************************/
+WORD16 fixMRIInstruction(WORD16 instruction, WORD16 value)
+{
+ /* Now have the address part of the MRI instruction. */
+ if( value < 00200 )
+ {
+ instruction |= value; /* Page zero MRI. */
+ }
+ else if( (( fieldlc + reloc ) & 07600 ) <= value
+ && value <= ((( fieldlc + reloc ) & 07600) | 0177 ))
+ {
+ instruction |= ( PAGE_BIT | (value & ADDRESS_FIELD )); /* Current page MRI */
+ }
+ else
+ {
+ if(( instruction & INDIRECT_BIT ) == INDIRECT_BIT )
+ {
+ /* Already indirect, can't generate */
+ errorSymbol( &illegal_indirect, NULL, lexstartprev );
+ }
+ else
+ {
+ if( literals_ok )
+ {
+ /* Now fix off page reference. */
+ /* Search current page literal pool for needed instruction. */
+ /* Set Indirect Current Page */
+ instruction |= ( 00600 | insertLiteral( cp, value, GET_PAGE_INDEX(clc) ));
+ indirect_generated = TRUE;
+ if (pass == 2)
+ {
+ links++;
+ }
+ }
+ else
+ {
+ errorSymbol( &illegal_reference, NULL, lexstartprev );
+ instruction |= ( value & 0177 );
+ }
+ }
+ }
+ return instruction;
+}
+/******************************************************************************/
+/* */
+/* Function: getExprs */
+/* */
+/* Synopsis: Or together a list of blank separated expressions, from the */
+/* current lexeme onward. Leave the current lexeme as */
+/* the last one in the list. */
+/* */
+/******************************************************************************/
+WORD16 getExprs()
+{
+ SYM_T *symv;
+ SYM_T *symt;
+ WORD16 temp;
+ SYMTYP temp_type;
+ WORD16 value;
+ SYMTYP value_type;
+ BOOL MRI_held = FALSE;
+ WORD16 held_value = 0;
+
+ symv = getExpr();
+ value = symv->val;
+ value_type = symv->type;
+
+ while( TRUE )
+ {
+ if( isdone( line[lexstart] ))
+ {
+ if (MRI_held)
+ {
+ value = fixMRIInstruction(value, held_value);
+ }
+ return( value );
+ }
+ switch( line[lexstart] )
+ {
+ case ')':
+ case ']':
+ case '<':
+ if (MRI_held)
+ {
+ value = fixMRIInstruction(value, held_value);
+ }
+ return( value );
+
+ default:
+ break;
+ }
+
+ /* Interpret space as logical or */
+ symt = getExpr();
+ temp = symt->val & 07777;
+ temp_type = symt->type;
+
+ switch( value_type & (MRI | MRIFIX))
+ {
+ case MRI:
+ case MRIFIX:
+ /* Previous symbol was a Memory Reference Instruction. */
+ switch( temp_type & (MRI | MRIFIX) )
+ {
+ case MRI:
+ case MRIFIX:
+ /* If we have held value don't or in more MRI's to instuction, they */
+ /* are now instuction value */
+ if (MRI_held)
+ {
+ held_value |= temp;
+ }
+ else
+ {
+ /* Current symbol is also a Memory Reference Instruction. */
+ value |= temp; /* Just OR the MRI instructions. */
+ }
+ break;
+
+ default:
+ held_value |= temp;
+ MRI_held = TRUE;
+ break;
+ }
+ break;
+
+ default:
+ if (value_type == UNDEFINED || temp_type == UNDEFINED) {
+ value = 0;
+ } else {
+ value |= temp; /* Normal 12 bit value. */
+ }
+ break;
+ }
+ } /* end while */
+} /* getExprs() */
+
+
+/******************************************************************************/
+/* */
+/* Function: getExpr */
+/* */
+/* Synopsis: Get an expression, from the current lexeme onward, leave the */
+/* current lexeme as the one after the expression. Expressions */
+/* contain terminal symbols (identifiers) separated by operators. */
+/* */
+/******************************************************************************/
+SYM_T *getExpr()
+{
+ SYM_T *sym;
+ delimiter = line[lexterm];
+
+
+ if( line[lexstart] == '-' )
+ {
+ nextLexBlank();
+ sym_getexpr = *(eval());
+ sym_getexpr.val = ( - sym_getexpr.val ) & 07777;
+ }
+ else
+ {
+ if( line[lexstart] == '+' )
+ {
+ nextLexBlank();
+ }
+ sym_getexpr = *(eval());
+ sym_getexpr.val = sym_getexpr.val & 07777;
+ }
+
+ if( is_blank( delimiter ))
+ {
+ return( &sym_getexpr );
+ }
+
+ /* Here we assume the current lexeme is the operator separating the */
+ /* previous operator from the next, if any. */
+ while( TRUE )
+ {
+ /* assert line[lexstart] == delimiter */
+ if( is_blank( delimiter ))
+ {
+ return( &sym_getexpr );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '+': /* add */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val += sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ case '-': /* subtract */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val -= sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ case '^': /* multiply */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val *= sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ case '%': /* divide */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val /= sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ case '&': /* and */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val &= sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ case '!': /* or */
+ nextLexBlank(); /* skip over the operator */
+ sym = eval();
+ sym_getexpr.val |= sym->val;
+ if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
+ sym_getexpr.val = 0;
+ sym_getexpr.type = UNDEFINED;
+ }
+ break;
+
+ default:
+ if( isend( line[lexstart] ))
+ {
+ return( &sym_getexpr );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '/':
+ case ';':
+ case ')':
+ case ']':
+ case '<':
+ break;
+
+ case '=':
+ errorMessage( &illegal_equals, lexstart );
+ moveToEndOfLine();
+ sym_getexpr.val = 0;
+ break;
+
+ default:
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ sym_getexpr.val = 0;
+ break;
+ }
+ return( &sym_getexpr );
+ }
+ } /* end while */
+} /* getExpr() */
+
+
+/******************************************************************************/
+/* */
+/* Function: eval */
+/* */
+/* Synopsis: Get the value of the current lexeme, set delimiter and advance.*/
+/* */
+/******************************************************************************/
+SYM_T *eval()
+{
+ WORD16 digit;
+ int from;
+ WORD16 loc;
+ SYM_T *sym;
+ WORD16 val;
+
+ val = 0;
+
+ delimiter = line[lexterm];
+ if( isalpha( line[lexstart] ))
+ {
+ sym = evalSymbol();
+ if( M_UNDEFINED( sym->type ) && pass == 2 )
+ {
+ errorSymbol( &undefined_symbol, sym->name, lexstart );
+ nextLexeme();
+ return( sym );
+ }
+ else
+ {
+ nextLexeme();
+ return( sym );
+ }
+ }
+ else if( isdigit( line[lexstart] ))
+ {
+ from = lexstart;
+ val = 0;
+ while( from < lexterm )
+ {
+ if( isdigit( line[from] ))
+ {
+ digit = (WORD16) line[from++] - (WORD16) '0';
+ if( digit < radix )
+ {
+ val = val * radix + digit;
+ }
+ else
+ {
+ errorLexeme( &number_not_radix, from - 1 );
+ val = 0;
+ from = lexterm;
+ }
+ }
+ else
+ {
+ errorLexeme( ¬_a_number, lexstart );
+ val = 0;
+ from = lexterm;
+ }
+ }
+ nextLexeme();
+ sym_eval.val = val;
+ return( &sym_eval );
+ }
+ else
+ {
+ switch( line[lexstart] )
+ {
+ case '"': /* Character literal */
+ if( cc + 1 <= maxcc )
+ {
+ val = line[lexstart + 1] | 0200;
+ delimiter = line[lexstart + 2];
+ cc = lexstart + 2;
+ }
+ else
+ {
+ errorMessage( &no_literal_value, lexstart );
+ }
+ nextLexeme();
+ break;
+
+ case '.': /* Value of Current Location Counter */
+ val = (clc & 07777) + reloc;
+ nextLexeme();
+ break;
+
+ case '[': /* Generate literal on page zero. */
+ if( !literals_ok && LITERAL_ERROR)
+ {
+ errorMessage( &literal_gen_off, lexstart );
+ }
+ nextLexBlank(); /* Skip bracket */
+ val = getExprs() & 07777;
+
+ if( line[lexstart] == ']' )
+ {
+ nextLexBlank(); /* Skip end bracket */
+ }
+
+ sym_eval.val = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp , val,
+ GET_PAGE_INDEX(field)) : 0;
+ return( &sym_eval );
+
+ case '(': /* Generate literal on current page. */
+ if( !literals_ok && LITERAL_ERROR)
+ {
+ errorMessage( &literal_gen_off, lexstart );
+ }
+
+ nextLexBlank(); /* Skip paren */
+ val = getExprs() & 07777;
+
+ if( line[lexstart] == ')' )
+ {
+ nextLexBlank(); /* Skip end paren */
+ }
+
+ loc = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp, val, GET_PAGE_INDEX(clc) ) : 0;
+ sym_eval.val = loc + (( clc + reloc ) & 077600 );
+ return( &sym_eval );
+
+ default:
+ switch( line[lexstart] )
+ {
+ case '=':
+ errorMessage( &illegal_equals, lexstart );
+ moveToEndOfLine();
+ break;
+
+ default:
+ errorMessage( &illegal_character, lexstart );
+ break;
+ }
+ val = 0; /* On error, set value to zero. */
+ nextLexBlank(); /* Go past illegal character. */
+ }
+ }
+ sym_eval.val = val;
+ return( &sym_eval );
+} /* eval() */
+
+
+/******************************************************************************/
+/* */
+/* Function: inputDubl */
+/* */
+/* Synopsis: Get the value of the current lexeme as a double word. */
+/* */
+/******************************************************************************/
+void inputDubl()
+{
+ WORD32 dublvalue;
+ BOOL scanning_line;
+
+ scanning_line = TRUE;
+ do
+ {
+ while( scanning_line )
+ {
+ if( isend( line[lexstart] ))
+ {
+ scanning_line = FALSE;
+ }
+ else
+ {
+ switch( line[lexstart] )
+ {
+ case '/':
+ scanning_line = FALSE;
+ break;
+
+ case ';':
+ nextLexeme();
+ break;
+
+ case '+':
+ delimiter = line[lexterm];
+ nextLexBlank();
+ case '-':
+ default:
+ if( isdigit( line[lexstart] ) || line[lexstart] == '-' )
+ {
+ dublvalue = getDublExprs();
+ punchOutObject( clc, (WORD16)(( dublvalue >> 12 ) & 07777 ));
+ incrementClc();
+ punchOutObject( clc, (WORD16)( dublvalue & 07777 ));
+ incrementClc();
+ }
+ else
+ {
+ return; /* Non-numeric input, back to assembly. */
+ }
+ break;
+ } /* end switch */
+ } /* end if */
+
+ if( error_in_line )
+ {
+ return; /* Error occurred, exit DUBL input mode. */
+ }
+ } /* end while( scanning_line ) */
+ readLine();
+ nextLexeme();
+ scanning_line = TRUE;
+ }
+ while( TRUE );
+} /* inputDubl() */
+
+
+/******************************************************************************/
+/* */
+/* Function: getDublExprs */
+/* */
+/* Synopsis: Get a DUBL expression. */
+/* */
+/******************************************************************************/
+WORD32 getDublExprs()
+{
+ WORD32 dublvalue;
+
+ dublvalue = getDublExpr();
+
+ while( TRUE )
+ {
+ if( isdone( line[lexstart] ))
+ {
+ return( dublvalue );
+ }
+ else
+ {
+ errorMessage( &illegal_expression, lexstart - 1 );
+ return( 0 );
+ }
+ } /* end while */
+} /* getDublExprs() */
+
+
+/******************************************************************************/
+/* */
+/* Function: getDublExpr */
+/* */
+/* Synopsis: Get the value of the current lexeme as a double word. The */
+/* number is always considered to have a decimal radix. */
+/* */
+/******************************************************************************/
+WORD32 getDublExpr()
+{
+ WORD32 dublvalue;
+
+ delimiter = line[lexterm];
+ if( line[lexstart] == '-' )
+ {
+ nextLexBlank();
+ dublvalue = evalDubl( 0 );
+ nextLexeme();
+ /* Test for any value greater than 23 bits in length. */
+ if( (unsigned long int)dublvalue > 040000000L )
+ {
+ errorMessage( &dubl_overflow, lexstart );
+ dublvalue = 0;
+ }
+ dublvalue = -dublvalue;
+ }
+ else
+ {
+ dublvalue = evalDubl( 0 );
+ nextLexeme();
+ /* Test for any value greater than 23 bits in length. */
+ if( (unsigned long int)dublvalue > 037777777L )
+ {
+ errorMessage( &dubl_overflow, lexstart );
+ dublvalue = 0;
+ }
+ }
+
+ if( is_blank( delimiter ))
+ {
+ return( dublvalue );
+ }
+
+ /* Here we assume the current lexeme is the operator separating the */
+ /* previous operator from the next, if any. */
+ while( TRUE )
+ {
+ /* assert line[lexstart] == delimiter */
+ if( is_blank( delimiter ))
+ {
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ dublvalue = 0;
+ return( dublvalue );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '+': /* add */
+ case '-': /* subtract */
+ case '^': /* multiply */
+ case '%': /* divide */
+ case '&': /* and */
+ case '!': /* or */
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ dublvalue = 0;
+ break;
+
+ default:
+ if( isend( line[lexstart] ))
+ {
+ return( dublvalue );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '/':
+ case ';':
+ break;
+
+ default:
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ dublvalue = 0;
+ break;
+ }
+ return( dublvalue );
+ }
+ } /* end while */
+} /* getDublExpr() */
+
+
+/******************************************************************************/
+/* */
+/* Function: evalDubl */
+/* */
+/* Synopsis: Get the value of the current lexeme as a double word. The */
+/* number is always considered to have a decimal radix. */
+/* */
+/******************************************************************************/
+WORD32 evalDubl( WORD32 initial_value )
+{
+ WORD32 digit;
+ int from;
+ WORD32 dublvalue;
+ WORD32 olddublvalue;
+
+ overflow = FALSE;
+ delimiter = line[lexterm];
+ from = lexstart;
+ dublvalue = initial_value;
+
+ while( from < lexterm )
+ {
+ if( isdigit( line[from] ))
+ {
+ olddublvalue = dublvalue;
+ digit = (WORD32)( line[from++] - '0' );
+ dublvalue = dublvalue * 10 + digit;
+ if( dublvalue < olddublvalue )
+ {
+ overflow = TRUE;
+ }
+ }
+ else
+ {
+ errorLexeme( ¬_a_number, from );
+ dublvalue = 0;
+ from = lexterm;
+ }
+ }
+ return( dublvalue );
+} /* evalDubl() */
+
+
+/******************************************************************************/
+/* */
+/* Function: inputFltg */
+/* */
+/* Synopsis: Get the value of the current lexeme as a Floating Point const. */
+/* */
+/******************************************************************************/
+void inputFltg()
+{
+ FLTG_T *fltg;
+ BOOL scanning_line;
+
+ fltg_input = TRUE; /* Set lexeme scanner for floating point. */
+ scanning_line = TRUE;
+ while( TRUE )
+ {
+ while( scanning_line )
+ {
+ if( isend( line[lexstart] ))
+ {
+ scanning_line = FALSE;
+ }
+ else
+ {
+ switch( line[lexstart] )
+ {
+ case '/':
+ scanning_line = FALSE;
+ break;
+
+ case ';':
+ nextLexeme();
+ break;
+
+ case '+':
+ delimiter = line[lexterm];
+ nextLexBlank();
+ case '-':
+ default:
+ if( isdigit( line[lexstart] ) || line[lexstart] == '-' )
+ {
+ fltg = getFltgExprs();
+ punchOutObject( clc, ( fltg->exponent & 07777 ));
+ incrementClc();
+ punchOutObject( clc, (WORD16)(( fltg->mantissa >> 12 ) & 07777 ));
+ incrementClc();
+ punchOutObject( clc, (WORD16)( fltg->mantissa & 07777 ));
+ incrementClc();
+ }
+ else
+ {
+ fltg_input = FALSE; /* Reset lexeme scanner. */
+ return; /* Non-numeric input, back to assembly. */
+ }
+ break;
+ } /* end switch */
+ } /* end if */
+
+ if( error_in_line )
+ {
+ fltg_input = FALSE; /* Reset lexeme scanner. */
+ return; /* Error occurred, exit FLTG input mode. */
+ }
+ } /* end while( scanning_line ) */
+ readLine();
+ nextLexeme();
+ scanning_line = TRUE;
+ }
+} /* inputFltg() */
+
+
+/******************************************************************************/
+/* */
+/* Function: getFltgExprs */
+/* */
+/* Synopsis: Get a FLTG expression. */
+/* */
+/******************************************************************************/
+FLTG_T *getFltgExprs()
+{
+ FLTG_T *fltg;
+
+ fltg = getFltgExpr();
+
+ while( TRUE )
+ {
+ if( isdone( line[lexstart] ))
+ {
+ return( fltg );
+ }
+ else
+ {
+ errorMessage( &illegal_expression, lexstart - 1 );
+ return( 0 );
+ }
+ } /* end while */
+} /* getFltgExprs() */
+
+
+/******************************************************************************/
+/* */
+/* Function: getFltgExpr */
+/* */
+/* Synopsis: Get the value of the current lexeme as a double word. The */
+/* number is always considered to have a decimal radix. */
+/* */
+/******************************************************************************/
+FLTG_T *getFltgExpr()
+{
+ FLTG_T *fltg;
+
+ delimiter = line[lexterm];
+ fltg = evalFltg();
+ /* Test for any value greater than 23 bits in length. */
+ if( (unsigned long int)fltg->mantissa> 077777777L )
+ {
+ errorMessage( &fltg_overflow, lexstart );
+ }
+
+ if( is_blank( delimiter ))
+ {
+ return( fltg );
+ }
+
+ /* Here we assume the current lexeme is the operator separating the */
+ /* previous operator from the next, if any. */
+ while( TRUE )
+ {
+ /* assert line[lexstart] == delimiter */
+ if( is_blank( delimiter ))
+ {
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ fltg = 0;
+ return( fltg );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '+': /* add */
+ case '-': /* subtract */
+ case '^': /* multiply */
+ case '%': /* divide */
+ case '&': /* and */
+ case '!': /* or */
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ fltg = NULL;
+ break;
+
+ default:
+ if( isend( line[lexstart] ))
+ {
+ return( fltg );
+ }
+
+ switch( line[lexstart] )
+ {
+ case '/':
+ case ';':
+ break;
+
+ default:
+ errorMessage( &illegal_expression, lexstart );
+ moveToEndOfLine();
+ fltg = NULL;
+ break;
+ }
+ return( fltg );
+ }
+ } /* end while */
+} /* getFltgExpr() */
+
+
+/******************************************************************************/
+/* */
+/* Function: evalFltg */
+/* */
+/* Synopsis: Get the value of the current lexeme as a floating point value. */
+/* Floating point input is alwasy considered decimal. */
+/* The general format of a floating point number is: */
+/* +-ddd.dddE+-dd where each d is a decimal digit. */
+/* */
+/******************************************************************************/
+FLTG_T *evalFltg()
+{
+ int current_state;
+ int current_col;
+ WORD16 exponent;
+ FLTG_T *fltg;
+ WORD32 input_value;
+ BOOL negate;
+ BOOL negate_exponent;
+ int next_state;
+ int right_digits;
+
+ /* This uses a lexical analyzer to parse the floating point format. */
+ static BYTE state_table[][10] =
+ {
+ /* 0 1 2 3 4 5 6 Oolumn index */
+ /* + - d . E sp p State Comment */
+ { 2, 1, 3, 4, 10, 10, 10 }, /* 0 Initial state. */
+ { 11, 11, 3, 4, 11, 11, 11 }, /* 1 - */
+ { 11, 11, 3, 4, 11, 11, 11 }, /* 2 + */
+ { 10, 10, 10, 4, 6, 10, 10 }, /* 3 # (+-ddd) */
+ { 11, 11, 5, 11, 11, 10, 10 }, /* 4 . (+-ddd.) */
+ { 11, 11, 11, 11, 6, 10, 11 }, /* 5 # (+-ddd.ddd) */
+ { 8, 7, 9, 11, 11, 11, 11 }, /* 6 E (+-ddd.dddE) */
+ { 11, 11, 9, 11, 11, 11, 11 }, /* 7 - (+-ddd.dddE- */
+ { 11, 11, 9, 11, 11, 11, 11 }, /* 8 + (+-ddd.dddE+ */
+ { 11, 11, 11, 11, 11, 10, 11 } /* 9 # (+-ddd.dddE+-dd */
+ /* 10 Completion state */
+ /* 11 Error state. */
+ };
+
+ delimiter = line[lexterm];
+ fltg = &fltg_ac;
+ fltg->exponent = 0;
+ fltg->mantissa = 0;
+ input_value = 0;
+ negate = FALSE;
+ negate_exponent = FALSE;
+ next_state = 0;
+ exponent = 0;
+ right_digits = 0;
+ current_state = 0;
+
+ while( TRUE )
+ {
+ /* Classify character. This is the column index. */
+ switch( line[lexstart] )
+ {
+ case '+':
+ current_col = 0;
+ break;
+
+ case '-':
+ current_col = 1;
+ break;
+
+ case '.':
+ current_col = 3;
+ break;
+
+ case 'E': case 'e':
+ current_col = 4;
+ break;
+
+ default:
+ if( isdigit( line[lexstart] ))
+ {
+ current_col = 2;
+ }
+ else if( isdone( line[lexstart] ))
+ {
+ current_col = 5;
+ }
+ else
+ {
+ current_col = 6;
+ }
+ break;
+ }
+
+ next_state = state_table[current_state][current_col];
+
+ switch( next_state )
+ {
+ case 1: /* - */
+ negate = TRUE;
+ case 2: /* + */
+ delimiter = line[lexterm]; /* Move past the + or - character. */
+ nextLexBlank();
+ break;
+
+ case 3: /* Number (+-ddd) */
+ input_value = evalDubl( 0 ); /* Integer part of the number. */
+ nextLexeme(); /* Move past previous lexeme. */
+ break;
+
+ case 4:
+ delimiter = line[lexterm];
+ nextLexBlank(); /* Move past the . character. */
+ break;
+
+ case 5: /* . (+-ddd.ddd) */
+ /* Fractional part of the number. */
+ input_value = evalDubl( input_value );
+ right_digits = lexterm - lexstart;/* Digit count to right of decimal. */
+ nextLexeme(); /* Move past previous lexeme. */
+ break;
+
+ case 6: /* E (+-ddd.dddE) */
+ delimiter = line[lexterm]; /* Move past the E. */
+ nextLexBlank();
+ break;
+
+ case 7: /* - (+-ddd.dddE-) */
+ negate_exponent = TRUE;
+ case 8: /* + (+-ddd.dddE+) */
+ delimiter = line[lexterm]; /* Move past the + or - character. */
+ nextLexBlank();
+ break;
+
+ case 9: /* # (+-ddd.dddE+-dd) */
+ exponent = (int)evalDubl( 0 ); /* Exponent of floating point number. */
+ if( negate_exponent ) { exponent = - exponent; }
+ nextLexeme(); /* Move past previous lexeme. */
+ break;
+
+ case 10: /* Floating number parsed, convert */
+ /* the number. */
+ /* Get the exponent for the number as input. */
+ exponent -= right_digits;
+
+ /* Remove trailing zeros and adjust the exponent accordingly. */
+ while(( input_value % 10 ) == 0 )
+ {
+ input_value /= 10;
+ exponent++;
+ }
+
+ /* Convert the number to floating point. The number is calculated with */
+ /* a 27 bit mantissa to improve precision. The extra 3 bits are */
+ /* discarded after the result has been calculated. */
+ fltg->exponent = 26;
+ fltg->mantissa = input_value << 3;
+ normalizeFltg( fltg );
+
+
+ while( exponent != 0 )
+ {
+ if( exponent < 0 )
+ {
+ /* Decimal point is to the left. */
+ fltg->mantissa /= 10;
+ normalizeFltg( fltg );
+ exponent++;
+ }
+ else if( exponent > 0 )
+ {
+ /* Decimal point is to the right. */
+ fltg->mantissa *= 10;
+ normalizeFltg( fltg );
+ exponent--;
+ }
+ }
+
+ /* Discard the extra precsion used for calculating the number. */
+ fltg->mantissa >>= 3;
+ fltg->exponent -= 3;
+ if( negate )
+ {
+ fltg->mantissa = (- fltg->mantissa ) & 077777777L;
+ }
+ return( fltg );
+
+ case 11: /* Error in format. */
+ /* Not a properly constructued floating point number. */
+ return( fltg );
+ default:
+ break;
+ }
+ /* Set state for next pass through the loop. */
+ current_state = next_state;
+ }
+} /* evalFltg() */
+
+
+
+/******************************************************************************/
+/* */
+/* Function: normalizeFltg */
+/* */
+/* Synopsis: Normalize a PDP-8 double precision floating point number. */
+/* */
+/******************************************************************************/
+void normalizeFltg( FLTG_T *fltg )
+{
+ /* Normalize the floating point number. */
+ if( fltg->mantissa != 0 )
+ {
+ if(( fltg->mantissa & ~0x3FFFFFFL ) == 0 )
+ {
+ while(( fltg->mantissa & ~0x1FFFFFFL ) == 0 )
+
+ {
+ fltg->mantissa <<= 1;
+ fltg->exponent--;
+ }
+ }
+ else
+ {
+ while(( fltg->mantissa & ~0x3FFFFFFL ) != 0 )
+ {
+ fltg->mantissa >>= 1;
+ fltg->exponent++;
+ }
+ }
+ }
+ else
+ {
+ fltg->exponent = 0;
+ }
+ return;
+}
+
+
+/******************************************************************************/
+/* */
+/* Function: incrementClc */
+/* */
+/* Synopsis: Set the next assembly location. Test for collision with */
+/* the literal tables. */
+/* */
+/******************************************************************************/
+WORD16 incrementClc()
+{
+ testForLiteralCollision( clc );
+
+ /* Incrementing the location counter is not to change field setting. */
+ clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 );
+ fieldlc = clc & 07777;
+ return( clc );
+} /* incrementClc() */
+
+
+/******************************************************************************/
+/* */
+/* Function: testForLiteralCollision */
+/* */
+/* Synopsis: Test the given location for collision with the literal tables. */
+/* */
+/******************************************************************************/
+BOOL testForLiteralCollision( WORD16 loc )
+{
+ WORD16 pagelc;
+ BOOL result = FALSE;
+ WORD16 tmppage;
+ int tmpfield;
+
+ tmpfield = GET_PAGE_INDEX(loc);
+ tmppage = loc & 07600;
+ pagelc = loc & 00177;
+
+ if ( pagelc > max_page_used[tmpfield] )
+ {
+ max_page_used[tmpfield] = pagelc;
+ }
+ if ( pagelc >= cp[tmpfield].loc )
+ {
+ if ( tmppage == 0 )
+ {
+ errorMessage( &pz_literal_overflow, -1 );
+ }
+ else
+ {
+ errorMessage( &literal_overflow, -1 );
+ }
+ result = TRUE;
+ }
+
+ return( result );
+} /* testForLiteralCollision() */
+
+
+/******************************************************************************/
+/* */
+/* Function: readLine */
+/* */
+/* Synopsis: Get next line of input. Print previous line if needed. */
+/* */
+/******************************************************************************/
+void readLine()
+{
+ WORD16 ix;
+ WORD16 iy;
+ char inpline[LINELEN];
+
+ listLine(); /* List previous line if needed. */
+ lineno++; /* Count lines read. */
+ indirect_generated = FALSE; /* Mark no indirect address generated. */
+ listed = FALSE; /* Mark as not listed. */
+ cc = 0; /* Initialize column counter. */
+ lexstartprev = 0;
+
+ error_in_line = FALSE;
+ if(( fgets( inpline, LINELEN - 1, infile )) == NULL )
+ {
+ inpline[0] = '$';
+ inpline[1] = '\n';
+ inpline[2] = '\0';
+ if (!dollar_not_required) {
+ error_in_line = TRUE;
+ }
+ }
+
+ /* Remove any tabs from the input line by inserting the required number */
+ /* of spaces to simulate N character tab stops, where N defaults to 8 and */
+ /* is set by the command line option -t. (RK 20071029) */
+ /* Ignore \r if there is one. (DPI 20150501) */
+ for( ix = 0, iy = 0; inpline[ix] != '\0' && iy < (LINELEN - 2); ix++ )
+ {
+ switch( inpline[ix] )
+ {
+ case '\t':
+ do
+ {
+ line[iy] = ' ';
+ iy++;
+ }
+ while(( iy % tabstops ) != 0 && iy < (LINELEN - 2));
+ break;
+
+ case '\r': /* dont copy the carriage return */
+ break;
+
+ default:
+ line[iy] = inpline[ix];
+ iy++;
+ break;
+ }
+ }
+ if (iy >= (LINELEN - 2)) {
+ line [iy] = '\n';
+ iy++;
+ }
+ line[iy] = '\0';
+
+ maxcc = iy; /* Save the current line length. */
+ /* Save the first line for possible use as the listing title. */
+ if( lineno == 1 )
+ {
+ strcpy( list_title, line );
+ }
+} /* readLine() */
+
+
+/******************************************************************************/
+/* */
+/* Function: listLine */
+/* */
+/* Synopsis: Output a line to the listing file. */
+/* */
+/******************************************************************************/
+void listLine()
+/* generate a line of listing if not already done! */
+{
+ if( listfile != NULL && listed == FALSE )
+ {
+ printLine( line, 0, 0, LINE );
+ }
+} /* listLine() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printPageBreak */
+/* */
+/* Synopsis: Output a Top of Form and listing header if new page necessary. */
+/* */
+/******************************************************************************/
+void printPageBreak()
+{
+ if( page_lineno >= LIST_LINES_PER_PAGE )
+ /* ( list_lineno % LIST_LINES_PER_PAGE ) == 0 ) */
+ {
+ if( !list_title_set )
+ {
+ /* strcpy( list_title, line ); */
+ if( list_title[strlen(list_title) - 1] == '\n' )
+ {
+ list_title[strlen(list_title) - 1] = '\0';
+ }
+ if( strlen( list_title ) > TITLELEN )
+ {
+ list_title[TITLELEN] = '\0';
+ }
+ list_title_set = TRUE;
+ }
+ topOfForm( list_title, NULL );
+
+ }
+} /* printPageBreak() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printLine */
+/* */
+/* Synopsis: Output a line to the listing file with new page if necessary. */
+/* */
+/******************************************************************************/
+void printLine( char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle )
+{
+ char rlc;
+
+ if( listfile == NULL )
+ {
+ save_error_count = 0;
+ return;
+ }
+
+ printPageBreak();
+
+ list_lineno++;
+ page_lineno++;
+
+ if (reloc == 0)
+ {
+ rlc = ' ';
+ }
+ else
+ {
+ rlc = '*';
+ }
+
+ switch( linestyle )
+ {
+ default:
+ case LINE:
+ fprintf(listfile, "%5d ", lineno );
+ fputs( line, listfile );
+ listed = TRUE;
+ break;
+
+ case LINE_VAL:
+ fprintf(listfile, "%5d %4.4o ", lineno, val );
+ fputs( line, listfile );
+ listed = TRUE;
+ break;
+
+ case LINE_LOC_VAL:
+ if( !listed )
+ {
+ if( indirect_generated )
+ {
+ fprintf( listfile, "%5d %5.5o%c %4.4o@ ", lineno, loc, rlc, val );
+ }
+ else
+ {
+ fprintf( listfile, "%5d %5.5o%c %4.4o ", lineno, loc, rlc, val );
+ }
+ fputs( line, listfile );
+ listed = TRUE;
+ }
+ else
+ {
+ fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val );
+ }
+ break;
+
+ case LOC_VAL:
+ fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val );
+ break;
+ }
+ printErrorMessages();
+} /* printLine() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printErrorMessages */
+/* */
+/* Synopsis: Output any error messages from the current list of errors. */
+/* */
+/******************************************************************************/
+void printErrorMessages()
+{
+ WORD16 ix;
+ WORD16 iy;
+
+ if( listfile != NULL )
+ {
+ /* If any errors, display them now. */
+ for( iy = 0; iy < save_error_count; iy++ )
+ {
+ printPageBreak();
+ fprintf( listfile, "%-18.18s", error_list[iy].mesg );
+ if( error_list[iy].col >= 0 )
+ {
+ for( ix = 0; ix < error_list[iy].col; ix++ )
+ {
+ if( line[ix] == '\t' )
+ {
+ putc( '\t', listfile );
+ }
+ else
+ {
+ putc( ' ', listfile );
+ }
+ }
+ fputs( "^", listfile );
+ list_lineno++;
+ page_lineno++;
+ }
+ fputs( "\n", listfile );
+ }
+ }
+ save_error_count = 0;
+} /* printErrorMessages() */
+
+
+/******************************************************************************/
+/* */
+/* Function: endOfBinary */
+/* */
+/* Synopsis: Outputs both literal tables at the end of a binary segment. */
+/* */
+/******************************************************************************/
+void endOfBinary()
+{
+ /* Punch page 0 also. */
+ punchLiteralPool( cp, 1 );
+ if( error_in_line )
+ {
+ listed = TRUE;
+ clc = ( clc & 070000 ) + (( clc - 1 ) & 07777 );
+ errorMessage( &end_of_file, -1 );
+ clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 );
+ }
+ else
+ {
+ listLine(); /* List line if not done yet. */
+ }
+ return;
+} /* endOfBinary() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchChecksum */
+/* */
+/* Synopsis: Output a checksum if the current mode requires it and an */
+/* object file exists. */
+/* */
+/******************************************************************************/
+void punchChecksum()
+{
+ /* If the assembler has output any BIN data output the checksum. */
+ if( binary_data_output && !rim_mode )
+ {
+ punchLocObject( 0, checksum );
+ }
+ binary_data_output = FALSE;
+ checksum = 0;
+} /* punchChecksum() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchLeader */
+/* */
+/* Synopsis: Generate 2 feet of leader on object file, as per DEC */
+/* documentation. Paper tape has 10 punches per inch. */
+/* */
+/******************************************************************************/
+void punchLeader( int count )
+{
+ int ix;
+
+ /* If value is zero, set to the default of 2 feet of leader. */
+ count = ( count == 0 ) ? 240 : count;
+
+ if( objectfile != NULL )
+ {
+ for( ix = 0; ix < count; ix++ )
+ {
+ fputc( 0200, objectfile );
+ }
+ }
+} /* punchLeader() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchOrigin */
+/* */
+/* Synopsis: Output an origin to the object file. */
+/* */
+/******************************************************************************/
+void punchOrigin( WORD16 loc )
+{
+ punchObject((( loc >> 6 ) & 0077 ) | 0100 );
+ punchObject( loc & 0077 );
+} /* punchOrigin() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchObject */
+/* */
+/* Synopsis: Put one character to object file and include it in checksum. */
+/* */
+/******************************************************************************/
+void punchObject( WORD16 val )
+{
+ val &= 0377;
+ if( objectfile != NULL )
+ {
+ fputc( val, objectfile );
+ checksum += val;
+ }
+ binary_data_output = TRUE;
+} /* punchObject() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchOutObject */
+/* */
+/* Synopsis: Output the current line and then then punch value to the */
+/* object file. */
+/* */
+/******************************************************************************/
+void punchOutObject( WORD16 loc, WORD16 val )
+{
+ /* Adding reloc makes printout agree with PAL8 where is prints the */
+ /* relocated address, not the address in the BIN file */
+ printLine( line,( ( field | loc ) + reloc ), val, LINE_LOC_VAL );
+ punchLocObject( loc, val );
+} /* punchOutObject() */
+
+/******************************************************************************/
+/* */
+/* Function: punchLocObject */
+/* */
+/* Synopsis: Output the word (with origin if rim format) to the object file.*/
+/* */
+/******************************************************************************/
+void punchLocObject( WORD16 loc, WORD16 val )
+{
+ if( rim_mode )
+ {
+ punchOrigin( loc );
+ }
+ punchObject(( val >> 6 ) & 0077 );
+ punchObject( val & 0077 );
+} /* punchLocObject() */
+
+
+/******************************************************************************/
+/* */
+/* Function: punchLiteralPool */
+/* */
+/* Synopsis: Output the current page data. */
+/* */
+/******************************************************************************/
+void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 )
+{
+ WORD16 loc;
+ WORD16 tmplc;
+ int lpool_page = 0; /* Silence false uninitialized error from GCC */
+ int i;
+
+ for (i = MAX_PAGES-1; i >= 0; i--) {
+ lpool_page = (i << 7) & 07600;
+
+ if ( p[i].loc != p[i].last_punched && (punch_page0 || lpool_page != 0) )
+ {
+ if( !rim_mode )
+ {
+ /* Put out origin if not in rim mode. */
+ punchOrigin( p[i].loc | lpool_page );
+ }
+ /* Put the literals in the object file. */
+ for( loc = p[i].loc; loc < p[i].last_punched; loc++ )
+ {
+ tmplc = loc + lpool_page;
+ printLine( line, (field | tmplc), p[i].pool[loc], LOC_VAL );
+ punchLocObject( tmplc, p[i].pool[loc] );
+ }
+ p[i].last_punched = p[i].loc;
+ }
+ }
+} /* punchLiteralPool() */
+
+
+/******************************************************************************/
+/* */
+/* Function: insertLiteral */
+/* */
+/* Synopsis: Add a value to the given literal pool if not already in pool. */
+/* Return the location of the value in the pool. */
+/* */
+/******************************************************************************/
+WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index )
+{
+ WORD16 ix;
+ LPOOL_T *p;
+
+ p = &pool[fieldpage_index];
+
+ /* Search the literal pool for any occurence of the needed value. */
+ ix = PAGE_SIZE - 1;
+ while( ix >= p->loc && p->pool[ix] != value )
+ {
+ ix--;
+ }
+
+ /* Check if value found in literal pool. If not, then insert value. */
+ if( ix < p->loc )
+ {
+ (p->loc)--;
+ p->pool[p->loc] = value;
+ ix = p->loc;
+ if( max_page_used[fieldpage_index] >= p->loc ) {
+ if ( (fieldpage_index & 017) == 0 )
+ {
+ errorMessage( &pz_literal_overflow, -1 );
+ }
+ else
+ {
+ errorMessage( &literal_overflow, -1 );
+ }
+ }
+ }
+ return( ix );
+} /* insertLiteral() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printSymbolTable */
+/* */
+/* Synopsis: Output the symbol table. */
+/* */
+/******************************************************************************/
+void printSymbolTable()
+{
+ int col;
+ int cx;
+ char *fmt;
+ int ix;
+ char mark;
+ int page;
+ int row;
+ int symbol_base;
+ int symbol_lines;
+
+ symbol_base = number_of_fixed_symbols;
+
+ for( page=0, list_lineno=0, col=0, ix=symbol_base; ix < symbol_top; page++ )
+ {
+ topOfForm( list_title, s_symtable );
+ symbol_lines = LIST_LINES_PER_PAGE - page_lineno;
+
+ for( row = 0; page_lineno < LIST_LINES_PER_PAGE && ix < symbol_top; row++)
+ {
+ list_lineno++;
+ page_lineno++;
+ fprintf( listfile, "%5d", list_lineno );
+
+ for( col = 0; col < SYMBOL_COLUMNS && ix < symbol_top; col++ )
+ {
+ /* Get index of symbol for the current line and column */
+ cx = symbol_lines * ( SYMBOL_COLUMNS * page + col ) + row;
+ cx += symbol_base;
+
+ /* Make sure that there is a symbol to be printed. */
+ if( number_of_fixed_symbols <= cx && cx < symbol_top )
+ {
+ switch( symtab[cx].type & LABEL )
+ {
+ case LABEL:
+ fmt = " %c%-6.6s %5.5o ";
+ break;
+
+ default:
+ fmt = " %c%-6.6s %4.4o ";
+ break;
+ }
+
+ switch( symtab[cx].type & ( DEFINED | REDEFINED ))
+ {
+ case UNDEFINED:
+ mark = '?';
+ break;
+
+ case REDEFINED:
+ mark = '#';
+ break;
+
+ default:
+ mark = ' ';
+ break;
+ }
+ fprintf( listfile, fmt, mark, symtab[cx].name, symtab[cx].val );
+ ix++;
+ }
+ }
+ fprintf( listfile, "\n" );
+ }
+ }
+} /* printSymbolTable() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printPermanentSymbolTable */
+/* */
+/* Synopsis: Output the permanent symbol table to a file suitable for */
+/* being input after the EXPUNGE pseudo-op. */
+/* */
+/******************************************************************************/
+void printPermanentSymbolTable()
+{
+ int ix;
+ FILE *permfile;
+ char *s_type;
+
+ if(( permfile = fopen( permpathname, "w" )) == NULL )
+ {
+ exit( 2 );
+ }
+
+ fprintf( permfile, "/ PERMANENT SYMBOL TABLE\n/\n" );
+ fprintf( permfile, " EXPUNGE\n/\n" );
+ /* Print the memory reference instructions first. */
+ s_type = "FIXMRI";
+ for( ix = 0; ix < symbol_top; ix++ )
+ {
+ if( M_MRI( symtab[ix].type ))
+ {
+ fprintf( permfile, "%-7s %s=%4.4o\n",
+ s_type, symtab[ix].name, symtab[ix].val );
+ }
+ }
+
+ s_type = " ";
+ for( ix = 0; ix < symbol_top; ix++ )
+ {
+ if( M_FIXED( symtab[ix].type ))
+ {
+ if( !M_MRI( symtab[ix].type ) && !M_PSEUDO( symtab[ix].type ))
+ {
+ fprintf( permfile, "%-7s %s=%4.4o\n",
+ s_type, symtab[ix].name, symtab[ix].val );
+ }
+ }
+ }
+ fprintf( permfile, "/\n FIXTAB\n" );
+ fclose( permfile );
+} /* printPermanentSymbolTable() */
+
+
+/******************************************************************************/
+/* */
+/* Function: printCrossReference */
+/* */
+/* Synopsis: Output a cross reference (concordance) for the file being */
+/* assembled. */
+/* */
+/******************************************************************************/
+void printCrossReference()
+{
+ int ix;
+ int symbol_base;
+ int xc;
+ int xc_index;
+ int xc_refcount;
+ int xc_cols;
+
+ /* Force top of form for first page. */
+ page_lineno = LIST_LINES_PER_PAGE;
+
+ list_lineno = 0;
+ symbol_base = number_of_fixed_symbols;
+
+ for( ix = symbol_base; ix < symbol_top; ix++ )
+ {
+ list_lineno++;
+ page_lineno++;
+ if( page_lineno >= LIST_LINES_PER_PAGE )
+ {
+ topOfForm( list_title, s_xref );
+ }
+
+ fprintf( listfile, "%5d", list_lineno );
+
+ /* Get reference count & index into concordance table for this symbol. */
+ xc_refcount = symtab[ix].xref_count;
+ xc_index = symtab[ix].xref_index;
+ /* Determine how to label symbol on concordance. */
+ switch( symtab[ix].type & ( DEFINED | REDEFINED ))
+ {
+ case UNDEFINED:
+ fprintf( listfile, " U ");
+ break;
+
+ case REDEFINED:
+ fprintf( listfile, " M %5d ", xreftab[xc_index] );
+ break;
+
+ default:
+ fprintf( listfile, " A %5d ", xreftab[xc_index] );
+ break;
+ }
+ fprintf( listfile, "%-6.6s ", symtab[ix].name );
+
+ /* Output the references, 8 numbers per line after symbol name. */
+ for( xc_cols = 0, xc = 1; xc < xc_refcount + 1; xc++, xc_cols++ )
+ {
+ if( xc_cols >= XREF_COLUMNS )
+ {
+ xc_cols = 0;
+ page_lineno++;
+ if( page_lineno >= LIST_LINES_PER_PAGE )
+ {
+ topOfForm( list_title, s_xref);
+ }
+ list_lineno++;
+ fprintf( listfile, "\n%5d%-19s", list_lineno, " " );
+ }
+ fprintf( listfile, " %5d", xreftab[xc_index + xc] );
+ }
+ fprintf( listfile, "\n" );
+ }
+} /* printCrossReference() */
+
+
+/******************************************************************************/
+/* */
+/* Function: topOfForm */
+/* */
+/* Synopsis: Prints title and sub-title on top of next page of listing. */
+/* */
+/******************************************************************************/
+void topOfForm( char *title, char *sub_title )
+{
+ char temp[10];
+
+ list_pageno++;
+ strcpy( temp, s_page );
+ sprintf( temp, "%s %d", s_page, list_pageno );
+
+ /* Output a top of form if not the first page of the listing. */
+ if( list_pageno > 1 )
+ {
+ fprintf( listfile, "\f" );
+ }
+ fprintf( listfile, "\n\n\n %-63s %10s\n", title, temp );
+
+ /* Reset the current page line counter. */
+ page_lineno = 3;
+ if( sub_title != NULL )
+ {
+ fprintf( listfile, "%80s\n", sub_title );
+ page_lineno++;
+ }
+ else
+ {
+ fprintf( listfile, "\n" );
+ page_lineno++;
+ }
+ fprintf( listfile, "\n" );
+ page_lineno++;
+} /* topOfForm() */
+
+
+/******************************************************************************/
+/* */
+/* Function: lexemeToName */
+/* */
+/* Synopsis: Convert the current lexeme into a string. */
+/* */
+/******************************************************************************/
+char *lexemeToName( char *name, int from, int term )
+{
+ int to;
+
+ to = 0;
+
+ while( from < term && to < ( SYMLEN - 1 ))
+ {
+ name[to++] = toupper( line[from++] );
+ }
+
+ while( to < SYMLEN )
+ {
+ name[to++] = '\0';
+ }
+ return( name );
+} /* lexemeToName() */
+
+/******************************************************************************/
+/* */
+/* Function: defineLexeme */
+/* */
+/* Synopsis: Put lexeme into symbol table with a value. */
+/* */
+/******************************************************************************/
+SYM_T *defineLexeme( int start, /* start of lexeme being defined. */
+ int term, /* end+1 of lexeme being defined. */
+ WORD16 val, /* value of lexeme being defined. */
+ SYMTYP type ) /* how symbol is being defined. */
+{
+ char name[SYMLEN];
+
+ lexemeToName( name, start, term);
+ return( defineSymbol( name, val, type, start ));
+} /* defineLexeme() */
+
+
+/******************************************************************************/
+/* */
+/* Function: defineSymbol */
+/* */
+/* Synopsis: Define a symbol in the symbol table, enter symbol name if not */
+/* not already in table. */
+/* */
+/******************************************************************************/
+SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start )
+{
+ SYM_T *sym;
+ int xref_count;
+
+ if( strlen( name ) < 1 )
+ {
+ return( &sym_undefined ); /* Protect against non-existent names. */
+ }
+ sym = lookup( name );
+ /* OS/8 PAL8 seems to allow permanent symbold to be redefined without error */
+ if( ( M_FIXED( sym->type ) && pass == 1 && perm_redef_error ) ||
+ (M_PERM_REDEFINED( sym->type ) && (sym->val != val)) )
+ {
+ type |= PERM_REDEFINED;
+ }
+
+ xref_count = 0; /* Set concordance for normal defintion. */
+
+ if( M_DEFINED( sym->type ))
+ {
+ if( pass == 2 && ( (sym->val & 07777) != (val & 07777) || M_PERM_REDEFINED(sym->type)) )
+ {
+ /* Generate diagnostic if redefining a symbol. */
+ if( M_PERM_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) )
+ {
+ errorSymbol( &illegal_redefine, sym->name, start );
+ } else
+ {
+ /* Generate diagnostic if redefining a symbol. */
+ if( M_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) )
+ {
+ errorSymbol( &redefined_symbol, sym->name, start );
+ }
+ }
+ type = type | REDEFINED;
+ sym->xref_count++; /* Referenced suymbol, count it. */
+ xref_count = sym->xref_count;
+ }
+ }
+
+ if( pass == 2 && xref )
+ {
+ /* Put the definition line number in the concordance table. */
+ /* Defined symbols are not counted as references. */
+ xreftab[sym->xref_index] = lineno;
+ /* Put the line number in the concordance table. */
+ xreftab[sym->xref_index + xref_count] = lineno;
+ }
+
+ /* Now set the value and the type. */
+ sym->val = ( M_LABEL(type) ) ? val : val & 07777;
+ sym->type = ( pass == 1 ) ? ( type | CONDITION ) : type;
+ return( sym );
+} /* defineSymbol() */
+
+
+/******************************************************************************/
+/* */
+/* Function: lookup */
+/* */
+/* Synopsis: Find a symbol in table. If not in table, enter symbol in */
+/* table as undefined. Return address of symbol in table. */
+/* */
+/******************************************************************************/
+SYM_T *lookup( char *name )
+{
+ int ix; /* Insertion index */
+ int lx; /* Left index */
+ int rx; /* Right index */
+
+ /* First search the permanent symbols. */
+ lx = 0;
+ ix = binarySearch( name, lx, number_of_fixed_symbols );
+
+ /* If symbol not in permanent symbol table. */
+ if( ix < 0 )
+ {
+ /* Now try the user symbol table. */
+ ix = binarySearch( name, number_of_fixed_symbols, symbol_top );
+
+ /* If symbol not in user symbol table. */
+ if( ix < 0 )
+ {
+ /* Must put symbol in table if index is negative. */
+ ix = ~ix;
+ if( symbol_top + 1 >= SYMBOL_TABLE_SIZE )
+ {
+ errorSymbol( &symbol_table_full, name, lexstart );
+ exit( 1 );
+ }
+
+ for( rx = symbol_top; rx >= ix; rx-- )
+ {
+ symtab[rx + 1] = symtab[rx];
+ }
+ symbol_top++;
+
+ /* Enter the symbol as UNDEFINED with a value of zero. */
+ strcpy( symtab[ix].name, name );
+ symtab[ix].type = UNDEFINED;
+ symtab[ix].val = 0;
+ symtab[ix].xref_count = 0;
+ if( xref && pass == 2 )
+ {
+ xreftab[symtab[ix].xref_index] = 0;
+ }
+ }
+ }
+
+ return( &symtab[ix] ); /* Return the location of the symbol. */
+} /* lookup() */
+
+
+/******************************************************************************/
+/* */
+/* Function: binarySearch */
+/* */
+/* Synopsis: Searches the symbol table within the limits given. If the */
+/* symbol is not in the table, it returns the insertion point. */
+/* */
+/******************************************************************************/
+int binarySearch( char *name, int start, int symbol_count )
+{
+ int lx; /* Left index */
+ int mx; /* Middle index */
+ int rx; /* Right index */
+ int compare; /* Results of comparison */
+
+ lx = start;
+ rx = symbol_count - 1;
+ while( lx <= rx )
+ {
+ mx = ( lx + rx ) / 2; /* Find center of search area. */
+
+ compare = strcmp( name, symtab[mx].name );
+
+ if( compare < 0 )
+ {
+ rx = mx - 1;
+ }
+ else if( compare > 0 )
+ {
+ lx = mx + 1;
+ }
+ else
+ {
+ return( mx ); /* Found a match in symbol table. */
+ }
+ } /* end while */
+ return( ~lx ); /* Return insertion point. */
+} /* binarySearch() */
+
+
+/******************************************************************************/
+/* */
+/* Function: compareSymbols */
+/* */
+/* Synopsis: Used to presort the symbol table when starting assembler. */
+/* */
+/******************************************************************************/
+int compareSymbols( const void *a, const void *b )
+{
+ return( strcmp( ((SYM_T *) a)->name, ((SYM_T *) b)->name ));
+} /* compareSymbols() */
+
+
+/******************************************************************************/
+/* */
+/* Function: evalSymbol */
+/* */
+/* Synopsis: Get the pointer for the symbol table entry if exists. */
+/* If symbol doesn't exist, return a pointer to the undefined sym */
+/* */
+/******************************************************************************/
+SYM_T *evalSymbol()
+{
+ char name[SYMLEN];
+ SYM_T *sym;
+
+ sym = lookup( lexemeToName( name, lexstart, lexterm ));
+
+ /* The symbol goes in the concordance iff it is in a different position in */
+ /* the assembler source file. */
+ if( lexstart != last_xref_lexstart || lineno != last_xref_lineno )
+ {
+ sym->xref_count++; /* Count the number of references to symbol. */
+ last_xref_lexstart = lexstart;
+ last_xref_lineno = lineno;
+
+ /* Put the line number in the concordance table. */
+ if( xref && pass == 2 )
+ {
+ xreftab[sym->xref_index + sym->xref_count] = lineno;
+ }
+ }
+
+ return( sym );
+} /* evalSymbol() */
+
+
+/******************************************************************************/
+/* */
+/* Function: moveToEndOfLine */
+/* */
+/* Synopsis: Move the parser input to the end of the current input line. */
+/* */
+/******************************************************************************/
+void moveToEndOfLine()
+{
+ while( !isend( line[cc] )) cc++;
+ lexstart = cc;
+ lexterm = cc;
+ lexstartprev = lexstart;
+} /* moveToEndOfLine() */
+
+/******************************************************************************/
+/* */
+/* Function: nextLexeme */
+/* */
+/* Synopsis: Get the next lexical element from input line. */
+/* */
+/******************************************************************************/
+void nextLexeme()
+{
+ /* Save start column of previous lexeme for diagnostic messages. */
+ lexstartprev = lexstart;
+ lextermprev = lexterm;
+
+ while( is_blank( line[cc] )) { cc++; }
+ lexstart = cc;
+
+ if( isalnum( line[cc] ))
+ {
+ while( isalnum( line[cc] )) { cc++; }
+ }
+ else if( isend( line[cc] ))
+ {
+ /* End-of-Line, don't advance cc! */
+ }
+ else
+ {
+ switch( line[cc] )
+ {
+ case '"': /* Quoted letter */
+ if( cc + 2 < maxcc )
+ {
+ cc++;
+ cc++;
+ }
+ else
+ {
+ errorMessage( &no_literal_value, lexstart );
+ cc++;
+ }
+ break;
+
+ case '/': /* Comment, don't advance cc! */
+ break;
+
+ default: /* All other punctuation. */
+ cc++;
+ break;
+ }
+ }
+ lexterm = cc;
+} /* nextLexeme() */
+
+
+/******************************************************************************/
+/* */
+/* Function: nextLexBlank */
+/* */
+/* Synopsis: Used to prevent illegal blanks in expressions. */
+/* */
+/******************************************************************************/
+void nextLexBlank()
+{
+ nextLexeme();
+ if( is_blank( delimiter ))
+ {
+ errorMessage( &illegal_blank, lexstart - 1 );
+ }
+ delimiter = line[lexterm];
+} /* nextLexBlank() */
+
+
+/******************************************************************************/
+/* */
+/* Function: pseudoOperators */
+/* */
+/* Synopsis: Process pseudo-ops (directives). */
+/* */
+/******************************************************************************/
+BOOL pseudoOperators( PSEUDO_T val )
+{
+ int count, count2;
+ int delim;
+ int index;
+ int ix;
+ int lexstartsave;
+ WORD16 newfield;
+ WORD16 oldclc;
+ int pack;
+ BOOL status;
+ SYM_T *sym;
+ FILE *temp;
+ int term;
+ WORD16 value;
+ char os8_name[8];
+ int reloc_clc;
+
+ status = TRUE;
+ switch( (PSEUDO_T) val )
+ {
+ case ASCII:
+ /* added 18-Jan-2003 PNT -- derived from TEXT */
+ delim = line[lexstart];
+ index = lexstart + 1;
+ while( line[index] != delim && !isend( line[index] ))
+ {
+ punchOutObject( clc, (line[index] & 127) | 128 );
+ incrementClc();
+ index++;
+ }
+ if( isend( line[index] ))
+ {
+ cc = index;
+ lexterm = cc;
+ errorMessage( &text_string, cc );
+ }
+ else
+ {
+ cc = index + 1;
+ lexterm = cc;
+ }
+ nextLexeme();
+ break;
+
+ case BANK:
+ errorSymbol( &no_pseudo_op, "BANK", lexstartprev );
+ /* should select a different 32K out of 128K */
+ break;
+
+ case BINPUNCH:
+ /* If there has been data output and this is a mode switch, set up to */
+ /* output data in BIN mode. */
+ if( binary_data_output && rim_mode )
+ {
+ clearLiteralTable();
+ punchLeader( 8 ); /* Generate a short leader/trailer. */
+ checksum = 0;
+ binary_data_output = FALSE;
+ }
+ rim_mode = FALSE;
+ break;
+
+ case DECIMAL:
+ radix = 10;
+ break;
+
+ case DUBL:
+ inputDubl();
+ break;
+
+ case EJECT:
+ page_lineno = LIST_LINES_PER_PAGE; /* This will force a page break. */
+ status = FALSE; /* This will force reading of next line */
+ break;
+
+ case ENPUNCH:
+ if( pass == 2 )
+ {
+ objectfile = objectsave;
+ }
+ break;
+
+ case EXPUNGE: /* Erase symbol table */
+ if( pass == 1 )
+ {
+ symtab[0] = sym_undefined;
+ symbol_top = 0;
+ number_of_fixed_symbols = symbol_top;
+ fixed_symbols = &symtab[symbol_top - 1];
+
+ /* Enter the pseudo-ops into the symbol table. */
+ for( ix = 0; ix < DIM( pseudo ); ix++ )
+ {
+ defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 );
+ }
+ /* Enter the really permanent symbols into the table. */
+ /* Also make them part of the permanent symbol table. */
+ for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ )
+ {
+ defineSymbol( really_permanent_symbols[ix].name,
+ really_permanent_symbols[ix].val,
+ really_permanent_symbols[ix].type | DEFFIX , 0 );
+ }
+ number_of_fixed_symbols = symbol_top;
+ fixed_symbols = &symtab[symbol_top - 1];
+
+ }
+ break;
+
+ case FIELD:
+ /* Punch page 0 also */
+ punchLiteralPool( cp, 1 );
+ newfield = field >> 12;
+ lexstartsave = lexstartprev;
+ if( isdone( line[lexstart] ))
+ {
+ newfield += 1; /* Blank FIELD directive. */
+ }
+ else
+ {
+ newfield = (getExpr())->val; /* FIELD with argument. */
+ }
+
+ if( rim_mode )
+ {
+ errorMessage( &in_rim_mode, lexstartsave ); /* Can't change fields. */
+ }
+ else if( newfield > 7 || newfield < 0 )
+ {
+ errorMessage( &illegal_field_value, lexstartprev );
+ }
+ else
+ {
+ value = (( newfield & 0007 ) << 3 ) | 00300;
+ punchObject( value );
+ if( objectfile != NULL ) /* Only fix checksum if punching */
+ {
+ checksum -= value; /* Field punches are not added to checksum. */
+ }
+ field = newfield << 12;
+ }
+
+ clc = 0200 | field;
+ fieldlc = clc & 07777;
+
+ if( !rim_mode )
+ {
+ punchOrigin( clc );
+ }
+
+ clearLiteralTable();
+
+ break;
+
+ case FIXMRI:
+ if( line[lexterm] == '=' && isalpha( line[lexstart] ))
+ {
+ lexstartsave = lexstart;
+ term = lexterm;
+ nextLexeme(); /* Skip symbol. */
+ nextLexeme(); /* Skip trailing = */
+ defineLexeme( lexstartsave, term, getExprs(), MRI );
+ }
+ else
+ {
+ errorLexeme( &symbol_syntax, lexstart );
+ nextLexeme(); /* Skip symbol. */
+ nextLexeme(); /* Skip trailing = */
+ (void) getExprs(); /* Skip expression. */
+ }
+ break;
+
+ case FIXTAB:
+ if (pass == 1) /* Only fix on first pass, on second all are defined */
+ {
+ /* Mark all current symbols as permanent symbols. */
+ for( ix = 0; ix < symbol_top; ix++ )
+ {
+ symtab[ix].type = symtab[ix].type | FIXED;
+ }
+ number_of_fixed_symbols = symbol_top;
+ fixed_symbols = &symtab[symbol_top - 1];
+
+ /* Re-sort the symbol table */
+ qsort( symtab, symbol_top, sizeof(symtab[0]), compareSymbols );
+ }
+ break;
+
+ case FLTG:
+ inputFltg();
+ /* errorSymbol( &no_pseudo_op, "FLTG", lexstartprev ); */
+ break;
+
+ case IFDEF:
+ if( isalpha( line[lexstart] ))
+ {
+ sym = evalSymbol();
+ nextLexeme();
+ if( M_DEFINED_CONDITIONALLY( sym->type ))
+ {
+ conditionTrue();
+ }
+ else
+ {
+ conditionFalse();
+ }
+ }
+ else
+ {
+ errorLexeme( &label_syntax, lexstart );
+ }
+ break;
+
+ case IFNDEF:
+ if( isalpha( line[lexstart] ))
+ {
+ sym = evalSymbol();
+ nextLexeme();
+ if( M_DEFINED_CONDITIONALLY( sym->type ))
+ {
+ conditionFalse();
+ }
+ else
+ {
+ conditionTrue();
+ }
+ }
+ else
+ {
+ errorLexeme( &label_syntax, lexstart );
+ }
+ break;
+
+ case IFNZERO:
+ if( getExprs() == 0 )
+ {
+ conditionFalse();
+ }
+ else
+ {
+ conditionTrue();
+ }
+ break;
+
+ case IFZERO:
+ if( getExprs() == 0 )
+ {
+ conditionTrue();
+ }
+ else
+ {
+ conditionFalse();
+ }
+ break;
+
+ case NOPUNCH:
+ if( pass == 2 )
+ {
+ objectfile = NULL;
+ }
+ break;
+
+ case OCTAL:
+ radix = 8;
+ break;
+
+ case PAGE:
+ reloc_clc = clc + reloc;
+ punchLiteralPool( cp, 0 );
+ oldclc = clc;
+ if( isdone( line[lexstart] ))
+ {
+ clc = (( reloc_clc + 0177 ) & 077600) - reloc; /* No argumnet. */
+ fieldlc = clc & 07777;
+ }
+ else
+ {
+ value = (getExpr())->val;
+ clc = field + (( value & 037 ) << 7 ) - reloc;
+ fieldlc = clc & 07777;
+ }
+ testForLiteralCollision( clc + reloc );
+
+ if( !rim_mode && clc != oldclc )
+ {
+ punchOrigin( clc );
+ }
+ break;
+
+ case PAUSE:
+ break;
+
+ case RELOC:
+ if( isdone( line[lexstart] ))
+ {
+ reloc = 0; /* Blank RELOC directive. */
+ }
+ else
+ {
+ value = (getExpr())->val; /* RELOC with argument. */
+ reloc = (value & 07777) - ( clc & 07777);
+ }
+ break;
+
+ case RIMPUNCH:
+ /* If the assembler has output any BIN data, output the literal tables */
+ /* and the checksum for what has been assembled and setup for RIM mode. */
+ if( binary_data_output && !rim_mode )
+ {
+ endOfBinary();
+ clearLiteralTable();
+ punchChecksum();
+ punchLeader( 8 ); /* Generate a short leader/trailer. */
+ }
+ rim_mode = TRUE;
+ break;
+
+ case SEGMNT:
+ punchLiteralPool( cp, 0 );
+ if( isdone( line[lexstart] ))
+ { /* No argument. */
+ clc = ( clc & 06000 ) + 02000;
+ fieldlc = clc & 07777;
+ }
+ else
+ {
+ getExpr();
+ clc = ( val & 003 ) << 10;
+ fieldlc = clc & 07777;
+ }
+ if( !rim_mode )
+ {
+ punchOrigin( clc );
+ }
+ testForLiteralCollision( clc );
+ break;
+
+ case TEXT:
+ delim = line[lexstart];
+ pack = 0;
+ count = 0;
+ index = lexstart + 1;
+ while( line[index] != delim && !isend( line[index] ))
+ {
+ pack = ( pack << 6 ) | ( line[index] & 077 );
+ count++;
+ if( count > 1 )
+ {
+ punchOutObject( clc, pack );
+ incrementClc();
+ count = 0;
+ pack = 0;
+ }
+ index++;
+ }
+
+ if( count != 0 )
+ {
+ punchOutObject( clc, pack << 6 );
+ incrementClc();
+ }
+ else
+ {
+ punchOutObject( clc, 0 );
+ incrementClc();
+ }
+
+ if( isend( line[index] ))
+ {
+ cc = index;
+ lexterm = cc;
+ errorMessage( &text_string, cc );
+ }
+ else
+ {
+ cc = index + 1;
+ lexterm = cc;
+ }
+ nextLexeme();
+ break;
+
+ case FILENAME:
+ memset(os8_name, 0, sizeof(os8_name));
+ delimiter=line[lexstart];
+ if (delimiter != '.')
+ {
+ for (index = lexstart, count = 0; index < lexterm && count < 6; index++)
+ {
+ os8_name[count++] = line[index];
+ }
+ delimiter=line[lexterm];
+ if (delimiter == '.')
+ {
+ nextLexeme(); /* Skip . */
+ }
+ }
+ nextLexeme();
+ if (delimiter == '.')
+ {
+ for (index = lexstart, count = 6; index < lexterm && count < 8; index++)
+ {
+ os8_name[count++] = line[index];
+ }
+ }
+
+ pack = 0;
+ count = 0;
+ for (count2 = 0; count2 < 8; count2++)
+ {
+ pack = ( pack << 6 ) | ( os8_name[count2] & 077 );
+ count++;
+ if( count > 1 )
+ {
+ punchOutObject( clc, pack );
+ incrementClc();
+ count = 0;
+ pack = 0;
+ }
+ }
+ nextLexeme();
+ break;
+
+ case DEVICE:
+ memset(os8_name, 0, sizeof(os8_name));
+ for (index = lexstart, count = 0; index < lexterm && count < 4; index++)
+ {
+ os8_name[count++] = line[index];
+ }
+
+ pack = 0;
+ count = 0;
+ for (count2 = 0; count2 < 4; count2++)
+ {
+ pack = ( pack << 6 ) | ( os8_name[count2] & 077 );
+ count++;
+ if( count > 1 )
+ {
+ punchOutObject( clc, pack );
+ incrementClc();
+ count = 0;
+ pack = 0;
+ }
+ }
+
+ nextLexeme();
+ break;
+
+ case TITLE:
+ delim = line[lexstart];
+ ix = lexstart + 1;
+ /* Find string delimiter. */
+ do
+ {
+ if( list_title[ix] == delim && list_title[ix + 1] == delim )
+ {
+ ix++;
+ }
+ ix++;
+ } while( line[ix] != delim && !isend(line[ix]) );
+
+ if( line[ix] == delim )
+ {
+ count = 0;
+ ix = lexstart + 1;
+ do
+ {
+ if( list_title[ix] == delim && list_title[ix + 1] == delim )
+ {
+ ix++;
+ }
+ list_title[count] = line[ix];
+ count++;
+ ix++;
+ list_title[count] = '\0';
+ } while( line[ix] != delim && !isend(line[ix]) );
+
+ if( strlen( list_title ) > TITLELEN )
+ {
+ list_title[TITLELEN] = '\0';
+ }
+
+ cc = ix + 1;
+ lexterm = cc;
+ page_lineno = LIST_LINES_PER_PAGE;/* Force top of page for new titles. */
+ list_title_set = TRUE;
+ }
+ else
+ {
+ cc = ix;
+ lexterm = cc;
+ errorMessage( &text_string, cc );
+ }
+
+ nextLexeme();
+ break;
+
+ case XLIST:
+ if( isdone( line[lexstart] ))
+ {
+ temp = listfile; /* Blank XLIST directive. */
+ listfile = listsave;
+ listsave = temp;
+ }
+ else
+ {
+ if( (getExpr())->val == 0 )
+ {
+ if( listfile == NULL )
+ {
+ listfile = listsave;
+ listsave = NULL;
+ }
+ }
+ else
+ {
+ if( listfile != NULL )
+ {
+ listsave = listfile;
+ listfile = NULL;
+ }
+ }
+ }
+ break;
+
+ case ZBLOCK:
+ value = (getExpr())->val;
+ if( value < 0 )
+ {
+ errorMessage( &zblock_too_small, lexstartprev );
+ }
+ else if( value + ( clc & 07777 ) - 1 > 07777 )
+ {
+ errorMessage( &zblock_too_large, lexstartprev );
+ }
+ else
+ {
+ for( ; value > 0; value-- )
+ {
+ punchOutObject( clc, 0 );
+ incrementClc();
+ }
+ }
+
+ break;
+
+ default:
+ break;
+ } /* end switch for pseudo-ops */
+ return( status );
+} /* pseudoOperators() */
+
+
+/******************************************************************************/
+/* */
+/* Function: conditionFalse */
+/* */
+/* Synopsis: Called when a false conditional has been evaluated. */
+/* Lex should be the opening <; ignore all text until */
+/* the closing >. */
+/* */
+/******************************************************************************/
+void conditionFalse()
+{
+ int level;
+
+ if( line[lexstart] == '<' )
+ {
+ /* Invariant: line[cc] is the next unexamined character. */
+ level = 1;
+ while( level > 0 )
+ {
+ if( isend( line[cc] ))
+ {
+ readLine();
+ }
+ else
+ {
+ switch( line[cc] )
+ {
+ case '>':
+ level--;
+ cc++;
+ break;
+
+ case '<':
+ level++;
+ cc++;
+ break;
+
+ case '$':
+ level = 0;
+ cc++;
+ break;
+
+ default:
+ cc++;
+ break;
+ } /* end switch */
+ } /* end if */
+ } /* end while */
+ nextLexeme();
+ }
+ else
+ {
+ errorMessage( <_expected, lexstart );
+ }
+} /* conditionFalse() */
+
+/******************************************************************************/
+/* */
+/* Function: conditionTrue */
+/* */
+/* Synopsis: Called when a true conditional has been evaluated. */
+/* Lex should be the opening <; skip it and setup for */
+/* normal assembly. */
+/* */
+/******************************************************************************/
+void conditionTrue()
+{
+ if( line[lexstart] == '<' )
+ {
+ nextLexeme(); /* Skip the opening '<' */
+ }
+ else
+ {
+ errorMessage( <_expected, lexstart );
+ }
+} /* conditionTrue() */
+
+
+/******************************************************************************/
+/* */
+/* Function: errorLexeme */
+/* */
+/* Synopsis: Display an error message using the current lexical element. */
+/* */
+/******************************************************************************/
+void errorLexeme( EMSG_T *mesg, int col )
+{
+ char name[SYMLEN];
+
+ errorSymbol( mesg, lexemeToName( name, lexstart, lexterm ), col );
+} /* errorLexeme() */
+
+
+/******************************************************************************/
+/* */
+/* Function: errorSymbol */
+/* */
+/* Synopsis: Display an error message with a given string. */
+/* */
+/******************************************************************************/
+void errorSymbol( EMSG_T *mesg, char *name, int col )
+{
+ char linecol[12];
+ char *s;
+
+ if( pass == 2 )
+ {
+ s = ( name == NULL ) ? "" : name ;
+ errors++;
+ sprintf( linecol, "(%d:%d)", lineno, col + 1 );
+ fprintf( errorfile, "%s%-9s : error: %s \"%s\" at Loc = %5.5o\n",
+ filename, linecol, mesg->file, s, clc );
+ saveError( mesg->list, col );
+ }
+ error_in_line = TRUE;
+} /* errorSymbol() */
+
+
+/******************************************************************************/
+/* */
+/* Function: errorMessage */
+/* */
+/* Synopsis: Display an error message without a name argument. */
+/* */
+/******************************************************************************/
+void errorMessage( EMSG_T *mesg, int col )
+{
+ char linecol[12];
+
+ if( pass == 2 )
+ {
+ errors++;
+ sprintf( linecol, "(%d:%d)", lineno, col + 1 );
+ fprintf( errorfile, "%s%-9s : error: %s at Loc = %5.5o\n",
+ filename, linecol, mesg->file, clc );
+ saveError( mesg->list, col );
+ }
+ error_in_line = TRUE;
+} /* errorMessage() */
+
+/******************************************************************************/
+/* */
+/* Function: saveError */
+/* */
+/* Synopsis: Save the current error in a list so it may displayed after the */
+/* the current line is printed. */
+/* */
+/******************************************************************************/
+void saveError( char *mesg, int col )
+{
+ if( save_error_count < DIM( error_list ))
+ {
+ error_list[save_error_count].mesg = mesg;
+ error_list[save_error_count].col = col;
+ save_error_count++;
+ }
+ error_in_line = TRUE;
+
+ if( listed )
+ {
+ printErrorMessages();
+ }
+} /* saveError() */
+/* End-of-File */
Index: src/PDP8/pdp8_cpu.c
==================================================================
--- src/PDP8/pdp8_cpu.c
+++ src/PDP8/pdp8_cpu.c
@@ -410,11 +410,11 @@
// We're about to leave the loop, so repaint one last time
// in case this is a Ctrl-E and we later get a "cont"
// command. Set a flag that will let us auto-resume.
extern int resumeFromInstructionLoopExit, swStop, swSingInst;
resumeFromInstructionLoopExit = swStop = swSingInst = 1;
- set_pidp8i_leds (PC, MA, IR, LAC, MQ, IF, DF, SC,
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC,
int_req, Pause);
// Also copy SR hardware value to software register in case
// the user tries poking at it from the sim> prompt.
SR = get_switch_register();
@@ -436,11 +436,11 @@
// Have to keep display updated while stopped. This does
// mean if the software starts with the STOP switch held
// down, we'll put garbage onto the display for MA, MB, and
// IR, but that's what the real hardware does, too. See
// https://github.com/simh/simh/issues/386
- set_pidp8i_leds (PC, MA, IR, LAC, MQ, IF, DF, SC,
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC,
int_req, Pause);
// Go no further in STOP mode. In particular, fetch no more
// instructions, and do not touch PC!
continue;
@@ -1528,11 +1528,12 @@
// Save skips to inst counter and reset
inst_count += skip_count;
skip_count = 0;
// We need to update the LED data again
- set_pidp8i_leds (PC, MA, IR, LAC, MQ, IF, DF, SC, int_req, Pause);
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC, int_req, Pause);
+ Pause = 0;
// Has it been ~1s since we updated our max_skips value?
time_t now;
if (time(&now) > last_update) {
// Yep; simulator IPS may have changed, so freshen it.
@@ -1542,11 +1543,10 @@
// max_skips, dither, inst_count / 1e6);
inst_count = 0;
}
dither = max_skips > 32 ? lrand48() % (max_skips >> 3) : 0; // 12.5%
}
- Pause = 0; // it's set outside the "if", so it must be *reset* outside
/* ---PiDP end---------------------------------------------------------------------------------------------- */
} /* end while */
/* Simulation halted */
Index: src/PDP8/pidp8i.c.in
==================================================================
--- src/PDP8/pidp8i.c.in
+++ src/PDP8/pidp8i.c.in
@@ -247,13 +247,13 @@
// Given all of the PDP-8's internal registers that affect the front
// panel display, modify the GPIO thread's LED state values accordingly.
//
// Also update the LED brightness values based on those new states.
-void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sIR, int32 sLAC,
- int32 sMQ, int32 sIF, int32 sDF, int32 sSC, int32 int_req,
- int Pause)
+void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sMB,
+ uint16 sIR, int32 sLAC, int32 sMQ, int32 sIF, int32 sDF,
+ int32 sSC, int32 int_req, int Pause)
{
// Bump the instruction count. This should always be equal to the
// Fetch LED's value, but integers are too cheap to get cute here.
//
// Note that we only update pdis_update directly once in this whole
@@ -261,22 +261,16 @@
// working: we want to finish work on the same display even though
// it's now called the paint-from display, so it's consistent.
display* pd = pdis_update;
++pd->inst_count;
- // Rows 0-4, easy cases: single-register LED strings.
- //
- // The only non-obvious one is that we use the PDP-8 simulator's IR
- // register value for the MB lights due to a quirk in the way the
- // register states are set at the time this function is called; MB
- // is not passed to us because its value at the call time is bogus.
+ // Rows 0-4, easy cases: single-register LED strings
set_pidp8i_row_leds (pd, 0, sPC);
set_pidp8i_row_leds (pd, 1, sMA);
- set_pidp8i_row_leds (pd, 2, sIR);
+ set_pidp8i_row_leds (pd, 2, sMB);
set_pidp8i_row_leds (pd, 3, sLAC & 07777);
set_pidp8i_row_leds (pd, 4, sMQ);
-
#if 0 // debugging
static time_t last = 0, now;
if (time(&now) != last) {
uint16* pcurr = pd->curr;
@@ -305,26 +299,19 @@
if ((inst_type <= 05000) && // it's a memory reference instruction
(sIR & 00400)) { // and indirect addressing flag is set
set_pidp8i_led (pd, 5, 1);
}
- // Row 5c: The Fetch & Execute LEDs are pulsed once per instruction.
- // On real hardware, the pulses don't happen at exactly the same
- // time, but we can't simulate that because SIMH handles each CPU
- // instruction "whole." When running real code, all we care about
- // is that both LEDs are twiddled so rapidly that they both just
- // become a 50% blur, mimicking the hardware closely enough.
- //
- // The exception is that when the CPU is stopped, both LEDs are off,
- // because the pulses happen "outside" the STOP state: Fetch before
- // and Execute after resuming from STOP.
+ // Row 5c: The Fetch LED is bumped once per CPU instruction, as is
+ // Execute while we're not in STOP state. They're set at different
+ // times, but they're twiddled so rapidly that they both just become
+ // a 50% blur in normal operation, so we don't make the CPU core set
+ // these "on-time." It just doesn't matter.
extern int swStop, swSingInst;
int running = !swStop && !swSingInst;
- if (running) {
- set_pidp8i_led (pd, 5, 2); // Execute
- set_pidp8i_led (pd, 5, 3); // Fetch
- }
+ if (running) set_pidp8i_led (pd, 5, 2); // Execute
+ set_pidp8i_led (pd, 5, 3); // Fetch
// Row 6a: Remaining LEDs in upper right block
pd->curr[6] = 0;
if (running) set_pidp8i_led (pd, 6, 7); // bump Run LED
if (Pause) set_pidp8i_led (pd, 6, 8); // bump Pause LED
@@ -347,17 +334,17 @@
}
}
//// mount_usb_stick_file //////////////////////////////////////////////
-// Search for a PDP-8 media image on a USB device mounted under /media
-// and attempt to ATTACH it to the simulator.
+// Search for a PDP-8 media image in one of the Pi's USB auto-mount
+// directories and attempt to ATTACH it to the simulator.
static void mount_usb_stick_file (int devNo, char *devCode)
{
char sFoundFile[CBUFSIZE] = { '\0' };
- char sDirName[CBUFSIZE]; // will be "/media/DIRNAME" etc
+ char sUSBPath[CBUFSIZE]; // will be "/media/usb0" etc
char fileExtension[4]; // will be ".RX" etc
int i, j;
// Build expected file name extension from the first two characters of
// the passed-in device code.
@@ -376,71 +363,59 @@
// a given floppy image file attached to both RX01 drives, but you *can*
// repeatedly re-ATTACH the same floppy image to the first RX01 drive.
static char mountedFiles[8][CBUFSIZE];
mountedFiles[devNo][0] = '\0';
- // Search all directories under /media
- DIR *pDir1 = opendir ("/media");
- if (pDir1) {
- struct dirent* pDE1;
- while ((pDE1 = readdir (pDir1)) != 0) {
- if (pDE1->d_type != DT_DIR) continue;
-
- // Found a directory under /media. Search it for plausibly
- // named files given devCode.
- snprintf (sDirName, sizeof(sDirName), "/media/%s", pDE1->d_name);
- DIR *pDir2 = opendir (sDirName);
- if (pDir2) {
- struct dirent* pDE2;
- while ((pDE2 = readdir (pDir2)) != 0) { // search all files in directory
- if (pDE2->d_name[0] == '.') continue; // dotfiles clutter debug output
-
- char* pext = strstr (pDE2->d_name, fileExtension);
- if (pext && (pext == (pDE2->d_name + strlen (pDE2->d_name) - 3))) {
- snprintf (sFoundFile, sizeof (sFoundFile), "%s/%s",
- sDirName, pDE2->d_name);
- #if 0 // debugging
- printf("\r\nFound candidate file %s for dev %s, ext *%s...",
- sFoundFile, devCode, fileExtension);
- #endif
- for (j = 0; j < 7; ++j) {
- if (strncmp (mountedFiles[j], sFoundFile, CBUFSIZE) == 0) {
- #if 0 // debugging
- printf("\r\nAlready have %s mounted, slot %d; will not remount.",
- sFoundFile, j);
- #endif
- sFoundFile[0] = '\0'; // don't leave outer loop; keep looking
- break;
- }
- }
- if (j == 7) {
- // Media image file is not already mounted, so leave while
- // loop with path set to mount it
- break;
- }
- }
- #if 0 // debugging
- else {
- printf("\r\nFile %s on %s doesn't match *%s...",
- pDE2->d_name, sDirName, fileExtension);
- }
- #endif
- } // end while (pDE2...)
-
- closedir (pDir2);
- } // end if (pDir2)
- else {
- // USB auto-mounting either doesn't work here or uses
- // something other than the /media/DIR/FILE.EXT scheme
- // we expect.
- printf ("\r\nCannot open %s: %s\r\n", sDirName, strerror (errno));
- return;
- }
- } // end while (pDE1...)
-
- closedir(pDir1);
- } // end if (pDir1)
+ for (i = 0; i < 8 && sFoundFile[0] == '\0'; ++i) {
+ // search all 8 USB mount points, numbered 0-7
+ snprintf (sUSBPath, sizeof (sUSBPath), "/media/usb%d", i);
+ DIR *pDir = opendir (sUSBPath);
+ if (pDir) {
+ struct dirent* pDirent;
+ while ((pDirent = readdir (pDir)) != 0) { // search all files in directory
+ if (pDirent->d_name[0] == '.') continue; // dotfiles clutter debug output
+
+ char* pext = strstr (pDirent->d_name, fileExtension);
+ if (pext && (pext == (pDirent->d_name + strlen (pDirent->d_name) - 3))) {
+ snprintf (sFoundFile, sizeof (sFoundFile), "%s/%s",
+ sUSBPath, pDirent->d_name);
+#if 0 // debugging
+ printf("\r\nFound candidate file %s for dev %s, ext *%s...",
+ sFoundFile, devCode, fileExtension);
+#endif
+ for (j = 0; j < 7; ++j) {
+ if (strncmp (mountedFiles[j], sFoundFile, CBUFSIZE) == 0) {
+#if 0 // debugging
+ printf("\r\nAlready have %s mounted, slot %d; will not remount.",
+ sFoundFile, j);
+#endif
+ sFoundFile[0] = '\0'; // don't leave outer loop; keep looking
+ break;
+ }
+ }
+ if (j == 7) {
+ // Media image file is not already mounted, so leave while
+ // loop with path set to mount it
+ break;
+ }
+ }
+#if 0 // debugging
+ else {
+ printf("\r\nFile %s on %s doesn't match *%s...",
+ pDirent->d_name, sUSBPath, fileExtension);
+ }
+#endif
+ }
+
+ closedir (pDir);
+ }
+ else {
+ // Not a Pi or the USB auto-mounting software isn't installed
+ printf ("\r\nCannot open %s: %s\r\n", sUSBPath, strerror (errno));
+ return;
+ }
+ }
if (sFoundFile[0]) { // no file found, exit
if (access (sFoundFile, R_OK) == 0) {
char sAttachCmd[CBUFSIZE] = { '\0' };
snprintf (sAttachCmd, sizeof(sAttachCmd), "%s %s",
Index: src/PDP8/pidp8i.h
==================================================================
--- src/PDP8/pidp8i.h
+++ src/PDP8/pidp8i.h
@@ -45,10 +45,10 @@
extern pidp8i_flow_t handle_flow_control_switches (uint16* pM,
uint32 *pPC, uint32 *pMA, int32 *pMB, int32 *pLAC, int32 *pIF,
int32 *pDF, int32* pint_req);
-extern void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sIR,
- int32 sLAC, int32 sMQ, int32 sIF, int32 sDF, int32 sSC,
- int32 int_req, int Pause);
+extern void set_pidp8i_leds (uint32 sPC, uint32 sMA, uint16 sMB,
+ uint16 sIR, int32 sLAC, int32 sMQ, int32 sIF, int32 sDF,
+ int32 sSC, int32 int_req, int Pause);
#endif // !defined(PIDP8I_H)
DELETED src/cc8/GPL3.txt
Index: src/cc8/GPL3.txt
==================================================================
--- src/cc8/GPL3.txt
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
DELETED src/cc8/Makefile.in
Index: src/cc8/Makefile.in
==================================================================
--- src/cc8/Makefile.in
+++ /dev/null
@@ -1,46 +0,0 @@
-########################################################################
-# Makefile.in - Processed by autosetup's configure script to generate
-# an intermediate GNU make(1) file for building the PiDP-8/I software
-# from within its src/cc8/ subdirectory.
-#
-# The resulting Makefile will redirect simple "make" calls to the top
-# level as well as the major top-level targets (e.g. "make clean") but
-# purposefully will not redirect anything like an installation or "run
-# the system" type target. Its only purpose is to help out those who
-# are working on CC8 from within this directory. If you need to work
-# on the wider system, do it from the project's top level.
-#
-# If you are seeing this at the top of a file called Makefile and you
-# intend to make edits, do that in Makefile.in. Saying "make" will then
-# re-build Makefile from that modified Makefile.in before proceeding to
-# do the "make" operation.
-#
-# Copyright © 2017 Warren Young
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-all clean ctags distclean tags reconfig:
- cd @builddir@; make $@
DELETED src/cc8/README.md
Index: src/cc8/README.md
==================================================================
--- src/cc8/README.md
+++ /dev/null
@@ -1,448 +0,0 @@
-# A Minimal Implementation of C for the DEC PDP-8 Processor
-
-## Introduction
-
-The C language and its derivatives are now the industry standard for the
-development of operating systems and utilities. The language has evolved
-significantly since its initial specification in 1972. At this time, the
-PDP-7 was used for the initial implementation and the compiler ported to
-a number of other systems including the PDP-11. Also, the first
-glimmerings of Unix appeared following a re-write of the assembly
-language version in C and the rest is of course history. The PDP-8 was
-introduced by DEC in 1965 at the same time as the PDP-7 with the
-intention of being a small and cheap processor that could be used in a
-variety of environments. From this simple machine, the modern desktop
-device has evolved which I am using to type this document. Nonetheless,
-far from fading into obscurity, there is a very active group of
-enthusiasts who have looked to implementing the PDP-8 on modern hardware
-and the thanks to Oscar Vermuelen and others, we can all have a PDP8/I
-to play with. With this in mind, I thought it was time to have a modern
-language compiler running on the PDP-8 which as far as I can tell, the
-last native compiler developed for the PDP-8 was Pascal in 1979 by Heinz
-Stegbauer. In more recent times, one cross-compiler has been developed
-by Vince Slyngstad and updated by Paolo Maffei based on Ron Cain’s
-Small-C using a VM approach. [This code][sms] is most certainly worth
-examining, and I am delighted to acknowledge this work as I have used
-some of the C library code in this project.
-
-[sms]: http://so-much-stuff.com/pdp8/C/C.php
-
-Finally, I would refer the reader to Fabrice Bellard’s OTCC. It is this
-bit of remarkable software that suggested that there may be a chance to
-implement a native PDP-8 compiler.
-
-Developing a native compiler for the PDP-8 is not an easy task as this
-processor has a very limited address space and no hardware stack. And,
-although the option exists to write the whole thing in assembly language
-as has been the case for Pascal and Algol, this project has explored the
-option of writing the compiler itself in C. To this end, 2 compilers
-have been written. Firstly, a cross-compiler based again on Ron Cain’s
-Small-C which is used to compile the native OS/8 compiler and library.
-As yet, the native compiler has rather limited functionality and will
-not compile itself. The cross-compiler will compile itself but produces
-an enormous (28K) assembler file which cannot be run on the PDP-8.
-
-
-# The Cross-Compiler
-
-The code for this is in the `cross` subdirectory, and is built along
-with the top-level PiDP-8/I software. As above, this is based upon Ron
-Cain’s Small-C compiler, and the reader is directed to the extensive
-documentation available on the web. The key file is the code generator
-section in `code8.c`. This is used to generate SABR (Symbolic Assembler
-for Binary Relocatable programmes) assembly output which is normally
-used as the second pass of the OS/8 FORTRAN II system.
-
-You use this cross-compiler to compile the 3 components of the OS/8 C
-compiler:
-
-1. `n8.c` → `n8.s`: The parser/tokeniser section of the compiler
-
-2. `p8.c` → `p8.s`: The token to SABR code converter section.
-
-3. `libc.c` → `libc.s`: The C library used by both of the above
- via the `libc.h` include file.
-
-When you build and run this cross-compiler on a POSIX type system such
-as the Raspbian PiDP-8/I environment, the resulting `*.s` files will
-have LF-only line endings. You may need to run these files through a
-`unix2dos` type utility in order to produce the CRLF line endings that
-OS/8's SABR assembler expects, depending on how you get those `*.s`
-files into OS/8 as `*.SB`.
-
-The `*.SB` files may be assembled under OS/8:
-
- .COMP N8.SB
- .COMP LIBC.SB
- .COMP P8.SB
-
-This will create the `*.RL` files for the linking loader (`LOADER.SV`).
-
-The cross-compiler has some non-standard features to enable the
-interface between the main programme and the C library. This constitutes
-a compile time linkage system to allow for standard and vararg functions
-to be called in the library. The 3 SABR files generated from the source
-files as above may then be separately downloaded, compiled, loaded and
-linked under OS/8. Each of these SABR files generates just less than 4K
-of relocatable code as `N8.RL`, `P8.RL` and `LIBC.RL`. These are linked
-in pairs under OS/8 to create the 2 native OS/8 compiler phases:
-
-Phase 1: Link `N8.RL` and `LIBC.RL` to be saved as `CC1.SV`
-
-Phase 2: Link `P8.RL` and `LIBC.RL` to be saved as `CC2.SV`
-
-The commands are as follows, with `$` being an Escape keypress:
-
- .R LOADER
- *N8,LIBC/I$
- .SAVE SYS CC1
- .R LOADER
- P8,LIBC/I/O$
- .SAVE SYS CC2
-
-N8 (`CC1.SV`) terminates by chaining to `CC2.SV` to complete the process
-of generating a final SABR file.
-
-Several of the C programs in this distribution reference a PAL assembly
-initialization routine `cc8/include/init.pa`, which is symlinked into
-each directory that uses it. It defines some low-level subroutines,
-initializes the environment for the programs, and calls into the LIBC
-initialization code. If you are going to compile these programs with the
-OS/8 native compiler, you will need to copy `init.pa` into the OS/8
-environment as well.
-
-The same goes for `cc8/include/libc.h`, which defines the mappings
-between the familiar C library routine names and their underlying
-implementation names.
-
-The linking loader determines the core layout of each of the pairs of
-`.RL` files as above. Typically this is as follows:
-
-**Field 0:** FOTRAN library utility functions and OS/8 I/O system
-
-**Field 1:** Reserved for the programme’s runtime stack/globals/literals.
-
-**Field 2:** Usually the primary programme ... either N8 or P8.
-
-**Field 3:** Usually the LIBC library.
-
-In all, each phase of the native OS/8 compiler will use 16K of core.
-
-
-## The Native Compiler
-
-This compiler is built and linked as above. The final two files
-generated are `CC1.SV` and `CC2.SV`. These should be on the OS/8 system
-device. (`SYS:`) The compiler expects the source file in C to be in `CC.CC`
-on the default user device. (`DSK:`) In addition, you will need to file
-`HEADER.SB` on the default user device. This is used by `CC2.SV`. I suggest
-you use the provided RK05 image as this has the `SYS:` and `DSK:` partitions
-configured as required and include a linked copy of the compiler and
-some example programs.
-
-To try it out:
-
-Boot OS/8 within the PiDP-8/I environment as you normally would. If
-you're at the Linux command prompt within the PiDP-8/I source tree, you
-can start it most easily with a `make run` command.
-
-With the OS/8 environment running, you can enter a C programme in lower
-case via the editor, but before doing that, try building a copy of one
-of the example programs:
-
- .RUN CC0 ⇠ preprocessor/compiler front end
- >ps.cc ⇠ takes name of C program; creates CC.SB
- .COMP CC ⇠ compile SABR output of CC8 to CC.RL
-
-Link and run it with:
-
- .R LOADER
- *CC,LIBC/G ⇠ CC.RL + pre-built LIBC.RL = runnable program; /G = "go"
-
-
-## GOVERNMENT HEALTH WARNING
-
-**You are hereby warned**: The native OS/8 compiler does not contain any
-error checking whatsoever. If the source files contain an error, you
-may get:
-
-* A runtime crash in the compiler
-* SABR assembly output that won't assemble
-* Output that assembles but won't run correctly
-
-Rarely will any of these failure modes give any kind of sensible hint as
-to the cause. OS/8 CC8 cannot afford the hundreds of kilobytes of error
-checking and text reporting that you get in a modern compiler like GCC
-or Clang. That would have required a roomful of core memory to achieve
-on a real PDP-8. Since we're working within the constraints of the old
-PDP-8 architecture, we only have about 3 kWords to construct the parse
-result, for example.
-
-In addition, the native OS/8 compiler is also severely limited in code
-space, so it does not understand the full C language. It is almost
-certainly less functional in all respects than K&R C 1978; we do not
-have a good benchmark for what it compares to in terms of other early C
-dialects, but we can sum it up in a single word: "primitive."
-
-Nonetheless, our highly limited C dialect is Turing complete. It might
-be better to think of it as a high-level assembly language that
-resembles C rather than as "C" proper.
-
-
-### Features
-
-Here is what is known to work:
-
-1. **Local and global variables**
-
-1. **Pointers,** within limitations given in the following section.
-
-1. **Functions:** Parameter lists must be declared in K&R form:
-
- int foo (a, b)
- int a, b;
- {
- ...
- }
-
-1. **Recursion:** See [`FIB.CC`][fib] for an example of this.
-
-[fib]: https://tangentsoft.com/pidp8i/doc/src/cc8/examples/fib.c
-
-1. **Simple arithmetic operators:** `+`, `-`, `*`, `/`, etc.
-
-1. **Bitwise operators:** `&`, ¦, `~` and `!`
-
-1. **Simple comparison operators:** False expressions evaluate as 0 and
- true as -1 in twos complement form, meaning all 1's in binary form.
- See the list of limitations below for the operators excluded by our
- "simple" qualifier.
-
-1. **A few 2-character operators:** `++`, `--` (postfix only) and `==`.
-
-1. **Limited library:** See `libc.h` for allowed libc functions, of
- which there are currently 31, including:
-
- 1. **A subset of stdio:**
-
- * `fopen` is implemented as
-
- void fopen(char *filename, char *mode)
-
- The filename must be upper case. Mode is either "w" or "r".
-
- * Only 1 input file and 1 output may be open at any one time
-
- * `fclose()` only closes the output file.
-
- * Call `fopen` to open a new input file. The current file does
- not need to be closed.
-
- * `fprintf`, `fputc`, and `fputs` are as expected.
-
- * `fgets` is implemented. It will read and retain CR/LF. It
- returns a null string on EOF.
-
- * `fscanf` is not implemented. Read a line with `fgets()` and
- then call `sscanf` on it.
-
- * `feof` is not implemented; `fgetc` and `fgets` will return a
- null on EOF.
-
- 1. **printf:** See `libc.c` for the allowed format specifiers:
- `%d`, `%s` etc. Length and width.precision formatting is supported.
-
- There are many limitations in this library relative to Standard C or
- even K&R C, which are documented below.
-
-1. **Limited structuring constructs:** `if`, `while`, `for`, etc. are
- supported, but they may not work as expected when deeply nested or
- in long `if/else if/...` chains.
-
-
-### Known Limitations
-
-Much of what you understand as "C" does not work in our dialect:
-
-1. The language is typeless in that everything is a 12 bit integer and
- any variable/array can interpreted as `int`, `char` or pointer. All
- variables and arrays must be declared as `int`. The return type may
- be left off of a function's definition; it is implicitly `int` in
- all cases, since `void` is not supported.
-
-2. There must be an `int main()` which must be the last function in the
- single input C file.
-
-3. We do not yet support separate compilation of multiple C modules
- that get linked together. You can produce relocatable libraries in
- OS/8 `*.RL` format and link them with the OS/8 LOADER, but because
- of the previous limitation, only one of these can be written in C.
-
-4. Unlike the CC8 cross-compiler, the OS/8 compiler ignores `#include`
- directives. (One day, `CC0` may get that ability, but not today.)
- This means you cannot use `#include` directives to string multiple C
- modules into a single program.
-
- If that then makes you wonder how the OS/8 compiler looks up its
- stock library functions — note that I've resisted using the word
- "standard" here, for they are anything but that in the Standard C
- sense — it is that the entry point mappings declared in `libc.h` are
- hard-coded into the `CC2` compiler stage, implemented in `p8.c`.
-
- If you have a program that is compiled using both the cross-compiler
- and the OS/8 compiler, you may wish to use `#include` statements,
- since the cross-compiler does process them.
-
-5. Variables are implicitly `static`, even when local.
-
-6. Arrays may only be single indexed. See `PS.CC` for an example.
-
-7. We do not even support all of K&R C yet, much less post-C89 features
- such as statement-scoped variable declarations:
-
- for (int i = ...
-
- All variables must either be predeclared at the top of the function
- they're used in, or they must be global.
-
-8. The compiler does not yet understand how to assign a variable's
- initial value as part of its declaration. This:
-
- int i = 5;
-
- must instead be:
-
- int i;
- i = 5;
-
-9. There is no `&&` nor ¦¦. Neither is there support for
- complex relational operators like `>=` nor even `!=`. Abandon all
- hope for complex assignment operators like `+=`.
-
- Most of this can be worked around through clever coding. For
- example, this:
-
- if (i != 0 || j == 5)
-
- could be rewritten to avoid both missing operators as:
-
- if (!(i == 0) | (j == 5))
-
- because a true result in each subexpression yields -1 per the
- previous point, which when bitwise OR'd together means you get -1 if
- either subexpression is true, which means the whole expression
- evaluates to true if either subexpression is true.
-
- If the code you were going to write was instead:
-
- if (i != 0 || j != 5)
-
- then the rewrite is even simpler owing to the rules of [Boolean
- algebra](https://en.wikipedia.org/wiki/Boolean_algebra):
-
- if (!(i == 0 & j == 5))
-
- These rules mean that if we negate the entire expression, we get the
- same truth table if we flip the operators around and swap the
- logical test from OR to AND, which in this case converts the
- expression to a form that is now legal in our limited C dialect. All
- of this comes from the Laws section of the linked Wikipedia article;
- if you learn nothing else about Boolean algebra, you would be well
- served to memorize those rules.
-
-10. `atoi` is non-standard: `int atoi(char *, int *)`, returning
- the length of the numeric string.
-
-11. `scanf` is not implemented; use `gets` then `sscanf`
-
-12. Dereferencing parenthesized expressions does not work: `*()`
-
-13. `struct` is not supported.
-
-14. Double precision `int`, `float` etc. are not supported. If you need
- to do heavy duty maths, use FORTRAN, U/W FOCAL, or even OS/8 BASIC.
-
-15. The stack, which includes all globals and literals, is only 4 kwords.
- Stack overflow is not detected. Literals are inlcuded in this due
- to a limitation in the way `COMMON` is implemented in SABR.
-
-16. There is no argument list checking, not even for standard library
- functions.
-
-17. `do/while` is parsed, but code for it is not properly generated.
-
-
-### Known Bugs
-
-1. Binary file I/O is not always reliable. You are strongly encouraged
- to limit I/O to text files.
-
-2. Don’t forget to handle form feed. See `c8.c`.
-
-3. For some obscure reason, always open the input file first, then the
- output file. I suspect a fault in `libc.c`, which you are welcome to
- fix, keeping in mind that we're using every trick in the book to fit
- as much functionality in as we currently do. It may not be possible
- to make this as reliable as modern C programmers expect.
-
-
-## Preprocessor
-
-The compiler distribution includes a pre-processor file (`c8.c` →
-`CC0.SV`). This is a stub and merely asks for a filename and calls the
-compiler chain. This file may be extended and used to process `#define`
-`#include`, etc.
-
-Compile using the cross-compiler to `c8.s`, copy to `C8.SB` under OS/8
-on your PDP-8 target system, then:
-
- .COMP C8.SB
- .R LOADER
- *C8,LIBC/I/O$
- .SAVE SYS CC0
- .R CC0
- > enter filename and press Return
- .COMP CC.SB
- .R LOADER
- *CC,LIBC/G if no file I/O; or...
- *CC,LIBC/I/O/G ...if using file I/O
-
-Try the examples in `*.CC` on `DSK:`. I personally like `PS.CC`,
-Pascal’s triangle. This version does not require factorials, which are a
-bit out of range for 12 bits!!
-
-Try it with:
-
- .R CC0
- >PS.CC
- .COMP CC.SB
- .R LOADER
- *CC,LIBC/G
-
-
-## Conclusion
-
-This is a somewhat limited manual which attempts to give an outline of a
-very simple compiler for which I apologise as the source code is obscure
-and badly commented. However, the native OS/8 compiler/tokeniser
-(`n8.c`) is only 600 lines which is a nothing in the scale of things
-these days. However, I hope this project gives some insight into
-compiler design and code generation strategies to target a most
-remarkable computer. I would also like to give credit to the builders of
-OS/8 and in particular the FORTRAN II system which was never designed to
-survive the onslaught of this kind of modern software.
-
-Don’t expect too much! This compiler will not build this week’s bleeding
-edge kernel. But, it may be used to build any number of useful utility
-programs for OS/8.
-
-
-## License
-
-This document is under the [GNU GPLv3 License][gpl], copyright © May,
-June, and November 2017 by [Ian Schofield][ian], with minor updates by
-[Warren Young][wy].
-
-[gpl]: https://www.gnu.org/licenses/gpl.html
-[ian]: mailto:Isysxp@gmail.com
-[wy]: https://tangentsoft.com/
DELETED src/cc8/cross/README.md
Index: src/cc8/cross/README.md
==================================================================
--- src/cc8/cross/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-This directory contains the sources for the CC8 cross-compiler, which is
-based on Ron Cain's Small-C system.
-
-It is built by the top-level build system as `bin/cc8` and is installed
-to `$prefix/bin/cc8`.
-
-Call it as:
-
- cc8 myfile.c
-
-The compiler does not have any consequential command line options.
-
-The output file is `myfile.s` which is in SABR assembly code, intended
-to be assembled within the PiDP-8/I OS/8 environment. See the `test`
-subdirectory and [the top-level README][/doc/trunk/cc8/README.md] for
-further details.
DELETED src/cc8/cross/code8.c
Index: src/cc8/cross/code8.c
==================================================================
--- src/cc8/cross/code8.c
+++ /dev/null
@@ -1,1126 +0,0 @@
-/*
- * This file is part of the CC8 cross-compiler.
- *
- * The CC8 cross-compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 cross-compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 cross-compiler as ../GPL3.txt. If not, see
- * .
- */
-
-#define unix
-
-#include
-#include "defs.h"
-#include "data.h"
-#include
-
-/* Define ASNM and LDNM to the names of the assembler and linker
- respectively */
-
-/*
- * Some predefinitions:
- *
- * INTSIZE is the size of an integer in the target machine
- * BYTEOFF is the offset of an byte within an integer on the
- * target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
- * 360 = 3)
- * This compiler assumes that an integer is the SAME length as
- * a pointer - in fact, the compiler uses INTSIZE for both.
- */
-#define INTSIZE 1
-#define BYTEOFF 0
-
-/*
- * print all assembler info before any code is generated
- *
- */
-header ()
-{
- outstr ("/ Small C PDP8 Coder (1.0:27/1/99)");
- nl();
- FEvers();
- nl ();
- ol ("OPDEF ANDI 0400");
- ol ("OPDEF TADI 1400");
- ol ("OPDEF ISZI 2400");
- ol ("OPDEF DCAI 3400");
- ol ("OPDEF JMSI 4400");
- ol ("OPDEF JMPI 5400");
- ol ("OPDEF MQL 7421");
- ol ("OPDEF MQA 7701");
- ol ("OPDEF MQO 7501");
- ol ("OPDEF SWP 7521");
- ol ("OPDEF CDF1 6211");
- ol ("OPDEF CDF0 6201");
- ol ("OPDEF RIF 6224");
- ol ("OPDEF CAF0 6203");
- ol ("OPDEF BSW 7002");
- ol ("OPDEF CAM 7621");
- ol ("/");
- return 0;
-}
-
-nl ()
-{
- outbyte (EOL);
-/* outbyte (10); */
- return 0;
-}
-initmac()
-{
- defmac("cpm\t1");
- defmac("I8080\t1");
- defmac("RMAC\t1");
- defmac("smallc\t1");
- return 0;
-}
-
-galign(t)
-int t;
-{
- return(t);
-}
-
-/*
- * return size of an integer
- */
-intsize() {
- return(INTSIZE);
-}
-
-/*
- * return offset of ls byte within word
- * (ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
- */
-byteoff() {
- return(BYTEOFF);
-}
-
-/*
- * Output internal generated label prefix
- */
-olprfix() {
- ot("CC");
- return 0;
-}
-
-/*
- * Output a label definition terminator
- */
-col ()
-{
- outbyte (',');
- return 0;
-}
-
-/*
- * begin a comment line for the assembler
- *
- */
-comment ()
-{
- outbyte ('/');
- return 0;
-}
-
-/*
- * Emit user label prefix
- */
-prefix ()
-{
- return 0;
-}
-
-/* Stkbase output stack base->literals =stkp+2 ... ie 202(8) =130(10) + sizeof(globals) */
-stkbase()
-{
- ot("GBL");
- return 0;
-}
-
-/*
- * print any assembler stuff needed after all code
- *
- */
-trailer ()
-{
-// ot("\tENTRY ");
-// outbyte('M');
-// printlabel (litlab);
-// nl();
- outbyte('M');
- printlabel (litlab);
- col();
- ot("\t0");
- nl();
- ol("\tCDF1");
- ot("\tTAD L");
- printlabel (litlab);
- nl();
- ol ("\tSNA CLA / Any literals to push?");
- ot ("\tJMP I M");
- printlabel (litlab);
- nl();
- ot("\tTAD X");
- printlabel (litlab);
- nl();
- ol ("\tDCA JLC");
- outbyte('D');
- printlabel (litlab);
- col();
- ol("CDF0");
- ot("\tTADI JLC");
- nl();
- ol ("\tJMSI PSH");
- ol ("\tCLA");
- ol ("\tISZ JLC");
- ot("\tISZ L");
- printlabel (litlab);
- nl();
- ot("\tJMP D");
- printlabel (litlab);
- nl();
- ot ("\tJMP I M");
- printlabel (litlab);
- nl();
- ol("CCEND,\t0");
- ol ("END");
- return 0;
-}
-
-
-/*
- * function prologue
- */
-prologue (sym)
-char *sym;
-{
- return 0;
-}
-
-/*
- * text (code) segment
- */
-gtext ()
-{
-/* ol ("cseg"); */
- return 0;
-}
-
-/*
- * data segment
- */
-gdata ()
-{
-/* ol ("dseg"); */
- return 0;
-}
-
-/*
- * Output the variable symbol at scptr as an extrn or a public
- */
-ppubext(scptr) char *scptr; {
- if (scptr[STORAGE] == STATIC) return 0;
-// ot (scptr[STORAGE] == EXTERN ? "extrn\t" : "public\t");
-// prefix ();
-// outstr (scptr);
-// nl();
- return 0;
-}
-
-/*
- * Output the function symbol at scptr as an extrn or a public
- */
-fpubext(scptr) char *scptr; {
-/* if (scptr[STORAGE] == STATIC) return;
-// ot (scptr[OFFSET] == FUNCTION ? "public\t" : "extrn\t");
-// prefix ();
-// outstr (scptr);
-// nl (); */
- return 0;
-}
-
-/*
- * Output a decimal number to the assembler file
- */
-onum(num) int num; {
- outdec(num); /* pdp11 needs a "." here */
- return 0;
-}
-
-
-/*
- * fetch a static memory cell into the primary register
-getmem (sym)
-char *sym;
-{
- int adr;
- ol ("\tCLA");
- immd3 ();
- adr=glint(sym)+128;
- onum(glint(sym)+128);
- nl();
- ol("\tDCA JLC");
- ol("\tTADI JLC");
-}*/
-
-getmem (sym)
-char *sym;
-{
- int adr;
- ol ("\tCLA");
- immd4 ();
- adr=glint(sym)+128;
- onum(glint(sym)+128);
- nl();
- return 0;
-}
-/*
- * fetch a static memory cell into the primary register (pre-increment*/
-
-getincmem (sym)
-char *sym;
-{
- int adr;
- ol ("\tCLA");
- adr=glint(sym)+128;
- ot ("\tISZI (");
- onum(adr);
- nl();
- immd4 ();
- onum(adr);
- nl();
- return 0;
-}
-
-
-/*
- * fetch the address of the specified symbol into the primary register
- *
- */
-getloc (sym)
-char *sym;
-{
- ol("\tCLA");
- ol("\tTAD STKP");
- if (sym[STORAGE] == LSTATIC) {
- immd3 ();
- printlabel(-1-glint(sym));
- nl();
- } else {
- if (stkp-glint(sym)==0) outstr("/");
- immd3 ();
- outdec (stkp-glint(sym));
- nl ();
- }
- return 0;
-}
-
-/*
- * store the primary register into the specified static memory cell
- *
-
-putmem (sym)
-char *sym;
-{
- ol("\tMQL");
- immd3 ();
- onum(glint(sym)+128);
- nl();
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tDCAI JLC");
- ol("\tTADI JLC");
-}
-*/
-
-putmem (sym)
-char *sym;
-{
- ot("\tDCAI (");
- onum(glint(sym)+128);
- nl();
- immd4 ();
- onum(glint(sym)+128);
- nl();
- return 0;
-}
-
-/*
- * store the specified object type in the primary register
- * at the address on the top of the stack
- *
- */
-putstk (typeobj)
-char typeobj;
-{
- ol("\tJMSI PTSK");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * fetch the specified object type indirect through the primary
- * register into the primary register
- *
- */
-indirect (typeobj)
-char typeobj;
-{
- ol("\tDCA JLC");
-/* ol("\tCDF1"); */
- ol("\tTADI JLC");
- return 0;
-}
-
-/*
- * fetch the specified object type indirect through the primary
- * register into the primary register (pre-increment)
- *
- */
-incdirect (typeobj)
-char typeobj;
-{
- ol("\tDCA JLC");
- ol("\tISZI JLC");
- ol("\tTADI JLC");
- return 0;
-}
-
-
-/*
- * swap the primary and secondary registers
- *
- */
-swap ()
-{
- ol ("\tSWP");
- return 0;
-}
-/*
-* Clear primary reg
-*/
-cpri()
-{
- ol("\tCLA");
- return 0;
-}
-/*
- * print partial instruction to get an immediate value into
- * the primary register
- *
- */
-immed ()
-{
- ol ("\tCLA");
- ot ("\tTAD (");
- return 0;
-}
-immd2 ()
-{
- ol ("\tCLA");
- ot ("\tTAD ");
- return 0;
-}
-immd3 ()
-{
- ot ("\tTAD (");
- return 0;
-}
-
-immd4 ()
-{
- ot("\tTADI (");
- return 0;
-}
-/*
- * push the primary register onto the stack
- *
- */
-gpush ()
-{
- ol ("\tJMSI PSH");
- stkp = stkp - INTSIZE;
- return 0;
-}
-
-/*
- * pop the top of the stack into the secondary register
- *
- */
-gpop ()
-{
- ol ("\tJMSI POP");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * swap the primary register and the top of the stack
- *
- */
-swapstk ()
-{
- ol ("\tMQL");
- gpop();
- ol ("\tSWP");
- gpush();
- ol ("\tSWP");
- return 0;
-}
-
-/*
- * call the specified subroutine name
- * varag is allowed for libc functions using a v prefix. In this case, the arg count+1 is pushed onto the stack as well.
- * For the actual routine, the declaration should be a single arg eg printf(int args) in this case, the value of args is the count and &args-args point to the first arg in the caller's list.
- */
-gcall (sname,nargs)
-char *sname;
-int *nargs;
-{
- char tm[10];
-
- if (strstr(sname,"vlibc")) {
- immed();
- sname++;
- outdec(*nargs);
- outstr("\t/ PUSH ARG COUNT");
- nl();
- ol("\tJMSI PSH");
- stkp = stkp - INTSIZE;
- (*nargs)++;
- }
- if (strstr(sname,"libc"))
- {
- strcpy(tm,sname);
- immed();
- outstr(tm+4);
- nl();
- ol("\tMQL");
- ol("\tCALL 1,LIBC");
- ol("\tARG STKP");
- ol("\tCDF1"); /* Make sure DF is correct */
- return 0;
- }
- ol("\tCPAGE 2");
- ol("\tJMSI PCAL");
- ot ("\t");
- outstr (sname);
- nl ();
- return 0;
-}
-
-stri()
-{
- ol("\tDCAI 10");
- return 0;
-}
-iinit()
-{
- ol("\tCIA;CMA");
- ol("\tDCA 10");
- return 0;
-}
-
-/*
- * return from subroutine
- *
- */
-gret (sym)
-char *sym;
-{
- ol ("\tJMPI POPR");
- return 0;
-}
-
-/*
- * perform subroutine call to value on top of stack
- *
- */
-callstk ()
-{
- immed ();
- outstr ("$+5");
- nl ();
- swapstk ();
- ol ("pchl");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * jump to specified internal label number
- *
- */
-jump (label)
-int label;
-{
- ot ("\tJMP\t");
- printlabel (label);
- nl ();
- return 0;
-}
-
-/*
- * test the primary register and jump if false to label
- *
- */
-testjump (label, ft)
-int label,
- ft;
-{
- if (ft)
- ol ("\tSZA");
- else
- ol ("\tSNA");
- jump (label);
- return 0;
-}
-
-casejump()
-{
- ol("\tTAD TMP");
- ol("\tSNA CLA");
- return 0;
-}
-/*
- * print pseudo-op to define a byte
- *
- */
-defbyte ()
-{
- ot ("\t");
- return 0;
-}
-
-/*
- * print pseudo-op to define storage
- *
- */
-defstorage ()
-{
- ot ("COMMN\t");
- return 0;
-}
-
-/*
- * print pseudo-op to define a word
- *
- */
-defword ()
-{
- ot ("\t");
- return 0;
-}
-
-/*
- * modify the stack pointer to the new value indicated
- *
- */
-modstk (newstkp)
-int newstkp;
-{
- int k;
-
- k = galign(stkp-newstkp);
- if (k == 0)
- return (newstkp);
- if (k>0 && k<5) {
- while (k--) ol ("\tISZ STKP");
- return (newstkp);
- }
- ol ("\tMQL");
- immd3 ();
- outdec (k);
- nl ();
- ol ("\tTAD STKP");
- ol ("\tDCA STKP");
- swap ();
- return (newstkp);
-}
-
-/*
- * multiply the primary register by INTSIZE
- */
-gaslint ()
-{
- return 0;
-}
-
-/*
- * divide the primary register by INTSIZE
- */
-gasrint()
-{
- return 0;
-}
-
-/*
- * Case jump instruction
- */
-gjcase() {
- ol ("\tCIA");
- ol ("\tDCA TMP");
- return 0;
-}
-
-/*
- * add the primary and secondary registers
- * if lval2 is int pointer and lval is not, scale lval
- */
-gadd (lval,lval2) int *lval,*lval2;
-{
-/* if (lval==0) ol("\tCIA");*/
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tTAD JLC");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * subtract the primary register from the secondary
- *
- */
-gsub ()
-{
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tTAD JLC");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * multiply the primary and secondary registers
- * (result in primary)
- *
- */
-gmult ()
-{
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tCALL 1,MPY");
- ol("\tARG JLC");
- ol("\tCDF1");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * divide the secondary register by the primary
- * (quotient in primary, remainder in secondary)
- *
- */
-gdiv ()
-{
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tCALL 1,DIV");
- ol("\tARG JLC");
- ol("\tCDF1");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * compute the remainder (mod) of the secondary register
- * divided by the primary register
- * (remainder in primary, quotient in secondary)
- *
- */
-gmod ()
-{
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tCALL 1,DIV");
- ol("\tARG JLC");
- ol("\tCALL 1,IREM");
- ol("\tARG 0");
- ol("\tCDF1");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * inclusive 'or' the primary and secondary registers
- *
- */
-gor ()
-{
- ol("\tJMSI POP");
- ol("\tMQA");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * exclusive 'or' the primary and secondary registers
- *
- */
-gxor ()
-{
- gpop();
- gcall ("?xor");
- return 0;
-}
-
-/*
- * 'and' the primary and secondary registers
- *
- */
-gand ()
-{
- ol("\tDCA JLC");
- ol("\tJMSI POP");
- ol("\tMQA");
- ol("\tAND JLC");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * arithmetic shift right the secondary register the number of
- * times in the primary register
- * (results in primary register)
- *
- */
-gasr ()
-{
- int lbl;
-
- lbl=getlabel();
- ol("\tCIA");
- ol("\tJMSI POP");
- gnlabel(lbl);
- ol("\tSWP");
- ol("\tCLL RAR");
- ol("\tSWP");
- ol("\tIAC");
- ol("\tSZA");
- jump(lbl);
- ol("\tSWP");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * arithmetic shift left the secondary register the number of
- * times in the primary register
- * (results in primary register)
- *
- */
-gasl ()
-{
- int lbl;
-
- lbl=getlabel();
- ol("\tCIA");
- ol("\tJMSI POP");
- gnlabel(lbl);
- ol("\tSWP");
- ol("\tCLL RAL");
- ol("\tSWP");
- ol("\tIAC");
- ol("\tSZA");
- jump(lbl);
- ol("\tSWP");
- stkp = stkp + INTSIZE;
- return 0;
-}
-
-/*
- * two's complement of primary register
- *
- */
-gneg ()
-{
- ol("\tCIA");
- return 0;
-}
-
-/*
- * logical complement of primary register
- *
- */
-glneg ()
-{
- ol("\tSNA CLA");
- ol("\tCMA");
- return 0;
-}
-
-/*
- * one's complement of primary register
- *
- */
-gcom ()
-{
- ol("\tCMA");
- return 0;
-}
-
-/*
- * Convert primary value into logical value (0 if 0, 1 otherwise)
- *
- */
-gbool ()
-{
- ol("\tSZA CLA");
- ol("\tIAC");
- return 0;
-}
-
-/*
- * increment the primary register by 1 if char, INTSIZE if
- * int
- */
-ginc (lval) int lval[];
-{
- ol ("\tIAC");
-/* if (lval[2] == CINT)
-// ol ("inx\th"); */
- return 0;
-}
-/*
- * Shortened INC
-*/
-
-gisz (lval)
-int *lval;
-{
- int adr;
- char *sym=lval[0];
-
- if (lval[1]) {
- ol ("\tISZI JLC");
- return 0;
- }
-
- ot ("\tISZI (");
- adr=stkp-glint(sym);
-// if (lval[STORAGE] == PUBLIC)
- adr=glint(sym)+128;
- onum(adr);
- nl();
- return 0;
-}
-/*
- * decrement the primary register by one if char, INTSIZE if
- * int
- */
-gdec (lval) int lval[];
-{
- ol ("\tTAD (-1");
-/* if (lval[2] == CINT)
-// ol("dcx\th"); */
- return 0;
-}
-
-/*
- * following are the conditional operators.
- * they compare the secondary register against the primary register
- * and put a literl 1 in the primary if the condition is true,
- * otherwise they clear the primary register
- *
- */
-
-/*
- * equal
- *
- */
-geq ()
-{
- ol("\tCIA");
- ol("\tTADI STKP");
- gpop();
- ol("\tSNA CLA");
- ol("\tCMA");
- return 0;
-}
-
-/*
- * not equal
- *
- */
-gne ()
-{
- gpop();
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- return 0;
-}
-
-/*
- * less than (signed)
- *
- */
-glt ()
-{
- gpop();
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tAND (2048");
- return 0;
-}
-
-/*
- * less than or equal (signed)
- *
- */
-gle ()
-{
- gpop();
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNA");
- ol("\tCLA CMA");
- ol("\tAND (2048");
- return 0;
-}
-
-/*
- * greater than (signed)
- *
- */
-ggt ()
-{
- gpop();
- ol("\tSWP");
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tAND (2048");
- return 0;
-}
-
-/*
- * greater than or equal (signed)
- *
- */
-gge ()
-{
- gpop();
- ol("\tSWP");
- ol("\tCIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNA");
- ol("\tCLA CMA");
- ol("\tAND (2048");
- return 0;
-}
-
-/*
- * less than (unsigned)
- *
- */
-gult ()
-{
- gpop();
- ol("\tCLL CIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNL CLA");
- ol("\tIAC");
- return 0;
-}
-
-/*
- * less than or equal (unsigned)
- *
- */
-gule ()
-{
- gpop();
- ol("\tCLL CIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNL CLA");
- ol("\tIAC");
- return 0;
-}
-
-/*
- * greater than (unsigned)
- *
- */
-gugt ()
-{
- gpop();
- ol("\tCLL CIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNA SZL CLA");
- ol("\tIAC");
- return 0;
-}
-
-/*
- * greater than or equal (unsigned)
- *
- */
-guge ()
-{
- gpop();
- ol("\tSWP");
- ol("\tCLL CIA");
- ol("\tDCA JLC");
- ol("\tMQA");
- ol("\tTAD JLC");
- ol("\tSNL CLA");
- ol("\tIAC");
- return 0;
-}
-
-/* Squirrel away argument count in a register that modstk
- doesn't touch.
-*/
-
-gnargs(d)
-int d; {
-/* ot ("mvi\ta,");
-// onum(d);
-// nl (); */
- return 0;
-}
-
-assemble(s)
-char *s; {
-#ifdef ASNM
- char buf[100];
- strcpy(buf, ASNM);
- strcat(buf, " ");
- strcat(buf, s);
- buf[strlen(buf)-1] = 's';
- return(system(buf));
-#else
- return(0);
-#endif
-}
DELETED src/cc8/cross/ctype.h
Index: src/cc8/cross/ctype.h
==================================================================
--- src/cc8/cross/ctype.h
+++ /dev/null
@@ -1,1 +0,0 @@
-/* Nothing needed in this file */
DELETED src/cc8/cross/data.c
Index: src/cc8/cross/data.c
==================================================================
--- src/cc8/cross/data.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* File data.c: 2.2 (84/11/27,16:26:13) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-
-/* storage words */
-
-char symtab[SYMTBSZ];
-char *glbptr, *rglbptr, *locptr;
-int ws[WSTABSZ];
-int *wsptr;
-int swstcase[SWSTSZ];
-int swstlab[SWSTSZ];
-int swstp;
-char litq[LITABSZ];
-int litptr;
-char macq[MACQSIZE];
-int macptr;
-char line[LINESIZE];
-char mline[LINESIZE];
-int lptr, mptr, gsize;
-
-/* miscellaneous storage */
-
-int nxtlab,
- litlab,
- stkp,
- argstk,
- ncmp,
- errcnt,
- glbflag,
- ctext,
- cmode,
- lastst,
- inbreak;
-
-FILE *input, *input2, *output;
-FILE *inclstk[INCLSIZ];
-int inclsp;
-char fname[20];
-FILE *bfile;
-
-char quote[2];
-unsigned char *cptr;
-int *iptr;
-int fexitlab;
-int iflevel, skiplevel;
-int errfile;
-int sflag;
-int cflag;
-int errs;
-int aflag;
DELETED src/cc8/cross/data.h
Index: src/cc8/cross/data.h
==================================================================
--- src/cc8/cross/data.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* File data.h: 2.2 (84/11/27,16:26:11) */
-
-/* storage words */
-
-extern char symtab[];
-extern char *glbptr, *rglbptr, *locptr;
-extern int ws[];
-extern int *wsptr;
-extern int swstcase[];
-extern int swstlab[];
-extern int swstp;
-extern char litq[];
-extern int litptr;
-extern char macq[];
-extern int macptr;
-extern char line[];
-extern char mline[];
-extern int lptr, mptr, gsize;
-
-/* miscellaneous storage */
-
-extern int nxtlab,
- litlab,
- stkp,
- argstk,
- ncmp,
- errcnt,
- glbflag,
- ctext,
- cmode,
- lastst,
- inbreak;
-
-extern FILE *input, *input2, *output, *bfile;
-extern FILE *inclstk[];
-extern int inclsp;
-extern char fname[];
-
-extern char quote[];
-extern char *cptr;
-extern int *iptr;
-extern int fexitlab;
-extern int iflevel, skiplevel;
-extern int errfile;
-extern int sflag;
-extern int cflag;
-extern int errs;
-extern int aflag;
DELETED src/cc8/cross/defs.h
Index: src/cc8/cross/defs.h
==================================================================
--- src/cc8/cross/defs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* File defs.h: 2.1 (83/03/21,02:07:20) */
-
-
-#define FOREVER for(;;)
-#define FALSE 0
-#define TRUE 1
-#define NO 0
-#define YES 1
-
-/* miscellaneous */
-
-#define EOS 0
-#define EOL 10
-#define BKSP 8
-#define CR 13
-#define FFEED 12
-#define TAB 9
-
-/* symbol table parameters */
-
-#define SYMSIZ 14
-#define SYMTBSZ 2800
-#define NUMGLBS 150
-#define STARTGLB symtab
-#define ENDGLB (STARTGLB+NUMGLBS*SYMSIZ)
-#define STARTLOC (ENDGLB+SYMSIZ)
-#define ENDLOC (symtab+SYMTBSZ-SYMSIZ)
-
-/* symbol table entry format */
-
-#define NAME 0
-#define IDENT 9
-#define TYPE 10
-#define STORAGE 11
-#define OFFSET 12
-
-/* system-wide name size (for symbols) */
-
-#define NAMESIZE 20
-#define NAMEMAX 20
-
-/* possible entries for "ident" */
-
-#define VARIABLE 1
-#define ARRAY 2
-#define POINTER 3
-#define FUNCTION 4
-
-/* possible entries for "type" */
-
-#define CCHAR 1
-#define CINT 2
-
-/* possible entries for storage */
-
-#define PUBLIC 1
-#define AUTO 2
-#define EXTERN 3
-
-#define STATIC 4
-#define LSTATIC 5
-#define DEFAUTO 6
-/* "do"/"for"/"while"/"switch" statement stack */
-
-#define WSTABSZ 100
-#define WSSIZ 7
-#define WSMAX ws+WSTABSZ-WSSIZ
-
-/* entry offsets in "do"/"for"/"while"/"switch" stack */
-
-#define WSSYM 0
-#define WSSP 1
-#define WSTYP 2
-#define WSCASEP 3
-#define WSTEST 3
-#define WSINCR 4
-#define WSDEF 4
-#define WSBODY 5
-#define WSTAB 5
-#define WSEXIT 6
-
-/* possible entries for "wstyp" */
-
-#define WSWHILE 0
-#define WSFOR 1
-#define WSDO 2
-#define WSSWITCH 3
-
-/* "switch" label stack */
-
-#define SWSTSZ 100
-
-/* literal pool */
-
-#define LITABSZ 2000
-#define LITMAX LITABSZ-1
-
-/* input line */
-
-#define LINESIZE 200
-#define LINEMAX (LINESIZE-1)
-#define MPMAX LINEMAX
-
-/* macro (define) pool */
-
-#define MACQSIZE 1000
-#define MACMAX (MACQSIZE-1)
-
-/* "include" stack */
-
-#define INCLSIZ 3
-
-/* statement types (tokens) */
-
-#define STIF 1
-#define STWHILE 2
-#define STRETURN 3
-#define STBREAK 4
-#define STCONT 5
-#define STASM 6
-#define STEXP 7
-#define STDO 8
-#define STFOR 9
-#define STSWITCH 10
DELETED src/cc8/cross/error.c
Index: src/cc8/cross/error.c
==================================================================
--- src/cc8/cross/error.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* File error.c: 2.1 (83/03/20,16:02:00) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-error (ptr)
-char ptr[];
-{
- FILE *tempfile;
-
- tempfile = output;
- output = stdout;
- doerror(ptr);
- output = tempfile;
- doerror(ptr);
- errcnt++;
- return 0;
-}
-
-doerror(ptr)
-char *ptr;
-{
- int k;
- comment ();
- outstr (line);
- nl ();
- comment ();
- k = 0;
- while (k < lptr) {
- if (line[k] == 9)
- tab ();
- else
- outbyte (' ');
- k++;
- }
- outbyte ('^');
- nl ();
- comment ();
- outstr ("****** ");
- outstr (ptr);
- outstr (" ******");
- nl ();
- return 0;
-}
DELETED src/cc8/cross/expr.c
Index: src/cc8/cross/expr.c
==================================================================
--- src/cc8/cross/expr.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* File expr.c: 2.2 (83/06/21,11:24:26) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * lval[0] - symbol table address, else 0 for constant
- * lval[1] - type indirect object to fetch, else 0 for static object
- * lval[2] - type pointer or array, else 0
- */
-
-expression (comma)
-int comma;
-{
- int lval[3];
-
- do {
- if (heir1 (lval))
- rvalue (lval);
- if (!comma)
- return 0;
- } while (match (","));
- return 0;
-}
-
-heir1 (lval)
-int lval[];
-{
- int k, lval2[3];
- char fc;
-
- k = heir1a (lval);
- if (match ("=")) {
- if (k == 0) {
- needlval ();
- return (0);
- }
- if (lval[1])
- gpush ();
- if (heir1 (lval2))
- rvalue (lval2);
- store (lval);
- return (0);
- } else
- {
- fc = ch();
- if (match ("-=") ||
- match ("+=") ||
- match ("*=") ||
- match ("/=") ||
- match ("%=") ||
- match (">>=") ||
- match ("<<=") ||
- match ("&=") ||
- match ("^=") ||
- match ("|=")) {
- if (k == 0) {
- needlval ();
- return (0);
- }
- if (lval[1])
- gpush ();
- rvalue (lval);
- gpush ();
- if (heir1 (lval2))
- rvalue (lval2);
- switch (fc) {
- case '-': {
- if (dbltest(lval,lval2))
- gaslint();
- gsub();
- result (lval, lval2);
- break;
- }
- case '+': {
- if (dbltest(lval,lval2))
- gaslint();
- gadd (lval,lval2);
- result(lval,lval2);
- break;
- }
- case '*': gmult (); break;
- case '/': gdiv (); break;
- case '%': gmod (); break;
- case '>': gasr (); break;
- case '<': gasl (); break;
- case '&': gand (); break;
- case '^': gxor (); break;
- case '|': gor (); break;
- }
- store (lval);
- return (0);
- } else
- return (k);
- }
-}
-
-heir1a (lval)
-int lval[];
-{
- int k, lval2[3], lab1, lab2;
-
- k = heir1b (lval);
- blanks ();
- if (ch () != '?')
- return (k);
- if (k)
- rvalue (lval);
- FOREVER
- if (match ("?")) {
- testjump (lab1 = getlabel (), FALSE);
- if (heir1b (lval2))
- rvalue (lval2);
- jump (lab2 = getlabel ());
- printlabel (lab1);
- col ();
- nl ();
- blanks ();
- if (!match (":")) {
- error ("missing colon");
- return (0);
- }
- if (heir1b (lval2))
- rvalue (lval2);
- printlabel (lab2);
- col ();
- nl ();
- } else
- return (0);
-}
-
-heir1b (lval)
-int lval[];
-{
- int k, lval2[3], lab;
-
- k = heir1c (lval);
- blanks ();
- if (!sstreq ("||"))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER
- if (match ("||")) {
- testjump (lab = getlabel (), TRUE);
- if (heir1c (lval2))
- rvalue (lval2);
- printlabel (lab);
- col ();
- nl ();
- gbool();
- } else
- return (0);
-}
-
-heir1c (lval)
-int lval[];
-{
- int k, lval2[3], lab;
-
- k = heir2 (lval);
- blanks ();
- if (!sstreq ("&&"))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER
- if (match ("&&")) {
- testjump (lab = getlabel (), FALSE);
- if (heir2 (lval2))
- rvalue (lval2);
- printlabel (lab);
- col ();
- nl ();
- gbool();
- } else
- return (0);
-}
-
-heir2 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir3 (lval);
- blanks ();
- if ((ch() != '|') | (nch() == '|') | (nch() == '='))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if ((ch() == '|') & (nch() != '|') & (nch() != '=')) {
- inbyte ();
- gpush ();
- if (heir3 (lval2))
- rvalue (lval2);
- gor ();
- blanks();
- } else
- return (0);
- }
-}
-
-heir3 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir4 (lval);
- blanks ();
- if ((ch () != '^') | (nch() == '='))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if ((ch() == '^') & (nch() != '=')){
- inbyte ();
- gpush ();
- if (heir4 (lval2))
- rvalue (lval2);
- gxor ();
- blanks();
- } else
- return (0);
- }
-}
-
-heir4 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir5 (lval);
- blanks ();
- if ((ch() != '&') | (nch() == '|') | (nch() == '='))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if ((ch() == '&') & (nch() != '&') & (nch() != '=')) {
- inbyte ();
- gpush ();
- if (heir5 (lval2))
- rvalue (lval2);
- gand ();
- blanks();
- } else
- return (0);
- }
-}
-
-heir5 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir6 (lval);
- blanks ();
- if (!sstreq ("==") &
- !sstreq ("!="))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if (match ("==")) {
- gpush ();
- if (heir6 (lval2))
- rvalue (lval2);
- geq ();
- } else if (match ("!=")) {
- gpush ();
- if (heir6 (lval2))
- rvalue (lval2);
- gne ();
- } else
- return (0);
- }
-}
-
-heir6 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir7 (lval);
- blanks ();
- if (!sstreq ("<") &&
- !sstreq ("<=") &&
- !sstreq (">=") &&
- !sstreq (">"))
- return (k);
- if (sstreq ("<<") || sstreq (">>"))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if (match ("<=")) {
- gpush ();
- if (heir7 (lval2))
- rvalue (lval2);
- if (lval[2] || lval2[2]) {
- gule ();
- continue;
- }
- gle ();
- } else if (match (">=")) {
- gpush ();
- if (heir7 (lval2))
- rvalue (lval2);
- if (lval[2] || lval2[2]) {
- guge ();
- continue;
- }
- gge ();
- } else if ((sstreq ("<")) &&
- !sstreq ("<<")) {
- inbyte ();
- gpush ();
- if (heir7 (lval2))
- rvalue (lval2);
- if (lval[2] || lval2[2]) {
- gult ();
- continue;
- }
- glt ();
- } else if ((sstreq (">")) &&
- !sstreq (">>")) {
- inbyte ();
- gpush ();
- if (heir7 (lval2))
- rvalue (lval2);
- if (lval[2] || lval2[2]) {
- gugt ();
- continue;
- }
- ggt ();
- } else
- return (0);
- blanks ();
- }
-}
-
-heir7 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir8 (lval);
- blanks ();
- if (!sstreq (">>") &&
- !sstreq ("<<") || sstreq(">>=") || sstreq("<<="))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if (sstreq(">>") && ! sstreq(">>=")) {
- inbyte(); inbyte();
- gpush ();
- if (heir8 (lval2))
- rvalue (lval2);
- gasr ();
- } else if (sstreq("<<") && ! sstreq("<<=")) {
- inbyte(); inbyte();
- gpush ();
- if (heir8 (lval2))
- rvalue (lval2);
- gasl ();
- } else
- return (0);
- blanks();
- }
-}
-
-heir8 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir9 (lval);
- blanks ();
- if ((ch () != '+') & (ch () != '-') | nch() == '=')
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if (match ("+")) {
- gpush ();
- if (heir9 (lval2))
- rvalue (lval2);
- /* if left is pointer and right is int, scale right */
- if (dbltest (lval, lval2))
- gaslint ();
- /* will scale left if right int pointer and left int */
- gadd (lval,lval2);
- result (lval, lval2);
- } else if (match ("-")) {
- gpush ();
- if (heir9 (lval2))
- rvalue (lval2);
- /* if dbl, can only be: pointer - int, or
- pointer - pointer, thus,
- in first case, int is scaled up,
- in second, result is scaled down. */
- if (dbltest (lval, lval2))
- gaslint ();
- gsub ();
- /* if both pointers, scale result */
- if ((lval[2] == CINT) && (lval2[2] == CINT)) {
- gasrint(); /* divide by intsize */
- }
- result (lval, lval2);
- } else
- return (0);
- }
-}
-
-heir9 (lval)
-int lval[];
-{
- int k, lval2[3];
-
- k = heir10 (lval);
- blanks ();
- if (((ch () != '*') && (ch () != '/') &&
- (ch () != '%')) || (nch() == '='))
- return (k);
- if (k)
- rvalue (lval);
- FOREVER {
- if (match ("*")) {
- gpush ();
- if (heir10 (lval2))
- rvalue (lval2);
- gmult ();
- } else if (match ("/")) {
- gpush ();
- if (heir10 (lval2))
- rvalue (lval2);
- gdiv ();
- } else if (match ("%")) {
- gpush ();
- if (heir10 (lval2))
- rvalue (lval2);
- gmod ();
- } else
- return (0);
- }
-}
-
-heir10 (lval)
-int lval[];
-{
- int k;
- unsigned char *ptr;
-
- if (match ("++")) {
- if ((k = heir10 (lval)) == 0) {
- needlval ();
- return (0);
- }
-// if (lval[1])
-// gpush ();
- rivalue (lval);
-// ginc (lval);
-// store (lval);
- return (0);
- } else if (match ("--")) {
- if ((k = heir10 (lval)) == 0) {
- needlval ();
- return (0);
- }
- if (lval[1])
- gpush ();
- rvalue (lval);
- gdec (lval);
- store (lval);
- return (0);
- } else if (match ("-")) {
- k = heir10 (lval);
- if (k)
- rvalue (lval);
- gneg ();
- return (0);
- } else if (match ("~")) {
- k = heir10 (lval);
- if (k)
- rvalue (lval);
- gcom ();
- return (0);
- } else if (match ("!")) {
- k = heir10 (lval);
- if (k)
- rvalue (lval);
- glneg ();
- return (0);
- } else if (ch()=='*' && nch() != '=') {
- inbyte();
- k = heir10 (lval);
- if (k)
- rvalue (lval);
- if (ptr = lval[0])
- lval[1] = ptr[TYPE];
- else
- lval[1] = CINT;
- lval[2] = 0; /* flag as not pointer or array */
- return (1);
- } else if (ch()=='&' && nch()!='&' && nch()!='=') {
- inbyte();
- k = heir10 (lval);
- if (k == 0) {
- error ("illegal address");
- return (0);
- }
- ptr = lval[0];
- lval[2] = ptr[TYPE];
- if (lval[1])
- return (0);
- /* global and non-array */
- immed ();
- k=128+ptr[OFFSET]+ptr[OFFSET+1]*256;
- onum(k);
- ot("\t/Offset from stackbase at 128 (200(8))");
- nl ();
- lval[1] = ptr[TYPE];
- return (0);
- } else {
- k = heir11 (lval);
- if (match ("++")) {
- if (k == 0) {
- needlval ();
- return (0);
- }
-// if (lval[1])
-// gpush ();
- rvalue (lval);
- gisz (lval);
-// ginc (lval);
-// store (lval);
-// gdec (lval);
- return (0);
- } else if (match ("--")) {
- if (k == 0) {
- needlval ();
- return (0);
- }
- if (lval[1])
- gpush ();
- rvalue (lval);
- gdec (lval);
- store (lval);
- ginc (lval);
- return (0);
- } else
- return (k);
- }
-}
-
-heir11 (lval)
-int *lval;
-{
- int k;
- char *ptr;
-
- k = primary (lval);
- ptr = lval[0];
- blanks ();
- if ((ch () == '[') | (ch () == '('))
- FOREVER {
- if (match ("[")) {
- if (ptr == 0) {
- error ("can't subscript");
- junk ();
- needbrack ("]");
- return (0);
- } else if (ptr[IDENT] == POINTER)
- rvalue (lval);
- else if (ptr[IDENT] != ARRAY) {
- error ("can't subscript");
- k = 0;
- }
- gpush ();
- expression (YES);
- needbrack ("]");
- if (ptr[TYPE] == CINT)
- gaslint ();
- gadd (NULL,NULL);
- lval[0] = 0;
- lval[1] = ptr[TYPE];
- k = 1;
- } else if (match ("(")) {
- if (ptr == 0)
- callfunction (0);
- else if (ptr[IDENT] != FUNCTION) {
- rvalue (lval);
- callfunction (0);
- } else
- callfunction (ptr);
- k = lval[0] = 0;
- } else
- return (k);
- }
- if (ptr == 0)
- return (k);
- if (ptr[IDENT] == FUNCTION) {
- immed ();
- prefix ();
- outstr (ptr);
- nl ();
- return (0);
- }
- return (k);
-}
DELETED src/cc8/cross/function.c
Index: src/cc8/cross/function.c
==================================================================
--- src/cc8/cross/function.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* File function.c: 2.1 (83/03/20,16:02:04) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * begin a function
- *
- * called from "parse", this routine tries to make a function out
- * of what follows
- * modified version. p.l. woods
- *
- */
-int argtop;
-newfunc ()
-{
- char n[NAMESIZE], *ptr, rtn[NAMESIZE];
- fexitlab = getlabel();
-
- if (!symname (n) ) {
- error ("illegal function or declaration");
- kill_line ();
- return 0;
- }
- if (ptr = findglb (n)) {
- if (ptr[IDENT] != FUNCTION)
- multidef (n);
- else if (ptr[OFFSET] == FUNCTION)
- multidef (n);
- else
- ptr[OFFSET] = FUNCTION;
- } else
- addglb (n, FUNCTION, CINT, 0, PUBLIC); // Do not allocate any storage to global functions
- if (!match ("("))
- error ("missing open paren");
- prefix ();
- if (astreq(n,"main",4)) {
- if (inbreak) {
- ol("\tEND");
- output=bfile;
- }
- outstr("xmain");
- }
- else outstr (n);
- strcpy(rtn,n);
- col ();
-// outstr("\t0");
- nl ();
- if (inbreak) {
- ol("\tCLA CLL");
- ol("\tCALL 2,PGINIT");
- ol("\tARG STKP");
- ol("\tARG GBL");
- }
- prologue (rtn);
- locptr = STARTLOC;
- argstk = 0;
- while (!match (")")) {
- if (symname (n)) {
- if (findloc (n))
- multidef (n);
- else {
- addloc (n, 0, 0, argstk, AUTO);
- argstk = argstk + intsize();
- }
- } else {
- error ("illegal argument name");
- junk ();
- }
- blanks ();
- if (!streq (line + lptr, ")")) {
- if (!match (","))
- error ("expected comma");
- }
- if (endst ())
- break;
- }
- stkp = 0;
- argtop = argstk;
- while (argstk) {
- if (amatch ("register", 8)) {
- if (amatch("char", 4))
- getarg(CCHAR);
- else if (amatch ("int", 3))
- getarg(CINT);
- else
- getarg(CINT);
- ns();
- } else if (amatch ("char", 4)) {
- getarg (CCHAR);
- ns ();
- } else if (amatch ("int", 3)) {
- getarg (CINT);
- ns ();
- } else {
- error ("wrong number args");
- break;
- }
- }
- statement(YES);
- printlabel(fexitlab);
- col();
- nl();
- if (astreq(n,"main",4)) /* On exit from main pop literal table as well */
- modstk(0);
- else
- modstk (0);
- gret (rtn);
- stkp = 0;
- locptr = STARTLOC;
- return 0;
-}
-
-/*
- * declare argument types
- *
- * called from "newfunc", this routine add an entry in the local
- * symbol table for each named argument
- * completely rewritten version. p.l. woods
- *
- */
-getarg (t)
-int t;
-{
- int j, legalname, address;
- char n[NAMESIZE], c, *argptr;
-
- FOREVER {
- if (argstk == 0)
- return 0;
- if (match ("*"))
- j = POINTER;
- else
- j = VARIABLE;
- if (!(legalname = symname (n)))
- illname ();
- if (match ("[")) {
- while (inbyte () != ']')
- if (endst ())
- break;
- j = POINTER;
- }
- if (legalname) {
- if (argptr = findloc (n)) {
- argptr[IDENT] = j;
- argptr[TYPE] = t;
- address = argtop - glint(argptr);
- if (t == CCHAR && j == VARIABLE)
- address = address + byteoff();
- argptr[OFFSET] = (address) & 0xff;
- argptr[OFFSET + 1] = (address >> 8) & 0xff;
- } else
- error ("expecting argument name");
- }
- argstk = argstk - intsize();
- if (endst ())
- return 0;
- if (!match (","))
- error ("expected comma");
- }
-}
DELETED src/cc8/cross/gen.c
Index: src/cc8/cross/gen.c
==================================================================
--- src/cc8/cross/gen.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/* File gen.c: 2.1 (83/03/20,16:02:06) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/* ToUpper routine */
-
- ucase(ch)
- int ch;
- {
- if ('a'>ch || ch>'z') return(ch);
- return(ch-32);
- }
-/*
- * return next available internal label number
- *
- */
-getlabel ()
-{
- return (nxtlab++);
-}
-
-/*
- * print specified number as label
- */
-printlabel (label)
-int label;
-{
- olprfix ();
- outdec (label);
- return 0;
-}
-
-/*
- * glabel - generate label
- */
-glabel (lab)
-char *lab;
-{
- prefix ();
- outstr (lab);
- col ();
- nl ();
- return 0;
-}
-
-/*
- * gnlabel - generate numeric label
- */
-gnlabel (nlab)
-int nlab;
-{
- printlabel (nlab);
- col ();
- nl ();
- return 0;
-}
-
-outbyte (c)
-char c;
-{
- if (c == 0)
- return (0);
- fputc (c, output);
- return (c);
-}
-
-outstr (ptr)
-char ptr[];
-{
- int k;
-
- k = 0;
- while (outbyte (ucase(ptr[k++])));
- return 0;
-}
-
-
-tab ()
-{
- outbyte (9);
- return 0;
-}
-
-ol (ptr)
-char ptr[];
-{
- ot (ptr);
- nl ();
- return 0;
-}
-
-ot (ptr)
-char ptr[];
-{
- outstr (ptr);
- return 0;
-}
-
-outdec (number)
-int number;
-{
- int k, zs;
- char c;
-
- if (number == -32768) {
- outstr ("-32768");
- return 0;
- }
- zs = 0;
- k = 10000;
- if (number < 0) {
- number = (-number);
- outbyte ('-');
- }
- while (k >= 1) {
- c = number / k + '0';
- if ((c != '0' | (k == 1) | zs)) {
- zs = 1;
- outbyte (c);
- }
- number = number % k;
- k = k / 10;
- }
- return 0;
-}
-
-store (lval)
-int *lval;
-{
- if (lval[1] == 0)
- putmem (lval[0]);
- else
- putstk (lval[1]);
- return 0;
-}
-
-rvalue (lval)
-int *lval;
-{
- if ((lval[0] != 0) & (lval[1] == 0))
- getmem (lval[0]);
- else
- indirect (lval[1]);
- return 0;
-}
-
-rivalue (lval)
-int *lval;
-{
- if ((lval[0] != 0) & (lval[1] == 0))
- getincmem (lval[0]);
- else
- incdirect (lval[1]);
- return 0;
-}
-
-test (label, ft)
-int label,
- ft;
-{
- needbrack ("(");
- expression (YES);
- needbrack (")");
- testjump (label, ft);
- return 0;
-}
DELETED src/cc8/cross/io.c
Index: src/cc8/cross/io.c
==================================================================
--- src/cc8/cross/io.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/* File io.c: 2.1 (83/03/20,16:02:07) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * open input file
- */
-openin (p) char *p;
-{
- strcpy(fname, p);
- fixname (fname);
- if (!checkname (fname))
- return (NO);
- if ((input = fopen (fname, "r")) == NULL) {
- pl ("Open failure\n");
- return (NO);
- }
- kill_line ();
- return (YES);
-}
-
-/*
- * open output file
- */
-openout ()
-{
- outfname (fname);
- if ((output = fopen (fname, "w")) == NULL) {
- pl ("Open failure");
- return (NO);
- }
- kill_line ();
- return (YES);
-}
-
-/*
- * change input filename to output filename
- */
-outfname (s)
-char *s;
-{
- while (*s)
- s++;
- *--s = 's';
- return 0;
-}
-
-/*
- * remove NL from filenames
- *
- */
-fixname (s)
-char *s;
-{
- while (*s && *s++ != EOL);
- if (!*s) return 0;
- *(--s) = 0;
- return 0;
-}
-
-/*
- * check that filename is "*.c"
- */
-checkname (s)
-char *s;
-{
- while (*s)
- s++;
- if (*--s != 'c')
- return (NO);
- if (*--s != '.')
- return (NO);
- return (YES);
-}
-
-kill_line ()
-{
- lptr = 0;
- line[lptr] = 0;
- return 0;
-}
-
-inln ()
-{
- int k;
- FILE *unit;
-
- FOREVER {
- if (feof (input))
- return 0;
- if ((unit = input2) == NULL)
- unit = input;
- kill_line ();
- while ((k = fgetc (unit)) != EOF) {
- if ((k == EOL) | (lptr >= LINEMAX))
- break;
- if (k != 13) line[lptr++] = k;
- }
- line[lptr] = 0;
- if (output && cmode) {
- outstr("/\t");
- ol(line);
- }
- if (k <= 0)
- if (input2 != NULL) {
- input2 = inclstk[--inclsp];
- fclose (unit);
- }
- if (lptr) {
- if ((ctext) & (cmode)) {
- comment ();
- outstr (line);
- nl ();
- }
- lptr = 0;
- return 0;
- }
- }
-}
-
-inbyte ()
-{
- while (ch () == 0) {
- if (feof (input))
- return (0);
- preprocess ();
- }
- return (gch ());
-}
-
-inchar ()
-{
- if (ch () == 0)
- inln ();
- if (feof (input))
- return (0);
- return (gch ());
-}
-
-gch ()
-{
- if (ch () == 0)
- return (0);
- else
- return (line[lptr++] & 127);
-}
-
-nch ()
-{
- if (ch () == 0)
- return (0);
- else
- return (line[lptr + 1] & 127);
-}
-
-ch ()
-{
- return (line[lptr] & 127);
-}
-
-/*
- * print a carriage return and a string only to console
- *
- */
-pl (str)
-char *str;
-{
- int k;
-
- k = 0;
- putchar (EOL);
- while (str[k])
- putchar (str[k++]);
- return 0;
-}
DELETED src/cc8/cross/lex.c
Index: src/cc8/cross/lex.c
==================================================================
--- src/cc8/cross/lex.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* File lex.c: 2.1 (83/03/20,16:02:09) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * semicolon enforcer
- *
- * called whenever syntax requires a semicolon
- *
- */
-ns ()
-{
- if (!match (";"))
- error ("missing semicolon");
- return 0;
-}
-
-junk ()
-{
- if (an (inbyte ()))
- while (an (ch ()))
- gch ();
- else
- while (an (ch ())) {
- if (ch () == 0)
- break;
- gch ();
- }
- blanks ();
- return 0;
-}
-
-endst ()
-{
- blanks ();
- return ((streq (line + lptr, ";") | (ch () == 0)));
-}
-
-needbrack (str)
-char *str;
-{
- if (!match (str)) {
- error ("missing bracket");
- comment ();
- outstr (str);
- nl ();
- }
- return 0;
-}
-
-/*
- * test if given character is alpha
- *
- */
-alpha (c)
-char c;
-{
- c = c & 127;
- return (((c >= 'a') & (c <= 'z')) |
- ((c >= 'A') & (c <= 'Z')) |
- (c == '_'));
-}
-
-/*
- * test if given character is numeric
- *
- */
-numeric (c)
-char c;
-{
- c = c & 127;
- return ((c >= '0') & (c <= '9'));
-}
-
-/*
- * test if given character is alphanumeric
- *
- */
-an (c)
-char c;
-{
- return ((alpha (c)) | (numeric (c)));
-}
-
-sstreq (str1) char *str1; {
- return (streq(line + lptr, str1));
-}
-
-streq (str1, str2)
-char str1[], str2[];
-{
- int k;
-
- k = 0;
- while (str2[k]) {
- if ((str1[k] != str2[k]))
- return (0);
- k++;
- }
- return (k);
-}
-
-astreq (str1, str2, len)
-char str1[], str2[];
-int len;
-{
- int k;
-
- k = 0;
- while (k < len) {
- if ((str1[k] != str2[k]))
- break;
- if (str1[k] == 0)
- break;
- if (str2[k] == 0)
- break;
- k++;
- }
- if (an (str1[k]))
- return (0);
- if (an (str2[k]))
- return (0);
- return (k);
-}
-
-match (lit)
-char *lit;
-{
- int k;
-
- blanks ();
- if (k = streq (line + lptr, lit)) {
- lptr = lptr + k;
- return (1);
- }
- return (0);
-}
-
-amatch (lit, len)
-char *lit;
-int len;
-{
- int k;
-
- blanks ();
- if (k = astreq (line + lptr, lit, len)) {
- lptr = lptr + k;
- while (an (ch ()))
- inbyte ();
- return (1);
- }
- return (0);
-}
-
-blanks ()
-{
- FOREVER {
- while (ch () == 0) {
- preprocess ();
- if (feof (input))
- break;
- }
- if (ch () == ' ')
- gch ();
- else if (ch () == 9)
- gch ();
- else
- return 0;
- }
-}
DELETED src/cc8/cross/main.c
Index: src/cc8/cross/main.c
==================================================================
--- src/cc8/cross/main.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* File main.c: 2.7 (84/11/28,10:14:56) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-main (argc, argv)
-int argc;
-char** argv; /* OS/8 CC8 can't cope, but bootstrapping CC8 doesn't work, either */
-{
- char *p,*bp;
- int smacptr;
- macptr = 0;
- ctext = 0;
- argc--; argv++;
- errs = 0;
- aflag = 1;
- while (p = *argv++)
- if (*p == '-') while (*++p)
- switch(*p) {
- case 't': case 'T':
- ctext = 1;
- break;
- case 's': case 'S':
- sflag = 1;
- break;
- case 'c': case 'C':
- cflag = 1;
- break;
- case 'a': case 'A':
- aflag = 0;
- break;
- case 'd': case 'D':
- bp = ++p;
- if (!*p) usage();
- while (*p && *p != '=') p++;
- if (*p == '=') *p = '\t';
- while (*p) p++;
- p--;
- defmac(bp);
- break;
- default:
- usage();
- }
- else break;
-
- smacptr = macptr;
- if (!p)
- usage();
- while (p) {
- errfile = 0;
- if (typof(p) == 'c' || typof(p) =='C') {
- glbptr = STARTGLB;
- locptr = STARTLOC;
- wsptr = ws;
- inclsp =
- iflevel =
- skiplevel =
- swstp =
- litptr =
- stkp =
- errcnt =
- ncmp =
- lastst =
- quote[1] =
- gsize =
- inbreak =
- 0;
- macptr = smacptr;
- input2 = NULL;
- quote[0] = '"';
- cmode = 1;
- glbflag = 1;
- nxtlab = 0;
- litlab = getlabel ();
- defmac("end\tmemory");
- rglbptr = glbptr;
- defmac("short\tint");
- initmac();
- /*
- * compiler body
- */
- if (!openin (p))
- return 0;
- if (!openout ())
- return 0;
- header ();
- gtext ();
- parse ();
- fclose (input);
- gdata ();
- dumplits ();
- dumpglbs ();
- errorsummary ();
- trailer ();
- fclose (output);
- pl ("");
- errs = errs || errfile;
-#ifndef NOASLD
- }
- if (!errfile && !sflag)
- errs = errs || assemble(p);
-#else
- } else {
- fputs("Don't understand file ", stderr);
- fputs(p, stderr);
- errs = 1;
- }
-#endif
- p = *argv++;
- }
- exit(errs != 0);
- return 0;
-}
-
-FEvers()
-{
- outstr("/\tFront End (1.0:27/1/99)");
- return 0;
-}
-
-usage()
-{
- fputs("usage: sccXXXX [-tcsa] [-dSYM[=VALUE]] files\n", stderr);
- exit(1);
-}
-
-/*
- * process all input text
- *
- * at this level, only static declarations, defines, includes,
- * and function definitions are legal.
- *
- */
-parse ()
-{
- while (!feof (input)) {
- if (amatch ("extern", 6))
- dodcls(EXTERN);
- else if (amatch ("static",6))
- dodcls(STATIC);
- else if (dodcls(PUBLIC)) ;
- else if (match ("#asm"))
- doasm ();
- else if (match ("#include"))
- doinclude ();
- else if (match ("#define"))
- dodefine();
- else if (match ("#undef"))
- doundef();
- else
- newfunc ();
- blanks ();
- }
- return 0;
-}
-
-/*
- * parse top level declarations
- */
-
-dodcls(stclass)
-int stclass; {
- blanks();
- if (amatch("char", 4))
- declglb(CCHAR, stclass);
- else if (amatch("int", 3))
- declglb(CINT, stclass);
- else if (stclass == PUBLIC)
- return(0);
- else
- declglb(CINT, stclass);
- ns ();
- return(1);
-}
-
-
-/*
- * dump the literal pool
- */
-dumplits ()
-{
- int j, k;
-
-/* A loc containing the size */
- ol("\tLAP");
- ot ("\tCPAGE ");
- onum (2+litptr);
- nl();
- outbyte('L');
- printlabel (litlab);
- col();
- ot("\t");
- onum (-litptr);
- nl();
- if (litptr == 0)
- return 0;
-/* Generate a loc containing the address of the literals */
- outbyte('X');
- printlabel (litlab);
- col();
- ot("\t");
- printlabel (litlab);
- nl();
- printlabel (litlab);
- col ();
- k = 0;
- while (k < litptr) {
- defbyte ();
- j = 8;
- while (j--) {
- onum (litq[k++] & 127);
- if ((j == 0) | (k >= litptr)) {
- nl ();
- break;
- }
- outbyte (';');
- }
- }
- ol("\tEAP");
- return 0;
-}
-
-/*
- * dump all static variables
- */
-dumpglbs ()
-{
- int j;
-
- if (!glbflag) {
- ot("GBLS,\t0");
- nl();
- return 0;
- }
- cptr = rglbptr;
- while (cptr < glbptr) {
- if (cptr[IDENT] != FUNCTION) {
- ppubext(cptr);
- if (cptr[STORAGE] != EXTERN) {
- //prefix ();
- //outstr (cptr);
- //col ();
- //defstorage ();
- j = glint(cptr);
- if ((cptr[TYPE] == CINT) ||
- (cptr[IDENT] == POINTER))
- j = j * intsize();
- //onum (j);
- //nl ();
- }
- } else {
- fpubext(cptr);
- }
- cptr = cptr + SYMSIZ;
- }
- ot("GBLS,\t");
- onum(gsize+128); // Beginning of stack after globals
- nl();
- return 0;
-}
-
-/*
- * report errors
- */
-errorsummary ()
-{
- if (ncmp)
- error ("missing closing bracket");
- nl ();
- comment ();
- outdec (errcnt);
- if (errcnt) errfile = YES;
- outstr (" error(s) in compilation");
- nl ();
- comment();
- ot("literal pool:");
- outdec(litptr);
- nl();
- comment();
- ot("global pool:");
- outdec(glbptr-rglbptr);
- nl();
- comment();
- ot("Macro pool:");
- outdec(macptr);
- nl();
- pl (errcnt ? "Error(s)" : "No errors");
- return 0;
-}
-
-typof(s)
-char *s; {
- s += strlen(s) - 2;
- if (*s == '.')
- return(*(s+1));
- return(' ');
-}
DELETED src/cc8/cross/preproc.c
Index: src/cc8/cross/preproc.c
==================================================================
--- src/cc8/cross/preproc.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/* File preproc.c: 2.3 (84/11/27,11:47:40) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * open an include file
- */
-doinclude ()
-{
- char *p;
- FILE *inp2;
-
- blanks ();
- if (inp2 = fixiname ())
- if (inclsp < INCLSIZ) {
- inclstk[inclsp++] = input2;
- input2 = inp2;
- } else {
- fclose (inp2);
- error ("too many nested includes");
- }
- else {
- error ("Could not open include file");
- }
- kill_line ();
- return 0;
-}
-
-/*
- * fixiname - remove "brackets" around include file name
- */
-fixiname ()
-{
- char c1, c2, *p, *ibp;
- char buf[20];
-
- ibp = &buf[0];
-
- if ((c1 = gch ()) != '"' && c1 != '<')
- return (NULL);
- for (p = line + lptr; *p ;)
- *ibp++ = *p++;
- c2 = *(--p);
- if (c1 == '"' ? (c2 != '"') : (c2 != '>')) {
- error ("incorrect delimiter");
- return (NULL);
- }
- *(--ibp) = 0;
-
- return c1 == '<' ? fopen(buf, "r") : NULL;
-}
-
-/*
- * "asm" pseudo-statement
- *
- * enters mode where assembly language statements are passed
- * intact through parser
- *
- */
-doasm ()
-{
- cmode = 0;
- FOREVER {
- inln ();
- if (match ("#endasm")) {
- ol("/\t#ENDASM");
- break;
- }
- if (feof (input))
- break;
- outstr (line);
- nl ();
- }
- kill_line ();
- cmode = 1;
- return 0;
-}
-
-dodefine ()
-{
- addmac();
- return 0;
-}
-
-doundef ()
-{
- int mp;
- char sname[NAMESIZE];
-
- if (!symname(sname)) {
- illname();
- kill_line ();
- return 0;
- }
-
- if (mp = findmac(sname))
- delmac(mp);
- kill_line ();
- return 0;
-}
-
-preprocess ()
-{
- if (ifline()) return 0;
- while (cpp());
- return 0;
-}
-
-doifdef (ifdef)
-int ifdef;
-{
- char sname[NAMESIZE];
- int k;
-
- blanks();
- ++iflevel;
- if (skiplevel) return 0;
- k = symname(sname) && findmac(sname);
- if (k != ifdef) skiplevel = iflevel;
- return 0;
-}
-
-ifline()
-{
- FOREVER {
- inln();
- if (feof(input)) return(1);
- if (match("#ifdef")) {
- doifdef(YES);
- continue;
- } else if (match("#ifndef")) {
- doifdef(NO);
- continue;
- } else if (match("#else")) {
- if (iflevel) {
- if (skiplevel == iflevel) skiplevel = 0;
- else if (skiplevel == 0) skiplevel = iflevel;
- } else noiferr();
- continue;
- } else if (match("#endif")) {
- if (iflevel) {
- if (skiplevel == iflevel) skiplevel = 0;
- --iflevel;
- } else noiferr();
- continue;
- }
- if (!skiplevel) return(0);
- }
-}
-
-noiferr()
-{
- error("no matching #if...");
- return 0;
-}
-
-
-cpp ()
-{
- int k;
- char c, sname[NAMESIZE];
- int tog;
- int cpped; /* non-zero if something expanded */
-
- cpped = 0;
- /* don't expand lines with preprocessor commands in them */
- if (!cmode || line[0] == '#') return(0);
-
- mptr = lptr = 0;
- while (ch ()) {
- if ((ch () == '/') & (nch () == '/')) {
- inln();
- }
- if ((ch () == ' ') | (ch () == 9)) {
- keepch (' ');
- while ((ch () == ' ') | (ch () == 9))
- gch ();
- } else if (ch () == '"') {
- keepch (ch ());
- gch ();
- while (ch () != '"') {
- if (ch () == 0) {
- error ("missing quote");
- break;
- }
- if (ch() == '\\') keepch(gch());
- keepch (gch ());
- }
- gch ();
- keepch ('"');
- } else if (ch () == 39) {
- keepch (39);
- gch ();
- while (ch () != 39) {
- if (ch () == 0) {
- error ("missing apostrophe");
- break;
- }
- if (ch() == '\\') keepch(gch());
- keepch (gch ());
- }
- gch ();
- keepch (39);
- } else if ((ch () == '/') & (nch () == '*')) {
- inchar ();
- inchar ();
- while ((((c = ch ()) == '*') & (nch () == '/')) == 0)
- if (c == '$') {
- inchar ();
- tog = TRUE;
- if (ch () == '-') {
- tog = FALSE;
- inchar ();
- }
- if (alpha (c = ch ())) {
- inchar ();
- toggle (c, tog);
- }
- } else {
- if (ch () == 0)
- inln ();
- else
- inchar ();
- if (feof (input))
- break;
- }
- inchar ();
- inchar ();
- } else if (an (ch ())) {
- k = 0;
- while (an (ch ())) {
- if (k < NAMEMAX)
- sname[k++] = ch ();
- gch ();
- }
- sname[k] = 0;
- if (k = findmac (sname)) {
- cpped = 1;
- while (c = macq[k++])
- keepch (c);
- } else {
- k = 0;
- while (c = sname[k++])
- keepch (c);
- }
- } else
- keepch (gch ());
- }
- keepch (0);
- if (mptr >= MPMAX)
- error ("line too long");
- lptr = mptr = 0;
- while (line[lptr++] = mline[mptr++]);
- lptr = 0;
- return(cpped);
-}
-
-keepch (c)
-char c;
-{
- mline[mptr] = c;
- if (mptr < MPMAX)
- mptr++;
- return (c);
-}
-
-defmac(s)
-char *s;
-{
- kill_line();
- strcpy(line, s);
- addmac();
- return 0;
-}
-
-addmac ()
-{
- char sname[NAMESIZE];
- int k;
- int mp;
-
- if (!symname (sname)) {
- illname ();
- kill_line ();
- return 0;
- }
- if (mp = findmac(sname)) {
- error("Duplicate define");
- delmac(mp);
- }
- k = 0;
- while (putmac (sname[k++]));
- while (ch () == ' ' | ch () == 9)
- gch ();
- while (putmac (gch ()));
- if (macptr >= MACMAX)
- error ("macro table full");
- return 0;
-}
-
-delmac(mp) int mp; {
- --mp; --mp; /* step over previous null */
- while (mp >= 0 && macq[mp]) macq[mp--] = '%';
- return 0;
-}
-
-
-putmac (c)
-char c;
-{
- macq[macptr] = c;
- if (macptr < MACMAX)
- macptr++;
- return (c);
-}
-
-findmac (sname)
-char *sname;
-{
- int k;
-
- k = 0;
- while (k < macptr) {
- if (astreq (sname, macq + k, NAMEMAX)) {
- while (macq[k++]);
- return (k);
- }
- while (macq[k++]);
- while (macq[k++]);
- }
- return (0);
-}
-
-toggle (name, onoff)
-char name;
-int onoff;
-{
- switch (name) {
- case 'C':
- ctext = onoff;
- break;
- }
- return 0;
-}
DELETED src/cc8/cross/primary.c
Index: src/cc8/cross/primary.c
==================================================================
--- src/cc8/cross/primary.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/* File primary.c: 2.4 (84/11/27,16:26:07) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-primary (lval)
-int *lval;
-{
- unsigned char *ptr, sname[NAMESIZE];
- int num[1];
- int k;
-
- lval[2] = 0; /* clear pointer/array type */
- if (match ("(")) {
- k = heir1 (lval);
- needbrack (")");
- return (k);
- }
- if (amatch("sizeof", 6)) {
- needbrack("(");
- immed();
- if (amatch("int", 3)) onum(intsize());
- else if (amatch("char", 4)) onum(1);
- else if (symname(sname)) {
- if ((ptr = findloc(sname)) ||
- (ptr = findglb(sname))) {
- if (ptr[STORAGE] == LSTATIC)
- error("sizeof local static");
- k = glint(ptr);
- if ((ptr[TYPE] == CINT) ||
- (ptr[IDENT] == POINTER))
- k *= intsize();
- onum(k);
- } else {
- error("sizeof undeclared variable");
- onum(0);
- }
- } else {
- error("sizeof only on type or variable");
- }
- needbrack(")");
- nl();
- return(lval[0] = lval[1] = 0);
- }
- if (symname (sname)) {
- if (ptr = findloc (sname)) {
- getloc (ptr);
- lval[0] = ptr;
- lval[1] = ptr[TYPE];
- if (ptr[IDENT] == POINTER) {
- lval[1] = CINT;
- lval[2] = ptr[TYPE];
- }
- if (ptr[IDENT] == ARRAY) {
- lval[2] = ptr[TYPE];
- lval[2] = 0;
- return (0);
- }
- else
- return (1);
- }
- if (ptr = findglb (sname))
- if (ptr[IDENT] != FUNCTION) {
- lval[0] = ptr;
- lval[1] = 0;
- if (ptr[IDENT] != ARRAY) {
- if (ptr[IDENT] == POINTER)
- lval[2] = ptr[TYPE];
- return (1);
- }
- immed ();
- onum(128+ptr[OFFSET]+ptr[OFFSET+1]*256);
- ot("\t/Offset from stackbase at 128 (200(8))");
- nl ();
- lval[1] = lval[2] = ptr[TYPE];
- lval[2] = 0;
- return (0);
- }
- blanks ();
- if (ch() != '(')
- error("undeclared variable");
- ptr = addglb (sname, FUNCTION, CINT, 0, PUBLIC);
- lval[0] = ptr;
- lval[1] = 0;
- return (0);
- }
- if (constant (num))
- return (lval[0] = lval[1] = 0);
- else {
- error ("invalid expression");
- immed ();
- onum (0);
- nl ();
- junk ();
- return (0);
- }
-}
-
-/*
- * true if val1 -> int pointer or int array and val2 not pointer or array
- */
-dbltest (val1, val2)
-int val1[], val2[];
-{
- if (val1 == NULL)
- return (FALSE);
- if (val1[2] != CINT)
- return (FALSE);
- if (val2[2])
- return (FALSE);
- return (TRUE);
-}
-
-/*
- * determine type of binary operation
- */
-result (lval, lval2)
-int lval[],
- lval2[];
-{
- if (lval[2] && lval2[2])
- lval[2] = 0;
- else if (lval2[2]) {
- lval[0] = lval2[0];
- lval[1] = lval2[1];
- lval[2] = lval2[2];
- }
- return 0;
-}
-
-constant (val)
-int val[];
-{
- if (number (val))
- {
- if (val[0]==0) {
- ol("\t/ (0)");
- cpri();
- return (1);
- }
- immed ();
- }
- else if (pstr (val))
- immed ();
- else if (qstr (val)) {
- immd2 ();
- stkbase();
- nl();
-/* outbyte ('+'); */
- immd3 ();
- } else
- return (0);
- onum (val[0]);
- nl ();
- return (1);
-}
-
-number (val)
-int val[];
-{
- int k, minus, base;
- char c;
-
- k = minus = 1;
- while (k) {
- k = 0;
- if (match ("+"))
- k = 1;
- if (match ("-")) {
- minus = (-minus);
- k = 1;
- }
- }
- if (!numeric (c = ch ()))
- return (0);
- if (match ("0x") || match ("0X"))
- while (numeric (c = ch ()) ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'F')) {
- inbyte ();
- k = k * 16 +
- (numeric (c) ? (c - '0') : ((c & 07) + 9));
- }
- else {
- base = (c == '0') ? 8 : 10;
- while (numeric (ch ())) {
- c = inbyte ();
- k = k * base + (c - '0');
- }
- }
- if (minus < 0)
- k = (-k);
- val[0] = k;
- return (1);
-}
-
-pstr (val)
-int val[];
-{
- int k;
- char c;
-
- k = 0;
- if (!match ("'"))
- return (0);
- while ((c = gch ()) != 39) {
- c = (c == '\\') ? spechar(): c;
- k = (k & 255) * 256 + (c & 255);
- }
- val[0] = k;
- return (1);
-}
-
-qstr (val)
-int val[];
-{
- char c;
-
- if (!match (quote))
- return (0);
- val[0] = litptr;
- while (ch () != '"') {
- if (ch () == 0)
- break;
- if (litptr >= LITMAX) {
- error ("string space exhausted");
- while (!match (quote))
- if (gch () == 0)
- break;
- return (1);
- }
- c = gch();
- litq[litptr++] = (c == '\\') ? spechar(): c;
- }
- gch ();
- litq[litptr++] = 0;
- return (1);
-}
-
-/*
- * decode special characters (preceeded by back slashes)
- */
-spechar() {
- char c;
- c = ch();
-
- if (c == 'n') c = EOL;
- else if (c == 't') c = TAB;
- else if (c == 'r') c = CR;
- else if (c == 'f') c = FFEED;
- else if (c == 'b') c = BKSP;
- else if (c == '0') c = EOS;
- else if (c == EOS) return 0;
-
- gch();
- return (c);
-}
-
-/*
- * perform a function call
- *
- * called from "heir11", this routine will either call the named
- * function, or if the supplied ptr is zero, will call the contents
- * of HL
- * NB Added section to load Acc with nargs for vararg calls
- * NB have addded pseudo functions here as well
- */
-callfunction (ptr)
-char *ptr;
-{
- int nargs;
-
- if (strcmp(ptr,"stri")==0) {
- expression(NO);
- stri();
- needbrack(")");
- return 0;
- }
- if (strcmp(ptr,"iinit")==0) {
- expression(NO);
- iinit();
- needbrack(")");
- return 0;
- }
-
- nargs = 0;
- blanks ();
- if (ptr == 0)
- gpush ();
- while (!streq (line + lptr, ")")) {
- if (endst ())
- break;
- expression (NO);
- if (ptr == 0)
- swapstk ();
- gpush ();
- nargs = nargs + intsize();
- if (!match (","))
- break;
- }
- needbrack (")");
- if (aflag)
- gnargs(nargs / intsize());
- if (ptr)
- gcall (ptr,&nargs);
- else
- callstk ();
- stkp = modstk (stkp + nargs);
- return 0;
-}
-
-needlval ()
-{
- error ("must be lvalue");
- return 0;
-}
DELETED src/cc8/cross/stmt.c
Index: src/cc8/cross/stmt.c
==================================================================
--- src/cc8/cross/stmt.c
+++ /dev/null
@@ -1,438 +0,0 @@
-/* File stmt.c: 2.1 (83/03/20,16:02:17) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * statement parser
- *
- * called whenever syntax requires a statement. this routine
- * performs that statement and returns a number telling which one
- *
- * 'func' is true if we require a "function_statement", which
- * must be compound, and must contain "statement_list" (even if
- * "declaration_list" is omitted)
- */
-
-statement (func)
-int func;
-{
- if ((ch () == 0) & feof (input))
- return (0);
- lastst = 0;
- if (func)
- if (match ("{")) {
- compound (YES);
- return (lastst);
- } else
- error ("function requires compound statement");
- if (match ("{"))
- compound (NO);
- else
- stst ();
- return (lastst);
-}
-
-/*
- * declaration
- */
-stdecl ()
-{
- if (amatch("register", 8))
- doldcls(DEFAUTO);
- else if (amatch("auto", 4))
- doldcls(DEFAUTO);
- else if (amatch("static", 6))
- doldcls(LSTATIC);
- else if (doldcls(AUTO)) ;
- else
- return (NO);
- return (YES);
-}
-
-doldcls(stclass)
-int stclass;
-{
- blanks();
- if (amatch("char", 4))
- declloc(CCHAR, stclass);
- else if (amatch("int", 3))
- declloc(CINT, stclass);
- else if (stclass == LSTATIC || stclass == DEFAUTO)
- declloc(CINT, stclass);
- else
- return(0);
- ns();
- return(1);
-}
-
-
-/*
- * non-declaration statement
- */
-stst ()
-{
- if (amatch ("if", 2)) {
- doif ();
- lastst = STIF;
- } else if (amatch ("while", 5)) {
- dowhile ();
- lastst = STWHILE;
- } else if (amatch ("switch", 6)) {
- doswitch ();
- lastst = STSWITCH;
- } else if (amatch ("do", 2)) {
- dodo ();
- ns ();
- lastst = STDO;
- } else if (amatch ("for", 3)) {
- dofor ();
- lastst = STFOR;
- } else if (amatch ("return", 6)) {
- doreturn ();
- ns ();
- lastst = STRETURN;
- } else if (amatch ("break", 5)) {
- dobreak ();
- ns ();
- lastst = STBREAK;
- } else if (amatch ("continue", 8)) {
- docont ();
- ns ();
- lastst = STCONT;
- } else if (match (";"))
- ;
- else if (amatch ("case", 4)) {
- docase ();
- lastst = statement (NO);
- } else if (amatch ("default", 7)) {
- dodefault ();
- lastst = statement (NO);
- } else if (match ("#asm")) {
- doasm ();
- lastst = STASM;
- } else if (match ("{"))
- compound (NO);
- else {
- expression (YES);
-/* if (match (":")) {
- dolabel ();
- lastst = statement (NO);
- } else {
-*/ ns ();
- lastst = STEXP;
-/* }
-*/ }
- return 0;
-}
-
-/*
- * compound statement
- *
- * allow any number of statements to fall between "{" and "}"
- *
- * 'func' is true if we are in a "function_statement", which
- * must contain "statement_list"
- */
-compound (func)
-int func;
-{
- int decls;
-
- decls = YES;
- ncmp++;
- while (!match ("}")) {
- if (feof (input))
- return 0;
- if (decls) {
- if (!stdecl ())
- decls = NO;
- } else
- stst ();
- }
- ncmp--;
- return 0;
-}
-
-/*
- * "if" statement
- */
-doif ()
-{
- int fstkp, flab1, flab2;
- char *flev;
-
- flev = locptr;
- fstkp = stkp;
- flab1 = getlabel ();
- test (flab1, FALSE);
- statement (NO);
- stkp = modstk (fstkp);
- locptr = flev;
- if (!amatch ("else", 4)) {
- gnlabel (flab1);
- return 0;
- }
- jump (flab2 = getlabel ());
- gnlabel (flab1);
- statement (NO);
- stkp = modstk (fstkp);
- locptr = flev;
- gnlabel (flab2);
- return 0;
-}
-
-/*
- * "while" statement
- */
-dowhile ()
-{
- int ws[7];
-
- ws[WSSYM] = locptr;
- ws[WSSP] = stkp;
- ws[WSTYP] = WSWHILE;
- ws[WSTEST] = getlabel ();
- ws[WSEXIT] = getlabel ();
- addwhile (ws);
- gnlabel (ws[WSTEST]);
- test (ws[WSEXIT], FALSE);
- statement (NO);
- jump (ws[WSTEST]);
- gnlabel (ws[WSEXIT]);
- locptr = ws[WSSYM];
- stkp = modstk (ws[WSSP]);
- delwhile ();
- return 0;
-}
-
-/*
- * "do" statement
- */
-dodo ()
-{
- int ws[7];
-
- ws[WSSYM] = locptr;
- ws[WSSP] = stkp;
- ws[WSTYP] = WSDO;
- ws[WSBODY] = getlabel ();
- ws[WSTEST] = getlabel ();
- ws[WSEXIT] = getlabel ();
- addwhile (ws);
- gnlabel (ws[WSBODY]);
- statement (NO);
- if (!match ("while")) {
- error ("missing while");
- return 0;
- }
- gnlabel (ws[WSTEST]);
- test (ws[WSBODY], TRUE);
- gnlabel (ws[WSEXIT]);
- locptr = ws[WSSYM];
- stkp = modstk (ws[WSSP]);
- delwhile ();
- return 0;
-}
-
-/*
- * "for" statement
- */
-dofor ()
-{
- int ws[7],
- *pws;
-
- ws[WSSYM] = locptr;
- ws[WSSP] = stkp;
- ws[WSTYP] = WSFOR;
- ws[WSTEST] = getlabel ();
- ws[WSINCR] = getlabel ();
- ws[WSBODY] = getlabel ();
- ws[WSEXIT] = getlabel ();
- addwhile (ws);
- pws = readwhile ();
- needbrack ("(");
- if (!match (";")) {
- expression (YES);
- ns ();
- }
- gnlabel (pws[WSTEST]);
- if (!match (";")) {
- expression (YES);
- testjump (pws[WSBODY], TRUE);
- jump (pws[WSEXIT]);
- ns ();
- } else
- pws[WSTEST] = pws[WSBODY];
- gnlabel (pws[WSINCR]);
- if (!match (")")) {
- expression (YES);
- needbrack (")");
- jump (pws[WSTEST]);
- } else
- pws[WSINCR] = pws[WSTEST];
- gnlabel (pws[WSBODY]);
- statement (NO);
- jump (pws[WSINCR]);
- gnlabel (pws[WSEXIT]);
- locptr = pws[WSSYM];
- stkp = modstk (pws[WSSP]);
- delwhile ();
- return 0;
-}
-
-/*
- * "switch" statement
- */
-doswitch ()
-{
- int ws[7];
- int *ptr;
-
- ws[WSSYM] = locptr;
- ws[WSSP] = stkp;
- ws[WSTYP] = WSSWITCH;
- ws[WSCASEP] = swstp;
- ws[WSTAB] = getlabel ();
- ws[WSDEF] = ws[WSEXIT] = getlabel ();
- addwhile (ws);
-// immed ();
-// printlabel (ws[WSTAB]);
-// nl ();
-// gpush ();
- needbrack ("(");
- expression (YES);
- needbrack (")");
-// stkp = stkp + intsize(); /* '?case' will adjust the stack */
- gjcase ();
- jump (ws[WSTAB]);
- statement (NO);
- ptr = readswitch ();
-// if (ptr[WSDEF]!=ptr[WSEXIT]) jump (ptr[WSDEF]);
- jump (ptr[WSEXIT]);
- dumpsw (ptr);
- gnlabel (ptr[WSEXIT]);
- locptr = ptr[WSSYM];
-// stkp = modstk (ptr[WSSP]);
- swstp = ptr[WSCASEP];
- delwhile ();
- return 0;
-}
-
-/*
- * "case" label
- */
-docase ()
-{
- int val;
-
- val = 0;
- if (readswitch ()) {
- if (!number (&val))
- if (!pstr (&val))
- error ("bad case label");
- addcase (val);
- if (!match (":"))
- error ("missing colon");
- } else
- error ("no active switch");
- return 0;
-}
-
-/*
- * "default" label
- */
-dodefault ()
-{
- int *ptr,
- lab;
-
- if (ptr = readswitch ()) {
- ptr[WSDEF] = lab = getlabel ();
- gnlabel (lab);
- if (!match (":"))
- error ("missing colon");
- } else
- error ("no active switch");
- return 0;
-}
-
-/*
- * "return" statement
- */
-doreturn ()
-{
- if (endst () == 0)
- expression (YES);
- jump(fexitlab);
- return 0;
-}
-
-/*
- * "break" statement
- */
-dobreak ()
-{
- int *ptr;
-
- if ((ptr = readwhile ()) == 0)
- return 0;
- modstk (ptr[WSSP]);
- jump (ptr[WSEXIT]);
- return 0;
-}
-
-/*
- * "continue" statement
- */
-docont ()
-{
- int *ptr;
-
- if ((ptr = findwhile ()) == 0)
- return 0;
-/* modstk (ptr[WSSP]); */
- if (ptr[WSTYP] == WSFOR)
- jump (ptr[WSINCR]);
- else
- jump (ptr[WSTEST]);
- return 0;
-}
-
-/*
- * dump switch table
- */
-dumpsw (ws)
-int ws[];
-{
- int i,j;
-
- gdata ();
- gnlabel (ws[WSTAB]);
- if (ws[WSCASEP] != swstp) {
- j = ws[WSCASEP];
- while (j < swstp) {
- i = 4;
- while (i--) {
- immd3();
- onum (swstcase[j]);
- nl();
- casejump();
- jump (swstlab[j++]);
- if ((i == 0) | (j >= swstp)) {
- nl ();
- break;
- }
- nl();
- }
- }
- jump(ws[WSDEF]);
- }
- gtext ();
- return 0;
-}
DELETED src/cc8/cross/sym.c
Index: src/cc8/cross/sym.c
==================================================================
--- src/cc8/cross/sym.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* File sym.c: 2.1 (83/03/20,16:02:19) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-/*
- * declare a static variable
- */
-declglb (typ, stor)
-int typ,
- stor;
-{
- int k, j;
- char sname[NAMESIZE];
-
- FOREVER {
- FOREVER {
- if (endst ())
- return 0;
- k = 1;
- if (match ("*"))
- j = POINTER;
- else
- j = VARIABLE;
- if (!symname (sname))
- illname ();
- if (findglb (sname))
- multidef (sname);
- if (match ("[")) {
- k = needsub ();
- if (k || stor == EXTERN)
- j = ARRAY;
- else
- j = POINTER;
- }
- addglb (sname, j, typ, k, stor);
- break;
- }
- if (!match (","))
- return 0;
- }
-}
-
-/*
- * declare local variables
- *
- * works just like "declglb", but modifies machine stack and adds
- * symbol table entry with appropriate stack offset to find it again
- */
-declloc (typ, stclass)
-int typ, stclass;
-{
- int k, j;
- char sname[NAMESIZE];
-
- FOREVER {
- FOREVER {
- if (endst ())
- return 0;
- if (match ("*"))
- j = POINTER;
- else
- j = VARIABLE;
- if (!symname (sname))
- illname ();
- if (findloc (sname))
- multidef (sname);
- if (match ("[")) {
- k = needsub ();
- if (k) {
- j = ARRAY;
- if (typ == CINT)
- k = k * intsize();
- } else {
- j = POINTER;
- k = intsize();
- }
- } else
- if ((typ == CCHAR) & (j != POINTER))
- k = 1;
- else
- k = intsize();
- if (stclass != LSTATIC) {
- k = galign(k);
- stkp = modstk (stkp - k);
- addloc (sname, j, typ, stkp+k-1, AUTO); /* Reversed stack for PDP8 */
- } else
- addloc( sname, j, typ, k, LSTATIC);
- break;
- }
- if (!match (","))
- return 0;
- }
-}
-
-/*
- * get required array size
- */
-needsub ()
-{
- int num[1];
-
- if (match ("]"))
- return (0);
- if (!number (num)) {
- error ("must be constant");
- num[0] = 1;
- }
- if (num[0] < 0) {
- error ("negative size illegal");
- num[0] = (-num[0]);
- }
- needbrack ("]");
- return (num[0]);
-}
-
-findglb (sname)
-char *sname;
-{
- char *ptr;
-
- ptr = STARTGLB;
- while (ptr != glbptr) {
- if (astreq (sname, ptr, NAMEMAX))
- return (ptr);
- ptr = ptr + SYMSIZ;
- }
- return (0);
-}
-
-findloc (sname)
-char *sname;
-{
- char *ptr;
-
- ptr = locptr;
- while (ptr != STARTLOC) {
- ptr = ptr - SYMSIZ;
- if (astreq (sname, ptr, NAMEMAX))
- return (ptr);
- }
- return (0);
-}
-
-addglb (sname, id, typ, value, stor)
-char *sname, id, typ;
-int value,
- stor;
-{
- char *ptr;
-
- if (cptr = findglb (sname))
- return (cptr);
- if (glbptr >= ENDGLB) {
- error ("global symbol table overflow");
- return (0);
- }
- cptr = ptr = glbptr;
- while (an (*ptr++ = *sname++));
- cptr[IDENT] = id;
- cptr[TYPE] = typ;
- cptr[STORAGE] = stor;
- cptr[OFFSET] = gsize & 0xff;
- cptr[OFFSET+1] = (gsize >> 8) & 0xff;
- gsize = gsize + value;
- glbptr = glbptr + SYMSIZ;
- return (cptr);
-}
-
-addloc (sname, id, typ, value, stclass)
-char *sname, id, typ;
-int value, stclass;
-{
- char *ptr;
- int k;
-
- if (cptr = findloc (sname))
- return (cptr);
- if (locptr >= ENDLOC) {
- error ("local symbol table overflow");
- return (0);
- }
- cptr = ptr = locptr;
- while (an (*ptr++ = *sname++));
- cptr[IDENT] = id;
- cptr[TYPE] = typ;
- cptr[STORAGE] = stclass;
- if (stclass == LSTATIC) {
- gdata();
- printlabel(k = getlabel());
- col();
- defstorage();
- onum(value);
- nl();
- gtext();
- value = k;
- } else
- value = galign(value);
- cptr[OFFSET] = value & 0xff;
- cptr[OFFSET+1] = (value >> 8) & 0xff;
- locptr = locptr + SYMSIZ;
- return (cptr);
-}
-
-/*
- * test if next input string is legal symbol name
- *
- */
-symname (sname)
-char *sname;
-{
- int k;
- char c;
-
- blanks ();
- if (!alpha (ch ()))
- return (0);
- k = 0;
- while (an (ch ()))
- sname[k++] = gch ();
- sname[k] = 0;
- return (1);
-}
-
-illname ()
-{
- error ("illegal symbol name");
- return 0;
-}
-
-multidef (sname)
-char *sname;
-{
- error ("already defined");
- comment ();
- outstr (sname);
- nl ();
- return 0;
-}
-
-glint(syment) char *syment; {
- short l,u,r;
- l = syment[OFFSET];
- u = syment[OFFSET+1];
- r = (l & 0xff) + ((u << 8) & ~0x00ff);
- return (r);
-}
DELETED src/cc8/cross/while.c
Index: src/cc8/cross/while.c
==================================================================
--- src/cc8/cross/while.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* File while.c: 2.1 (83/03/20,16:02:22) */
-/*% cc -O -c %
- *
- */
-
-#include
-#include "defs.h"
-#include "data.h"
-
-addwhile (ptr)
-int ptr[];
-{
- int k;
-
- if (wsptr == WSMAX) {
- error ("too many active whiles");
- return 0;
- }
- k = 0;
- while (k < WSSIZ)
- *wsptr++ = ptr[k++];
- return 0;
-}
-
-delwhile ()
-{
- if (readwhile ())
- wsptr = wsptr - WSSIZ;
- return 0;
-}
-
-int readwhile ()
-{
- if (wsptr == ws) {
- error ("no active do/for/while/switch");
- return (0);
- } else
- return (wsptr-WSSIZ);
-}
-
-int *findwhile ()
-{
- int *ptr;
-
- for (ptr = wsptr; ptr != ws;) {
- ptr = ptr - WSSIZ;
- if (ptr[WSTYP] != WSSWITCH)
- return (ptr);
- }
- error ("no active do/for/while");
- return (0);
-}
-
-int *readswitch ()
-{
- int *ptr;
-
- if (ptr = (int *)readwhile ())
- if (ptr[WSTYP] == WSSWITCH)
- return (ptr);
- return (0);
-}
-
-addcase (val)
-int val;
-{
- int lab;
-
- if (swstp == SWSTSZ)
- error ("too many case labels");
- else {
- swstcase[swstp] = val;
- swstlab[swstp++] = lab = getlabel ();
- printlabel (lab);
- col ();
- nl ();
- }
- return 0;
-}
DELETED src/cc8/examples/README.md
Index: src/cc8/examples/README.md
==================================================================
--- src/cc8/examples/README.md
+++ /dev/null
@@ -1,104 +0,0 @@
-# Using the Examples
-
-This directory contains several example programs. We will use the
-`calc.c` example throughout this section.
-
-The program may be compiled using the cc8 cross-compiler to SABR sources
-like so:
-
- $ cc8 calc.c
-
-You can then use the `txt2ptp` program to turn the resulting `calc.s`
-file into a paper tape to be loaded into OS/8:
-
- $ txt2ptp < calc.s > calc.pt
- $ pidp8i ⇠ ...start PDP-8 sim somehow, then hit Ctrl-E
- sim> att -r dt0 calc.pt
- sim> cont
- .R PIP
- *CALC.SBEnter key starts the transfer in the final command. The
-transfer stops when `PIP` sees the Ctrl-Z EOF marker added to
-the end of the paper tape by `txt2ptp`. The first Escape
-finalizes the transfer and the second exits PIP, returning you to the
-OS/8 command prompt.
-
-See the [assembly examples' `README.md` file][aerm] or the [U/W FOCAL
-manual supplement][uwfs] for more ideas on how to get text files like
-this SABR file into OS/8.
-
-However you manage it, you can then assemble, load, and run the programs
-on the OS/8 side with:
-
- .COMP CALC.SB
- .R LOADER
- *CALC,LIBC/G ⇠ press Esc to execute command and exit LOADER
-
-The `/G` flag causes the loader to run the linked program immediately,
-but once you're done modifying the program, you probably want to save it
-as a core image so it can be run directly instead of being linked and
-loaded again each time. You can give `/M` instead, which finalizes the
-link and then exits, printing a map file before it does so. You can then
-save the result where the OS/8 `R` command can find it with:
-
- .SAVE SYS:CALC
-
-That produces `SYS:CALC.SV`, which an `R CALC` command will load and
-run.
-
-If you wish to compile from C source code on the OS/8 side rather than
-cross-compile, I recommend using the `CC0` front-end rather than the
-method shown in the [top level `README.md` file][tlrm] involving the
-`CC1` stage:
-
- .R CC0
-
- >calc.cc
-
- .COMP CC.SB
-
- .R LOADER
- *CC,LIBC/M
-
-Notice that the front-end processor produces `CC.SB`, not `CALC.SB` as
-you might be expecting. This is where the `CC` comes from in the `COMP`
-and `LOADER` commands.
-
-Note that `CC0` tolerates lowercase input.
-
-
-[aerm]: /doc/trunk/examples/README.md
-[tlrm]: /doc/trunk/src/cc8/README.md
-[uwfs]: /doc/trunk/doc/uwfocal-manual-supp.md
-
-
-# The Examples
-
-In order of complexity, they are:
-
-## calc.c
-
-This is a simple 4-function calculator.
-
-
-## ps.c
-
-This prints several levels of [Pascal's triangle][pt].
-
-[pt]: https://en.wikipedia.org/wiki/Pascal%27s_triangle
-
-
-## fib.c
-
-This program calculates [Fibonacci humbers][fn], which implicitly
-demonstrates the C compiler's ability to handle [recursion][rec].
-
-[fn]: https://en.wikipedia.org/wiki/Fibonacci_number
-[rec]: https://en.wikipedia.org/wiki/Recursion_(computer_science)
-
-
-## basic.c
-
-A very simple BASIC interpreter. This program tests a broad swath of the
-compiler's functionality.
DELETED src/cc8/examples/basic.c
Index: src/cc8/examples/basic.c
==================================================================
--- src/cc8/examples/basic.c
+++ /dev/null
@@ -1,245 +0,0 @@
-#include
-#include
-
-
-#define SMAX 10
-#define CMAX 256
-#define BMAX 64
-#define LMAX 32
-#define DMAX 32
-#define CBMX 1024
-#define LXMX 999
-
-
-int E [SMAX]; /* subroutine line number stack */
-int L [CMAX]; /* FOR loop beginning line number */
-int M [CMAX]; /* FOR loop maximum index value */
-int P [CMAX]; /* program variable value */
-char Lb[CBMX]; /* Line buffer of CBMX chars */
-int l,i,j;
-int *C; /* subroutine stack pointer */
-char B [BMAX]; /* command input buffer */
-char F [2]; /* temporary search string */
-char *m [LXMX]; /* pointers to lines of program. This is a real waste of space! */
-char *p,*q,*x,*y,*z,*s,*d;
-
-
-
-G( ) { /* get program line from buffer */
- atoi(B,&l);
- y=m[l];
- if(y){
- if(strstr(B," "))
- strcpy(y,B);
- else
- y=m[l]=0;
- return;
- }
- y=Lb;
- while(*y)
- y=y+DMAX;
- strcpy(y,B);
- m [l]=y;
-} /* end G */
-
-/* recursive descent parser for arithmetic/logical expressions */
-S( ) {
- int o;
-
- o=J( );
- switch(*p++){
- case '=': return o==S( );
- break;
- case '#': return o!=S( );
- default: p--; return o;
- }
-} /* end S */
-
-J( ) {
- int o;
-
- o=K( );
- switch(*p++){
- case '<': return o': return o>J( );
- default: p--; return o;
- }
-} /* end J */
-
-K( ) {
- int o;
-
- o=V( );
- switch(*p++){
- case '$': return o<=K( );
- break;
- case '!': return o>=K( );
- default: p--; return o;
- }
-} /* end K */
-
-V( ) {
- int o;
-
- o=W( );
- switch(*p++){
- case '+': return o+V( );
- break;
- case '-': return o-V( );
- default: p--; return o;
- }
-} /* end V */
-
-W( ) {
- int o;
-
- o=Y( );
- switch(*p++){
- case '*': return o*W( );
- break;
- case '/': return o/W( );
- default: p--; return o;
- }
-} /* end W */
-
-Y( ) {
- int o;
-
- if(*p=='-'){
- p++;
- return -Y();
- }
- q=p;
- if(*p>='0'&&*p<='9'){
- while(*p>='0'&&*p<='9')
- p++;
- atoi(q,&o);
- return o;
- }
- if(*p=='('){
- p++; o=S( ); p++;
- return o;
- }
- return P [*p++];
-} /* end Y */
-
-bufclear()
-{
- memset(m,0,LXMX);
- memset(Lb,0,CBMX);
-}
-
-main( ) {
- int tmp; /* temp var to fix bug 07Sep2005 Somos */
-
- bufclear();
- while(puts("Ok\r\n"),gets(B))
- switch(*B){
- case 'R': /* "RUN" command */
- C=E;
- l=1;
- for(i=0; i" ) ) ) * p ++ = '#' , * p = ' ' ;
- while ( ( p = strstr ( s , "<=" ) ) ) * p ++ = '$' , * p = ' ' ;
- while ( ( p = strstr ( s , ">=" ) ) ) * p ++ = '!' , * p = ' ' ;
- }
- d=B;
- j=0;
- while(*s){
- if(*s=='"') j++;
- if(*s!=' '||(j&1)) *d++=*s;
- s++;
- }
- *d=j=0;
- d--; /* backup to last char in line */
- if(B [1]!='='){
- switch(*B){
- case 'E': /* "END" */
- l=-1;
- break;
- case 'R': /* "REM" */
- if(B [2]!='M') l=*--C; /* "RETURN" */
- break;
- case 'I':
- if(B [1]=='N'){ /* "INPUT" */
- tmp=*d; /* save for bug fix next line 07Sep2005 Somos */
- gets(p=B); P [tmp]=S( );
- } else { /* "IF" */
- *(tmp=strstr(B,"TH"))=0; /* "THEN" */
- p=B+2;
- if(S( )){
- p=tmp+4; l=S( )-1;
- }
- }
- break;
- case 'P': /* "PRINT" */
- tmp=',';
- p=B+5;
- while(tmp==','){
- if(*p=='"'){
- while(*++p!='"')
- putc(*p);
- p++;
- } else {
- printf("%d",S( ));
- }
- tmp=*p++;
- putc(' ');
- }
- puts("\r\n");
- break;
- case 'G': /* "GOTO" */
- p=B+4;
- if(B [2]=='S'){ /* "GOSUB" */
- *C++=l; p++;
- }
- l=S( )-1;
- break;
- case 'F': /* "FOR" */
- *(tmp=strstr(B,"TO"))=0; /* "TO" */
- p=B+5;
- P [i=B [3]]=S( );
- p=tmp+2;
- M [i]=S( );
- L [i]=l;
- break;
- case 'N': /* "NEXT" */
- tmp=*d;
- if(P [tmp] 'Z') ans = ans - 32;
-
- /* You might be tempted to write "if (ans != 'Y') break;" and
- * then do away with one indent level for the main body of code
- * that follows, but CC8 doesn't know the != operator yet. */
- if (ans == 'Y') {
- printf("\r\nENTER ANY TWO NUMBERS.\r\n");
-
- printf("ENTER THE FIRST NUMBER: ");
- gets(bfr);
- sscanf(bfr, "%d", &x);
-
- printf("ENTER THE SECOND NUMBER: ");
- gets(bfr);
- sscanf(bfr, "%d", &y);
-
- printf("SELECT THE OPERATION:\r\n");
-
- printf("1: ADDITION\r\n");
- printf("2: SUBTRACTION\r\n");
- printf("3: MULTIPLICATION\r\n");
- printf("4: DIVISION\r\n");
-
- printf("CHOICE: ");
- gets(bfr);
- sscanf(bfr, "%d", &choice);
-
- if (choice == 1) printf("Result: %d\r\n", x + y);
- if (choice == 2) printf("Result: %d\r\n", x - y);
- if (choice == 3) printf("Result: %d\r\n", x * y);
- if (choice == 4) printf("Result: %d\r\n", x / y);
-
- printf("DO YOU WISH TO CONTINUE (Y/N): ");
- ans = getc();
- }
- else {
- break;
- }
- }
-}
DELETED src/cc8/examples/fib.c
Index: src/cc8/examples/fib.c
==================================================================
--- src/cc8/examples/fib.c
+++ /dev/null
@@ -1,15 +0,0 @@
-int fib(n)
-{
- if (n < 2)
- return n;
- else
- return fib(n-1)+fib(n-2);
-}
-
-
-int main()
-{
- int i;
- for (i=0;i<10;i++)
- printf("Fib#:%d = %d\r\n", i, fib(i));
-}
DELETED src/cc8/examples/init.pa
Index: src/cc8/examples/init.pa
==================================================================
--- src/cc8/examples/init.pa
+++ /dev/null
@@ -1,1 +0,0 @@
-../include/init.pa
DELETED src/cc8/examples/libc.h
Index: src/cc8/examples/libc.h
==================================================================
--- src/cc8/examples/libc.h
+++ /dev/null
@@ -1,1 +0,0 @@
-../include/libc.h
DELETED src/cc8/examples/ps.c
Index: src/cc8/examples/ps.c
==================================================================
--- src/cc8/examples/ps.c
+++ /dev/null
@@ -1,16 +0,0 @@
-int main()
-{
- int ar[20],i,j,n;
-
- n=14;
- for (i=1;i1;j--)
- ar[j]=ar[j-1]+ar[j];
- for (j=0;j<2*(n-i-1);j++)
- putc(' ');
- for (j=1;j.
- */
-
-#asm
-/
-/ PDP8/E Run time routines for Small c compiler
-/
-ABSYM POP 160
-ABSYM PSH 161
-ABSYM JLC 162
-ABSYM STKP 163
-ABSYM PTSK 164
-ABSYM POPR 165
-ABSYM PCAL 166
-ABSYM TMP 167
-ABSYM GBL 170
-ABSYM ZTMP 171
-/
- DECIM
-/
-STK, COMMN 3840
-/
-/
-/
- ENTRY MAIN
-MAIN, BLOCK 2
- TAD GBLS
- DCA STKP
- TAD GBLS
- DCA GBL
- ISZ GBL / LOCAL LITERALS = STKP+1
- TAD PVL
- DCA PSH
- TAD OVL
- DCA POP
- TAD MVL
- DCA PTSK
- TAD PVR
- DCA POPR
- TAD PVC
- DCA PCAL
- RIF
- TAD (3201
- DCA PCL1
- TAD PCL1
- DCA DCC0
- JMS MCC0
- CLA CMA
- MQL
- CALL 1,LIBC
- ARG STKP
- CALL 0,OPEN
- JMSI PCAL
- XMAIN
- CALL 0,EXIT
-/
-PUSH, 0
- CDF1
- ISZ STKP
- DCAI STKP
- TADI STKP
- JMPI PUSH
-PPOP, 0
- CDF1
- DCA TMP
- TADI STKP
- MQL
- CMA
- TAD STKP
- DCA STKP
- TAD TMP
- JMPI PPOP
-PUTSTK, 0
- JMSI POP
- SWP
- DCA JLC
- SWP
- DCAI JLC
- TADI JLC
- JMPI PUTSTK
-POPRET, JMSI POP
- SWP
- DCA ZTMP
- SWP
- JMPI ZTMP
-PCALL, 0
- CLA CLL
-PCL1, 0
- TADI PCALL
- DCA ZTMP
- TAD PCALL
- IAC
- JMSI PSH / PUSH RETURN
- CLA
- JMPI ZTMP
-PVL, PUSH
-OVL, PPOP
-MVL, PUTSTK
-SVL, STK
-PVR, POPRET
-PVC, PCALL
-/
-#endasm
DELETED src/cc8/include/libc.h
Index: src/cc8/include/libc.h
==================================================================
--- src/cc8/include/libc.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the CC8 cross-compiler.
- *
- * The CC8 cross-compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 cross-compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 cross-compiler as ../GPL3.txt. If not, see
- * .
- */
-
-/*
- * Libc header
- *
- * Please note: no function declarations are made, so make sure the
- * arg lists are correct in the calling code.
- *
-*/
-
-#define itoa libc0
-#define puts libc1
-#define nl libc2
-#define getc libc3
-#define gets libc4
-#define atoi libc5
-#define sscanf vlibc6
-#define xinit libc7
-#define memcpy libc8
-#define kbhit libc9
-#define putc libc10
-#define strcpy libc11
-#define strcat libc12
-#define strstr libc13
-#define exit libc14
-#define isnum libc15
-#define isdigit libc15
-#define isalpha libc16
-#define sprintf vlibc17
-#define memset libc18
-#define fgetc libc19
-#define fopen libc20
-#define fputc libc21
-#define fclose libc22
-#define printf vlibc23
-#define isalnum libc24
-#define isspace libc25
-#define fprintf vlibc26
-#define fputs libc27
-#define strcmp libc28
-#define cupper libc29
-#define fgets libc30
DELETED src/cc8/os8/Makefile.in
Index: src/cc8/os8/Makefile.in
==================================================================
--- src/cc8/os8/Makefile.in
+++ /dev/null
@@ -1,46 +0,0 @@
-########################################################################
-# Makefile.in - Processed by autosetup's configure script to generate
-# an intermediate GNU make(1) file for building the PiDP-8/I software
-# from within its src/cc8/os8 subdirectory.
-#
-# The resulting Makefile will redirect simple "make" calls to the top
-# level as well as the major top-level targets (e.g. "make clean") but
-# purposefully will not redirect anything like an installation or "run
-# the system" type target. Its only purpose is to help out those who
-# are working on CC8 from within this directory. If you need to work
-# on the wider system, do it from the project's top level.
-#
-# If you are seeing this at the top of a file called Makefile and you
-# intend to make edits, do that in Makefile.in. Saying "make" will then
-# re-build Makefile from that modified Makefile.in before proceeding to
-# do the "make" operation.
-#
-# Copyright © 2017 Warren Young
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-all clean ctags distclean tags reconfig:
- cd @builddir@; make $@
DELETED src/cc8/os8/bldcc8.bi
Index: src/cc8/os8/bldcc8.bi
==================================================================
--- src/cc8/os8/bldcc8.bi
+++ /dev/null
@@ -1,15 +0,0 @@
-$JOB BUILD C COMPILER AND LIBRARY
-.COMP C8.SB
-.COMP P8.SB
-.COMP N8.SB
-.COMP LIBC.SB
-.R LOADER
-*P8,LIBC/I/O$
-.SAVE SYS CC2
-.R LOADER
-*C8,LIBC/I/O$
-.SAVE SYS CC0
-.R LOADER
-*N8,LIBC/I/O$
-.SAVE SYS CC1
-$END
DELETED src/cc8/os8/c8.c
Index: src/cc8/os8/c8.c
==================================================================
--- src/cc8/os8/c8.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * This file is part of the CC8 OS/8 C compiler.
- *
- * The CC8 OS/8 C compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 OS/8 C compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 OS/8 C compiler as ../GPL3.txt. If not, see
- * .
- */
-
-#include
-#include
-
-/* C pre-processor stub for PDP/8 c compiler 2017 */
-/* Ask for input file, copy to CC.CC and run CC1 */
-
-
-main()
-{
- int bfr;
- int fnm[10];
-
- putc('>');
- gets(fnm);
- cupper(fnm);
- fopen(fnm,"r");
- fopen("CC.CC","w");
- while (bfr=fgetc())
- if (bfr!=12) /* Ignore form feed */
- fputc(bfr);
- fclose();
-#asm
- CALL 1,CHAIN
- ARG FNM
- HLT
-FNM, TEXT "CC1@@@"
-#endasm
-
-
-}
DELETED src/cc8/os8/header.sb
Index: src/cc8/os8/header.sb
==================================================================
--- src/cc8/os8/header.sb
+++ /dev/null
@@ -1,135 +0,0 @@
-//
-// This file is part of the CC8 OS/8 C compiler.
-//
-// The CC8 OS/8 C compiler is free software: you can redistribute it
-// and/or modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// The CC8 OS/8 C compiler is distributed in the hope that it will be
-// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with the CC8 OS/8 C compiler as ../GPL3.txt. If not, see
-// .
-//
-
-/ SABR DEFINITIONS
-/ FRONT END (2.0:1/4/2017)
-
-OPDEF ANDI 0400
-OPDEF TADI 1400
-OPDEF ISZI 2400
-OPDEF DCAI 3400
-OPDEF JMSI 4400
-OPDEF JMPI 5400
-OPDEF MQL 7421
-OPDEF MQA 7701
-OPDEF MQO 7501
-OPDEF SWP 7521
-OPDEF CDF1 6211
-OPDEF CDF0 6201
-OPDEF RIF 6224
-OPDEF CAF0 6203
-OPDEF BSW 7002
-OPDEF CAM 7621
-/
-/ PDP8/E Run time routines for Small c compiler
-/
-ABSYM POP 160
-ABSYM PSH 161
-ABSYM JLC 162
-ABSYM STKP 163
-ABSYM PTSK 164
-ABSYM POPR 165
-ABSYM PCAL 166
-ABSYM TMP 167
-ABSYM GBL 170
-ABSYM ZTMP 171
-/
- DECIM
-/
-STK, COMMN 3840
-/
-/
-/
- ENTRY MAIN
-MAIN, BLOCK 2
- TAD GBLS
- DCA STKP
- TAD GBLS
- DCA GBL
- ISZ GBL / LOCAL LITERALS = STKP+1
- TAD PVL
- DCA PSH
- TAD OVL
- DCA POP
- TAD MVL
- DCA PTSK
- TAD PVR
- DCA POPR
- TAD PVC
- DCA PCAL
- RIF
- TAD (3201
- DCA PCL1
- TAD PCL1
- DCA DCC0
- JMS MCC0
- CLA CMA
- MQL
- CALL 1,LIBC
- ARG STKP
- CALL 0,OPEN
- JMSI PCAL
- XMAIN
- CALL 0,EXIT
-/
-PUSH, 0
- CDF1
- ISZ STKP
- DCAI STKP
- TADI STKP
- JMPI PUSH
-PPOP, 0
- CDF1
- DCA TMP
- TADI STKP
- MQL
- CMA
- TAD STKP
- DCA STKP
- TAD TMP
- JMPI PPOP
-PUTSTK, 0
- JMSI POP
- SWP
- DCA JLC
- SWP
- DCAI JLC
- TADI JLC
- JMPI PUTSTK
-POPRET, JMSI POP
- SWP
- DCA ZTMP
- SWP
- JMPI ZTMP
-PCALL, 0
- CLA CLL
-PCL1, 0
- TADI PCALL
- DCA ZTMP
- TAD PCALL
- IAC
- JMSI PSH / PUSH RETURN
- CLA
- JMPI ZTMP
-PVL, PUSH
-OVL, PPOP
-MVL, PUTSTK
-SVL, STK
-PVR, POPRET
-PVC, PCALL
-/
DELETED src/cc8/os8/init.pa
Index: src/cc8/os8/init.pa
==================================================================
--- src/cc8/os8/init.pa
+++ /dev/null
@@ -1,1 +0,0 @@
-../include/init.pa
DELETED src/cc8/os8/libc.c
Index: src/cc8/os8/libc.c
==================================================================
--- src/cc8/os8/libc.c
+++ /dev/null
@@ -1,985 +0,0 @@
-/*
- * This file is part of the CC8 OS/8 C compiler.
- *
- * The CC8 OS/8 C compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 OS/8 C compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 OS/8 C compiler as ../GPL3.txt. If not, see
- * .
- */
-
-/*
- * PDP8/E LIBC routines for Small-C compiler.
- *
- * THIS IS A COMPLEX COLLECTION OF MIXED C AND ASSEMBLY ROUTINES.
- * SOME FUNCTIONS HAVE BEEN SUBSTANTIALLY SHORTENED TO SAVE SPACE.
- * EVENTUALLY, MOST WILL NEED TO BE WRITTEN IN ASSEMBLY AND HAND
- * OPTIMISED; E.G. ATOI.
- */
-
-#asm
-ABSYM POP 147
-ABSYM PSH 150
-ABSYM JLC 151
-ABSYM STKP 152
-ABSYM PTSK 153
-ABSYM POPR 154
-ABSYM PCAL 155
-ABSYM TMP 156
-ABSYM GBL 157
-ABSYM ZTMP 146
-ABSYM ZPTR 145
-ABSYM ZCTR 144
-ABSYM FPTR 160
-/
- DECIM
-/
-/
-/
-/
- DUMMY ARGST
- DUMMY ARGNM
-ARGST, BLOCK 2
-ARGNM, BLOCK 2
-/
- ENTRY LIBC
-LIBC, BLOCK 2
- CLA CLL
- TAD I LIBC
- DCA ARGST
- INC LIBC#
- TAD I LIBC
- DCA ARGST#
- INC LIBC#
- TAD I ARGST
- DCA STKP
- IAC
- TAD LCALL / INIT ? LCALL==-1
- SZA CLA
- JMP LB1
- TAD STKP
- DCA GBL / SET LOCAL GBL(LITPTR)
- ISZ GBL
- TAD PVL
- DCA PSH
- TAD OVL
- DCA POP
- TAD MVL
- DCA PTSK
- TAD PVR
- DCA POPR
- TAD PVC
- DCA PCAL
- RIF
- TAD (3201
- DCA PCL1
- TAD PCL1
- DCA DCC0
- JMS MCC0
- TAD STKP
- DCA I ARGST / UPDATE MASTER STKP
- DCA ZPTR / INIT PRINTF FLAG
- DCA FPTR / INIT FPRINTF FLAG
-LB1, MQA / CALL INDEX IN MQ
- SPA
- JMP LRET
- TAD CPNT
- DCA LCALL
- TAD I LCALL
- DCA LCALL
- JMSI PCAL
-LCALL, -1
- RETRN LIBC
-LRET, CLA MQL
- DCA LCALL / INIT OK
- RETRN LIBC
-/
-PUSH, 0
- CDF1
- ISZ STKP
- DCAI STKP
- TADI STKP
- JMPI PUSH
-PPOP, 0
- CDF1
- DCA TMP
- TADI STKP
- MQL
- CMA
- TAD STKP
- DCA STKP
- TAD TMP
- JMPI PPOP
-PUTSTK, 0
- JMSI POP
- SWP
- DCA JLC
- SWP
- DCAI JLC
- TADI JLC
- JMPI PUTSTK
-POPRET, JMSI POP
- SWP
- DCA ZTMP
- TAD STKP
- DCA I ARGST / UPDATE MASTER STKP
- SWP
- CDF1
- JMPI ZTMP
-PCALL, 0
- CLA CLL
-PCL1, 0
- TADI PCALL
- DCA ZTMP
- TAD PCALL
- IAC
- JMSI PSH / PUSH RETURN
- CLA
- TAD STKP
- DCA I ARGST / UPDATE MASTER STKP
- CDF1
- JMPI ZTMP
-PVL, PUSH
-OVL, PPOP
-MVL, PUTSTK
-PVR, POPRET
-PVC, PCALL
-/
-CPNT, CLIST
- CPAGE 24
-/
-/ THIS IS THE DISPATCH LIST FOR THIS LIBRARY
-/ MAKE SURE LIBC.H MATCHES
-/
-CLIST, ITOA
- PUTS
- DISPXY
- GETC
- GETS
- ATOI
- SSCANF
- XINIT
- MEMCPY
- KBHIT
- PUTC
- STRCPY
- STRCAT
- STRSTR
- EXIT
- ISNUM
- ISALPHA
- SPRINTF
- MEMSET
- FGETC
- FOPEN
- FPUTC
- FCLOSE
- PRINTF
- ISALNUM
- ISSPACE
- FPRINTF
- FPUTS
- STRCMP
- CUPPER
- FGETS
-#endasm
-
-#define stdout 0
-#define NULL 0
-#define isdigit isnum
-
-
-
-fgetc()
-{
-#asm
-
- CLA CLL
- CALL 2,CHRIO
- ARG (-4
- ARG FRSL
- TAD FRSL
- TAD (-26 /^Z
- SNA CLA
- DCA FRSL
- TAD FRSL
- CDF1
- JMPI POPR
-FRSL,BLOCK 2
-
-// CHRIO - CHARACTER I/O.
-/
-/ CALL CHRIO(IDEVN,ICHAR)
-/
-/ IDEV = FORT II DEVICE NUMBER.
-/
-/ ICHAR = 7 OR 8 BIT CHARACTER.
-/
-/ IF IDEV IS POSITIVE, THE CHAR IS OUTPUTTED.
-/
-/ IF IDEV IS NEGATIVE, THE NEXT CHAR IS
-/ READ FROM THE DEVICE, AND PUT IN ICHAR.
-/
-//
- ENTRY CHRIO
-CHRIO, BLOCK 2
- JMS GETP
- SPA /WHAT IS DEVICE SIGN?
- JMP RCHAR /NEG DEV. MEANS READ.
- JMS SETDEV /POS DEV. MEANS WRITE.
- 0000
- JMS GETP
- DCA ICHAR
- JMS CHSUB
- JMP XIT
-
-IDEV, 0
-ICHAR, 0
-ADDR, 0
-
-RCHAR, CIA /READ A CHAR.
- JMS SETDEV
- 1024 /SET BIT FOR READ. (8 UNITS NOW!)
- JMS GETP
- CLA
- TAD CDFB
- DCA CDFCH
- JMS CHSUB
-CDFCH, HLT
- AND (127 / 7 BIT FOR NOW
- DCAI ADDR
-XIT, CLA
- RETRN CHRIO
-
-SETDEV, 0
- TAD (-1
- AND (7
- CLL RAR;RTR;RTR
- TAD I SETDEV
- INC SETDEV
- DCA IDEV
- JMP I SETDEV
-
-CHSUB, 0
- TAD ICHAR
- AND (255
- TAD IDEV
- CALL 0,GENIO
- JMP I CHSUB
-
-GETP, 0
- TAD CHRIO
- DCA CDFA
-CDFA, HLT
- TADI CHRIO#
- DCA CDFB
- INC CHRIO#
- TADI CHRIO#
- DCA ADDR
- INC CHRIO#
-CDFB, HLT
- TADI ADDR
- JMP I GETP
-#endasm
-}
-
-fputc(ch)
-int ch;
-{
- ch;
-#asm
- DCA FRSL
- CALL 2,CHRIO
- ARG (4
- ARG FRSL
- CDF1
- TAD FRSL
-#endasm
-}
- sixbit(p)
-char *p;
-{
- *p++;
-#asm
- AND (63
- BSW
- MQL
-#endasm
- *p;
-#asm
- AND (63
- MQO
-#endasm
-}
-
-fputs(p)
-int *p;
-{
- while (*p++)
-#asm
- DCA FRSL
- CALL 2,CHRIO
- ARG (4
- ARG FRSL
- CDF1
-#endasm
-}
-
-
-fopen (fnm,flg)
-char *fnm;
-int flg;
-{
- char *p;
- p=fnm;
- p=strstr(fnm,".");
- if (p==0)
- return(-1);
- if (*flg=='w') {
-#asm
- CLA
- TAD FC1#
- DCA FBSE#
- JMP FC3
-FC1, CALL 0,OOPEN
-FC2, CALL 0,IOPEN
-#endasm
- }
- if (*flg=='r') {
-#asm
- CLA
- TAD FC2#
- DCA FBSE#
-FC3, CDF1
-#endasm
- *p++=0;
- sixbit(p);
-#asm
- PAGE
- / OFFSET IOPEN+81 = FILEEX
- DCA ZTMP
- TAD FC2# / CODE
- AND (63
- TAD (128
- DCA FDCT
- CDF0
- TADI FDCT
- DCA FEX1
- TAD FDCT
- TAD (64
- DCA FDCT
- TADI FDCT
- TAD (81 / OFFSET OF EXTENSION
- DCA FDCT
-FEX1, HLT
- TAD ZTMP
- DCAI FDCT
- CDF1
-#endasm
- fnm;
-#asm
- DCA ZTMP / PACK 6 8BIT CHARS INTO FILENAME
- TAD (-3
- DCA FDCT
- TAD FDCA
- DCA FP4
-FP1, CAM
- TADI ZTMP
- SNA
- JMP FP2
- AND (63
- BSW
- MQL
- ISZ ZTMP
-FP2, TADI ZTMP / WILL USE STACK FIELD
- AND (63
- SZA
- ISZ ZTMP
- MQO
-FP4, DCA FFNM
- ISZ FP4
- ISZ FDCT
- JMP FP1
- TAD (46
- DCAI ZTMP / PUT . BACK INTO FNM
- CLA CLL CMA
- TAD STKP
- DCA STKP
-FBSE, CALL 2,IOPEN
- ARG FDEV
- ARG FFNM
- JMPI POPR
-FDCA, DCA FFNM
-FDCT, 0
-FFNM, TEXT /TM@@@@/
-FDEV, TEXT /DSK@@@/
-#endasm
- }
-}
-
-fclose()
-{
-#asm
- CALL 0,OCLOS
-#endasm
-}
-
-
-puts(p)
-char *p;
- {
- while (*p++)
-#asm
- TLS
-XC1, TSF
- JMP XC1
-#endasm
- }
-
-dispxy(x,y)
-int x,y;
-{
- x;
-#asm
- 3115 / DIX
-#endasm
- y;
-#asm
- 3116 / DIY
- 3117 / DIL
-#endasm
-}
-
-getc()
-{
-#asm
- CLA
-GT1, KSF
- JMP GT1
- KRB
- TLS
- AND (127 /* 7 BIT! */
-#endasm
-}
-
-gets(p)
-char *p;
-{
-int q,tm;
- tm=1;
- q=p;
- while (tm) {
-#asm
-XC2, CLA CLL
- KSF
- JMP XC2
- KRB
- TAD (-255
- CLA
- KRB
- SNL / DO NOT ECHO BS
- TLS
-XC3, AND (127
- TAD (-13 / CR IS END OF STRING -> 0
- SZA
- TAD (13
- DCAI STKP
-#endasm
- if (tm!=127)
- *p++=tm;
- else
- if (p-q) {
- puts("\b \b");
- p--;
- }
- }
- putc(10); /* newline */
- return 1;
-}
-
-
-atoi(p,rsl)
-char *p;
-int *rsl;
-{
-#asm
- DCA ZTMP
- DCA ZCTR
- TAD (3584 / NOP
- DCA XINV
- CDF1 / Change DF back to 1 in case SABR changes it!
-#endasm
- while (*p==' ')
- p++;
- if (*p=='-') {
-#asm
- CLA
- TAD (3617
- DCA XINV / CIA
- CDF1
-#endasm
- p++;
- }
- while (*p++) {
-#asm
- TAD (-48 / '0' ... SEE CODE
- DCA JLC
- TAD JLC
- SPA CLA
- JMP XRET
- TAD (-10
- TAD JLC
- SMA CLA
- JMP XRET / EXIT IF NOT NUMBER
- TAD ZTMP
- CLL RTL / *4
- TAD ZTMP / *5
- CLL RAL / *10
- TAD JLC
- DCA ZTMP
- ISZ ZCTR / CHAR COUNTER
-#endasm
- }
-#asm
-XRET, TAD ZCTR
- MQL
- CMA
- TAD STKP / ->RSL
- DCA TMP
- TADI TMP
- DCA TMP
- TAD ZTMP
-XINV, NOP
- DCAI TMP / WRITE RSL
- MQA / RETURN LENGTH
-#endasm
-}
-
-
-xinit()
-{
- puts("PDP-8 C Compiler V1.0:\r\n");
-}
-
-
-memcpy(dst,src,cnt)
-int dst,src,cnt;
-{
-#asm
- CLA
- TAD STKP
- TAD (-4
- DCA 12
- CMA
- TADI 12
- DCA 11
- CMA
- TADI 12
- DCA 10
- TADI 12
- CIA
- DCA ZTMP
-CP1, TADI 10
- DCAI 11
- ISZ ZTMP
- JMP CP1
-#endasm
-
-}
-
-kbhit()
-{
-#asm
- CLA CMA
- KSF
- CLA
-#endasm
-}
-
-putc(p)
-char p;
-{
- p;
-#asm
- TLS
-MP1, TSF
- JMP MP1
-#endasm
-}
-
-strcmp( dm , sm )
-char *dm,*sm;
-{
- int rsl;
-
- rsl=0;
- while (*dm)
- rsl+=(*sm++-*dm++);
- return rsl;
-}
-
-strcpy( dm , sm )
-char *dm,*sm;
-{
- while (*dm++=*sm++);
-}
-
-strcat( dm , sm )
-char *dm,*sm;
-{
- int qm;
- qm=dm;
- while(*dm) dm++;
- strcpy(dm,sm);
- return qm;
-}
-
-strstr ( s , o )
-char *s , *o ;
-{
-char *x , *y , *z ;
- for ( x = s ; * x ; x ++ ) {
- for ( y = x , z = o ; * z && * y == * z ; y ++ ) z ++ ;
- if ( z > o && ! * z ) return x ;
- } return 0 ;
-}
-
-exit(retval)
-int retval;
-{
-#asm
- CALL 0,EXIT
- HLT
-#endasm
-}
-
-isalnum(vl)
-int vl;
-{
- return (isnum(vl) + isalpha(vl));
-}
-
-isnum(vl)
-int vl;
-{
- vl;
-#asm
- TAD (-48
- SPA
- JMP XNO
- TAD (-10
- SMA CLA
-XNO, CLA SKP
- IAC
-#endasm
-}
-
-isspace(vl)
-int vl;
-{
- vl;
-#asm
- SNA
- JMP YNO
- TAD (-33
- SMA CLA
-YNO, CLA SKP
- IAC
-#endasm
-}
-
-
-isalpha(vl)
-int vl;
-{
- vl; /* Include '?' and '@' as alpha vars */
-#asm
- TAD (-65
- SPA
- JMP ANO
- TAD (-26
- SPA
- JMP BNO
- TAD (-6
- SPA
- JMP ANO
- TAD (-26
-BNO, SMA CLA
-ANO, CLA SKP
- IAC
-#endasm
-}
-
-cupper(p) /* In place convert to uppercase */
-int p;
-{
- p;
-#asm
- DCA ZTMP
-CPP1, CLA
- TADI ZTMP
- SNA
- JMP CPP2
- TAD (-97
- SPA
- JMP CPP3
- TAD (-26
- SMA
- JMP CPP3
- TAD (91
- DCAI ZTMP
-CPP3, ISZ ZTMP
- JMP CPP1
-CPP2,
-#endasm
-}
-
-/* Arbitrary fgets(). Read until LF, CR/LF are retained*/
-/* EOF returns null, else strlen(*p) */
-
-fgets(p)
-char *p;
-{
-char *q;
- q=p;
- while(*p=fgetc()) {
- if (*p++==10)
- break;
- }
- *p=0;
- return (p-q);
-}
-
-memset(dst, dt, sz)
-char *dst;
-int dt,sz;
-{
- int i;
- for (i=0;ilen) width = width - len; else width = 0;
- if(!left) while(width--) {*obfr++=pad; ++cc;}
- while(len--) {*obfr++=*sptr++; ++cc; }
- if(left) while(width--) {*obfr++=pad; ++cc;}
- }
- *obfr=0;
- zptr;
-#asm
- SNA / IF ZPTR, EITHER USE PUTS OR FPUTS
- JMP PF1
- JMSI PSH
- CLA
- TAD FPTR
- SNA CLA
- JMP PF2
- JMSI PCAL
- FPUTS
- JMP PF3
-PF2, JMSI PCAL
- PUTS
-PF3, JMSI POP
-PF1, CLA
- DCA ZPTR
- DCA FPTR
-#endasm
-
- return(cc);
- }
-
-/*
-** itoa(n,s) - Convert n to characters in s
-*/
-itoa(n, s) char *s; int n; {
- int sign;
- char *ptr;
- ptr = s;
- if ((sign = n) < 0) n = -n;
- do {
- *ptr++ = n % 10 + '0';
- } while ((n = n / 10) > 0);
- if (sign < 0) *ptr++ = '-';
- *ptr = '\0';
- reverse(s);
- }
-
-/*
-** itoab(n,s,b) - Convert "unsigned" n to characters in s using base b.
-** NOTE: This is a non-standard function.
-*/
-itoab(n, s, b) int n; char *s; int b; {
- char *ptr;
- int lowbit;
- ptr = s;
- b >>= 1;
- do {
- lowbit = n & 1;
- n = (n >> 1) & 4095;
- *ptr = ((n % b) << 1) + lowbit;
- if(*ptr < 10) *ptr += '0'; else *ptr += 55;
- ++ptr;
- } while(n /= b);
- *ptr = 0;
- reverse (s);
- }
-
-
-strlen(p)
-char *p;
-{
- int n;
-
- n=0;
- while (*p++)
- n++;
- return n;
-}
-
-#define EOF 0
-
-sscanf(nxtarg) int nxtarg; {
- char *ctl;
- int u;
- int *narg, wast, ac, width, ch, cnv, base, ovfl, sign, *ibfr;
- ac = 0;
- nxtarg = &nxtarg-nxtarg;
- ibfr = *nxtarg++;
- ctl = *nxtarg++;
- while(*ctl) {
- if(*ctl++ != '%') continue;
- narg = *nxtarg++;
- ctl += atoi(ctl, &width);
- if (!width)
- width=-1;
- if(!(cnv = *ctl++)) break;
- switch(cnv) {
- case 'c':
- *narg = *ibfr++;
- break;
- case 's':
- while(width--)
- if((*narg++ = *ibfr++) == 0) break;
- *narg = 0;
- break;
- default:
- switch(cnv) {
- case 'b': base = 2; break;
- case 'd': base = 10; break;
- case 'o': base = 8; break;
- case 'x': base = 16; break;
- default: return (ac);
- }
- *narg = u = 0;
- sign = 1;
- while(width-- && (ch=*ibfr++)>32) {
- if(ch == '-') {sign = -1; continue;}
- if(ch < '0') break;
- if(ch >= 'a') ch -= 87;
- else if(ch >= 'A') ch -= 55;
- else ch -= '0';
- u = u * base + ch;
- }
- *narg = sign * u;
- }
- ++ac;
- }
- return (ac);
- }
-
DELETED src/cc8/os8/libc.h
Index: src/cc8/os8/libc.h
==================================================================
--- src/cc8/os8/libc.h
+++ /dev/null
@@ -1,1 +0,0 @@
-../include/libc.h
DELETED src/cc8/os8/n8.c
Index: src/cc8/os8/n8.c
==================================================================
--- src/cc8/os8/n8.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * This file is part of the CC8 OS/8 C compiler.
- *
- * The CC8 OS/8 C compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 OS/8 C compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 OS/8 C compiler as ../GPL3.txt. If not, see
- * .
- */
-
-
-#include
-#include
-
-
-#define SMAX 10
-#define CMAX 256
-#define BMAX 64
-#define LMAX 32
-#define DMAX 32
-#define CBMX 1024
-#define LXMX 999
-
-int asm[CBMX];
-int ltbf[512];
-int xlt[CMAX];
-int gm[CMAX]; /* Global symbol table */
-int tkbf[LMAX];
-int *p,*q,*s,*ltpt;
-int gsym,lsym,gadr,ladr,stkp,lctr,*fptr,gsz,ctr,tm,ectr,cop;
-int glim,*n,ccm;
-int tmp;
-int tkn[BMAX];
-int bfr[BMAX];
-int tmbf[LMAX];
-int smbf[LMAX];
-int Lb[BMAX];
-int lm[CMAX]; /* Auto symbol table */
-int fstk[BMAX]; /* Push down stack for For etc. */
-int inproc,addr,cbrk;
-int izf,ixf,idf,ssz,icd;
-
-
-skpsp()
-{
- while (isspace(*p))
- p++;
-}
-
-getsym()
-{
- q=tkbf;
- skpsp();
- while (isalnum(*p))
- *q++=*p++;
- *q=0;
- skpsp();
- return *tkbf;
-}
-
-
-/* recursive descent parser for arithmetic/logical expressions */
-
-S( ) {
-
- cop=0;
- J( );
- switch(*p++){
- case '=':
- S();
- stri(1);
- stkp--;
- break;
- case ']':
- case ')':
- return 1;
- case ',':
- break;
- default:
- p--;
- }
- return 0;
-} /* end S */
-
-J( ) {
-
- K( );
- switch(*p++){
- case '&': J( ); stri(20); break;
- case '|': J( ); stri(-20); break;
- default: p--; return;
- }
- stkp--;
-} /* end J */
-
-K( ) {
-
- V( );
- switch(*p++){
- case '<': K( ); stri(11); break;
- case '>': K( ); stri(-11); break;
- case '$': K( ); stri(24); break;
- default: p--; return;
- }
- stkp--;
-} /* end K */
-
-V( ) {
-
- W( );
- switch(*p++){
- case '+': V(); stri(2); break;
- case '-': V(); stri(3); break;
- default: p--; return;
- }
- stkp--;
-} /* end V */
-
-W( ) {
-
- Y( );
- skpsp();
- cop=*p;
- switch(*p++) {
- case '*': W( ); stri(13); break;
- case '/': W( ); stri(14); break;
- case '%': W( ); stri(14);stri(-14); break;
- case '=': if (*p=='=') {
- *p='$';return;
- }
- default: p--; return;
- }
- stkp--;
-} /* end W */
-
-
-Y( ) {
- int o,ctx;
- int txbf[10];
-
- skpsp();
-
- if (!*p)
- return;
-
- if (cop) {
- stri(19);
- stkp++;
- }
-
- if (*p=='"') {
- stri(10);
- stri(ltpt-ltbf);
- while (*++p-'"') {
- if (*p=='\\')
- switch (*++p) {
- case 'r':
- *p=13;
- break;
- case 'n':
- *p=10;
- }
- *ltpt++=*p;
- }
- *ltpt++=0;
- p++;
- return;
- }
- n=q=p;
- if (*p=='-')
- p++;
- if(isdigit(*p)) {
- while(isdigit(*p))
- p++;
- stri(4);
- atoi(q,&tmp);
- stri(tmp);
- return;
- }
- if (*p==39) {
- stri(4);
- stri(*++p);
- p+=2;
- return;
- }
- ixf=izf=idf=icd=0;
- if (!getsym()) {
- switch (*p++) {
- case '&':
- getsym();
- stri(21);
- stri(fndlcl(tkbf));
- return;
- case '*':
- getsym();
- ixf++;
- break;
- case '!':
- Y();
- stri(26);
- return;
- case '~':
- Y();
- stri(-26);
- return;
- case '(':
- S();
- return;
- case ')':
- icd=1;
- return;
- }
- }
- if(*p=='('){
- strcpy(txbf,tkbf);
- ctx=o=0;p++;
- while (*p && !o) {
- o=S( );
- if (icd)
- break;
- stkp++;
- stri(19);
- ctx++; /* arg count */
- }
- stri(9);
- stri(ctx);
- stkp-=ctx;
- if ((o=strstr(gm,txbf))){
- stri(o-gm);
- }
- else {
- stri(gsz);
- strpad(txbf);
- strcat(gm,smbf);
- gsz+=9;
- }
- return;
- }
- /* Digraphs */
-
- q=p+1;
- if (tmp=*q==*p)
- switch (*p) {
- case '+':
- izf=-tmp;
- p+=2;
- break;
- case '-':
- idf=-tmp;
- p+=2;
- break;
- }
-
- o=fndlcl(tkbf);
- tmp=-17;
- if (ssz>1) {
- if (*p=='[') {
- stri(21);
- stri(o);
- stri(19);
- stkp++;
- p++;S();
- stri(2);
- if (*p=='=')
- stri(19);
- else {
- stri(22);
- stkp--;
- }
- return;
- }
- tmp=21;
- }
- switch (*p) {
- case '=':
- if (*q=='=')
- break;
- tmp=8;
- if (ixf)
- tmp=-8;
- ixf=0;
- stkp++;
- break;
- }
- stri(tmp);
- stri(o);
- if (*n=='-')
- stri(27);
- if (izf)
- stri(15);
- if (idf)
- stri(25);
- if (ixf)
- stri(22);
- return;
-} /* end Y */
-
-procst(trm)
-char trm;
-{
- ccm=ctr=1;
- p=q=Lb;
- while(1) {
- tm=fgetc();
- ctr-=tm=='(';
- ctr+=tm==')';
- ccm-=tm==',';
- if (!ctr || tm==trm)
- break;
- *q++=tm;
- }
- *q=0;
- if (inproc)
- while (*p)
- S();
-}
-
-strpad(sym)
-char *sym;
-{
- char *a,*b;
-
- strcpy(a=smbf," "); /* 9 spaces */
- while (*sym)
- *a++=*sym++;
-}
-
-addsym(sym,sz)
-char *sym;
-int sz;
-{
- strpad(sym);
- smbf[8]=sz;
- if (inproc+(sz<0)) {
- smbf[7]=stkp+1;
- stkp+=sz;
- strcat(lm,smbf);
- stri(6);
- stri(sz);
- return;
- }
- smbf[7]=gadr;
- gadr+=sz;
- strcat(gm,smbf);
- gsz+=9;
-}
-
-fndlcl(sym)
-char *sym;
-{
- strpad(sym);
- smbf[7]=0;
- if (s=strstr(lm,smbf)) {
- ssz=s[8];
- s=s+7;
- return *s-stkp;
- }
- if (s=strstr(gm,smbf)) {
- ssz=s[8];
- s=s+7;
- return *s;
- }
- return 0;
-}
-
-gettk()
-{
- char xtm;
-
- q=tkbf;
- while (isspace(xtm=fgetc()));
- while (isalnum(xtm)) {
- *q++=xtm;
- xtm=fgetc();
- }
- *q=0;
- return xtm;
-}
-
-popfr()
-{
- while (*fptr==inproc) {
- cbrk=*--fptr;
- stri(23);
- stri(*--fptr);
- stri(5);
- stri(*fptr+2);
- fptr--;
- }
-}
-
-dostt()
-{
- p=tmbf;
- while (tm!=';') {
- *p++=tm;
- tm=fgetc();
- }
- *p=0;
- strcpy(Lb,tkbf);
- strcat(Lb,tmbf);
- p=Lb;
- S();
- tm=1;
-}
-
-fnbrk()
-{
- while (tm!='(')
- tm=fgetc();
-}
-
-next()
-{
- char *lp;
- int fflg;
-
- lp=0;
- if (*tkbf) {
- strcat(tkbf," ");
- lp=strstr(tkn,tkbf);
- }
- fflg=lctr;
- if (lp) {
- switch(lp-tkn) {
- case 0:
- while (tm!=';' && tm!='{') {
- tm=gettk();
- strcpy(bfr,tkbf);
- while (isspace(tm))
- tm=fgetc();
- switch (tm) {
- case '[':
- tm=gettk();
- atoi(tkbf,&fflg);
- addsym(bfr,fflg);
- tm=fgetc();
- break;
- case '(':
- stri(7);
- stri(gsz);
- if (strstr("main",tkbf))
- strcpy(tkbf,"XMAIN");
- addsym(tkbf,1);
- procst(')');
- stkp=-(ccm+1);
- while (*p) {
- getsym();
- addsym(tkbf,-1);
- p++;
- stkp+=2;
- }
- stkp=0;
- tm=gettk();
- cbrk=100;
- break;
- case ',':
- case ';':
- addsym(tkbf,1);
- break;
- } /* end whie */
- } /* end case 0: */
- break;
- case 4:
- fflg=fflg+100;
- case 12:
- fnbrk();
- stri(5);
- *++fptr=fflg;
- stri(fflg);
- procst(0);
- stri(12);
- stri(tm=*fptr+2);
- *++fptr=cbrk;
- if (fflg<100)
- cbrk=tm;
- *++fptr=inproc;
- lctr+=3;
- tm=0;
- stri(99);
- break;
- case 7:
- tm=0;
- break;
- case 18:
- stri(23);
- stri(cbrk);
- break;
- case 24:
- procst(';');
- stri(23);
- stri(ectr);
- tm=1;
- break;
- case 31:
- fnbrk();
- procst(';');
- stri(5);
- stri(lctr++);
- *++fptr=lctr;
- procst(';');
- stri(12);
- stri(lctr+2);
- stri(23);
- stri(lctr+1);
- stri(5);
- stri(lctr++);
- procst(')');
- *++fptr=cbrk;
- *++fptr=inproc;
- stri(23);
- stri(lctr-2);
- stri(5);
- stri(lctr++);
- cbrk=lctr++;
- tm=0;
- break;
- default:
- dostt();
- } /* End switch */
- } else
- switch (tm) {
- case '{':
- tm=1;
- inproc++;
- break;
- case '}':
- break;
- case -1:
- case 0:
- stri(0);
-#asm
- CALL 1,CHAIN
- ARG FNM
- HLT
-FNM, TEXT "CC2@@@"
-#endasm
- case '/':
- while (fgetc()!='/'); /* Skip comment */
- tm=1;
- break;
- default:
- dostt();
- }
- return tm;
-}
-
-
-
-main()
-{
- char trm;
-
- memset(ltbf,0,&ssz-ltbf);
- fopen("CC.CC","r");
- strcpy(tkn,"int if else while break return for ");
- lctr = 10;
- ectr = 900;
- ltpt = ltbf;
- fptr = fstk;
- *fptr = -1;
- gadr = 128; /* Start of globals */
- iinit(asm);
- tm=gettk();
- while (1) {
- trm=next();
- tm=gettk();
- switch (trm) {
- case '{':
- inproc++;
- break;
- case '}':
- inproc--;
- if (!inproc) {
- stri(5);
- stri(ectr++);
- stri(16);
- stri(-stkp);
- stkp = *lm = 0;
- break;
- }
- case ';':
- case 1:
- stri(99);
- if (!strcmp("else",tkbf)) {
- stri(-23);
- stri(100+lctr+2);
- popfr();
- *++fptr=100+lctr++;
- *++fptr=cbrk;
- *++fptr=inproc;
- }
- else
- popfr();
- case 0:
- break;
- default:
- procst(';');
- }
- }
-}
-
DELETED src/cc8/os8/p8.c
Index: src/cc8/os8/p8.c
==================================================================
--- src/cc8/os8/p8.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * This file is part of the CC8 OS/8 C compiler.
- *
- * The CC8 OS/8 C compiler is free software: you can redistribute it
- * and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * The CC8 OS/8 C compiler is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with the CC8 OS/8 C compiler as ../GPL3.txt. If not, see
- * .
- */
-
-
-#include
-#include
-
-#define SMAX 10
-#define CMAX 256
-#define BMAX 64
-#define LMAX 32
-#define DMAX 32
-#define CBMX 1024
-#define LXMX 999
-
-int asm[CBMX];
-int ltbf[512];
-int xlt[CMAX];
-int gm[CMAX]; /* Global symbol table */
-int tkbf[LMAX];
-int *p,*q,*s,*ltpt;
-int gsym,lsym,gadr,ladr,stkp,*as,lctr,*fptr,gsz,ctr,tm,ectr;
-int glim;
-int ltsz,pflg,t;
-int tmstr[32];
-
-main()
-{
-
- as=asm;
- fopen("HEADER.SB","r");
- fopen("CC.SB","w");
- strcpy(xlt,"ITOA PUTS DISPXY GETC GETS ATOI SSCANF XINIT MEMCPY KBHIT PUTC STRCPY STRCAT STRSTR EXIT ISNUM ");
- strcat(xlt,"ISALPH SPRINTF MEMSET FGETC FOPEN FPUTC FCLOSE PRINTF ISALNUM ISSPACE FPRINTF FPUTS STRCMP CUPPER FGETS ");
- while (t=fgetc())
- if (t!=12) /* Ignore form feed */
- fputc(t);
- cupper(gm);
- while (*as) {
- pflg=0;
- *tmstr=0;
- switch (*as++) {
- case 99:
- fprintf("/\r");
- break;
- case 1:
- fprintf("\tJMSI PTSK\r");
- break;
- case 3:
- strcpy(tmstr,"\tCIA\r");
- case 2:
- fprintf("%s\tTADI STKP\r\tJMSI POP\r",tmstr);
- break;
- case 4:
- fprintf("\tCLA\r\tTAD (%d\r",*as++);
- break;
- case 5:
- if (*as<0)
- *as=100-*as;
- fprintf("CC%d,\r",*as++);
- break;
- case 6:
- if (*as>1)
- fprintf("\tTAD STKP\r\tTAD (%d\r\tDCA STKP\r",*as);
- else
- if (*as>0)
- fputs("\tISZ STKP\r");
- as++;
- break;
- case 7:
- p=gm+*as++;
- while (*p-' ')
- fputc(*p++);
- fputs(",\r");
- break;
- case -8:
- strcpy(tmstr,"\tDCA JLC\r\tTADI JLC\r");
- case 8:
- if (*as>0)
- fprintf("\tCLA\r\tTAD (%d\r%s\tJMSI PSH\r",*as++,tmstr);
- else
- fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r%s\tJMSI PSH\r",*as++,tmstr);
- break;
- case 9:
- tm=*as++;
- p=gm+*as++;
- strcpy(tkbf," ");
- memcpy(tkbf,p,7);
- if (p=strstr(xlt,tkbf)) {
- t=(p-xlt)>>3;
- if ((t==6) + (t==17) + (t==23))
- fprintf("\tCLA\r\tTAD (%d\r\tJMSI PSH\r",tm++);
- fprintf("\tCLA\r\tTAD (%d\r\tMQL\r\tCALL 1,LIBC\r\tARG STKP\r\tCDF1\r",t);
- }
- else
- fprintf("\tJMSI PCAL\r\t%s\r",tkbf);
- if (tm)
- fprintf("\tMQL\r\tTAD (%d\r\tTAD STKP\r\tDCA STKP\r\tSWP\r",-tm);
- break;
- case 10:
- fprintf("\tCLA\r\tTAD GBL\r\tTAD (%d\r",*as++);
- break;
- case -11:
- fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSMA SZA CLA\r\tCMA\r");
- break;
- case 11:
- fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSPA CLA\r\tCMA\r");
- break;
- case 12:
- fprintf("\tSNA\r\tJMP CC%d\r",*as++);
- break;
- case 13:
- fprintf("\tJMSI POP\r\tDCA JLC\r\tSWP\r\tCALL 1,MPY\r\tARG JLC\r\tCDF1\r");
- break;
- case -14:
- fprintf("\tCALL 1,IREM\r\tARG 0\r\tCDF1\r");
- break;
- case 14:
- fprintf("\tJMSI POP\r\tDCA JLC\r\tSWP\r\tCALL 1,DIV\r\tARG JLC\r\tCDF1\r");
- break;
- case 15:
- fprintf("\tISZI JLC\r\tNOP\r");
- break;
- case 16:
- fprintf("\tMQL\r\tTAD STKP\r\tTAD (%d\r\tDCA STKP\r\tSWP\r\tJMPI POPR\r/\r",*as++);
- break;
- case 17:
- pflg++;
- case -17:
- if (*as>0)
- fprintf("\tCLA\r\tTAD (%d\r\tDCA JLC\r\tTADI JLC\r",*as++);
- else
- fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r\tDCA JLC\r\tTADI JLC\r",*as++);
- if (pflg==0)
- break;
- case 19:
- fprintf("\tJMSI PSH\r");
- break;
- case 20:
- fprintf("\tANDI STKP\r\tJMSI POP\r");
- break;
- case -20:
- fprintf("\tJMSI POP\r\tMQO\r");
- break;
- case 21:
- if (*as>0)
- fprintf("\tCLA\r\tTAD (%d\r",*as++);
- else
- fprintf("\tCLA\r\tTAD STKP\r\tTAD (%d\r",*as++);
- break;
- case 22:
- fprintf("\tDCA JLC\r\tTADI JLC\r");
- break;
- case 23:
- if (*as<100)
- fprintf("\tJMP CC%d\r",*as);
- as++;
- break;
- case -23:
- fprintf("\tJMP CC%d\r",*as++);
- break;
- case 24:
- fprintf("\tCIA\r\tTADI STKP\r\tJMSI POP\r\tSNA CLA\r\tCMA\r");
- break;
- case 25:
- fprintf("\tMQL\r\tCMA\r\tTADI JLC\r\tDCAI JLC\r\tSWP\r");
- break;
- case 26:
- fprintf("\tSNA CLA\r");
- case -26:
- fprintf("\tCMA\r");
- break;
- case 27:
- fputs("\tCIA\r");
- }
- }
- ltsz=ltpt-ltbf;
- fprintf("\tLAP\r\tCPAGE %d\rLCC0,\t%d\rXCC0,\tCC0\rCC0,\t\r",ltsz+2,-ltsz);
- p=ltbf;
- while (ltsz) {
- fprintf("%d",*p++);
- if (ltsz>1)
- fputs("; ");
- if ((ltsz&7)==0)
- fputc(13);
- ltsz--;
- }
- fprintf("\r\tEAP\rGBLS,\t%d\r",gadr);
- fprintf("\rMCC0,\t0\r\tCDF1\r\tTAD LCC0\r\tSNA CLA\r\tJMP I MCC0\r\tTAD XCC0\r\tDCA JLC\rDCC0,\tCDF0\r\tTADI JLC\r");
- fprintf("\tJMSI PSH\r\tCLA\r\tISZ JLC\r\tISZ LCC0\r\tJMP DCC0\r\tJMP I MCC0\rCCEND,\t0\r\t\END\r");
-
- fclose();
-}
DELETED src/d8tape/LICENSE.md
Index: src/d8tape/LICENSE.md
==================================================================
--- src/d8tape/LICENSE.md
+++ /dev/null
@@ -1,12 +0,0 @@
-I received the following license grant via private email, which
-supercedes the LICENSE file text distributed with d8tape in 2002:
-
----------
-
- On Fri, Nov 10, 2017 at 6:38 PM, Rob Krten wrote:
-
- As far as d8tape goes:
-
- I, Robert Krten, hereby provide a royalty free, perpetual, worldwide
- license to use the source code and information provided in my PDP-8
- disassembler, called "d8tape" for any purpose whatsoever.
DELETED src/d8tape/d8tape.h
Index: src/d8tape/d8tape.h
==================================================================
--- src/d8tape/d8tape.h
+++ /dev/null
@@ -1,48 +0,0 @@
-
-/*
- * d8tape.h
- *
- * (C) Copyright 2007 by Robert Krten, all rights reserved.
- * Please see the LICENSE file for more information.
- *
- * This module contains the manifest constants and other header
- * information.
- *
- * 2007 10 25 R. Krten created
- * 2007 10 28 R. Krten added TAG_INDIRECTFC
-*/
-
-// constants
-#define CORE_SIZE 4096 // size of core memory
-
-#define TAG_DATA 0x0001 // memory region is tagged as data,
-#define TAG_SUB 0x0002 // subroutine target, or,
-#define TAG_LABEL 0x0004 // label
-#define TAG_RETURN 0x0008 // return from subroutine
-#define TAG_TYPE_MASK 0x00ff // mask of above types
-#define TAG_WRITABLE 0x0100 // set if anyone writes to this data location (else constant)
-#define TAG_KONSTANT 0x0200 // can be changed from Caaaa -> Kvvvv
-#define TAG_INDIRECTFC 0x0400 // target of an indirect flow control (JMS I / JMP I) (only meaningful if not writable)
-
-#include
-
-// segment info
-
-typedef struct
-{
- uint16_t saddr; // starting address
- uint16_t nwords; // number of contiguous words
-} segment_t;
-
-
-// prototypes
-
-// flow.c
-extern void flow (void);
-
-// dasm.c
-extern int ea (int addr, int opcode, int *indirect, int *curpage);
-extern void disassemble (void);
-extern int is_data (int v);
-extern int fetch_iot (int code, char *dis, char *com);
-
DELETED src/d8tape/dasm.c
Index: src/d8tape/dasm.c
==================================================================
--- src/d8tape/dasm.c
+++ /dev/null
@@ -1,687 +0,0 @@
-
-/*
- * dasm.c
- *
- * (C) Copyright 2003 by Robert Krten, all rights reserved.
- * Please see the LICENSE file for more information.
- *
- * This module contains the PDP-8 disassembler.
- * Note that the 8/I and 8/L are featured at this point; other models
- * should be added (particularly the 8/E's EAE instructions, as well
- * as new IOT decodings, etc)
- *
- * 2003 12 16 R. Krten created
- * 2007 10 29 R. Krten added better output formatting
- * 2007 11 02 R. Krten added xrefs
- * 2009 02 08 D. North fixups for missing 7002 BSW and removal of
- * 7600 CLA case (conflicts with 7200 on reassembly)
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "d8tape.h"
-#include "iot.h" // decode table for IOTs
-
-extern char *progname; // main.c
-extern char *version; // version.c
-
-extern int optv; // main.c
-extern char *tapename; // main.c, name of tape image
-
-extern short int core []; // main.c, in-core image (-1 means location never used)
-extern uint16_t tags []; // main.c, analysis tags
-extern segment_t *segments; // main.c, used to accumulate runs of data (from origin for nwords)
-extern int nsegments; // main.c, indicates how many segments we have
-
-static void header (void);
-static void disassemble_range (int start, int end);
-static void pad (char *buf, int off, int pos);
-static void xrefs (int addr);
-
-/*
- * dasm8
- *
- * This takes the current address and the instruction value
- * and prints the decoded instruction. A static variable
- * is used to kludge up 2-word instructions (e.g., MUY ).
- *
- * The IOTs are coded in a table; in some cases, conflicts exist, you'll
- * need to select the appropriate #defines to make them go away :-)
- * As shipped, the #defines match my preferences.
- *
- * Formatting rules:
- * - the following types of output exist:
- * - labels
- * - banners
- * - code
- * - data
- *
- * For each type, the following format is used (all tabs, as shown by the single backtick
- * character, are assumed to be at 4 character tabstops. If you don't like this, pipe
- * the output through "expand -4").
- *
- * Labels:
- * 1111111111222222222233333333334444444444555555555566666666667777777777
- * 01234567890123456789012345678901234567890123456789012345678901234567890123456789
- * t t t t t t t t t t t t t t t t t t t t
- * TAAAA,
- *
- * where "T" is the label type, one of "D" for data, "L" for executable label,
- * and "S" for subroutine entry, and "AAAA" is the four digit octal address.
- * (See "Data" below for additional details of the "D" type).
- *
- * Banners:
- * 1111111111222222222233333333334444444444555555555566666666667777777777
- * 01234567890123456789012345678901234567890123456789012345678901234567890123456789
- * t t t t t t t t t t t t t t t t t t t t
- * ////////////////////////////////////////////////////////////////////////////////
- * /
- * /```CONTENT
- * /
- * ////////////////////////////////////////////////////////////////////////////////
- *
- * Where "CONTENT" is the content of the banner, e.g., "SUBROUTINE S1234".
- *
- * Code:
- * 1111111111222222222233333333334444444444555555555566666666667777777777
- * 01234567890123456789012345678901234567890123456789012345678901234567890123456789
- * t t t t t t t t t t t t t t t t t t t t
- * op1`````````````````````/ COMMENTS..............................@@=AAAA,OOOO
- * opc1````````````````````/ COMMENTS..............................@@=AAAA,OOOO
- * op1 TAAAA```````````````/ COMMENTS..............................@@=AAAA,OOOO
- * op1 I TAAAA`````````````/ COMMENTS..............................@@=AAAA,OOOO
- * op1 op2 op3 op4 op5 op6`/ COMMENTS..............................@@=AAAA,OOOO
- * 12345678911234567892123 1234567891123456789212345678931234567 (DISLEN and COMLEN, resp.)
- * 01234567891123456789212345678 234567891123456789212345678931234567890 (COMSTART and DATASTART, resp.)
- *
- * Where "op1", "opc1", "op2" through "op6" are 3 or 4 character mnemonic
- * opcodes. "T" is the label type (as above), and "AAAA" is the address.
- * Tabs are used to fill whitespace to the "/" comment delimiter, and from the
- * end of the comment to the @@. The area at the "@@" indicates the address
- * and the contents.
- *
- * This is where the COMLEN and DISLEN buffer sizes are derived from, and the
- * COMSTART position (28, the start of the "/")
- *
- * Data:
- * 1111111111222222222233333333334444444444555555555566666666667777777777
- * 01234567890123456789012345678901234567890123456789012345678901234567890123456789
- * t t t t t t t t t t t t t t t t t t t t
- * CAAAA,``VVVV````````````````/ op1 op2 op3 op4 op5 op6 COMMENTS..................
- * DAAAA,``VVVV````````````````/ op1 op2 op3 op4 op5 op6 COMMENTS..................
- * KVVVV,``VVVV````````````````/ op1 op2 op3 op4 op5 op6 COMMENTS..................
- *
- * Where "C" is used for constants whose values are not unique, "D" is used
- * for writable data, and "K" is used for constants that can be added in the
- * symbol table. The distinction between "C" and "K" is that if two different
- * memory locations both define the same constant value, we need to use "C"
- * because it's tagged based on the address, whereas "K" is tagged based on
- * the value.
- *
- * Other types to consider are comment blocks imported from a control file.
-*/
-
-static const char *codes [6] = {"AND", "TAD", "ISZ", "DCA", "JMS", "JMP"}; // IOT and OPR are decoded elsewhere
-
-static unsigned short int two_word = 0; // set to hold two-word instruction (e.g., EAE ops), else zero (instruction 0, AND, is not a two-word instruction)
-
-#define COMLEN 37 // length of comment, see "Code", above (both the number of bytes and the max number of characters; tabs will only make the number of bytes less)
-#define DISLEN 23 // length of disassembly area, see "Code" above (ditto)
-#define COMSTART 28 // 0-based column number where the comments start
-#define DATASTART 40 // 0-based column number where the data (@@=AAAA,OOOO) starts
-static char disbuf [DISLEN + 1];
-static char combuf [COMLEN + 1];
-
-void
-dasm8 (int addr, unsigned short int buf)
-{
- int ind, cur;
- int eff_addr;
- int primary; // is primary disassembly 'c'ode or 'd'ata?
-
- if (optv > 1) {
- printf ("dasm8 (addr 0%04o word 0%04o tag 0x%04x)\n", addr, buf, tags [addr]);
- }
-
- eff_addr = ea (addr, buf, &ind, &cur);
-
- if (two_word) {
- printf ("\t%04o /\t\t\t\t\t / (operand)\n", buf);
- two_word = 0;
- return;
- }
-
- // prepare buffer areas for disassembly and comments.
- memset (disbuf, 0, sizeof (disbuf));
- memset (combuf, 0, sizeof (combuf));
-
- primary = 'c'; // default to code disassembly
-
- if (tags [addr] & TAG_LABEL) {
- printf ("L%04o,\n", addr);
- }
-
- if (tags [addr] & TAG_SUB) {
- printf ("\n");
- printf ("////////////////////////////////////////////////////////////////////////////////\n");
- printf ("/\n");
- printf ("/\tSUBROUTINE: S%04o\n", addr);
- printf ("/\n");
- xrefs (addr);
- printf ("////////////////////////////////////////////////////////////////////////////////\n");
- printf ("S%04o,\n", addr);
- printf ("\t0\t\t\t\t\t\t/ return area\n");
- // done; can't be SUB and anything else (except label, perhaps)
- return;
- }
-
- if (tags [addr] & TAG_DATA) {
- // if it's data, set primary as data
- primary = 'd';
- if ((addr & 07770) == 00010) { // addresses 0010 -> 0017 are autoindex
- printf ("AI%o,\t%04o\t\t\t\t/ AUTO-INDEX REGISTER", addr & 7, core [addr]);
- } else {
- if (tags [addr] & TAG_INDIRECTFC) {
- printf ("C%04o,\n", addr);
- }
- printf ("%c%04o,\t", tags [addr] & TAG_KONSTANT ? 'K' : tags [addr] & TAG_WRITABLE ? 'D' : 'C', tags [addr] & TAG_KONSTANT ? core [addr] : addr);
- printf ("%04o\t\t\t\t/", core [addr]);
- }
- }
-
- switch (buf & 07000) {
- case 00000: // AND
- case 01000: // TAD
- case 02000: // ISZ
- case 03000: // DCA
- case 04000: // JMS
- case 05000: // JMP
- sprintf (disbuf, "%s ", codes [buf >> 9]);
-
- if (ind) {
- strcat (disbuf, "I ");
- } else {
- strcat (disbuf, " ");
- }
-
- if (tags [eff_addr] & TAG_SUB) {
- strcat (disbuf, "S");
- } else if (tags [eff_addr] & TAG_LABEL) {
- strcat (disbuf, "L");
- } else {
- if ((eff_addr & 07770) == 00010) { // addresses 0010 -> 0017
- strcat (disbuf, "AI");
- strcat (combuf, "AUTO INDEX REGISTER");
- } else {
- strcat (disbuf, (tags [eff_addr] & TAG_KONSTANT) ? "K" : tags [eff_addr] & TAG_WRITABLE ? "D" : "C");
- }
- }
-
- if (tags [addr] & TAG_RETURN) {
- strcat (combuf, "return ");
- } else {
- // comment indirect flow control change to reflect ultimate target
- switch (buf & 07400) {
- case 04400:
- sprintf (combuf + strlen (combuf), "long call to S%04o ", core [eff_addr]);
- break;
- case 05400:
- sprintf (combuf + strlen (combuf), "long jump to L%04o ", core [eff_addr]);
- break;
- }
- }
-
- if ((eff_addr & 07770) == 00010) { // address 0010 -> 0017
- sprintf (disbuf + strlen (disbuf), "%o ", eff_addr & 7);
- } else {
- sprintf (disbuf + strlen (disbuf), "%04o ", (tags [eff_addr] & TAG_KONSTANT) ? core [eff_addr] : eff_addr);
- }
-
- break;
-
- case 06000: // IOT
- fetch_iot (buf, disbuf, combuf);
- break;
-
- case 07000: // OPR
- // perform "short form" OPRs here first...
- switch (buf) {
- case 07000: sprintf (disbuf, "NOP"); break;
- case 07002: sprintf (disbuf, "BSW"); break;
- case 07041: sprintf (disbuf, "CIA"); break;
- case 07120: sprintf (disbuf, "STL"); break;
- case 07204: sprintf (disbuf, "GLK"); break;
- case 07240: sprintf (disbuf, "STA"); strcat (combuf, "AC = 7777 (-0001)"); break;
- case 07300: sprintf (disbuf, "CLA CLL"); strcat (combuf, "AC = 0000"); break;
- case 07301: sprintf (disbuf, "CLA CLL IAC"); strcat (combuf, "AC = 0001"); break;
- case 07302: sprintf (disbuf, "CLA IAC BSW"); strcat (combuf, "AC = 0100 (64)"); break;
- case 07305: sprintf (disbuf, "CLA CLL IAC RAL"); strcat (combuf, "AC = 0002"); break;
- case 07325: sprintf (disbuf, "CLA CLL CML IAC RAL"); strcat (combuf, "AC = 0003"); break;
- case 07326: sprintf (disbuf, "CLA CLL CML RTL"); strcat (combuf, "AC = 0002"); break;
- case 07307: sprintf (disbuf, "CLA CLL IAC RTL"); strcat (combuf, "AC = 0004"); break;
- case 07327: sprintf (disbuf, "CLA CLL CML IAC RTL"); strcat (combuf, "AC = 0006"); break;
- case 07330: sprintf (disbuf, "CLA CLL CML RAR"); strcat (combuf, "AC = 4000 (-4000 = -2048 dec)"); break;
- case 07332: sprintf (disbuf, "CLA CLL CML RTR"); strcat (combuf, "AC = 2000 (1024)"); break;
- case 07333: sprintf (disbuf, "CLA CLL CML IAC RTL"); strcat (combuf, "AC = 6000 (-2000 = -1024 dec)"); break;
- case 07340: sprintf (disbuf, "CLA CLL CMA"); strcat (combuf, "AC = 7777 (-0001)"); break;
- case 07344: sprintf (disbuf, "CLA CLL CMA RAL"); strcat (combuf, "AC = 7776 (-0002)"); break;
- case 07346: sprintf (disbuf, "CLA CLL CMA RTL"); strcat (combuf, "AC = 7775 (-0003)"); break;
- case 07350: sprintf (disbuf, "CLA CLL CMA RAR"); strcat (combuf, "AC = 3777 (2047)"); break;
- case 07352: sprintf (disbuf, "CLA CLL CMA RTR"); strcat (combuf, "AC = 5777 (-2001 = -1025 dec)"); break;
- case 07401: sprintf (disbuf, "NOP"); break;
- case 07410: sprintf (disbuf, "SKP"); break;
- case 07600: sprintf (disbuf, "7600"); strcat (combuf, "AKA \"CLA\""); break;
- case 07610: sprintf (disbuf, "SKP CLA"); break;
- case 07604: sprintf (disbuf, "LAS"); break;
- case 07621: sprintf (disbuf, "CAM"); break;
- default:
-
- // determine group (0401 is 0000/0001 for group 1, 0400 for group 2, 0401 for EAE)
- switch (buf & 00401) {
- case 00000: // group 1
- case 00001: // group 1
- // sequence 1
- if (buf & 00200) {
- strcat (disbuf, "CLA ");
- }
- if (buf & 00100) {
- strcat (disbuf, "CLL ");
- }
- // sequence 2
- if (buf & 00040) {
- strcat (disbuf, "CMA ");
- }
- if (buf & 00020) {
- strcat (disbuf, "CML ");
- }
- // sequence 3
- if (buf & 00001) {
- strcat (disbuf, "IAC ");
- }
- // sequence 4
- if (buf & 00010) {
- if (buf & 00002) {
- strcat (disbuf, "RTR ");
- } else {
- strcat (disbuf, "RAR ");
- }
- }
- if (buf & 00004) {
- if (buf & 00002) {
- strcat (disbuf, "RTL ");
- } else {
- strcat (disbuf, "RAL ");
- }
- }
- break;
-
- case 00400: // group 2
- // sequence 1
- if (buf & 00100) {
- if (buf & 00010) {
- strcat (disbuf, "SPA ");
- } else {
- strcat (disbuf, "SMA ");
- }
- }
- if (buf & 00040) {
- if (buf & 00010) {
- strcat (disbuf, "SNA ");
- } else {
- strcat (disbuf, "SZA ");
- }
- }
- if (buf & 00020) {
- if (buf & 00010) {
- strcat (disbuf, "SZL ");
- } else {
- strcat (disbuf, "SNL ");
- }
- }
- // sequence 2
- if (buf & 00200) {
- strcat (disbuf, "CLA ");
- }
- // sequence 3
- if (buf & 00004) {
- strcat (disbuf, "OSR ");
- }
- if (buf & 00002) {
- strcat (disbuf, "HLT ");
- }
- break;
- case 00401: // EAE
- // sequence 1
- if (buf & 00200) {
- strcat (disbuf, "CLA ");
- }
- // sequence 2
- if (buf & 00100) {
- strcat (disbuf, "MQA ");
- }
- if (buf & 00040) {
- strcat (disbuf, "SCA ");
- }
- if (buf & 00020) {
- strcat (disbuf, "MQL ");
- }
- // sequence 3
- switch (buf & 00016) {
- case 0: // no further ops, done
- break;
- case 002:
- strcat (disbuf, "SCL ");
- two_word = buf;
- break;
- case 004:
- strcat (disbuf, "MUY ");
- two_word = buf;
- break;
- case 006:
- strcat (disbuf, "DVI ");
- two_word = buf;
- break;
- case 010:
- strcat (disbuf, "NMI");
- break;
- case 012:
- strcat (disbuf, "SHL ");
- two_word = buf;
- break;
- case 014:
- strcat (disbuf, "ASR ");
- two_word = buf;
- break;
- case 016:
- strcat (disbuf, "LSR ");
- two_word = buf;
- break;
- }
- break;
- }
- break;
- }
- break;
- }
- if (two_word) {
- strcat (disbuf, "+");
- }
- // trim any trailing spaces
- while (*disbuf && disbuf [strlen (disbuf) - 1] == ' ') {
- disbuf [strlen (disbuf) - 1] = 0;
- }
-
- if (primary == 'c') { // if primary is code, then spill data too
- pad (disbuf, 0, COMSTART - 4); // add tabs to get disassembly to comment start (one tab less because we print it next)
- printf ("\t%s", disbuf); // print disassembly so far
- printf ("/ "); // print comment start
- pad (combuf, 2, DATASTART); // pad comment buffer to get to data area
- printf ("%s@@%04o=%04o\n", combuf, addr, buf); // print comment, address and opcode
- } else { // else we've already spilled both, just terminate the line
- pad (disbuf, 2, DATASTART);
- printf (" %s", disbuf);
- printf ("\n");
- two_word = 0; // we don't care that it's a two-word when we're printing it as data
- }
-}
-
-/*
- * ea
- *
- * Calculate the effective address given the
- * address and opcode. Opcodes that don't have
- * an effective address (e.g., IOTs), return -1.
- *
- * The indirect pointer is optional, and, if specified,
- * will cause the location to be returned with a zero
- * or one indicating indirection. The indirect pointer
- * is not modified in case of a non-EA opcode.
- *
- * Similarly for the curpage pointer.
-*/
-
-int
-ea (int addr, int opcode, int *indirect, int *curpage)
-{
- int eff_addr;
- int c;
- int i;
-
- if (opcode >= 06000) { // IOTs and OPRs don't have an EA
- return (-1);
- }
-
- i = opcode & 00400;
- c = opcode & 00200;
- eff_addr = c ? (addr & 07600) + (opcode & 00177) : opcode & 00177;
- if (indirect) {
- *indirect = i;
- }
- if (curpage) {
- *curpage = c;
- }
- return (eff_addr);
-}
-
-/*
- * disassemble
- *
- * This drives disassembly once the flow analysis has been done.
- *
- * We disassemle in segment order.
-*/
-
-void
-disassemble (void)
-{
- int snum;
-
- header ();
- for (snum = 0; snum < nsegments; snum++) {
- printf ("\n*%04o\n", segments [snum].saddr);
- disassemble_range (segments [snum].saddr, segments [snum].saddr + segments [snum].nwords);
- }
-}
-
-static void
-header (void)
-{
- struct tm *tm;
- time_t now;
- int nused, ndata, ncode;
- int i;
-
- time (&now);
- tm = localtime (&now);
-
- nused = ndata = ncode = 0;
- for (i = 0; i < CORE_SIZE; i++) {
- if (core [i] >= 0) {
- nused++;
- if (tags [i] & TAG_DATA) {
- ndata++;
- } else {
- ncode++;
- }
- }
- }
-
- printf ("TITLE \"AUTOMATIC DISASSEMBLY OF %s BY D8TAPE\"\n", tapename);
- printf ("////////////////////////////////////////////////////////////////////////////////\n");
- printf ("/\n");
- printf ("/\tAutomatic Disassembly of %s\n", tapename);
- printf ("/\tGenerated %04d %02d %02d %02d:%02d:%02d\n", tm -> tm_year + 1900, tm -> tm_mon + 1, tm -> tm_mday, tm -> tm_hour, tm -> tm_min, tm -> tm_sec);
- printf ("/\tGenerated by d8tape version %s\n", version);
- printf ("/\tVisit http://www.pdp12.org/pdp8/software/index.html for updates\n");
- printf ("/\n");
- printf ("/\tSymbol format:\n");
- printf ("/\t\tAIx -- Auto-index variables (address range 001x)\n");
- printf ("/\t\tCaaaa -- Constants (non-unique)\n");
- printf ("/\t\tDaaaa -- Data (read/write variables)\n");
- printf ("/\t\tKvvvv -- Program-wide unique constants\n");
- printf ("/\t\tLaaaa -- Labels for control flow targets\n");
- printf ("/\t\tSaaaa -- Subroutines\n");
- printf ("/\n");
- printf ("/\tWhere:\n");
- printf ("/\t\taaaa is the definition address\n");
- printf ("/\t\tvvvv is the value of the constant\n");
- printf ("/\t\tx is the last digit of the address 001x for auto-index variables\n");
- printf ("/\n");
- printf ("/\t%04o locations used, %04o code and %04o data\n", nused, ncode, ndata);
- printf ("////////////////////////////////////////////////////////////////////////////////\n");
-}
-
-static void
-disassemble_range (int start, int end)
-{
- int addr;
-
- for (addr = start; addr < end; addr++) {
- dasm8 (addr, core [addr]);
- }
-}
-
-/*
- * fetch_iot
- *
- * This function looks up in the iot table (iot.h) to find
- * the opcode passed in "code" and updates the disassembled
- * output "dis" and the comment "com".
- *
- * More work needs to be done here for conflicting IOTs.
- *
- * Current, I assume that there are no conflicts (actually, I
- * return the first match, regardless of conflicts). A command
- * line / control file option needs to be created to allow
- * the selection of devices. Something like "-i vc8i", for example
- * to allow the VC8/I IOTs to be enabled.
-*/
-
-int
-fetch_iot (int code, char *dis, char *com)
-{
- int i;
-
- for (i = 0; i < sizeof (iots) / sizeof (iots [0]); i++) {
- if (code == iots [i].code) {
- if (dis) {
- strcpy (dis, iots [i].mnemonic);
- }
- if (com) {
- strncpy (com, iots [i].comment, COMLEN - 1);
- }
- return (1);
- }
- }
- if (dis) {
- sprintf (dis, "%04o", code);
- }
- if (com) {
- sprintf (com, "unknown IOT");
- }
- return (0);
-}
-
-/*
- * pad
- *
- * Figures out where the current print position is based on expanding
- * the current tabs in "buf" and adds more tabs to get to "pos".
-*/
-
-static void
-pad (char *buf, int loc, int pos)
-{
- for (; *buf; buf++) {
- if (*buf == '\t') {
- if ((loc & 3) == 0) {
- loc += 4;
- } else {
- loc += 4 - (loc & ~3);
- }
- } else {
- loc++;
- }
- }
-
- loc = pos / 4 - loc / 4;
- while (loc--) {
- *buf++ = '\t';
- }
- *buf = 0;
-}
-
-int
-is_data (int v)
-{
- return ((v & TAG_TYPE_MASK) == TAG_DATA);
-}
-
-static void
-xrefs (int addr)
-{
- int i;
- int eff;
- int count;
-
- count = 0;
- for (i = 0; i < CORE_SIZE; i++) {
- if (core [i] < 0) {
- continue;
- }
-
- if (tags [i] & TAG_DATA) {
-//printf ("+XREF ADDR %04o CHECK %04o IS DATA\n", addr, i);
- continue;
- }
-
-
- if ((core [i] & 07400) == 04000) { // direct JMS
- eff = ea (i, core [i], NULL, NULL);
-//printf ("+XREF ADDR %04o CHECK %04o %04o JMS EA %04o\n", addr, i, core [i], eff);
- if (eff == addr) {
- if (!count) {
- printf ("/\tCalled from:\n/\t");
- }
- printf ("%04o ", i);
- count++;
- if ((count % 15) == 0) {
- printf ("\n/\t");
- }
- }
- } else if ((core [i] & 07400) == 04400) { // indirect JMS
- eff = ea (i, core [i], NULL, NULL);
-//printf ("+XREF ADDR %04o CHECK %04o %04o JMS I EA %04o\n", addr, i, core [i], eff);
- if (tags [eff] & TAG_WRITABLE) {
- continue;
- }
-//printf ("+XREF ADDR %04o CHECK %04o %04o JMS I is not writable\n", addr, i, core [i]);
- if (core [eff] < 0) {
- continue;
- }
-//printf ("+XREF ADDR %04o CHECK %04o %04o JMS I has valid indirect value\n", addr, i, core [i]);
- if (core [eff] == addr) {
- if (!count) {
- printf ("/\tCalled from:\n/\t");
- }
- printf ("%04o ", i);
- count++;
- if ((count % 15) == 0) {
- printf ("\n/\t");
- }
- }
- }
- }
- if (count) {
- printf ("\n");
- printf ("/\tTotal %04o (%d) calls\n", count, count);
- } else {
- printf ("/\tNever called\n");
- }
-}
-
DELETED src/d8tape/flow.c
Index: src/d8tape/flow.c
==================================================================
--- src/d8tape/flow.c
+++ /dev/null
@@ -1,466 +0,0 @@
-
-/*
- * flow.c
- *
- * (C) Copyright 2007 by Robert Krten, all rights reserved.
- * Please see the LICENSE file for more information.
- *
- * This module contains the PDP-8 flow analyzer.
- *
- * 2007 10 25 R. Krten created
- * 2007 10 28 R. Krten added TAG_INDIRECTFC
-*/
-
-#include
-#include
-#include
-#include
-#include
-
-#include "d8tape.h"
-
-extern char *progname; // main.c
-extern char *version; // version.c
-
-extern int optv; // main.c
-extern short int core []; // main.c, in-core image (-1 means location never used)
-extern uint16_t tags []; // main.c, analysis tags
-
-char konstmap [4096]; // 12 bits gives us 0..4095, so 4096 different constants (0 == not used, 1 == unique, 2 == used but not unique)
-
-static void pass1 (void);
-static void pass2 (void);
-static void pass3 (void);
-static void pass4 (void);
-static void verify_subroutines (void);
-static int valid_opr (int opr);
-
-/*
- * Main flow analysis
- *
- * See individual functions for more details
- *
- * Basic idea is that there is a shadow array called "tags", which indicates
- * information about the given memory location (e.g., tags [0017] gives
- * information about core [0017]).
- *
- * The various passes affect the tags[] array with whatever they can detect.
-*/
-
-void
-flow (void)
-{
- pass1 ();
- pass2 ();
- pass3 ();
-// pass4 (); // this pass is fundamentally broken (well, maybe not the pass, but the interpretation of the results in dasm.c)
- verify_subroutines ();
-}
-
-/*
- * pass1
- *
- * On pass 1, we can say with certainty only the following statements:
- * - if it's an invalid IOT or OPR, then it's data.
- * - if the instruction must have a valid EA, and it's invalid,
- * then it's data.
- * - if the JMS (direct only) target is not zero or the same as the
- * address, then it's data
-*/
-
-static void
-pass1 (void)
-{
- int addr, eff;
-
- for (addr = 0; addr < CORE_SIZE; addr++) {
- // skip unused
- if (core [addr] == -1) {
- continue;
- }
- // handle IOTs
- if ((core [addr] & 07000) == 06000) {
- // if we can't decode it, it's not valid
- if (!fetch_iot (core [addr], NULL, NULL)) {
- tags [addr] |= TAG_DATA;
- }
- continue;
- }
- // check OPRs; if they're invalid, tag as DATA, else skip
- if ((core [addr] & 07000) == 07000) {
- if (!valid_opr (core [addr])) {
- tags [addr] |= TAG_DATA;
- if (optv > 1) {
- printf ("+FLOW1 %04o %04o has invalid OPR -> DATA\n", addr, core [addr]);
- }
- }
- // done OPRs, skip
- continue; // @@@ NOTE: this does not work with EAE OPRs that take the next location as their parameter...
- }
-
- // ea() is always valid for opcodes < 06000
- eff = ea (addr, core [addr], NULL, NULL);
-
- // if the instruction should have a valid EA and doesn't...
- if (core [eff] == -1) {
- // then it's not an instruction
- tags [addr] |= TAG_DATA;
- if (optv > 1) {
- printf ("+FLOW1 %04o %04o has EA %04o (invalid or not in core) and OP < 6000 -> DATA\n", addr, core [addr], eff);
- }
- continue;
- }
-
- // if it's a plain JMS
- if ((core [addr] & 07400) == 04000) {
- // and the target isn't zero or it's not the same as the address
- if (core [eff] && core [eff] != eff) {
- tags [addr] |= TAG_DATA;
- if (optv > 1) {
- printf ("+FLOW1 %04o %04o JMS target not 0000 or ADDR (EA %04o is %04o)\n", addr, core [addr], eff, core [eff]);
- }
- continue;
- }
- // else, if it's ok, then the target is writable, after all (JMS drops the return address there)
- tags [eff] |= TAG_WRITABLE;
- if (optv > 1) {
- printf ("+FLOW1 %04o %04o JMS target is 0000 or ADDR, marking EA %04o as WRITABLE\n", addr, core [addr], eff);
- }
- }
- }
-}
-
-/*
- * pass2
- *
- * In this pass, we operate on the direct targets (no indirection)
- * and mark the targets as data, variable, label, or subroutine
- * target.
-*/
-
-static void
-pass2 (void)
-{
- int addr;
- int eff;
-
- for (addr = 0; addr < CORE_SIZE; addr++) {
- // skip unused or data locations
- if (core [addr] == -1 || (tags [addr] & TAG_DATA)) {
- continue;
- }
-
- eff = ea (addr, core [addr], NULL, NULL);
-
- switch (core [addr] & 07400) { // check opcode
- case 00000: // AND
- case 00400: // AND I
- case 01000: // TAD
- case 01400: // TAD I
- case 02000: // ISZ
- case 02400: // ISZ I
- case 03000: // DCA
- case 03400: // DCA I
- tags [eff] |= TAG_DATA; // the referenced EA is data
- if (optv > 1) {
- printf ("+FLOW2 %04o %04o is AND/TAD/ISZ/DCA's EA %04o tagged as DATA\n", addr, core [addr], eff);
- }
-
- // mark as writable if someone writes to it directly (ISZ and DCA only)
- if ((core [addr] & 07400) == 02000 || (core [addr] & 07400) == 03000) {
- tags [eff] |= TAG_WRITABLE;
- if (optv > 1) {
- printf ("+FLOW2 %04o %04o is ISZ/DCA so EA %04o is WRITABLE\n", addr, core [addr], eff);
- }
- }
- break;
-
- case 04000: // JMS
- if (core [eff] == 0 || core [eff] == eff) { // first word of JMS target must be zero or the address itself
- tags [eff] |= TAG_SUB; // otherwise, it's a valid subroutine target
- if (optv > 1) {
- printf ("+FLOW2 %04o %04o is JMS with good target %04o content (%04o) so tagged as SUB\n", addr, core [addr], eff, core [eff]);
- }
- } else {
- tags [addr] |= TAG_DATA; // then invalidate this "instruction", it's bogus
- if (optv > 1) {
- printf ("+FLOW2 %04o %04o is JMS with bad target %04o content (%04o) so tagged as DATA\n", addr, core [addr], eff, core [eff]);
- }
- }
- break;
-
- case 05000: // JMP
- tags [eff] |= TAG_LABEL;
- if (optv > 1) {
- printf ("+FLOW2 %04o %04o is JMP so EA %04o is LABEL\n", addr, core [addr], eff);
- }
- break;
-
- break;
-
- // JMS I, JMP I, IOTs, and OPRs are not handled in this pass
- }
- }
-}
-
-/*
- * pass3
- *
- * In this pass, we verify and mark the indirects
-*/
-
-static void
-pass3 (void)
-{
- int addr;
- int eff;
-
- for (addr = 0; addr < CORE_SIZE; addr++) {
- // skip unused, data, or non-indirect opcodes
- if (core [addr] == -1 || (tags [addr] & TAG_DATA) || core [addr] >= 06000 || !(core [addr] & 00400)) {
- if (optv > 2 && core [addr] != -1) {
- printf ("+FLOW3 %04o %04o tags 0x%04x skipped\n", addr, core [addr], tags [addr]);
- }
- continue;
- }
-
- eff = ea (addr, core [addr], NULL, NULL);
-
- switch (core [addr] & 07000) { // check opcode (indirectness assured above)
- case 00000: // AND I
- case 01000: // TAD I
- case 02000: // ISZ I
- case 03000: // DCA I
- if (core [eff] != -1 && !(tags [eff] & TAG_WRITABLE)) { // if it's valid and constant
- tags [core [eff]] |= TAG_DATA; // then the target is data
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is AND/TAD/ISZ/DCA I through constant EA %04o so target %04o is DATA\n", addr, core [addr], eff, core [eff]);
- }
-
- // mark as writable if someone writes to it (ISZ and DCA only)
- if ((core [addr] & 07000) == 02000 || (core [addr] & 07000) == 03000) {
- tags [core [eff]] |= TAG_WRITABLE;
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is ISZ/DCA I thorugh constant EA %04o so target %04o is WRITABLE\n", addr, core [addr], eff, core [eff]);
- }
- }
- }
- break;
-
- case 04000: // JMS I
- if (core [eff] != -1 && !(tags [eff] & TAG_WRITABLE)) { // if it's valid and constant
- if (core [core [eff]] == 0 || core [core [eff]] == core [eff]) { // valid first word of JMS I target
- tags [core [eff]] |= TAG_SUB; // ultimate target is a valid subroutine target
- tags [eff] |= TAG_DATA; // and the pointer is a valid data type
- tags [eff] |= TAG_INDIRECTFC; // and the pointer is used in an indirect flow control target
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is JMS I through constant EA %04o so target %04o (content %04o) is ok, so tagged as SUB\n", addr, core [addr], eff, core [eff], core [core [eff]]);
- }
- } else {
- tags [addr] |= TAG_DATA; // then this isn't a valid instruction
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is JMS I through constant EA %04o with target %04o (invalid content %04o), so tagged as DATA\n", addr, core [addr], eff, core [eff], core [core [eff]]);
- }
- }
- }
- break;
-
- case 05000: // JMP I
- if (core [eff] != -1) { // if it's valid
- if (!(tags [eff] & TAG_WRITABLE)) { // and constant
- tags [eff] |= TAG_DATA; // pointer is a valid data type
- tags [eff] |= TAG_INDIRECTFC; // and the pointer is used in an indirect flow control target
- tags [core [eff]] |= TAG_LABEL; // ultimate target is a valid JMP target
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is JMP I through constant EA %04o with valid target %04o, so EA tagged as DATA | INDIRECTFC and target data %04o tagged as LABEL\n", addr, core [addr], eff, core [eff], core [core [eff]]);
- }
- }
- } else {
- tags [addr] |= TAG_DATA; // else, it's not really a valid constant expression
- if (optv > 1) {
- printf ("+FLOW3 %04o %04o is JMP I through constant EA %04o with invalid target %04o, so tagged as DATA\n", addr, core [addr], eff, core [eff]);
- }
- }
- break;
- }
- }
-}
-
-/*
- * pass4
- *
- * In this pass, we update the constant map (konstmap).
- *
- * This effectively converts Cxxxx to Kxxxx, and results in more human-
- * friendly code. So, instead of:
- *
- * C1234, 0777
- *
- * you'd see:
- *
- * K0777, 0777
- *
- * The only trick to this is that since symbols must be unique in 6
- * characters (for PAL compatibility), we need to ensure that the
- * items that convert from Cxxxx to Kxxxx are unique. That's why
- * konstmap[] has the values 0, 1, and 2:
- *
- * 0 == constant is not used anywhere in the code
- * 1 == constant is defined exactly once (can be converted)
- * 2 == constant has been defined more than once (cannot be converted)
- *
- * Any constant that's used in an indirect flow control manner, however,
- * is not a candidate, because technically it's not used as a K-style
- * constant.
-*/
-
-static void
-pass4 (void)
-{
- int i;
-
- memset (konstmap, 0, sizeof (konstmap));
-
- // populate konstant[] map
- for (i = 0; i < CORE_SIZE; i++) {
- if (core [i] == -1) {
- continue;
- }
-
- if (tags [i] & TAG_WRITABLE) {
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TAG %02X is writable, therefore, not a constant\n", i, core [i], tags [i]);
- }
- continue;
- }
-
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TAG %02X\n", i, core [i], tags [i]);
- }
- if ((tags [i] & TAG_DATA) && !(tags [i] & TAG_INDIRECTFC)) {
- switch (konstmap [core [i]]) {
- case 0:
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o FRESH KONSTANT\n", i, core [i]);
- }
- konstmap [core [i]]++; // this is our first one, bump the counter
- break;
- case 1:
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o NO LONGER UNIQUE KONSTANT\n", i, core [i]);
- }
- konstmap [core [i]]++; // this is our second one, go to "2"
- break;
- case 2:
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o PROMISCUOUS CONSTANT\n", i, core [i]);
- }
- // do nothing, we're at "2" indicating "non-unique"
- break;
- }
- }
- }
-
- // analyze konstant[] map
- for (i = 0; i < CORE_SIZE; i++) {
- if (core [i] == -1) {
- continue;
- }
- if (tags [i] & TAG_WRITABLE) {
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TAG %02X is writable, therefore, not a constant\n", i, core [i], tags [i]);
- }
- continue;
- }
-
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TESTING (%02X)\n", i, core [i], tags [i]);
- }
- if (tags [i] & TAG_DATA) {
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TESTING...DATA\n", i, core [i]);
- }
- if (konstmap [core [i]] == 1) { // if it's unique
- tags [i] |= TAG_KONSTANT; // then go ahead and tag it
- if (optv > 1) {
- printf ("+FLOW4 %04o %04o TAGGED AS KONSTANT\n", i, core [i]);
- }
- }
- }
- }
-}
-
-/*
- * verify_subroutines
- *
- * This is used to verify that a target really is a subroutine.
- * Verification consists of ensuring that somewhere within the
- * same page is a JMP I through the return address. If not,
- * then the subroutine is bogus, because you can't return from
- * it, so we knock down the "TAG_SUB" flag.
- *
- * BUG: This misses the following case:
- *
- * *0
- * 0 /return area
- * *4000
- * jmp i 0 / return through zero page
- *
- * because we only search for returns within the page that the
- * subroutine definition is in. I don't think this is a major
- * problem, just something to be aware of. Plus, the TAG_RETURN
- * is *really* only used as a comment field indicator anyway.
-*/
-
-static void
-verify_subroutines (void)
-{
- int addr;
- int page;
- int found;
-
- for (addr = 0; addr < CORE_SIZE; addr++) {
- if (!(tags [addr] & TAG_SUB)) {
- continue;
- }
-
- // try and find returns within page
- found = 0;
- for (page = addr; page <= (addr | 00177); page++) {
- if ((core [page] & 07400) == 05400) {
- if (ea (page, core [page], NULL, NULL) == addr) { // JMP I found!
- tags [page] |= TAG_RETURN; // mark the returns
- found++;
- }
- }
- }
- if (!found) {
- tags [addr] &= ~TAG_SUB; // not a subroutine, no return
- }
- }
-}
-
-static int
-valid_opr (int opr)
-{
- // a valid OPR must be 07xxx
- if ((opr & 07000) != 07000) {
- return (0);
- }
-
- if ((opr & 07400) == 07000) { // group 1
- if ((opr & 00014) == 00014) { // with both L and R rotate bits on
- return (0);
- }
- } else if ((opr & 07401) == 07400) { // group 2
- // all ok
- } else if ((opr & 07401) == 07401) { // EAE
- // if bits 6, 8, 9, or 10 are set...
- if (opr & 00056) {
- return (0); // @@@ we're disabling EAE for now
- }
- // otherwise it's an "MQ microinstruction", which is ok
- }
- return (1);
-}
-
DELETED src/d8tape/iot.h
Index: src/d8tape/iot.h
==================================================================
--- src/d8tape/iot.h
+++ /dev/null
@@ -1,418 +0,0 @@
-
-/*
- * iot.h
- *
- * (C) Copyright 2003 by Robert Krten, all rights reserved.
- * Please see the LICENSE file for more information.
- *
- * This module contains the IOT decode table.
- *
- * 2003 12 16 R. Krten created
-*/
-
-/*
- * Conflicting decodes for IOTs
- *
- * 6050 - 6077 VC8I or KV8I; one only
- * 6440 - 6457 PT08 uses some of the data areas from the Data Communications System 680/I -- definition of PT08 is optional
- * 6530 - 6547 AF01A or AF04A; one only
- * 6551 used by AA01A, AA05, or not used. Define zero or one only.
- * 6571 used by AF04A, AC01A, or not used. Define zero or one only.
- * 6600 - 6667 used by DP01AA, overrides DF32/RF08 selection. If defining DP01AA, don't bother with DF32/RF08
- * 6600 - 6627 used by DF32 and RF08, define one only.
- * 6640 - 6647 used by RF08 or not used, define RF08 or not.
- * 6700 - 6727 used by TC58, TR02, and TA8A, define one only
-*/
-
-// Select one of the following:
-#define VC8I
-//#define KV8I
-
-// Select PT08 if required; it will override some of the IOTs from the Data Communications System 680/I
-//#define PT08
-
-// Select one of the following:
-#define AF01A
-//#define AF04A
-
-// Select one of the following:
-#define AA01A
-//#define AA05
-
-// If selecting DP01AA, don't bother with DF32/RF08
-//#define DP01AA
-#ifndef DP01AA
-// Select one of the following:
-#define DF32
-// #define RF08
-#endif // DP01AA
-
-// Select one of the following:
-#define TA8A
-//#define TC58
-//#define TR02
-
-typedef struct
-{
- int code; // code number, e.g. 06001
- char *option; // hardware option, e.g., vc8i
- char *mnemonic; // decoded value, e.g., "ION"
- char *comment; // code description of IOT, e.g., "clear x coordinate buffer"
-} one_iot_t;
-
-#define OP_ALL ""
-one_iot_t iots [] =
-{
- // 6000 Interrupts
-{ 06001, OP_ALL, "ION", "Enable Interrupts"},
-{ 06002, OP_ALL, "IOF", "Disable Interrupts"},
- // 6010 High Speed Perforated Tape Reader and Control
-{ 06011, OP_ALL, "RSF", "Skip if reader flag is a 1."},
-{ 06012, OP_ALL, "RFB", "Read the content of the reader buffer and clear the reader flag. This instructions does not clear the AC. RB v AC4-11 -> AC4-11"},
-{ 06014, OP_ALL, "RFC", "Clear reader flag and reader buffer, fetch one character from tape and load it into the reader buffer, and set the reader flag when done."},
- // 6020 High Speed Perforated Tape Punch and Control
-{ 06021, OP_ALL, "PSF", "Skip if punch flag is a 1"},
-{ 06022, OP_ALL, "PCF", "Clear punch flag and punch buffer."},
-{ 06024, OP_ALL, "PPC", "Load the punch buffer from bits 4 through 11 of the AC and punch the character. This instructions does not clear the punch flag or punch buffer. AC4-11 v PB -> PB"},
-{ 06026, OP_ALL, "PLS", "Clear the punch flag, clear the bunch buffer, load the punch buffer from the content of bits 4 through 11 of the accumulator, punch the character, and set the punch flag to 1 when done."},
- // 6030 Teletype Keyboard / Reader
-{ 06031, OP_ALL, "KSF", "Skip if keyboard flag is a 1."},
-{ 06032, OP_ALL, "KCC", "Clear AC and clear keyboard flag."},
-{ 06034, OP_ALL, "KRS", "Read keyboard buffer static. This is a static command in that neither the AC nor the keyboard flag is cleared. TTI v AC4-11 -> AC4-11"},
-{ 06036, OP_ALL, "KRB", "Clear AC, clear keyboard flag, and read the content of the keyboard buffer into the content of AC4-11."},
- // 6040 Teletype Teleprinter / Punch
-{ 06041, OP_ALL, "TSF", "Skip if teleprinter flag is a 1."},
-{ 06042, OP_ALL, "TCF", "Clear teleprinter flag."},
-{ 06044, OP_ALL, "TPC", "Load the TTO from the content of AC4-11 and print and/or punch the character."},
-{ 06046, OP_ALL, "TLS", "Load the TTO from the content of AC4-11, clear the teleprinter flag, and print and/or punch the character."},
-#ifdef VC8I
- // 6050 Oscilloscope Display Type VC8/I [VC8/L]
-{ 06051, OP_ALL, "DCX", "Clear X coordinate buffer"},
-{ 06053, OP_ALL, "DXL", "Clear and load X coordinate buffer. AC2-11 -> YB"},
-{ 06054, OP_ALL, "DIX", "Intensify the point defined by the content of the X and Y coordinate buffers."},
-{ 06057, OP_ALL, "DXS", "Executes the combined functions of DXL followed by DIX"},
- // 6060 (continued)
-{ 06061, OP_ALL, "DCY", "Clear Y coordinate buffer"},
-{ 06063, OP_ALL, "DYL", "Clear and load Y coordinate buffer. AC2-11 -> YB"},
-{ 06064, OP_ALL, "DIY", "Intensify the point defined by the content of the X and Y coordinate buffers."},
-{ 06067, OP_ALL, "DYS", "Executes the combined functions of DYL followed by DIY"},
- // 6070 (continued)
-{ 06071, OP_ALL, "DSF", "(Light Pen Type 370) Skip if display flag is a 1."},
-{ 06072, OP_ALL, "DCF", "(Light Pen Type 370) Clear the display flag."},
-{ 06074, OP_ALL, "DSB", "Zero brightness"},
-{ 06075, OP_ALL, "DSB", "Set minimum brightness"},
-{ 06076, OP_ALL, "DSB", "Set medium brightness"},
-{ 06077, OP_ALL, "DSB", "Set maximum brightness"},
-#endif
-#ifdef KV8I
- // 6050 Storage Tube Display Control, Type KV8/I [KV8/L]
-{ 06051, OP_ALL, "SNC", "Senses the condition of the cursor interrupt flag. The flag produces an interrupt request when set by operation of the interrupt pushbutton on the joystick. The flag is initially cleared when the computer is started. As with all flag-sent instructions, SNC can be used under interrupt conditions to detect the source of the interrupt, or it can be used under interrupt on (ION) when the interrupt request has been caused by the operation of thecursor interrupt button. In a program running with the interrupt off, SNC can be used to ignore the cursor successive approximation subroutine in the program if a request for service has not been made from the joystick controller."},
-{ 06052, OP_ALL, "CCF", "This instruction is used to clear the cursor flag after a request for service has been acknowledged by the program."},
- // 6060 (continued)
-{ 06062, OP_ALL, "SAC", "The analog comparator is set to compare the analog content of any one of six analog sources with the content of the digital-to-analog converter. The analog sources are chosen according to a 3-bit binary code. This code establishes the parameter for choosing the wanted register according to the content of AC2, AC3, and AC6."},
-{ 06063, OP_ALL, "LDF", "This instruction is used to establish the mode in which a wanted graphic is to be produced according to a 2-bit binary code. This code determines whether the wanted vector will be linear absolute relative, whether the point plot mode will be used, or whether the cursor will be displayed. This code establishes the paramteres for these formats according to the content of AC2 and AC3. The LDF instruction must precede the LDX and LDY instructions."},
-{ 06064, OP_ALL, "LDX", "The X-axis sample and hold register is loaded with the binary equivalent of the X-axis coordinate according to the contents of AC2-11. This data appears at the output of the digital-to-analog converter as the analog equivalent of the X-axis value of the binary word stored in the AC. The LDX instruction clears an existing ready flag and sets the ready flag after 100 +/- 20 us."},
-{ 06065, OP_ALL, "LDY", "The Y-axis sample and hold register is loaded with the binary equivalent of the Y-axis coordinate according to the contents of AC2-11. This data appears at the output of the digital-to-analog converter as the analog equivalent of the binary word in the AC. The LDY instruction clears an existing ready flag and sets the ready flag after 100 +/- 20 us."},
-{ 06066, OP_ALL, "EXC", "Used to execute the wanted vector according to the contents of AC2-4 and AC6-11. The parameter word establishes long or short formats, circular vectors, display erasure, reset of the integrators, and intensification of the vector. The EXC instruction clears an existing ready flag and sets the ready flag as follows: a) after 20 +/- 5 us for a point or vector continue; b) after 250 us for short vectors; c) after 4.05 ms for long vectors; d) after 500 ms for an erase."},
- // 6070 (continued)
-{ 06071, OP_ALL, "SRF", "Used to determine when the controller is ready to perform the next execute instruction. The ready flag produces an interrupt condition when set. The flag can be set by pressing the erase pushbutton on the VT01 unit. Normally, however, the state of this flag is determined by the controller. This flag is initially cleared when the computer is started and prior to an LDX, LDY, or EXC instruction."},
-{ 06072, OP_ALL, "CRF", "This instruction clears the ready flag after a skip instruction has been acknowledged."},
-{ 06073, OP_ALL, "SDA", "Used in the successive approximation subroutine to determine the digital equivalent of the selected analog holding register. This instruction is used with the SAC (6062) instruction."},
-{ 06074, OP_ALL, "LDA", "This instruction is used to load the content of AC2-11. This instruction is used with DSA (6073) in the successive approximation subroutine to determine the digital value of the content of the selected analog holding register. Does not change flag states."},
-#endif
- // 6100 Memory Parity Type MP8/I [MP8/L]
- // 6100 Automatic Restart Type KP8/I [KP8/L]
-{ 06101, OP_ALL, "SMP", "(MP8/I) Skip if memory parity error flag = 0."},
-{ 06102, OP_ALL, "SPL", "(KP8/I) Skip if power low"},
-{ 06104, OP_ALL, "CMP", "(MP8/I) Clear memory parity error flag."},
- // 6110 Multiple Asynchronous Serial Line Interface Unit, Type DC02D
-{ 06111, OP_ALL, "MKSF", "Skip the next instruction if the keyboard flag is set."},
-{ 06112, OP_ALL, "MKCC", "Clear the keyboard and reader flags; clear the AC."},
-{ 06113, OP_ALL, "MTPF", "(DC02A) Transfer status of teleprinter flags to AC 0-3."},
-{ 06114, OP_ALL, "MKRS", "Transfer the shift register contents to AC 4-11."},
-{ 06115, OP_ALL, "MINT", "(DC02A) Interrupt on if AC 11 is set (interrupt request, if any flags)."},
-{ 06116, OP_ALL, "MKRB", "Clear the keyboard and reader flags, clear the AC, trasnfer the shift register contents to AC 4-11 (MKCC and MKRS combined)."},
-{ 06117, OP_ALL, "MTON", "Transfer AC0-3 to selection register (SELF) (select stations when bit is set)."},
- // 6120 Multiple Asynchronous Line Unit, Type DC02A
-{ 06121, OP_ALL, "MTSF", "Skip the next instruction if the teleprinter flag is set."},
-{ 06122, OP_ALL, "MTCF", "Clear the teleprinter flag."},
-{ 06123, OP_ALL, "MTKF", "Transfer status of keyboard flags to AC 0-3."},
-{ 06124, OP_ALL, "MTPC", "Load AC4-11 into the shift register (begin print/punch)."},
-{ 06125, OP_ALL, "MINS", "Skip if the interrupt request is active (if interrupt is on and any flag is raised)."},
-{ 06126, OP_ALL, "MTLS", "Clear the teleprinter flag and load AC4-11 into the shift register (MTCF and MTPC combined)"},
-{ 06127, OP_ALL, "MTRS", "Trasnfer the status of the selection register to AC 0-3."},
- // 6130 Real Time Clock, Type KW8/I [KW8/L]
-{ 06132, OP_ALL, "CCFF", "The flag, flag buffer, clock enable, and interrupt enable flip-flops are cleared. This disables the real-time clock."},
-{ 06133, OP_ALL, "CSCF", "When the flag flip-flop has been set by a clock pulse, the flag buffer flip-flop is set to a 1. Upon execution of this instruction, an IO BUS IN SKIP is generated if the flag is set. The content of the PC is incremented by 1, so that the next sequential instruction is skipped. The flag flip-flop is then cleared. If the flag flip-flop has not been set, no skip is generated nor is the flag flip-flop cleared."},
-{ 06134, OP_ALL, "CRCA", "The output buffer is gated to the I/O BUS during IOP4, and a CLK AC CLR signal generated. This register contains the last count in the count register. The transfer from the count register is synchronized with this instruction so that a transfer that would occur during this instruction is not made."},
-{ 06136, OP_ALL, "CCEC", "All clock control flip-flops are first cleared, then the clock enable flip-flop is set. For the variable frequency clock, the frequency source is enabled synchronously with program operation. With all clocks, the data input to the flag is enabled after IOP2 time. This represents an 800-ns mask, after the clock is enabled."},
-{ 06137, OP_ALL, "CECI", "All clock control flip-flops are cleared, then the clock enable, and interrupt enable flip-flops are set. The clock enable flip-flop is described with the CCEC instruction. The interrupt enable flip-flop allows an IO BUS IN INT signal when the flag is set."},
- // 6140
- // 6150
- // 6160
- // 6170
- // 6200 through 6277 Memory Extension Control Type MC8/I [MC8/L]
-{ 06201, OP_ALL, "CDF0", "Change to data field 0. The data field register is loaded with the selected field number (0). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06202, OP_ALL, "CIF0", "Prepare to change to instruction field N (0). The instruction buffer register is loaded with the selected field number (0). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06204, OP_ALL, "CINT", "(KT8/I) Clear user interrupt. Resets the user interrupt (UINT) flip-flop to the 0 state."},
- // 6210
-{ 06211, OP_ALL, "CDF0", "Change to data field 1. The data field register is loaded with the selected field number (1). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06212, OP_ALL, "CIF0", "Prepare to change to instruction field N (1). The instruction buffer register is loaded with the selected field number (1). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06214, OP_ALL, "RDF", "Read data field into AC6-8. Bit 0-5 and 9-11 of the AC are not affected."},
- // 6220
-{ 06221, OP_ALL, "CDF0", "Change to data field 2. The data field register is loaded with the selected field number (2). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06222, OP_ALL, "CIF0", "Prepare to change to instruction field N (2). The instruction buffer register is loaded with the selected field number (2). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06224, OP_ALL, "RIF", "Same as RDF except reads the instruction field"},
- // 6230
-{ 06231, OP_ALL, "CDF0", "Change to data field 3. The data field register is loaded with the selected field number (3). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06232, OP_ALL, "CIF0", "Prepare to change to instruction field N (3). The instruction buffer register is loaded with the selected field number (3). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06234, OP_ALL, "RIB", "Read interrupt buffer. The instruction field and data field stored during an interrupt are read into AC6-8 and AC9-11, respectively."},
- // 6240
-{ 06241, OP_ALL, "CDF0", "Change to data field 4. The data field register is loaded with the selected field number (4). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06242, OP_ALL, "CIF0", "Prepare to change to instruction field N (4). The instruction buffer register is loaded with the selected field number (4). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06244, OP_ALL, "RMF", "Restore memory field. Used to exit from a program interrupt."},
- // 6250
-{ 06251, OP_ALL, "CDF0", "Change to data field 5. The data field register is loaded with the selected field number (5). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06252, OP_ALL, "CIF0", "Prepare to change to instruction field N (5). The instruction buffer register is loaded with the selected field number (5). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06254, OP_ALL, "SINT", "(KT8/I) Skip on user interrupt. When the user interrupt (UINT) flip-flop is in the 1 state, sets the user skip flip-flop (USF) to the 1 state and causes the program to skip the next instruction."},
- // 6260
-{ 06261, OP_ALL, "CDF0", "Change to data field 6. The data field register is loaded with the selected field number (6). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06262, OP_ALL, "CIF0", "Prepare to change to instruction field N (6). The instruction buffer register is loaded with the selected field number (6). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06264, OP_ALL, "CUF", "(KT8/I) Clears the user flag. Clears the user buffer (UB) flip-flop."},
- // 6270
-{ 06271, OP_ALL, "CDF0", "Change to data field 7. The data field register is loaded with the selected field number (7). All subsequent memory requests for operands are automatically switched to that data field until the data field number is changed by a new CDF command."},
-{ 06272, OP_ALL, "CIF0", "Prepare to change to instruction field N (7). The instruction buffer register is loaded with the selected field number (7). The next JMP or JMS instruction causes the new field to be entered."},
-{ 06274, OP_ALL, "SUF", "(KT8/I) Sets the user flag. Sets user buffer (UB) and inhibits processor interrupts until the next JMP or JMS instruction. Generation of IB -> IF during the next JMP or JMS instruction transfers the state of UB to the user field (UF) flip-flop."},
- // 6400 Data Communications System 680/I
-{ 06401, OP_ALL, "TTINCR", "This instruction causes the contents of the line register to be incremented by 1. This command, when microprogrammed with a TTO command is executed."},
-{ 06402, OP_ALL, "TTI", "Causes a JMS to be executed (N+3) if the R register does not equal 0 and either the line hold bit of the selected line (specified by bits 2-8 of the LSW) is in the 1 state, or as a result of jamming the line state into and shifting the CAW; bit 11 of the CAW is a 1."},
-{ 06404, OP_ALL, "TTO", "Clears the link and shifts the link and accumulator one bit position to the right. Bit 11 of the accumulator is shifted into the line unit specified by the line register. The previuos contents (1 bit) of the selected line unit is lost."},
- // 6410
-{ 06411, OP_ALL, "TTCL", "The command sets the contents of the line register to 0."},
-{ 06412, OP_ALL, "TTSL", "The contents of AC5-11 are ORed into the line register."},
-{ 06413, OP_ALL, "TTLL", "The contents of AC5-11 are trasnferred into the line register. This is a microprogram of TTCL and TTSL."},
-{ 06414, OP_ALL, "TTRL", "The contents of the line register are ORed into AC5-11. The AC must be 0 for a true transfer."},
- // 6420
-{ 06421, OP_ALL, "T1skip", "(Data Communications System 680/I) Clock Control Instruction: Causes the program to skip the next instruction if clock flag 1 is in the 1 state. To clear the flag, either T1on or T1off can be used."},
-{ 06422, OP_ALL, "T1off", "(Data Communications System 680/I) Clock Control Instruction: Inhibits clock 1 from setting its flag. This instruction also sets the flag to the 0 state."},
-{ 06424, OP_ALL, "T1on", "(Data Communications System 680/I) Clock Control Instruction: Enables clock 1 to set its flag at the predetermined lcock rate. The flag in the 1 state causes a program interrupt when the interrupt is enabled. This instruction also sets the flag to the 0 state."},
- // 6430
-{ 06431, OP_ALL, "T2skip", "(Data Communications System 680/I) same as T1skip except for clock 2"},
-{ 06432, OP_ALL, "T2off", "(Data Communications System 680/I) same as T1off except for clock 2"},
-{ 06434, OP_ALL, "T2on", "(Data Communications System 680/I) same as T1on except for clock 2"},
-#ifdef PT08
- // 6440 Asynchronous Serial Line Interface, Type PT08
-{ 06441, OP_ALL, "TSFXXX", "Skip if teleprinter/punch 3 flag is a 1."},
-{ 06442, OP_ALL, "TCFXXX", "Clear teleprinter/punch 3 flag."},
-{ 06444, OP_ALL, "TPCXXX", "Load teleprinter 3 buffer (TTOX) with AC4-11 and print/punch the character."},
-{ 06446, OP_ALL, "TLSXXX", "Load TTOX with AC4-11, 3 flag, print/punch the character and clear teleprinter/punch."},
-{ "6450"},
-{ 06451, OP_ALL, "KSFXXX", "Skip if keyboard/reader 3 flag is a 1."},
-{ 06452, OP_ALL, "KCCXXX", "Clear AC and keyboard/reader 3 flag."},
-{ 06454, OP_ALL, "KRSXXX", "Read keyboard/reader 3 buffer (TTI3) static. TTI3 is loaded into AC4-11 by an OR transfer."},
-{ 06456, OP_ALL, "KRBXXX", "Clear the AC, read TTI3 into AC4-11, and clear keyboard 3 flag."},
-{#else "PT08"},
-{ 06441, OP_ALL, "T3skip", "(Data Communications System 680/I) same as T1skip except for clock 3"},
-{ 06442, OP_ALL, "T3off", "(Data Communications System 680/I) same as T1off except for clock 3"},
-{ 06444, OP_ALL, "T3on", "(Data Communications System 680/I) same as T1on except for clock 3"},
-{ 06451, OP_ALL, "T4skip", "(Data Communications System 680/I) same as T1skip except for clock 4"},
-{ 06452, OP_ALL, "T4off", "(Data Communications System 680/I) same as T1off except for clock 4"},
-{ 06454, OP_ALL, "T4on", "(Data Communications System 680/I) same as T1on except for clock 4"},
-#endif
-{ 06461, OP_ALL, "TTRINC", "(Data Communications System 680/I) This command causes the contents of the R register to be incremented by 1. Because it is loaded with a 2's complement number, the result is a subtract. This instruction can be microprogrammed with TTRR."},
-{ 06464, OP_ALL, "TTRR", "(Data Communications System 680/I) This command reads the contents of the R register into AC7-11. The contents of the AC must be 0s before issuing this instruction. This instruction, when microprogrammed with TTINCR, causes the incremented results to be read into the AC."},
- // 6470
-{ 06471, OP_ALL, "TTCR", "(Data Communications System 680/I) This command causes the R register to be set to 0"},
-{ 06472, OP_ALL, "TTLR", "(Data Communications System 680/I) This command causes the contents of AC7-11 to be trasnferred into the R register."},
- // 6500 Incremental Plotter and Control Type VP8/I
-{ 06501, OP_ALL, "PLSF", "Skip if plotter flag is a 1."},
-{ 06502, OP_ALL, "PLCF", "Clear plotter flag."},
-{ 06504, OP_ALL, "PLPU", "Plotter pen up. Raise pen off of paper."},
- // 6510
-{ 06511, OP_ALL, "PLPR", "Plotter pen right."},
-{ 06512, OP_ALL, "PLDU", "Plotter drum (paper) upward"},
-{ 06514, OP_ALL, "PLDD", "Plotter drum (paper) downward."},
- // 6520
-{ 06521, OP_ALL, "PLPL", "Plotter pen left."},
-{ 06522, OP_ALL, "PLUD", "Plotter drum (paper) upward. Same as 6512"},
-{ 06524, OP_ALL, "PLPD", "Plotter pen down. Lower pen on to paper."},
-#ifdef AF01A
- // 6530 General Purpose Converter and Multiplexer Control Type AF01A (this option is mutually exclusive with AF04A)
-{ 06531, OP_ALL, "ADSE", "Skip if A/D converter flag is a 1."},
-{ 06532, OP_ALL, "ADCV", "Clear A/D converter flag and convert input voltage to a digital number, flag will set to 1 at end of conversion. Number of bits in converted number determined by switch setting, 11 bits maximum."},
-{ 06534, OP_ALL, "ADRB", "Read A/D converter buffer into AC, left justified, and clear flag."},
- // 6540
-{ 06541, OP_ALL, "ADCC", "Clear multiplexer channel address register."},
-{ 06542, OP_ALL, "ADSC", "Set up multiplexer channel as per AC6-11. Maximum of 64 single ended or 32 differntial input channels."},
-{ 06544, OP_ALL, "ADIC", "Index multiplexer channel address (present address + 1). Upon reaching address limit, increment will cause channel 00 to be selected."},
-#endif // AF01A
-#ifdef AF04A
- // 6530 Guarded Scanning Digital Voltmeter Type AF04A (this option is mutually exclusive with AF01A)
-{ 06531, OP_ALL, "VSDR", "Skip if data ready flag is a 1."},
-{ 06532, OP_ALL, "VRD", "Selected byte of voltmeter is transferred to the accumulator and the data ready flag is cleared."},
-{ 06534, OP_ALL, "VBA", "BYTE ADVANCE command requests next twelve bits, data ready flag is set."},
- // 6540
-{ 06541, OP_ALL, "VCNV", "The contents of the accumulator are transferred to the AF04A channel address register. Analog signal on selected channel is automatically digitized."},
-{ 06542, OP_ALL, "VSEL", "The contents of the accumulator are transferred to the AF04A control register."},
-{ 06544, OP_ALL, "VINX", "The last channel address is incremented by one and the analog signal on the selected channel is automatically digitized."},
-#endif // AF04A
- // 6550
-#ifdef AA01A
-{ 06551, OP_ALL, "DAL1", "(AA01A) The character in the accumulator is loaded into the channel 1 buffer. The DAC then converts the buffered value to the analog equivalent. NOTE: Similar instructions for DAL2 and DAL3 load respective DACs."},
-#else // AA01A
-#ifdef AA05
-{ 06551, OP_ALL, "CLDA", "The address register in the AA05/AA07 is cleared."},
-#else // AA05
-#endif // AA05
-#endif // AA01A
-{ 06552, OP_ALL, "LDAD", "(AA05/AA07) The address register in the AA05/AA07 is loaded with the contents of AC0-5."},
- // 6560
-{ 06562, OP_ALL, "LDAR", "(AA05/AA07) The buffer (input buffer, if the channel is double-buffered) of the DAC is loaded from AC0-9."},
-{ 06564, OP_ALL, "UPDT", "(AA05/AA07) The contents of the input buffers of all double-buffered channels are trasnferred to their respective output buffers. The input buffer is not affected by this instruction."},
- // 6570
-#ifdef AF04A
-{ 06571, OP_ALL, "VSCC", "SAMPLE CURRENT CHANNEL when required to digitize analog signal on current channel repeatedly (AF04A)"},
-#else // AF04A
-#ifdef AC01A
-{ 06571, OP_ALL, "HRAN", "The contents of AC3-5 are trasnferred to the channel address register (CHAR). The 3-bit code is decoded to address any of the 8 channels."},
-#else // AC01A
-#endif // AC01A
-#endif // AF04A
-#ifdef AC01A
-{ 06572, OP_ALL, "HSIM", "Simultaneously places all 8 channels into the hold mode."},
-#else // AC01A
-#endif // AC01A
-{ 06574, OP_ALL, "SAMP", "(AA01A) Places all 8 channels into the sample (or track) mode."},
-#ifdef DP01AA
- // 6600 Synchronous Modem Interface, Type DP01AA
-{ 06601, OP_ALL, "TAC", "Causes the contents of the AC (6, 7, 8, or 9 bits right-justified) to be transferred into the TB."},
-{ 06602, OP_ALL, "CTF", "Resets the trasnmit flag. If trasnmit active flag is set, CTF also causes the program to skip the next instruction."},
-{ 06604, OP_ALL, "CIM", "Resets the transmit logic idle mode (IM) flip-flop."},
-{ 06611, OP_ALL, "STF", "Causes the program to skip the next instruction if the transmit flag is in the 0 state. When the transmit flag is in the 1 state, the trasnmit buffer register (TB) is ready to accept another character."},
-{ 06612, OP_ALL, "RRB", "Transfers the contents of the receiver buffer (RB) (6, 7, 8, or 9 bits, right-justified) to the computer AC. RRB also resets the receive flag."},
-{ 06614, OP_ALL, "SIM", "Sets the transmit idle mode (IM) flip-flop."},
-{ 06621, OP_ALL, "SEF", "Causes the program to skip the next instruction if the receive end flag is 0. The receive end flag slip-flop is set when the receive logic has stopped receiving serial data from the communications equipment due to termination of th SERIAL CLOCK RECEIVE pulse train."},
-{ 06622, OP_ALL, "CEF", "Clears the receive end flag"},
-{ 06624, OP_ALL, "SRE", "Sets the ring enable (RE) flip-flop to a 1, which permits the ring flag to request a program interrupt."},
-{ 06631, OP_ALL, "SRI", "Causes the program to skip the next instruction if the ring flag is 0. The ring flag is set when a ring input is received."},
-{ 06632, OP_ALL, "CRF", "Clears the ring flag."},
-{ 06634, OP_ALL, "STR", "Sets the terminal read (TR) flip-flop to the 1 state. This causes the terminal ready lead to the modem to be set on the ON state. The state changes to OFF for CTR"},
-{ 06641, OP_ALL, "SSR", "Causes the program to skip the next instruction if the data-set-ready lead from the modem is in the ON state."},
-{ 06642, OP_ALL, "CTR", "Clears the terminal ready (TR) flip-flop (see STR)"},
-{ 06644, OP_ALL, "CRE", "Clears the ring enable (RE) flip-flop."},
-{ 06651, OP_ALL, "SRF", "Causes the program to skip the next instruction if the receive flag is 0. The flag is set when a received character is ready for trasnfer to the AC and the flag is cleared when an RRB instruction is issued."},
-{ 06652, OP_ALL, "CRA", "Clears the receive active (RA) flip-flop, taking the receive logic out of the active state. This inhibits any more receive flags until a new sync character is received."},
-{ 06654, OP_ALL, "XOB", "Causes an exclusive OR of the AC with the buffer register (BR)."},
-{ 06661, OP_ALL, "COB", "Clears the XOR buffer."},
-{ 06662, OP_ALL, "ROB", "Transfers the buffer register (BR) content to the AC."},
-{ 06664, OP_ALL, "IOB", "Transfers 1s from the AC to the buffer register (BR)."},
-#else // DP01AA
-#ifdef DF32
- // 6600 Random Access Disc File (type DF32)
-{ 06601, OP_ALL, "DCMA", "Clears memory address register, parity erorr and completion flags. This instruction clears the disk memory request flag and interrupt flags."},
-{ 06603, OP_ALL, "DMAR", "The contents of the AC are loaded into the disk memory address register and the AC is cleared. Begin to read information from the disk into the specified core location. Clears parity error and completion flags. Clears interrupt flags."},
-{ 06605, OP_ALL, "DMAW", "The contents of the AC are loaded into the disk memory address register and the AC is cleared. Begin to write information into the disk from the specified core location. Clears parity error and completion flags."},
- // 6610
-{ 06611, OP_ALL, "DCEA", "Clears the disk extended address and memory address extension register."},
-{ 06612, OP_ALL, "DSAC", "Skips next instruction if address confirmed flag is a 1. AC is cleared."},
-{ 06615, OP_ALL, "DEAL", "The disk extended-address extension registers are cleared and loaded with the track data held in the AC."},
-{ 06616, OP_ALL, "DEAC", "Clear the AC then loads the contents of the disk extended-address register into the AC to allow program evaluation. Skip next instruction if address confirmed flag is a 1."},
- // 6620
-{ 06621, OP_ALL, "DFSE", "Skip next instruction if the completion flag is a 1. Indicates data transfer is complete."},
-{ 06626, OP_ALL, "DMAC", "Clear the AC then loads contents of disk memory address register into the AC to allow program evaluation."},
-#endif // DF32
-#ifdef RF08
- // 6600 Disk File and Control, Type RF08/Expander Disk File, Type RS08
- // 6610
-{ 06611, OP_ALL, "DCIM", "Clear the disk interrupt enable and core memory address extension register."},
-{ 06615, OP_ALL, "DIML", "Clear the interrupt enable and memory address extension register, then load the interrupt enable and memory address extension registers with data held in the AC. Then clear the AC. NOTE: Transfers cannot occur across memory fields. Attempts to do so will cause the transfer to "wrap around" within the specified memory field."},
-{ 06616, OP_ALL, "DIMA", "Clear the AC. Then load the contents of the status register (STR) into the AC to allow program evaluation."},
- // 6620
-{ 06621, OP_ALL, "DFSE", "Skip next instruction if there is a parity error, data request late, write lock status, or nonexistent disk flag set."},
-{ 06623, OP_ALL, "DISK", "If either the error or data completion flag (or both) is set, the next instruction is skipped."},
-#endif // RF08
- // 6630 Card Reader and Control Type CR8/I [CR8/L] (see also 6670)
-{ 06631, OP_ALL, "RCSF", "Generates an IOP pulse (IOP 1) to test the data-ready flag output. If the data ready flag is 1, the next sequential program instruction is skipped."},
-{ 06632, OP_ALL, "RCRA", "Generates an IOP pulse (IOP 2) to read the alphanumeric data at the control-logic buffer register and clear the data ready flag."},
-{ 06634, OP_ALL, "RCRB", "Generates an IOP pulse (IOP 4) to read the BCD data at the control logic buffer register and clear the data ready flag."},
-#ifdef RF08
- // 6640
-{ 06641, OP_ALL, "DCXA", "Clear the high order 8-bits of the disk address register (DAR)."},
-{ 06643, OP_ALL, "DXAL", "Clear the high order 8 bits of the DAR. Then load the DAR from data stored in the AC. Then clear the AC."},
-{ 06645, OP_ALL, "DXAC", "Clear the AC; then load the contents of the high order 8-bit DAR into the AC."},
-{ 06646, OP_ALL, "DMMT", "For maintenance purposes only with the appropriate maintenance cable connections and the disk disconnected from the RS08 logic, the (given) standard signals may be generated by IOT 6646 and associated AC bits. The AC is cleared and the maintenance register is initiated by issuing an IOT 6601 command."},
-#else // RF08
- // 6640
-#endif // RF08
- // 6650 Automatic Line Printer and Control Type 645
-{ 06651, OP_ALL, "LSE", "Skip if line printer error flag is a 1."},
-{ 06652, OP_ALL, "LCB", "Clear both sections of the printing buffer."},
-{ 06654, OP_ALL, "LLB", "Load printing buffer from the content of AC6-11 and clear the AC"},
- // 6660 Automatic Line Printer and Control Type 645 (continued)
-{ 06661, OP_ALL, "LSD", "Skip if the printer done flag is a 1."},
-{ 06662, OP_ALL, "LCF", "Clear line printer done and error flags."},
-{ 06664, OP_ALL, "LPR", "Clear the format register, load the format register from the content of AC9-11, print the line contained in the section of the printer buffer loaded last, clear the AC, and advance the paper in accordance with the selected channel of the format tape if the content of AC8=1. If the content of AC8=0, the line is printed and paper advance is inhibited."},
-#endif // DP01AA
- // 6670 Card Reader and Control Type CR8/I [CR8/L] (see also 6630)
-{ 06671, OP_ALL, "RCSD", "Generates an IOP pulse (IOP 1) to test the card-done flag output. If the card done flag is 1, the next sequential program instruction is skipped."},
-{ 06672, OP_ALL, "RCSE", "Generates an IOP pulse (IOP 2) to advance the card, clear the card done flag, and produce a skip flag is reader is ready. If skip flag is generated, the next sequential program instruction is skipped."},
-{ 06674, OP_ALL, "RCRD", "Generates an IOP pulse (IOP 4) to clear the card done flag."},
-#ifdef TA8A
- // 6700 -> 6707 TU60 DECassette Controller TA8A
-{ 06700, OP_ALL, "KCLR", "Clear All; clear the status A and B register"},
-{ 06701, OP_ALL, "KSDR", "Skip the next instruction if the data flag is set during read or write operations"},
-{ 06702, OP_ALL, "KSEN", "Skip the next instruction if any of the following are true: a) tape is at EOT/BOT, b) the TU60 is not ready or the selected drive is empty"},
-{ 06703, OP_ALL, "KSBF", "Skip the next instruction if the ready flag is set"},
-{ 06704, OP_ALL, "KLSA", "Load status A from AC4-AC11, clear the AC, and load the complement of status A back into the AC"},
-{ 06705, OP_ALL, "KSAF", "Skip on any flag or error condition"},
-{ 06706, OP_ALL, "KGOA", "Assert the contents of the status A register and transfer data into the AC during a read operation or out of the AC to the Read/Write buffer during a write operation. This instruction has three functions: a) enables the command in the status A register to be executed by the TU60, b) for read operations, the first KGOA instruction causes the tape to start moving, and when the data flag sets, a second KGOA transfers the first byte from the read/write buffer to the AC. The data flag sets after each 8-bit byte is read from the TU60. c) for write operations, the status A register is set up for a write, and the AC contains the first byte to be written on tape. When the KGOA instruction is executed, the tape starts to move and the first byte is transferred to the TU60."},
-{ 06707, OP_ALL, "KRSB", "Transfer the contents of the status B register into AC4-AC11."},
-#endif
-#ifdef TC58
- // 6700 Automatic Magnetic Tape Control Type TC58
-{ 06701, OP_ALL, "MTSF", "Skip on error flag or magnetic tape flag. The status of the error flag (EF) and the magnetic tape flag (MTF) are sampled. If either or both are set to 1, the content of the PC is incremented by one to skip the next sequential instruction."},
-{ 06702, OP_ALL, "6702", "(no mnemonic assigned) Clear the accumulator."},
-{ 06704, OP_ALL, "6704", "(no mnemonic assigned) Inclusively OR the contents of the status register into AC0-11"},
-{ 06706, OP_ALL, "MTRS", "Read the contents of the status register into AC0-11."},
- // 6710
-{ 06711, OP_ALL, "MTCR", "Skip on tape control ready (TCR). If the tape control is ready to receive a command, the PC is incremented by one to skip the next sequential instruction."},
-{ 06712, OP_ALL, "MTAF", "Clear the status and command registers, and the EF and MTF if tape control ready. If tape control not ready, clears MTF and EF flags only."},
-{ 06714, OP_ALL, "MTCM", "Inclusively OR the contents of AC0-5, AC9-11 into the command register; JAM transfer bits 6, 7, 8 (command function)"},
-{ 06716, OP_ALL, "MTLC", "Load the contents of AC0-1j1 into the command register."},
- // 6720
-{ 06721, OP_ALL, "MTTR", "Skip on tape transport ready (TTR). The next sequential instruction is skipped if the tape transport is ready."},
-{ 06722, OP_ALL, "MTGO", "Set "go" bit to execute command in the command register if command is legal."},
-{ 06724, OP_ALL, "MTRC", "Inclusively OR the contents of the contents of the command register into AC0-11."},
-#endif // TC58
-#ifdef TR02
- // 6700 Incremental Magnetic Tape Controller, Type TR02
-{ 06701, OP_ALL, "IRS", "When data is ready to be strobed into the AC from the read buffer (RB), the PC is incremented by one to skip the next sequential instruction. The read done flag is cleared only if the skip occurs."},
-{ 06702, OP_ALL, "ISR", "The content of the status register (STR) is read into AC0-8. The AC should be cleared before it is read by this instruction."},
-{ 06703, OP_ALL, "IWS", "If the write done flag is set, the next instruction is skipped and the write done flag is cleared."},
-{ 06704, OP_ALL, "IMC", "The move command decoded from AC0-2 is generated. This instruction also clears the read done, write done, and gap detect flags. The indicated flag is set when the command has been executed."},
-{ 06705, OP_ALL, "IGS", "If the gap detect flag is set, the next instruction is skipped and the gap detect flag is cleared."},
-{ 06706, OP_ALL, "IWR", "The contents of the AC are loaded into the tape input data buffer (WB) and a write step command is generated. The write done flag is set when writing is completed."},
-{ 06707, OP_ALL, "IRD", "The AC is cleared and the content of the read buffer (RB) is loaded into the AC. Data bits are transferred into AC6-11 (7-track) or AC4-11 (9-track). Parity error is transferred into AC0 which is 0 if there is no parity error."},
- // 6710
-{ 06711, OP_ALL, "IRSA", "When data is ready to be strobed into the AC from the read buffer (RB), the PC is incremented by one to skip the next sequential instruction. The read done flag is cleared only if the skip occurs."},
-{ 06712, OP_ALL, "ISRA", "The content of the status register (STR) is read into AC0-8. The AC should be cleared before it is read by this instruction."},
-{ 06713, OP_ALL, "IWSA", "If the write done flag is set, the next instruction is skipped and the write done flag is cleared."},
-{ 06714, OP_ALL, "IMCA", "The move command decoded from AC0-2 is generated. This instruction also clears the read done, write done, and gap detect flags. The indicated flag is set when the command has been executed."},
-{ 06715, OP_ALL, "IGSA", "If the gap detect flag is set, the next instruction is skipped and the gap detect flag is cleared."},
-{ 06716, OP_ALL, "IWRA", "The contents of the AC are loaded into the tape input data buffer (WB) and a write step command is generated. The write done flag is set when writing is completed."},
-{ 06717, OP_ALL, "IRDA", "The AC is cleared and the content of the read buffer (RB) is loaded into the AC. Data bits are transferred into AC6-11 (7-track) or AC4-11 (9-track). Parity error is transferred into AC0 which is 0 if there is no parity error."},
- // 6720
-#endif // TC58
- // 6730
- // 6740
- // 6750
- // 6760 DECtape Transport Type TU55 and DECtape Control Type TC01
-{ 06761, OP_ALL, "DTRA", "The content of status register A is read into AC0-9 by an OR transfer. The bit assignments are: AC0-2 = Transport unit select numnber; AC3-4 = Motion; AC5 = Mode; AC6-8 = Function; AC9 = Enable/disable DECtape control flag."},
-{ 06762, OP_ALL, "DCTA", "Clear status register A. All flags undisturbed."},
-{ 06764, OP_ALL, "DTXA", "Status register A is loaded by an exclusive OR transfer from the content of the AC, and AC10 and AC11 are sampled. If AC10 = 0, the error flags are cleared. If AC11 = 0, the DECtape control flag is cleared."},
- // 6770
-{ 06771, OP_ALL, "DTSF", "Skip if error flag is a 1 or if DECtape control flag is a 1."},
-{ 06772, OP_ALL, "DTRB", "The content of status register B is read into the AC by an OR transfer. The bit assignments are: AC0 = Error flag; AC1 = Mark track error; AC2 = End of tape ; AC3 = Select error ; AC4 = Parity error; AC5 = Timing error; AC6-8 = Memory field; AC9-10 = Unused; AC11 = DECtape flag."},
-{ 06774, OP_ALL, "DTLB", "The memory field portion of status register B is loaded from the content of AC6-8."},
-};
-
DELETED src/d8tape/main.c
Index: src/d8tape/main.c
==================================================================
--- src/d8tape/main.c
+++ /dev/null
@@ -1,848 +0,0 @@
-
-/*
- * main.c
- *
- * (C) Copyright 2000 by Robert Krten, all rights reserved.
- * Please see the LICENSE file for more information.
- *
- * This module represents the main module for the RIM/BIN
- * dumper/disassembler/converter/reverse engineering tool.
- *
- * This program will dump a RIM/BIN-formatted image to stdout, or
- * convert a tape from one format to another, or clean up a tape,
- * or disassemble a tape with reverse-engineering aids.
- *
- * 2001 01 07 R. Krten created
- * 2003 12 16 R. Krten added disassembler
- * 2003 12 17 R. Krten made it RIM/BIN aware.
- * 2007 10 25 R. Krten added reverse-engineering features
- * 2007 11 04 R. Krten fixed header skip logic (see dumptape())
-*/
-
-#ifdef __USAGE
-
-%C [options] papertapefile [papertapefile...]
-
-where [options] are optional parameters chosen from:
- -b generate a BIN-formatted output (adds ".bin")
- -d suppress disassembly (useful for conversion-only mode)
- -r generate a RIM-formatted output (adds ".rim")
- -T generate test pattern 0000=0000..7756=7756
- -v verbose operation
-
-Dumps the RIM- or BIN-formatted input file(s) specified on
-the command line. If the "-r" and/or "-b" options are
-present, also creates a RIM and/or BIN version of the output
-by adding ".rim" and/or ".bin" (respectively) to the input
-filename (can be used to "clean up" BIN and RIM images by
-deleting excess data before and after the leader/trailer).
-
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "d8tape.h"
-
-static void seg_add (uint16_t addr, int len);
-static void seg_more (int len);
-
-static void optproc (int, char **);
-static int dumptape (unsigned char *t, int n);
-static int dumprim (unsigned char *t, int n);
-static int dumpbin (unsigned char *t, int n);
-static int checkrim (unsigned char *t, int n);
-static int checkbin (unsigned char *t, int n);
-static void writebin (void);
-static void writerim (void);
-static int blank (short int *core, int size);
-
-const char *progname = "d8tape";
-const char *blankname= " ";
-extern char *version; // version.c
-
-int optb;
-int optd;
-int optr;
-int optT;
-int optv;
-unsigned char *tape; // paper tape image
-short int core [CORE_SIZE]; // in-core image (-1 means location never used)
-uint16_t tags [CORE_SIZE]; // analysis tags
-segment_t *segments; // used to accumulate runs of data (from origin for nwords)
-int nsegments; // indicates how many segments we have
-char *tapename;
-
-/*
- * main
- *
- * Main simply calls the option processor, from which everything happens.
-*/
-
-int
-main (int argc, char **argv)
-{
- optproc (argc, argv);
- exit (EXIT_SUCCESS);
-}
-
-/*
- * usageError
- *
- * This is the usage message
-*/
-
-static void
-usageError ()
-{
- fprintf (stderr, "\nUsage: %s [options] papertapefile [papertapefile...]\n\n", progname);
- fprintf (stderr, "where [options] are optional parameters chosen from:\n");
- fprintf (stderr, " -b generate a BIN-formatted output (adds \".bin\")\n");
- fprintf (stderr, " -d suppress disassembly (useful for conversion-only mode)\n");
- fprintf (stderr, " -r generate a RIM-formatted output (adds \".rim\")\n");
- fprintf (stderr, " -v verbose operation\n");
- fprintf (stderr, "\n");
- fprintf (stderr, "Dumps the RIM- or BIN-formatted input file(s) specified on\n");
- fprintf (stderr, "the command line. If the \"-r\" and/or \"-b\" options are\n");
- fprintf (stderr, "present, also creates a RIM and/or BIN version of the output\n");
- fprintf (stderr, "by adding \".rim\" and/or \".bin\" (respectively) to the input\n");
- fprintf (stderr, "filename (can be used to \"clean up\" BIN and RIM images by\n");
- fprintf (stderr, "deleting excess data before and after the leader/trailer).\n");
- fprintf (stderr, "\n");
- fprintf (stderr, "Disassembly conforms to PAL III input requirements\n");
- fprintf (stderr, "\n");
- exit (EXIT_FAILURE);
-}
-
-/*
- * optproc
- *
- * This is the option processor. It detects the command line options, and
- * then processes the individual files.
-*/
-
-static void
-optproc (int argc, char **argv)
-{
- int opt;
- int got_any;
- int fd;
- int i;
- struct stat statbuf;
- int sts;
-
- if (!argc) {
- usageError ();
- }
-
- // clear out option values to defaults
- optb = optr = optT = 0;
-
- // handle command line options
- got_any = 0;
- while ((opt = getopt (argc, argv, "bdrTv")) != -1) {
- switch (opt) {
- case 'b':
- optb++;
- break;
- case 'd':
- optd++;
- break;
- case 'r':
- optr++;
- break;
- case 'T':
- optT++;
- break;
- case 'v':
- optv++;
- if (optv > 1) {
- fprintf (stderr, "Verbosity is %d\n", optv);
- }
- break;
- default:
- usageError ();
- break;
- }
- }
-
- // handle command line arguments
- for (; optind < argc; optind++) {
- got_any++;
- tapename = argv [optind]; // snap tapename to global
-
- // open the tape
- fd = open (tapename, O_RDONLY);
- if (fd == -1) {
- fprintf (stderr, "%s: couldn't open %s for O_RDONLY, errno %d\n", progname, tapename, errno);
- perror (NULL);
- exit (EXIT_FAILURE);
- }
- fstat (fd, &statbuf); // get the size, so we can read it into memory
-
- tape = calloc (1, statbuf.st_size);
- if (tape == NULL) {
- fprintf (stderr, "%s: can't allocate %zu bytes during processing of %s, errno %d (%s)\n", progname, statbuf.st_size, tapename, errno, strerror (errno));
- exit (EXIT_FAILURE);
- }
-
- // initialize data areas
- memset (core, 0xff, sizeof (core)); // set to -1 -- since we are only using 12 bits of each 16 bit word, -1 isn't a valid PDP-8 core value
- memset (tags, 0, sizeof (tags)); // reset tags
- nsegments = 0;
- segments = NULL;
-
- read (fd, tape, statbuf.st_size);
- close (fd);
-
- // dump the tape (this also reads the tape into "core" and disassembles)
- sts = dumptape (tape, statbuf.st_size);
-
- free (tape);
-
- if (!sts) {
- continue; // skip tape
- }
-
- // convert to RIM/BIN if required (-b and/or -r)
- if (optb || optr) {
- // see if there is any data there at all..
- if (blank (core, CORE_SIZE)) {
- fprintf (stderr, "%s: tape image from %s is empty, not creating a BIN version\n", progname, tapename);
- return;
- }
- if (optb) {
- writebin ();
- }
- if (optr) {
- writerim ();
- }
- }
- }
-
- // if no arguments given, dump usage message
- if (optT) {
- memset (core, 0xff, sizeof (core)); // set to -1 (assumption; all 0xff's in an int is -1; pretty safe)
- for (i = 0; i < 07600; i++) {
- core [i] = ((i & 07700) >> 6) + ((i & 00077) << 6);
- }
- tapename = "test";
- if (optb) {
- writebin ();
- }
- if (optr) {
- writerim ();
- }
- } else {
- if (!got_any) {
- usageError ();
- }
- }
-}
-
-/*
- * dumptape
- *
- * This function does some basic processing (detecting and skipping the
- * header, killing off data past the trailer) and then determines via
- * checkrim() and ckeckbin() the format of the tape. Depending on the
- * type of tape, dumprim() or dumpbin() is called to read the tape into
- * the "core" array and disassemble it.
- *
- * 20071104: Changed the 'skip header' logic to look for a character
- * less than 0x80, not just not equal to, because a tape I received
- * had the following:
- * 0000000 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200 200
- * *
- * 0000100 300 100 000 000 000 050 001 000 002 000 003 000 000 000 000 054
- *
- * Notice the "300" (0xc0) at location 0100.
- *
- * Returns 0 on error.
-*/
-
-static int
-dumptape (unsigned char *t, int n)
-{
- int i;
-
- // basic preprocessing; find header
- for (i = 0; i < n; i++) {
- if (t [i] == 0x80) { // got a header
- break;
- }
- }
- if (i == n) {
- fprintf (stderr, "%s: couldn't find a 0x80 leader on tape %s; tape ignored\n", progname, tapename);
- return (0);
- }
-
- // skip header
- for (; i < n; i++) {
- if (t [i] < 0x80) { // RK 20071104 was "!= 0x80";
- break;
- }
- }
- if (i == n) {
- fprintf (stderr, "%s: no data content found after 0x80 leader on tape %s; tape ignored\n", progname, tapename);
- return (0);
- }
-
- // at this point, we're positioned on the first-non-leader byte of the tape
- if (n - i < 4) {
- fprintf (stderr, "%s: tape %s is too short; tape ignored\n", progname, tapename);
- return (0);
- }
-
- // skip leader (t now points to start of tape; n indicates remaining # bytes)
- if (optv) {
- fprintf (stderr, "%s: tape %s skipped %d (0x%0X, 0%0o) bytes of header, original size %d new size %d\n", progname, tapename, i, i, i, n, n - i);
- }
- t += i;
- n -= i;
-
- // find first 0x80 -- trailer
- for (i = 0; i < n; i++) {
- if (t [i] == 0x80) {
- break;
- }
- }
- if (i == n) {
- fprintf (stderr, "%s: warning -- tape %s does not have a trailer\n", progname, tapename);
- // find first data >= 0x80, then
- for (i = 0; i < n; i++) {
- if (t [i] >= 0x80) {
- // at least stop on the first invalid character, then
- break;
- }
- }
- }
-
- // reset end-of-tape to last character
- if (optv > 2) {
- printf ("%s: tape %s skipped %d bytes of trailer, new size is %d bytes\n", progname, tapename, n - i, i);
- }
- n = i;
-
- // determine type of tape and dump it
- if (checkrim (t, n)) {
- if (!dumprim (t, n)) {
- return (0);
- }
- } else if (checkbin (t, n)) {
- if (!dumpbin (t, n)) {
- return (0);
- }
- } else {
- fprintf (stderr, "%s: tape %s is neither RIM nor BIN (first four bytes are 0%03o 0%03o 0%03o 0%03o)\n", progname, tapename, t [0], t [1], t [2], t [3]);
- return (0);
- }
-
- if (!optd) {
- flow (); // perform flow analysis
- disassemble (); // disassemble
- printf ("\n$\n");
- }
- return (1);
-}
-
-/*
- * checkrim
- * checkbin
- *
- * These two functions try to determine what format the tape is in.
- * A zero return indicates the tape is not in the given format; a one
- * indicates it is. The heuristics used here are fairly simple.
-*/
-
-static int
-checkrim (unsigned char *t, int n)
-{
- int i;
-
- if (n % 4) {
- if (optv > 2) {
- printf ("%s: tape %s size (%d bytes) is not divisible by four; not a RIM tape\n", progname, tapename, n);
- }
- return (0);
- }
-
- // see if it's a RIM-formatted tape; we're looking for 01xxxxxx 00xxxxxx 00xxxxxx 00xxxxxx
- for (i = 0; i < n; i += 4) {
- if ((t [i] & 0xC0) != 0x40 || (t [i + 1] & 0xC0) || (t [i + 2] & 0xC0) || (t [i + 3] & 0xC0)) {
- if (optv > 2) {
- printf ("%s: tape %s does not have the RIM signature at offset 0%04o; expected 01xxxxxx 00xxxxxx 00xxxxxx 00xxxxxx, got 0%04o 0%04o 0%04o 0%04o\n", progname, tapename, i, t [i], t [i + 1], t [i + 2], t [i + 3]);
- }
- return (0);
- }
- }
- return (1);
-}
-
-static int
-checkbin (unsigned char *t, int n)
-{
- if (n % 2) {
- if (optv > 2) {
- printf ("%s: tape %s size (%d bytes) is not divisible by two; not a BIN tape\n", progname, tapename, n);
- }
- return (0);
- }
-
- // see if it's a BIN-formatted tape; 01xxxxxx 00xxxxxx (i.e., we at least expect an origin)
- if ((t [0] & 0xC0) != 0x40 || (t [1] & 0xC0)) {
- if (optv > 2) {
- printf ("%s: tape %s does not have the BIN origin signature; expected header of 01xxxxxx 00xxxxxx, got 0%04o 0%04o\n", progname, tapename, t [0], t [1]);
- }
- return (0);
- }
-
- return (1);
-}
-
-/*
- * From the PDP-8/I & PDP-8/L Small Computer Handbook (099-00272-A1983 / J-09-5)
- * Appendix D, "Perforated-Tape Loader Sequences", page 383
- *
- * READIN MODE LOADER
- * The readin mode (RIM) loader is a minimum length, basic perforated-tape
- * reader program for the ASR33, it is initially stored in memory by manual use
- * of the operator console keys and switches. The loader is permanently stored in
- * 18 locations of page 37.
- *
- * A perforated tape to be read by the RIM loader must be in RIM format:
- *
- * Tape Channel
- * 8 7 6 5 4 3 2 1 OCTAL Format
- * --------------- ----- ------------------------
- * 1 0 0 0 0 0 0 0 200 Leader-trailer code
- * 0 1 -A1- -A2- 1AA Absolute address to
- * 0 0 -A3- -A4- 0AA contain next 4 digits
- * 0 0 -X1- -X2- 0XX Content of previous
- * 0 0 -X3- -X4- 0XX 4-digit address
- * 0 1 -A1- -A2- 1AA Address
- * 0 0 -A3- -A4- 0AA
- * 0 0 -X1- -X2- 0XX Content
- * 0 0 -X3- -X4- 0XX
- * (etc) (etc)
- * 1 0 0 0 0 0 0 0 200 Leader-trailer code
- *
- * The RIM loader can only be used in conjunction with the ASR33 reader (not
- * the high-speed perforated-tape reader). Because a tape in RIM format is, in
- * effect, twice as long as it need be, it is suggested that the RIM loader be used
- * only to read the binary loader when using the ASR33. (Note that PDP-8 diag-
- * nostic program tapes are in RIM format.)
- *
- * The complete PDP-8/I RIM loader (SA=7756) is as follows:
- *
- * Absolute Octal
- * Address Content Tag Instruction I Z Comments
- * 7756, 6032 BEG, KCC /CLEAR AC AND FLAG
- * 7757, 6031 KSF /SKIP IF FLAG = 1
- * 7760, 5357 JMP .-1 /LOOKING FOR CHARACTER
- * 7761, 6036 KRB /READ BUFFER
- * 7762, 7106 CLL RTL
- * 7763, 7006 RTL /CHANNEL 8 IN AC0
- * 7764, 7510 SPA /CHECKING FOR LEADER
- * 7765, 5357 JMP BEG+1 /FOUND LEADER
- * 7766, 7006 RTL /OK, CHANNEL 7 IN LINK
- * 7767, 6031 KSF
- * 7770, 5367 JMP .-1
- * 7771, 6034 KRS /READ, DO NOT CLEAR
- * 7772, 7420 SNL /CHECKING FOR ADDRESS
- * 7773, 3776 DCA I TEMP /STORE CONTENT
- * 7774, 3376 DCA TEMP /STORE ADDRESS
- * 7775, 5356 JMP BEG /NEXT WORD
- * 7776, 0 TEMP, 0 /TEMP STORAGE
- * 7777, 5XXX JMP X /JMP START OF BIN LOADER
-*/
-
-/*
- * dumprim
- *
- * This is a finite-state-machine that runs through the tape reading the address
- * and data records, stuffs them into core[], and disassembles the opcodes unless
- * "-d" is specified.
- *
- * Note that disassembly is done after the complete tape has been read in, this
- * allows us to do some flow analysis.
-*/
-
-#define RIM_Initial 1 // waiting for address
-#define RIM_Addr 2 // got top part of address, process bottom part
-#define RIM_Data1 3 // got address, process top part of data
-#define RIM_Data2 4 // got top part of data, process bottom part
-
-static int
-dumprim (unsigned char *t, int n)
-{
- int state;
- int i;
- uint16_t addr, data;
- uint16_t cur_addr;
-
- state = RIM_Initial;
-
- cur_addr = 0xffff; // impossible address for PDP-8
-
- for (i = 0; i < n; i++) {
- if (optv > 2) {
- printf ("[%03o] ", t [i]); fflush (stdout);
- if ((i % 13) == 12) {
- printf ("\n");
- }
- }
- switch (state) {
- case RIM_Initial:
- if (t [i] & 0100) { // indicates 1st part of address
- addr = (t [i] & 0077) << 6; // store top part
- state = RIM_Addr;
- }
- break;
- case RIM_Addr:
- addr |= (t [i] & 0077);
- state = RIM_Data1;
- break;
- case RIM_Data1:
- data = (t [i] & 0077) << 6; // store top part
- state = RIM_Data2;
- break;
- case RIM_Data2: // final decode complete, store data
- data |= (t [i] & 0077);
- core [addr] = data; // stash data into core image
-
- // segment management -- if it's the next byte, add, else create new
- if (addr == cur_addr) {
- cur_addr++;
- seg_more (1);
- } else {
- seg_add (addr, 1);
- cur_addr = addr + 1;
- }
- state = RIM_Initial;
- break;
- }
- }
- if (optv > 2) {
- printf ("\n");
- }
- return (1);
-}
-
-/*
- * BIN format, from the same doc as above, page 384:
- *
- * BINARY LOADER
- * The binary loader (BIN) is used to read machine language tapes (in binary
- * format) produced by the program assembly language (PAL). A tape in binary
- * format is about one-half the length of the comparable RIM format tape. It can,
- * therefore, be read about twice as fast as a RIM tape and is, for this reason,
- * the more desirable format to use with the 10 cps ASR33 reader or the Type
- * PR8/I High-Speed Perforated-Tape Reader.
- *
- * The format of a binary tape is as follows:
- *
- * LEADER: about 2 feet of leader-trailer codes.
- *
- * BODY: characters representing the absolute, machine language program
- * in easy-to-read binary (or octal) form. The section of tape may contain
- * characters representing instructions (channel 8 and 7 not punched) or
- * origin resettings (channel 8 not punched, channel 7 punched) and is
- * concluded by 2 characters (channel 8 and 7 not punched) that represent
- * a check sum for the entire section.
- *
- * TRAILER: same as leader.
- *
- * I.e.,
- *
- * Tape Channel
- * 8 7 6 5 4 3 2 1 OCTAL Format
- * --------------- ----- ------------------------
- * 1 0 0 0 0 0 0 0 200 Leader
- * 0 1 A A A A A A 1AA Address (top)
- * 0 1 B B B B B B 1BB Address (bottom)
- * 0 0 C C C C C C 0CC Data (top)
- * 0 0 D D D D D D 0DD Data (bottom)
- * 0 0 C C C C C C 0CC Data (top)
- * 0 0 D D D D D D 0DD Data (bottom)
- * . . . ... next data (2 bytes)
- * 0 1 A A A A A A 1AA New address (top)
- * 0 1 B B B B B B 1BB New address (bottom)
- * . . . ... next data (2 bytes)
- * 0 0 X X X X X X 0XX Checksum (top)
- * 0 0 Y Y Y Y Y Y 0YY Checksum (bottom)
- *
-*/
-
-/*
- * dumpbin
- *
- * This is a finite-state-machine that runs through the tape looking for the
- * origin and subsequent data fields, stuffs them into the core[] array, and
- * optionally disassembles the opcodes.
- *
- * Every time we hit an origin change, we create a new segment and accumulate
- * bytes into it.
-*/
-
-#define BIN_Initial 1 // initial state; we require an origin to get out of it
-#define BIN_Origin 2 // we got the top part of the origin, now need to get the bottom part
-#define BIN_DataHW 3 // we have an address, so we are looking for another origin or the top part of the data
-#define BIN_DataLW 4 // we have the top part of the data, now fetching the low part
-
-static int
-dumpbin (unsigned char *t, int n)
-{
- int tape_checksum; // checksum stored on tape
- int calc_checksum; // calculated checksum
- int i;
- int state;
- unsigned short int addr, data;
-
- if (n < 4) {
- fprintf (stderr, "%s: tape %s is too short; tape skipped\n", progname, tapename);
- return (0);
- }
-
- tape_checksum = ((t [n - 2] & 0x3f) << 6) + (t [n - 1] & 0x3f);
- if (optv > 1) {
- printf ("%s: tape %s expected checksum 0%04o\n", progname, tapename, tape_checksum);
- }
- n -= 2; // tape is now shorter by the two bytes
-
- // now calculate checksum
- calc_checksum = 0;
- for (i = 0; i < n; i++) {
- calc_checksum += t [i];
- }
- calc_checksum &= 07777; // mask to 12 bits
- if (optv > 1) {
- printf ("%s: tape %s calculated checksum 0%04o\n", progname, tapename, calc_checksum);
- }
-
- if (tape_checksum != calc_checksum) {
- fprintf (stderr, "%s: tape %s calculated checksum [0%04o] != stored checksum [0%04o]; tape skipped\n", progname, tapename, calc_checksum, tape_checksum);
- return (0);
- }
-
- // now we can dump the binary data via the state machine
- state = BIN_Initial;
- for (i = 0; i < n; i++) {
- if (optv > 2) {
- printf ("[%03o] ", t [i]); fflush (stdout);
- if ((i % 13) == 12) {
- printf ("\n");
- }
- }
- switch (state) {
- case BIN_Initial:
- if (t [i] & 0100) { // indicates origin setting code
- addr = (t [i] & 0077) << 6; // store top part
- state = BIN_Origin;
- }
- break;
- case BIN_Origin:
- addr += (t [i] & 0077); // store bottom part
- state = BIN_DataHW;
- seg_add (addr, 0);
- break;
- case BIN_DataHW:
- if (t [i] & 0100) { // another origin; skip loading data and load address instead
- addr = (t [i] & 0077) << 6;
- state = BIN_Origin;
- } else {
- data = (t [i] & 0077) << 6; // store top part of data
- state = BIN_DataLW;
- }
- break;
- case BIN_DataLW:
- data += (t [i] & 0077);
- core [addr] = data;
- seg_more (1);
- addr++; // the magic of BIN-format is the autoincrement of the address
- state = BIN_DataHW;
- }
- }
- if (optv > 2) {
- printf ("\n");
- }
- return (1);
-}
-
-/*
- * writebin
- * writerim
- *
- * These two functions write the BIN and RIM format tapes to a file.
- * The filename is constructed by appending ".bin" or ".rim" to the
- * input filename.
- *
- * The header and trailer written are short, LEADER_LENGTH bytes.
- *
- * The writebin() uses a finit-state-machine to generate the origin.
-*/
-
-#define LEADER_LENGTH 16 // 16 chars of leader/trailer should be plenty
-
-#define WBIN_Initial 1 // looking for first/next in-use core[] element
-#define WBIN_Writing 2 // origin written, dumping consecutive words
-
-static void
-writebin (void)
-{
- char fname [PATH_MAX];
- char leader [LEADER_LENGTH];
- FILE *fp;
- int i;
- int cksum;
- int state;
-
- // create filename and open it
- sprintf (fname, "%s.bin", tapename);
- if ((fp = fopen (fname, "w")) == NULL) {
- fprintf (stderr, "%s: unable to open BIN output file %s for w, errno %d (%s); creation of output file skipped\n", progname, fname, errno, strerror (errno));
- return;
- }
-
- // write leader
- memset (leader, 0x80, sizeof (leader));
- fwrite (leader, 1, sizeof (leader), fp);
-
- // now scan through "core" and write the data out...
- cksum = 0;
- state = WBIN_Initial;
- for (i = 0; i < CORE_SIZE; i++) {
- switch (state) {
- case WBIN_Initial: // transit out of WBIN_Initial on a "used" core position
- if (core [i] != -1) {
- state = WBIN_Writing;
- fprintf (fp, "%c%c", 0x40 | ((i & 07700) >> 6), i & 00077); // write origin directive
- fprintf (fp, "%c%c", (core [i] & 07700) >> 6, core [i] & 00077); // write data
- cksum += (0x40 | ((i & 07700) >> 6)) + (i & 00077) + ((core [i] & 07700) >> 6) + (core [i] & 00077);
- }
- break;
- case WBIN_Writing:
- if (core [i] == -1) {
- state = WBIN_Initial; // waiting again for a used core position
- } else {
- fprintf (fp, "%c%c", (core [i] & 07700) >> 6, core [i] & 00077);
- cksum += ((core [i] & 07700) >> 6) + (core [i] & 00077);
- }
- break;
- }
- }
-
- // now write the checksum
- fprintf (fp, "%c%c", (cksum & 07700) >> 6, cksum & 00077);
-
- // write trailer
- fwrite (leader, 1, sizeof (leader), fp);
-
- fclose (fp);
-}
-
-static void
-writerim (void)
-{
- char fname [PATH_MAX];
- char leader [LEADER_LENGTH];
- FILE *fp;
- int i;
-
- // create the filename and open it
- sprintf (fname, "%s.rim", tapename);
- if ((fp = fopen (fname, "w")) == NULL) {
- fprintf (stderr, "%s: unable to open RIM output file %s for w, errno %d (%s); creation of output file skipped\n", progname, fname, errno, strerror (errno));
- return;
- }
-
- // write leader
- memset (leader, 0x80, sizeof (leader));
- fwrite (leader, 1, sizeof (leader), fp);
-
- for (i = 0; i < CORE_SIZE; i++) {
- if (core [i] != -1) {
- fprintf (fp, "%c%c%c%c", 0x40 + ((i & 07700) >> 6), i & 00077, (core [i] & 07700) >> 6, core [i] & 00077);
- }
- }
-
- // write trailer
- fwrite (leader, 1, sizeof (leader), fp);
-
- fclose (fp);
-}
-
-/*
- * blank
- *
- * A utility routine to see if core[] is blank (returns 1).
- * Used to avoid writing an empty tape.
-*/
-
-static int
-blank (short int *c, int size)
-{
- int i;
-
- for (i = 0; i < size; i++) {
- if (c [i] != -1) {
- return (0);
- }
- }
- return (1);
-}
-
-/*
- * seg_add (addr, len)
- * seg_more (more)
- *
- * These functions manipulate the segment data stored
- * in "segments[]" and "nsegments".
- *
- * seg_add creates a new segment with the given address
- * and length.
- *
- * seg_more lengthens the current segment by "more"
- * words.
-*/
-
-static void
-seg_add (uint16_t addr, int len)
-{
- if (optv > 3) {
- printf ("seg_add (0%04o, %d (0%04o))\n", addr, len, len);
- }
-
- segments = realloc (segments, (nsegments + 1) * sizeof (segments [0]));
- if (segments == NULL) {
- fprintf (stderr, "%s: couldn't realloc segments array to be %d elements (%ld bytes) long, errno %d (%s)\n", progname, nsegments + 1, (nsegments + 1) * sizeof (segments [0]), errno, strerror (errno));
- exit (EXIT_FAILURE);
- }
- segments [nsegments].saddr = addr;
- segments [nsegments].nwords = len;
- nsegments++;
-}
-
-static void
-seg_more (int len)
-{
- if (optv > 3) {
- printf ("seg_more (+%d (0%04o))\n", len, len);
- }
-
- if (nsegments) {
- segments [nsegments - 1].nwords += len;
- } else {
- fprintf (stderr, "%s: seg_more called with no segments in existence\n", progname);
- exit (EXIT_FAILURE);
- }
-}
-
DELETED src/d8tape/version.c
Index: src/d8tape/version.c
==================================================================
--- src/d8tape/version.c
+++ /dev/null
@@ -1,1 +0,0 @@
-const char *version="0.352";
DELETED src/palbart/LICENSE.md
Index: src/palbart/LICENSE.md
==================================================================
--- src/palbart/LICENSE.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# palbart License
-
-The following was extracted from the top of [`palbart.c`][1] in this
-directory:
-
----------
-
-This is free software. There is no fee for using it. You may make any
-changes that you wish and also give it away. If you can make commercial
-product out of it, fine, but do not put any limits on the purchaser's
-right to do the same. If you improve it or fix any bugs, it would be
-nice if you told me and offered me a copy of the new version.
-
----------
-
-[1]: https://tangentsoft.com/pidp8i/doc/trunk/palbart/palbart.c
DELETED src/palbart/palbart.1
Index: src/palbart/palbart.1
==================================================================
--- src/palbart/palbart.1
+++ /dev/null
@@ -1,200 +0,0 @@
-.\" Hey, EMACS: -*- nroff -*-
-.\" First parameter, NAME, should be all caps
-.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
-.\" other parameters are allowed: see man(7), man(1)
-.TH PALBART 1 "January 16, 2000"
-.\" Please adjust this date whenever revising the manpage.
-.\"
-.\" Some roff macros, for reference:
-.\" .nh disable hyphenation
-.\" .hy enable hyphenation
-.\" .ad l left justify
-.\" .ad b justify to both left and right margins
-.\" .nf disable filling
-.\" .fi enable filling
-.\" .br insert line break
-.\" .sp insert n+1 empty lines
-.\" for manpage-specific macros, see man(7)
-.SH NAME
-palbart \- BART enhanced PDP8 crossassembler
-.SH SYNOPSIS
-.B palbart
-.RI [options] inputfile
-.br
-.SH DESCRIPTION
-This manual page documents briefly the
-.B palbart
-command.
-It is a cross-assembler to for PDP/8 assembly language programs.
-It will produce an output file in bin format, rim format, and using the
-appropriate pseudo-ops, a combination of rim and bin formats.
-A listing file is always produced and with an optional symbol table
-and/or a symbol cross-reference (concordance). The permanent symbol
-table can be output in a form that may be read back in so a customized
-permanent symbol table can be produced. Any detected errors are output
-to a separate file giving the filename in which they were detected
-along with the line number, column number and error message as well as
-marking the error in the listing file.
-.PP
-The following file name extensions are used:
-.PP
- .pal source code (input)
-.PP
- .lst assembly listing (output)
-.PP
- .bin assembly output in DEC's bin format (output)
-.PP
- .rim assembly output in DEC's rim format (output)
-.PP
- .err assembly errors detected (if any) (output)
-.PP
- .prm permanent symbol table in form suitable for reading after the EXPUNGE pseudo-op.
-
-.PP
-.SH OPTIONS
-A summary of options is included below.
-.TP
-.B \-d
-Show symbol table at end of assembly
-.TP
-.B \-h
-Display help.
-.TP
-.B \-l
-Allow generation of literals (default is no literal generation)
-Show version of program.
-.TP
-.B \-p
-Generate a file with the permanent symbols in it.
-(To get the current symbol table, assemble a file than has only
-a $ in it.)
-.TP
-.B \-r
-Produce output in rim format (default is bin format)
-.TP
-.B \-v
-Display version information.
-.TP
-.B \-x
-Generate a cross-reference (concordance) of user symbols.
-
-.SH DIAGNOSTICS
-Assembler error diagnostics are output to an error file and inserted
-in the listing file. Each line in the error file has the form
-.PP
-(:) : error: at Loc =
-.PP
-An example error message is:
-.br
-bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616
-.PP
-The error diagnostics put in the listing start with a two character
-error code (if appropriate) and a short message. A carat '^' is
-placed under the item in error if appropriate.
-An example error message is:
-.PP
- 17 07616 3000 DCA UNDEF
-.br
- UD undefined ^
-.br
- 18 07617 1777 TAD I DUMMY
-.PP
-When an indirect is generated, an at character '@' is placed after the
-the instruction value in the listing as an indicator as follows:
-.PP
- 14 03716 1777@ TAD OFFPAG
-.PP
-Undefined symbols are marked in the symbol table listing by prepending
-a '?' to the symbol. Redefined symbols are marked in the symbol table
-listing by prepending a '#' to the symbol. Examples are:
-.PP
- #REDEF 04567
-.br
- SWITCH 07612
-.br
- ?UNDEF 00000
-.PP
-Refer to the code for the diagnostic messages generated.
-
-.SH BUGS
-Only a minimal effort has been made to keep the listing format
-anything like the PAL-8 listing format.
-The operation of the conditional assembly pseudo-ops may not function
-exactly as the DEC versions. I did not have any examples of these so
-the implementation is my interpretation of how they should work.
-.PP
-The RIMPUNch and BINPUNch pseudo-ops do not change the binary output
-file type that was specified on startup. This was intentional and
-and allows rim formatted data to be output prior to the actual binary
-formatted data. On UN*X style systems, the same effect can be achieved
-ing the "cat" command, but on DOS/Windows systems, doing this was
-a major chore.
-.PP
-The floating point input does not generate values exactly as the DEC
-compiler does. I worked out several examples by hand and believe that
-this implementation is slightly more accurate. If I am mistaken,
-let me know and, if possible, a better method of generating the values.
-.br
-
-.SH HISTORICAL NOTE
-This assembler was written to support the fleet of PDP-8 systems
-used by the Bay Area Rapid Transit System. As of early 1997,
-this includes about 40 PDP-8/E systems driving the train destination
-signs in passenger stations.
-
-.SH REFERENCES
-This assembler is based on the pal assember by:
-.br
-Douglas Jones and
-.br
-Rich Coon
-
-.SH DISCLAIMER
-See the symbol table for the set of pseudo-ops supported.
-.PP
-See the code for pseudo-ops that are not standard for PDP/8 assembly.
-.PP
-Refer to DEC's "Programming Languages (for the PDP/8)" for complete
-documentation of pseudo-ops.
-.PP
-Refer to DEC's "Introduction to Programming (for the PDP/8)" or a
-lower level introduction to the assembly language.
-
-.SH WARRANTY
-If you don't like it the way it works or if it doesn't work, that's
-tough. You're welcome to fix it yourself. That's what you get for
-using free software.
-
-.SH COPYRIGHT NOTICE
-This is free software. There is no fee for using it. You may make
-any changes that you wish and also give it away. If you can make
-a commercial product out of it, fine, but do not put any limits on
-the purchaser's right to do the same. If you improve it or fix any
-bugs, it would be nice if you told me and offered me a copy of the
-new version.
-Gary Messenbrink
-
-.SH VERSIONS
- Version Date by Comments
-.br
- v1.0 12Apr96 GAM Original
-.br
- v1.1 18Nov96 GAM Permanent symbol table initialization error.
-.br
- v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators.
-.br
- v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants).
-.br
- v1.4 29Nov96 GAM Fixed bug in checksum generation.
-.br
- v2.1 08Dec96 GAM Added concordance processing (cross reference).
-.br
- v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants).
-.br
- v2.3 2Feb97 GAM Fixed paging problem in cross reference output.
-.br
- v2.4 11Apr97 GAM Fixed problem with some labels being put in cross reference multiple times.
-
-.SH AUTHOR
-This manual page was written by Vince Mulhollon ,
-for the Debian GNU/Linux system (but may be used by others).
DELETED src/palbart/palbart.c
Index: src/palbart/palbart.c
==================================================================
--- src/palbart/palbart.c
+++ /dev/null
@@ -1,4352 +0,0 @@
-/******************************************************************************/
-/* */
-/* Program: PAL (BART version) */
-/* File: pal.c */
-/* Author: Gary A. Messenbrink */
-/* gam@rahul.net */
-/* */
-/* Purpose: A 2 pass PDP-8 pal-like assembler. */
-/* */
-/* PAL(1) */
-/* */
-/* NAME */
-/* pal - a PDP/8 pal-like assembler. */
-/* */
-/* SYNOPSIS: */
-/* pal [ -$ -d -h -e -l -p -r -t -v -x ] inputfile */
-/* */
-/* DESCRIPTION */
-/* This is a cross-assembler to for PDP/8 assembly language programs. */
-/* It will produce an output file in bin format, rim format, and using the */
-/* appropriate pseudo-ops, a combination of rim and bin formats. */
-/* A listing file is always produced and with an optional symbol table */
-/* and/or a symbol cross-reference (concordance). The permanent symbol */
-/* table can be output in a form that may be read back in so a customized */
-/* permanent symbol table can be produced. Any detected errors are output */
-/* to a separate file giving the filename in which they were detected */
-/* along with the line number, column number and error message as well as */
-/* marking the error in the listing file. */
-/* The following file name extensions are used: */
-/* .pal source code (input) */
-/* .lst assembly listing (output) */
-/* .bin assembly output in DEC's bin format (output) */
-/* .rim assembly output in DEC's rim format (output) */
-/* .err assembly errors detected (if any) (output) */
-/* .prm permanent symbol table in form suitable for reading after */
-/* the EXPUNGE pseudo-op. */
-/* */
-/* OPTIONS */
-/* -$ Allow files to not end with $ */
-/* -d Dump the symbol table at end of assembly */
-/* -h Show help */
-/* -e Don't allow generation of links */
-/* -l Allow generation of links (default is link generation) */
-/* -n No redefinition of permanent symbols with labels */
-/* -p Generate a file with the permanent symbols in it. */
-/* (To get the current symbol table, assemble a file than has only */
-/* a $ in it.) */
-/* -r Produce output in rim format (default is bin format) */
-/* -tN Set tab stops to N spaces (default is 8) */
-/* -v Display program version. */
-/* -x Generate a cross-reference (concordance) of user symbols. */
-/* */
-/* DIAGNOSTICS */
-/* Assembler error diagnostics are output to an error file and inserted */
-/* in the listing file. Each line in the error file has the form */
-/* */
-/* (:) : error: at Loc = */
-/* */
-/* An example error message is: */
-/* */
-/* bintst.pal(17:9) : error: undefined symbol "UNDEF" at Loc = 07616 */
-/* */
-/* The error diagnostics put in the listing start with a two character */
-/* error code (if appropriate) and a short message. A carat '^' is */
-/* placed under the item in error if appropriate. */
-/* An example error message is: */
-/* */
-/* 17 07616 3000 DCA UNDEF */
-/* UD undefined ^ */
-/* 18 07617 1777 TAD I DUMMY */
-/* */
-/* When an indirect is generated, an at character '@' is placed after the */
-/* the instruction value in the listing as an indicator as follows: */
-/* */
-/* 14 03716 1777@ TAD OFFPAG */
-/* */
-/* Undefined symbols are marked in the symbol table listing by prepending */
-/* a '?' to the symbol. Redefined symbols are marked in the symbol table */
-/* listing by prepending a '#' to the symbol. Examples are: */
-/* */
-/* #REDEF 04567 */
-/* SWITCH 07612 */
-/* ?UNDEF 00000 */
-/* */
-/* Refer to the code for the diagnostic messages generated. */
-/* */
-/* BUGS */
-/* This program will accept source that real PAL will not. To ensure */
-/* valid source assemble on real or simulated PDP-8. */
-/* Different PAL versions have different permanent symbols defined. This */
-/* program define more than and PAL version. By default redefining them */
-/* as a label is not an error. It is for normal PAL. The -n flag will */
-/* make redefining an error. */
-/* */
-/* Only a minimal effort has been made to keep the listing format */
-/* anything like the PAL-8 listing format. */
-/* The operation of the conditional assembly pseudo-ops may not function */
-/* exactly as the DEC versions. I did not have any examples of these so */
-/* the implementation is my interpretation of how they should work. */
-/* */
-/* The RIMPUNch and BINPUNch pseudo-ops do not change the binary output */
-/* file type that was specified on startup. This was intentional and */
-/* and allows rim formatted data to be output prior to the actual binary */
-/* formatted data. On UN*X style systems, the same effect can be achieved */
-/* by using the "cat" command, but on DOS/Windows systems, doing this was */
-/* a major chore. */
-/* */
-/* The floating point input does not generate values exactly as the DEC */
-/* compiler does. I worked out several examples by hand and believe that */
-/* this implementation is slightly more accurate. If I am mistaken, */
-/* let me know and, if possible, a better method of generating the values. */
-/* */
-/* CDF .-. */
-/* Generates 2201 when assembled at 5000. This looks like a bug in OS/8 */
-/* PAL */
-/* */
-/* BUILD and INSTALLATION */
-/* The current version has only been built under Linux. */
-/* Earlier versions have been built and successfully executed on: */
-/* a. Linux (80486 CPU)using gcc */
-/* b. RS/6000 (AIX 3.2.5) */
-/* c. Borland C++ version 3.1 (large memory model) */
-/* d. Borland C++ version 4.52 (large memory model) */
-/* with no modifications to the source code. */
-/* */
-/* On UNIX type systems, store the the program as the pal command */
-/* and on PC type systems, store it as pal.exe */
-/* */
-/* HISTORICAL NOTE: */
-/* This assembler was written to support the fleet of PDP-8 systems */
-/* used by the Bay Area Rapid Transit System. As of early 1997, */
-/* this includes about 40 PDP-8/E systems driving the train destination */
-/* signs in passenger stations. */
-/* */
-/* REFERENCES: */
-/* This assembler is based on the pal assembler by: */
-/* Douglas Jones and */
-/* Rich Coon */
-/* */
-/* DISCLAIMER: */
-/* See the symbol table for the set of pseudo-ops supported. */
-/* See the code for pseudo-ops that are not standard for PDP/8 assembly. */
-/* Refer to DEC's "Programming Languages (for the PDP/8)" for complete */
-/* documentation of pseudo-ops. */
-/* Refer to DEC's "Introduction to Programming (for the PDP/8)" or a */
-/* lower level introduction to the assembly language. */
-/* */
-/* WARRANTY: */
-/* If you don't like it the way it works or if it doesn't work, that's */
-/* tough. You're welcome to fix it yourself. That's what you get for */
-/* using free software. */
-/* */
-/* COPYRIGHT NOTICE: */
-/* This is free software. There is no fee for using it. You may make */
-/* any changes that you wish and also give it away. If you can make */
-/* a commercial product out of it, fine, but do not put any limits on */
-/* the purchaser's right to do the same. If you improve it or fix any */
-/* bugs, it would be nice if you told me and offered me a copy of the */
-/* new version. */
-/* */
-/* */
-/* Amendments Record: */
-/* Version Date by Comments */
-/* ------- ------- --- --------------------------------------------------- */
-/* v1.0 12Apr96 GAM Original */
-/* v1.1 18Nov96 GAM Permanent symbol table initialization error. */
-/* v1.2 20Nov96 GAM Added BINPUNch and RIMPUNch pseudo-operators. */
-/* v1.3 24Nov96 GAM Added DUBL pseudo-op (24 bit integer constants). */
-/* v1.4 29Nov96 GAM Fixed bug in checksum generation. */
-/* v2.1 08Dec96 GAM Added concordance processing (cross reference). */
-/* v2.2 10Dec96 GAM Added FLTG psuedo-op (floating point constants). */
-/* v2.3 2Feb97 GAM Fixed paging problem in cross reference output. */
-/* DJG: I started with the 2.5 RK version but found when looking on the net */
-/* later that multiple diverging version existed. I have tried to combine */
-/* the fixed into one version. I took the version info below from the versions*/
-/* I pulled from. */
-/* http://dustyoldcomputers.com/pdp-common/reference/host/index.html */
-/* http://www.dunnington.u-net.com/public/PDP-8/palbart.c */
-/* http://sourcecodebrowser.com/palbart/2.4/palbart-2_84_8c_source.html */
-/* http://packages.qa.debian.org/p/palbart.html */
-/* v2.4 11Apr97 GAM Fixed problem with some labels being put in cross */
-/* reference multiple times. */
-/* Started with RK version, Attempted to merge */
-/* GAM V2.4 and PNT change DJG */
-/* v2.4 29Oct07 RK Added 4 character tabstop; IOTs for TA8/E. */
-/* v2.4 19Jan03 PNT Added ASCII pseudo-op, like TEXT but not packed. */
-/* v2.5 03Nov07 RK Fixed buffer overflow problem in readLine and */
-/* increased symbol table size */
-/* v2.6 14Jul03 PNT Added missing TTY symbols, and "1st TTY" symbols. */
-/* v2.7 14Jun13 DJG David Gesswein djg@pdp8online.com */
-/* Merged other changes found online giving duplicate */
-/* Versions in the history */
-/* Didn't copy over deleting -l literal flag */
-/* All fixes to make it match OS/8 PAL8 better */
-/* Fixed handling of IFDEF type conditionals */
-/* Fixed excessive redefined symbol errors */
-/* PAL8 uses 12 bit symbols and this program label */
-/* symbols are 15 bit. */
-/* Added FILENAME and DEVNAME psuedo ops */
-/* Added OPR and KCF instructions. Fixed RMF */
-/* Allowed space after = */
-/* Prevented I and D from being deleted by EXPUNGE */
-/* Allowed permanent symbols to be redefined with error*/
-/* PAL8 updates without message. Error is just warning*/
-/* Fixed certain cases of memory reference generation */
-/* Allowed unary + */
-/* Fixed " character literal at end of line */
-/* Fixed errors in reloc handling */
-/* Fixed [CDF CIF type expressions */
-/* Made title default to first line */
-/* Fixed checksum when nopunch used */
-/* Fixed FIXTAB */
-/* Probably added more subtle bugs */
-/* v2.8 15Jun13 DJG Merged versions found on net. See above */
-/* Added * to RELOC addresses in listing */
-/* Changed default to literal/links on. Added -e to */
-/* turn off */
-/* Fixed PAGE when RELOC used */
-/* Changed SPF to TFL and SPI to TSK */
-/* Make error when changing permanent symbol to label */
-/* if -e flag is used */
-/* Allow space oring in IFZERO etc */
-/* Fixed handling of page zero overflow */
-/* v2.9 23Jun13 DJG Fixed properly all pages literal handling */
-/* changing page doesn't cause loss of last literal */
-/* location used. */
-/* Fixed bin generation if no origin set */
-/* v2.9a 01Jul13 DJG Fixed Comment. Binaries not updated */
-/* v2.10 08Feb14 DJG Changed trailer to 8 bytes since pip didn't like */
-/* trailer of one 0x80 */
-/* v2.11 19Apr15 DPI Fixed incorrect link generation with impled 0200 */
-/* starting address. Patch from Doug Ingrams */
-/* v2.12 28Apr15 DJG Fixed incorrect handling of reloc, expressions with */
-/* undefined symbols. Fixed conditional assembly with */
-/* undefined symbols. Added new flag to allow file to */
-/* not end with $ */
-/* v2.13 02May15 DPI Fixed bug in readLine when removing \r from a blank */
-/* line. Changed -s to -$ in -h display. Corrected */
-/* version comment. */
-/* v2.13 03May15 DJG Moved TITLE, BANK to new additional option. */
-/* Change release variable below when you update. Send changes back to */
-/* David Gesswein, djg@pdp8online.com. */
-/******************************************************************************/
-
-#include
-#include
-#include
-#include
-#include
-
-char *release = "pal-2.13, 03 May 2015";
-
-/* Set to 1 and use -e flag to make ( and [ literals errors */
-#define LITERAL_ERROR 0
-
-#define LINELEN 132
-#define LIST_LINES_PER_PAGE 55 /* Includes 5 line page header. */
-#define NAMELEN 128
-#define SYMBOL_COLUMNS 5
-#define SYMLEN 7
-#define SYMBOL_TABLE_SIZE 4096
-#define TITLELEN 63
-#define XREF_COLUMNS 8
-
-#define ADDRESS_FIELD 00177
-#define FIELD_FIELD 070000
-#define INDIRECT_BIT 00400
-#define LAST_PAGE_LOC 00177
-#define OP_CODE 07000
-#define PAGE_BIT 00200
-
-#ifdef PAGE_SIZE
-#undef PAGE_SIZE
-#endif
-#define PAGE_SIZE 00200
-
-#define PAGE_FIELD 07600
-#define PAGE_ZERO_END 00200
-
-/* Macro to get the number of elements in an array. */
-#define DIM(a) (sizeof(a)/sizeof(a[0]))
-
-/* Macro to get the address plus one of the end of an array. */
-#define BEYOND(a) ((a) + DIM(A))
-
-#define is_blank(c) ((c==' ') || (c=='\t') || (c=='\f') || (c=='>'))
-#define isend(c) ((c=='\0')|| (c=='\n'))
-#define isdone(c) ((c=='/') || (isend(c)) || (c==';'))
-
-/* Macros for testing symbol attributes. Each macro evaluates to non-zero */
-/* (true) if the stated condition is met. */
-/* Use these to test attributes. The proper bits are extracted and then */
-/* tested. */
-#define M_CONDITIONAL(s) ((s & CONDITION) == CONDITION)
-#define M_DEFINED(s) ((s & DEFINED) == DEFINED)
-#define M_DUPLICATE(s) ((s & DUPLICATE) == DUPLICATE)
-#define M_FIXED(s) ((s & FIXED) == FIXED)
-#define M_LABEL(s) ((s & LABEL) == LABEL)
-#define M_MRI(s) ((s & MRI) == MRI)
-#define M_MRIFIX(s) ((s & MRIFIX) == MRIFIX)
-#define M_PSEUDO(s) ((s & PSEUDO) == PSEUDO)
-#define M_REDEFINED(s) ((s & REDEFINED) == REDEFINED)
-#define M_UNDEFINED(s) (!M_DEFINED(s))
-#define M_PERM_REDEFINED(s) ((s & PERM_REDEFINED) == PERM_REDEFINED)
-
-/* This macro is used to test symbols by the conditional assembly pseudo-ops. */
-#define M_DEF(s) (M_DEFINED(s))
-#define M_COND(s) (M_CONDITIONAL(s))
-#define M_DEFINED_CONDITIONALLY(t) (M_DEF(t) && ((pass==1) ||!M_COND(t)))
-
-typedef unsigned char BOOL;
-typedef unsigned char BYTE;
-typedef short int WORD16;
-typedef long int WORD32;
-
-#ifndef FALSE
- #define FALSE 0
- #define TRUE (!FALSE)
-#endif
-
-/* Line listing styles. Used to control listing of lines. */
-enum linestyle_t
-{
- LINE, LINE_VAL, LINE_LOC_VAL, LOC_VAL
-};
-typedef enum linestyle_t LINESTYLE_T;
-
-/* Symbol Types. */
-/* Note that the names that have FIX as the suffix contain the FIXED bit */
-/* included in the value. */
-/* */
-/* The CONDITION bit is used when processing the conditional assembly PSEUDO- */
-/* OPs (e.g., IFDEF). During pass 1 of the assembly, the symbol is either */
-/* defined or undefined. The condition bit is set when the symbol is defined */
-/* during pass 1 and reset on pass 2 at the location the symbol was defined */
-/* during pass 1. When processing conditionals during pass 2, if the symbol */
-/* is defined and the condition bit is set, the symbol is treated as if it */
-/* were undefined. This gives consistent behavior of the conditional */
-/* pseudo-ops during both pass 1 and pass 2. */
-enum symtyp
-{
- UNDEFINED = 0000,
- DEFINED = 0001,
- FIXED = 0002,
- MRI = 0004 | DEFINED,
- LABEL = 0010 | DEFINED,
- REDEFINED = 0020 | DEFINED,
- DUPLICATE = 0040 | DEFINED,
- PSEUDO = 0100 | FIXED | DEFINED,
- CONDITION = 0200 | DEFINED,
- PERM_REDEFINED = 0400,
- MRIFIX = MRI | FIXED | DEFINED,
- DEFFIX = DEFINED | FIXED
-};
-typedef enum symtyp SYMTYP;
-
-enum pseudo_t
-{
- BANK, BINPUNCH, DECIMAL, DUBL, EJECT, ENPUNCH, EXPUNGE, FIELD,
- FIXMRI, FIXTAB, FLTG, IFDEF, IFNDEF, IFNZERO, IFZERO, NOPUNCH,
- OCTAL, PAGE, PAUSE, RELOC, RIMPUNCH, SEGMNT, TEXT, TITLE,
- XLIST, ZBLOCK, FILENAME, DEVICE, ASCII
-};
-typedef enum pseudo_t PSEUDO_T;
-
-struct sym_t
-{
- SYMTYP type;
- char name[SYMLEN];
- WORD16 val;
- int xref_index;
- int xref_count;
-};
-typedef struct sym_t SYM_T;
-
-struct lpool_t
-{
- WORD16 loc;
- WORD16 last_punched;
- WORD16 pool[PAGE_SIZE];
-};
-typedef struct lpool_t LPOOL_T;
-
-struct emsg_t
-{
- char *list;
- char *file;
-};
-typedef struct emsg_t EMSG_T;
-
-struct errsave_t
-{
- char *mesg;
- int col;
-};
-typedef struct errsave_t ERRSAVE_T;
-
-struct fltg_
-{
- WORD16 exponent;
- WORD32 mantissa;
-};
-typedef struct fltg_ FLTG_T;
-
-/*----------------------------------------------------------------------------*/
-
-/* Function Prototypes */
-
-int binarySearch( char *name, int start, int symbol_count );
-int compareSymbols( const void *a, const void *b );
-void conditionFalse( void );
-void conditionTrue( void );
-SYM_T *defineLexeme( int start, int term, WORD16 val, SYMTYP type );
-SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start);
-void endOfBinary( void );
-void errorLexeme( EMSG_T *mesg, int col );
-void errorMessage( EMSG_T *mesg, int col );
-void errorSymbol( EMSG_T *mesg, char *name, int col );
-SYM_T *eval( void );
-WORD32 evalDubl( WORD32 initial_value );
-FLTG_T *evalFltg( void );
-SYM_T *evalSymbol( void );
-void getArgs( int argc, char *argv[] );
-WORD32 getDublExpr( void );
-WORD32 getDublExprs( void );
-FLTG_T *getFltgExpr( void );
-FLTG_T *getFltgExprs( void );
-SYM_T *getExpr( void );
-WORD16 getExprs( void );
-WORD16 incrementClc( void );
-void inputDubl( void );
-void inputFltg( void );
-WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index );
-char *lexemeToName( char *name, int from, int term );
-void listLine( void );
-SYM_T *lookup( char *name );
-void moveToEndOfLine( void );
-void nextLexBlank( void );
-void nextLexeme( void );
-void normalizeFltg( FLTG_T *fltg );
-void onePass( void );
-void printCrossReference( void );
-void printErrorMessages( void );
-void printLine(char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle);
-void printPageBreak( void );
-void printPermanentSymbolTable( void );
-void printSymbolTable( void );
-BOOL pseudoOperators( PSEUDO_T val );
-void punchChecksum( void );
-void punchLocObject( WORD16 loc, WORD16 val );
-void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 );
-void punchOutObject( WORD16 loc, WORD16 val );
-void punchLeader( int count );
-void punchObject( WORD16 val );
-void punchOrigin( WORD16 loc );
-void readLine( void );
-void saveError( char *mesg, int cc );
-BOOL testForLiteralCollision( WORD16 loc );
-void topOfForm( char *title, char *sub_title );
-
-/*----------------------------------------------------------------------------*/
-
-/* Table of pseudo-ops (directives) which are used to setup the symbol */
-/* table on startup and when the EXPUNGE pseudo-op is executed. */
-SYM_T pseudo[] =
-{
- { PSEUDO, "ASCII", ASCII }, /* Put 8-bit ASCII into memory (see TEXT) */
- { PSEUDO, "BINPUN", BINPUNCH }, /* Output in Binary Loader format. */
- { PSEUDO, "DECIMA", DECIMAL }, /* Read literal constants in base 10. */
- { PSEUDO, "DEVICE", DEVICE }, /* Pack 6 bit device name into memory */
- { PSEUDO, "DUBL", DUBL }, /* Ignored (unsupported). */
- { PSEUDO, "EJECT", EJECT }, /* Eject a page in the listing. */
- { PSEUDO, "ENPUNC", ENPUNCH }, /* Turn on object code generation. */
- { PSEUDO, "EXPUNG", EXPUNGE }, /* Remove all symbols from symbol table. */
- { PSEUDO, "FIELD", FIELD }, /* Set origin to memory field. */
- { PSEUDO, "FILENA", FILENAME }, /* Pack 6 bit filename into memory. */
- { PSEUDO, "FIXMRI", FIXMRI }, /* Like =, but creates mem ref instruction*/
- { PSEUDO, "FIXTAB", FIXTAB }, /* Mark current symbols as permanent. */
- { PSEUDO, "FLTG", FLTG }, /* Ignored (unsupported). */
- { PSEUDO, "IFDEF", IFDEF }, /* Assemble if symbol is defined. */
- { PSEUDO, "IFNDEF", IFNDEF }, /* Assemble if symbol is not defined. */
- { PSEUDO, "IFNZER", IFNZERO }, /* Assemble if symbol value is not 0. */
- { PSEUDO, "IFNZRO", IFNZERO }, /* Assemble if symbol value is not 0. */
- { PSEUDO, "IFZERO", IFZERO }, /* Assemble if symbol value is 0. */
- { PSEUDO, "NOPUNC", NOPUNCH }, /* Turn off object code generation. */
- { PSEUDO, "OCTAL", OCTAL }, /* Read literal constants in base 8. */
- { PSEUDO, "PAGE", PAGE }, /* Set orign to page +1 or page n (0..37).*/
- { PSEUDO, "PAUSE", PAUSE }, /* Ignored */
- { PSEUDO, "RELOC", RELOC }, /* Assemble to run at a different address.*/
- { PSEUDO, "RIMPUN", RIMPUNCH }, /* Output in Read In Mode format. */
- { PSEUDO, "SEGMNT", SEGMNT }, /* Like page, but with page size=1K words.*/
- { PSEUDO, "TEXT", TEXT }, /* Pack 6 bit trimmed ASCII into memory. */
- { PSEUDO, "XLIST", XLIST }, /* Toggle listing generation. */
- { PSEUDO, "ZBLOCK", ZBLOCK }, /* Zero a block of memory. */
- { PSEUDO, "TITLE", TITLE }, /* Use the text string as a listing title.*/
- { PSEUDO, "BANK", BANK } /* Like field, select some 32K out of 128K*/
-};
-/* Number o extended pseudo operators to ignore unless command option specified
- * to enable */
-#define NUMBER_ADDITIONAL_PSEUDO 2
-
-/* Symbol Table */
-/* The table is put in lexical order on startup, so symbols can be */
-/* inserted as desired into the initial table. */
-/* really_permanent_symbols aren't removed by EXPUNGE */
-SYM_T really_permanent_symbols[] =
-{
- { MRIFIX, "I", 00400 }, /* INDIRECT ADDRESSING */
- { MRIFIX, "Z", 00000 } /* PAGE ZERO ADDRESS */
-};
-
-SYM_T permanent_symbols[] =
-{
- /* Memory Reference Instructions */
- { MRIFIX, "AND", 00000 }, /* LOGICAL AND */
- { MRIFIX, "TAD", 01000 }, /* TWO'S COMPLEMENT ADD */
- { MRIFIX, "ISZ", 02000 }, /* INCREMENT AND SKIP IF ZERO */
- { MRIFIX, "DCA", 03000 }, /* DEPOSIT AND CLEAR ACC */
- { MRIFIX, "JMP", 05000 }, /* JUMP */
- { MRIFIX, "JMS", 04000 }, /* JUMP TO SUBROUTINE */
- /* Floating Point Interpreter Instructions */
- { MRIFIX, "FEXT", 00000 }, /* FLOATING EXIT */
- { MRIFIX, "FADD", 01000 }, /* FLOATING ADD */
- { MRIFIX, "FSUB", 02000 }, /* FLOATING SUBTRACT */
- { MRIFIX, "FMPY", 03000 }, /* FLOATING MULTIPLY */
- { MRIFIX, "FDIV", 04000 }, /* FLOATING DIVIDE */
- { MRIFIX, "FGET", 05000 }, /* FLOATING GET */
- { MRIFIX, "FPUT", 06000 }, /* FLOATING PUT */
- { FIXED, "FNOR", 07000 }, /* FLOATING NORMALIZE */
- { FIXED, "FEXT", 00000 }, /* EXIT FROM FLOATING POINT INTERPRETER */
- { FIXED, "SQUARE", 00001 }, /* SQUARE C(FAC) */
- { FIXED, "SQROOT", 00002 }, /* TAKE SQUARE ROOT OF C(FAC) */
- /* Group 1 Operate Microinstrcutions */
- { FIXED, "OPR", 07000 }, /* NO OPERATION */
- { FIXED, "NOP", 07000 }, /* NO OPERATION */
- { FIXED, "IAC", 07001 }, /* INCREMENT AC */
- { FIXED, "RAL", 07004 }, /* ROTATE AC AND LINK LEFT ONE */
- { FIXED, "RTL", 07006 }, /* ROTATE AC AND LINK LEFT TWO */
- { FIXED, "RAR", 07010 }, /* ROTATE AC AND LINK RIGHT ONE */
- { FIXED, "RTR", 07012 }, /* ROTATE AC AND LINK RIGHT TWO */
- { FIXED, "CML", 07020 }, /* COMPLEMENT LINK */
- { FIXED, "CMA", 07040 }, /* COMPLEMEMNT AC */
- { FIXED, "CLL", 07100 }, /* CLEAR LINK */
- { FIXED, "CLA", 07200 }, /* CLEAR AC */
- /* Group 2 Operate Microinstructions */
- { FIXED, "BSW", 07002 }, /* Swap bytes in AC (PDP/8e) */
- { FIXED, "HLT", 07402 }, /* HALT THE COMPUTER */
- { FIXED, "OSR", 07404 }, /* INCLUSIVE OR SR WITH AC */
- { FIXED, "SKP", 07410 }, /* SKIP UNCONDITIONALLY */
- { FIXED, "SNL", 07420 }, /* SKIP ON NON-ZERO LINK */
- { FIXED, "SZL", 07430 }, /* SKIP ON ZERO LINK */
- { FIXED, "SZA", 07440 }, /* SKIP ON ZERO AC */
- { FIXED, "SNA", 07450 }, /* SKIP ON NON=ZERO AC */
- { FIXED, "SMA", 07500 }, /* SKIP MINUS AC */
- { FIXED, "SPA", 07510 }, /* SKIP ON POSITIVE AC (ZERO IS POSITIVE) */
- /* Combined Operate Microinstructions */
- { FIXED, "CIA", 07041 }, /* COMPLEMENT AND INCREMENT AC */
- { FIXED, "STL", 07120 }, /* SET LINK TO 1 */
- { FIXED, "GLK", 07204 }, /* GET LINK (PUT LINK IN AC BIT 11) */
- { FIXED, "STA", 07240 }, /* SET AC TO -1 */
- { FIXED, "LAS", 07604 }, /* LOAD ACC WITH SR */
- /* MQ Instructions (PDP/8e) */
- { FIXED, "MQL", 07421 }, /* Load MQ from AC, then clear AC. */
- { FIXED, "MQA", 07501 }, /* Inclusive OR MQ with AC */
- { FIXED, "SWP", 07521 }, /* Swap AC and MQ */
- { FIXED, "ACL", 07701 }, /* Load MQ into AC */
- /* Program Interrupt */
- { FIXED, "IOT", 06000 },
- { FIXED, "ION", 06001 }, /* TURN INTERRUPT PROCESSOR ON */
- { FIXED, "IOF", 06002 }, /* TURN INTERRUPT PROCESSOR OFF */
- /* Program Interrupt, PDP-8/e */
- { FIXED, "SKON", 06000 }, /* Skip if interrupt on and turn int off. */
- { FIXED, "SRQ", 06003 }, /* Skip on interrupt request. */
- { FIXED, "GTF", 06004 }, /* Get interrupt flags. */
- { FIXED, "RTF", 06005 }, /* Restore interrupt flags. */
- { FIXED, "SGT", 06006 }, /* Skip on greater than flag. */
- { FIXED, "CAF", 06007 }, /* Clear all flags. */
- /* Keyboard/Reader */
- { FIXED, "KCF", 06030 }, /* CLEAR KEYBOAR FLAG */
- { FIXED, "KSF", 06031 }, /* SKIP ON KEYBOARD FLAG */
- { FIXED, "KCC", 06032 }, /* CLEAR KEYBOARD FLAG & READ CHAR */
- { FIXED, "KRS", 06034 }, /* READ KEYBOARD BUFFER (STATIC) */
- { FIXED, "KIE", 06035 }, /* AC11 TO KEYBD/RDR INT ENABLE F/F */
- { FIXED, "KRB", 06036 }, /* READ KEYBOARD BUFFER & CLEAR FLAG */
- /* Teleprinter/Punch */
- { FIXED, "TFL", 06040 }, /* SET TELEPRINTER/PUNCH FLAG */
- { FIXED, "TSF", 06041 }, /* SKIP ON TELEPRINTER FLAG */
- { FIXED, "TCF", 06042 }, /* CLEAR TELEPRINTER FLAG */
- { FIXED, "TPC", 06044 }, /* LOAD TELEPRINTER & PRINT */
- { FIXED, "TSK", 06045 }, /* SKIP IF TELETYPE INTERRUPT */
- { FIXED, "TLS", 06046 }, /* LOAD TELPRINTER & CLEAR FLAG */
- /* High Speed Paper Tape Reader */
- { FIXED, "RSF", 06011 }, /* SKIP ON READER FLAG */
- { FIXED, "RRB", 06012 }, /* READ READER BUFFER AND CLEAR FLAG */
- { FIXED, "RFC", 06014 }, /* READER FETCH CHARACTER */
- /* PC8-E High Speed Paper Tape Reader & Punch */
- { FIXED, "RPE", 06010 }, /* Set interrupt enable for reader/punch */
- { FIXED, "PCE", 06020 }, /* Clear interrupt enable for rdr/punch */
- { FIXED, "RCC", 06016 }, /* Read reader buffer, clear flags & buf, */
- /* and fetch character. */
- /* High Speed Paper Tape Punch */
- { FIXED, "PSF", 06021 }, /* SKIP ON PUNCH FLAG */
- { FIXED, "PCF", 06022 }, /* CLEAR ON PUNCH FLAG */
- { FIXED, "PPC", 06024 }, /* LOAD PUNCH BUFFER AND PUNCH CHARACTER* */
- { FIXED, "PLS", 06026 }, /* LOAD PUNCH BUFFER AND CLEAR FLAG */
-
- /* DECassette TU60 (RK 20071008) */
- { FIXED, "KCLR", 06700 }, /* Clear all (clear A and B) */
- { FIXED, "KSDR", 06701 }, /* Skip if data flag set */
- { FIXED, "KSEN", 06702 }, /* Skip if EOT/BOT, not ready, or empty */
- { FIXED, "KSBF", 06703 }, /* Skip if ready flag set */
- { FIXED, "KLSA", 06704 }, /* AC4-11 -> A, clear A, -(AC4-11) -> A */
- { FIXED, "KSAF", 06705 }, /* Skip on any flag or error */
- { FIXED, "KGOA", 06706 }, /* Assert status A and transfer data to AC*/
- { FIXED, "KRSB", 06707 }, /* Transfer B -> AC4-11 */
-
- /* DECtape Transport Type TU55 and DECtape Control Type TC01 */
- { FIXED, "DTRA", 06761 }, /* Contents of status register is ORed */
- /* into AC bits 0-9 */
- { FIXED, "DTCA", 06762 }, /* Clear status register A, all flags */
- /* undisturbed */
- { FIXED, "DTXA", 06764 }, /* Status register A loaded by exclusive */
- /* OR from AC. If AC bit 10=0, clear */
- /* error flags; if AC bit 11=0, DECtape */
- /* control flag is cleared. */
- { FIXED, "DTLA", 06766 }, /* Combination of DTCA and DTXA */
- { FIXED, "DTSF", 06771 }, /* Skip if error flag is 1 or if DECtape */
- /* control flag is 1 */
- { FIXED, "DTRB", 06772 }, /* Contents of status register B is */
- /* ORed into AC */
- { FIXED, "DTLB", 06774 }, /* Memory field portion of status */
- /* register B loaded from AC bits 6-8 */
- /* Disk File and Control, Type DF32 */
- { FIXED, "DCMA", 06601 }, /* CLEAR DISK MEMORY REQUEST AND */
- /* INTERRUPT FLAGS */
- { FIXED, "DMAR", 06603 }, /* LOAD DISK FROM AC, CLEAR AC READ */
- /* INTO CORE, CLEAR INTERRUPT FLAG */
- { FIXED, "DMAW", 06605 }, /* LOAD DISK FROM AC, WRITE ONTO DISK */
- /* FROM CORE, CLEAR INTERRUPT FLAG */
- { FIXED, "DCEA", 06611 }, /* CLEAR DISK EXTENDED ADDRESS AND */
- { FIXED, "DSAC", 06612 }, /* SKIP IF ADDRESS CONFIRMED FLAG = 1 */
- /* MEMORY ADDRESS EXTENSION REGISTER */
- { FIXED, "DEAL", 06615 }, /* CLEAR DISK EXTENDED ADDRESS AND */
- /* MEMORY ADDRESS EXTENSION REGISTER */
- /* AND LOAD SAME FROM AC */
- { FIXED, "DEAC", 06616 }, /* CLEAR AC, LOAD AC FROM DISK EXTENDED */
- /* ADDRESS REGISTER, SKIP IF ADDRESS */
- /* CONFIRMED FLAG = 1 */
- { FIXED, "DFSE", 06621 }, /* SKIP IF PARITY ERROR, DATA REQUEST */
- /* LATE, OR WRITE LOCK SWITCH FLAG = 0 */
- /* (NO ERROR) */
- { FIXED, "DFSC", 06622 }, /* SKIP IF COMPLETION FLAG = 1 (DATA */
- /* TRANSFER COMPLETE) */
- { FIXED, "DMAC", 06626 }, /* CLEAR AC, LOAD AC FROM DISK MEMORY */
- /* ADDRESS REGISTER */
- /* Disk File and Control, Type RF08 */
- { FIXED, "DCIM", 06611 },
- { FIXED, "DIML", 06615 },
- { FIXED, "DIMA", 06616 },
- { FIXED, "DISK", 06623 },
- { FIXED, "DCXA", 06641 },
- { FIXED, "DXAL", 06643 },
- { FIXED, "DXAC", 06645 },
- { FIXED, "DMMT", 06646 },
- /* Memory Extension Control, Type 183 */
- { FIXED, "CDF", 06201 }, /* CHANGE DATA FIELD */
- { FIXED, "CIF", 06202 }, /* CHANGE INSTRUCTION FIELD */
- { FIXED, "CDI", 06203 }, /* Change data & instrution field. */
- { FIXED, "RDF", 06214 }, /* READ DATA FIELD */
- { FIXED, "RIF", 06224 }, /* READ INSTRUCTION FIELD */
- { FIXED, "RIB", 06234 }, /* READ INTERRUPT BUFFER */
- { FIXED, "RMF", 06244 }, /* RESTORE MEMORY FIELD */
- /* Memory Parity, Type MP8/I (MP8/L) */
- { FIXED, "SMP", 06101 }, /* SKIP IF MEMORY PARITY FLAG = 0 */
- { FIXED, "CMP", 06104 }, /* CLEAR MEMORY PAIRTY FLAG */
- /* Memory Parity, Type MP8-E (PDP8/e) */
- { FIXED, "DPI", 06100 }, /* Disable parity interrupt. */
- { FIXED, "SNP", 06101 }, /* Skip if no parity error. */
- { FIXED, "EPI", 06103 }, /* Enable parity interrupt. */
- { FIXED, "CNP", 06104 }, /* Clear parity error flag. */
- { FIXED, "CEP", 06106 }, /* Check for even parity. */
- { FIXED, "SPO", 06107 }, /* Skip on parity option. */
- /* Data Communications Systems, Type 680I */
- { FIXED, "TTINCR", 06401 }, /* The content of the line select */
- /* register is incremented by one. */
- { FIXED, "TTI", 06402 }, /* The line status word is read and */
- /* sampled. If the line is active for */
- /* the fourth time, the line bit is */
- /* shifted into the character assembly */
- /* word. If the line bit is active for */
- /* a number of times less than four, */
- /* the count is incremented. If the */
- /* line is not active, the active/inac- */
- /* tive status of the line is recorded */
- { FIXED, "TTO", 06404 }, /* The character in the AC is shifted */
- /* right one position, zeros are shifted */
- /* into vacated positions, and the orig- */
- /* inal content of AC11 is transferred */
- /* out of the computer on the TTY line. */
- { FIXED, "TTCL", 06411 }, /* The line select register is cleared. */
- { FIXED, "TTSL", 06412 }, /* The line select register is loaded by */
- /* an OR transfer from the content of */
- /* of AC5-11, the the AC is cleared. */
- { FIXED, "TTRL", 06414 }, /* The content of the line select regis- */
- /* ter is read into AC5-11 by an OR */
- /* transfer. */
- { FIXED, "TTSKP", 06421 }, /* Skip if clock flag is a 1. */
- { FIXED, "TTXON", 06424 }, /* Clock 1 is enabled to request a prog- */
- /* ram interrupt and clock 1 flag is */
- /* cleared. */
- { FIXED, "TTXOF", 06422 }, /* Clock 1 is disabled from causing a */
- /* program interrupt and clock 1 flag */
- /* is cleared. */
-}; /* End-of-Symbols for Permanent Symbol Table */
-
-/* Global variables */
-SYM_T *symtab; /* Symbol Table */
-int symbol_top; /* Number of entries in symbol table. */
-
-SYM_T *fixed_symbols; /* Start of the fixed symbol table entries. */
-int number_of_fixed_symbols;
-
-/*----------------------------------------------------------------------------*/
-
-WORD16 *xreftab; /* Start of the concordance table. */
-
-ERRSAVE_T error_list[20];
-int save_error_count;
-
-#define GET_PAGE_INDEX(x) (((x) & 07600) >> 7)
-#define MAX_PAGES 32
-LPOOL_T cp[MAX_PAGES]; /* Storage for page constants. */
-int max_page_used[MAX_PAGES];
-
-char s_detected[] = "detected";
-char s_error[] = "error";
-char s_errors[] = "errors";
-char s_no[] = "No";
-char s_page[] = "Page";
-char s_symtable[] = "Symbol Table";
-char s_xref[] = "Cross Reference";
-char s_generated[] = "generated";
-char s_link[] = "link";
-char s_links[] = "links";
-
-/* Assembler diagnostic messages. */
-/* Some attempt has been made to keep continuity with the PAL-III and */
-/* MACRO-8 diagnostic messages. If a diagnostic indicator, (e.g., IC) */
-/* exists, then the indicator is put in the listing as the first two */
-/* characters of the diagnostic message. The PAL-III indicators where used */
-/* when there was a choice between using MACRO-8 and PAL-III indicators. */
-/* The character pairs and their meanings are: */
-/* DT Duplicate Tag (symbol) */
-/* IC Illegal Character */
-/* ID Illegal Redefinition of a symbol. An attempt was made to give */
-/* a symbol a new value not via =. */
-/* IE Illegal Equals An equal sign was used in the wrong context, */
-/* (e.g., A+B=C, or TAD A+=B) */
-/* II Illegal Indirect An off page reference was made, but a literal */
-/* could not be generated because the indirect bit was already set. */
-/* IR Illegal Reference (address is not on current page or page zero) */
-/* ND No $ (the program terminator) at end of file. */
-/* PE Current, Non-Zero Page Exceeded (literal table flowed into code) */
-/* RD ReDefintion of a symbol */
-/* ST Symbol Table full */
-/* UA Undefined Address (undefined symbol) */
-/* ZE Zero Page Exceeded (see above, or out of space) */
-EMSG_T duplicate_label = { "DT duplicate", "duplicate label" };
-EMSG_T illegal_blank = { "IC illegal blank", "illegal blank" };
-EMSG_T illegal_character = { "IC illegal char", "illegal character" };
-EMSG_T illegal_expression = { "IC in expression", "illegal expression" };
-EMSG_T label_syntax = { "IC label syntax", "label syntax" };
-EMSG_T not_a_number = { "IC numeric syntax", "numeric syntax of" };
-EMSG_T number_not_radix = { "IC radix", "number not in current radix"};
-EMSG_T symbol_syntax = { "IC symbol syntax", "symbol syntax" };
-EMSG_T illegal_equals = { "IE illegal =", "illegal equals" };
-EMSG_T illegal_indirect = { "II off page", "illegal indirect" };
-EMSG_T illegal_reference = { "IR off page", "illegal reference" };
-EMSG_T undefined_symbol = { "UD undefined", "undefined symbol" };
-EMSG_T redefined_symbol = { "RD redefined", "redefined symbol" };
-EMSG_T illegal_redefine = { "ID redefined", "Illegal redefine of symbol" };
-EMSG_T literal_overflow = { "PE page exceeded",
- "current page literal capacity exceeded" };
-EMSG_T pz_literal_overflow = { "ZE page exceeded",
- "page zero capacity exceeded" };
-EMSG_T dubl_overflow = { "dubl overflow", "DUBL value overflow" };
-EMSG_T fltg_overflow = { "fltg overflow", "FLTG value overflow" };
-EMSG_T zblock_too_small = { "expr too small", "ZBLOCK value too small" };
-EMSG_T zblock_too_large = { "expr too large", "ZBLOCK value too large" };
-EMSG_T end_of_file = { "ND no $ at EOF", "No $ at End-of-File" };
-EMSG_T no_pseudo_op = { "not implemented",
- "not implemented pseudo-op" };
-EMSG_T illegal_field_value = { "expr out of range",
- "field value not in range of 0 through 7" };
-EMSG_T literal_gen_off = { "literals off",
- "literal generation is off" };
-EMSG_T no_literal_value = { "no value", "no literal value" };
-EMSG_T text_string = { "no delimiter",
- "text string delimiters not matched" };
-EMSG_T in_rim_mode = { "not OK in rim mode"
- "FIELD pseudo-op not valid in RIM mode" };
-EMSG_T lt_expected = { "'<' expected", "'<' expected" };
-EMSG_T symbol_table_full = { "ST Symbol Tbl Full",
- "Symbol Table Full" };
-/*----------------------------------------------------------------------------*/
-
-FILE *errorfile;
-FILE *infile;
-FILE *listfile;
-FILE *listsave;
-FILE *objectfile;
-FILE *objectsave;
-
-char errorpathname[NAMELEN];
-char filename[NAMELEN];
-char listpathname[NAMELEN];
-char objectpathname[NAMELEN];
-char *pathname;
-char permpathname[NAMELEN];
-
-int tabstops; /* number of characters to expand a tab to */
-int list_lineno;
-int list_pageno;
-char list_title[LINELEN];
-BOOL list_title_set; /* Set if TITLE pseudo-op used. */
-char line[LINELEN]; /* Input line. */
-int lineno; /* Current line number. */
-int page_lineno; /* print line number on current page. */
-BOOL listed; /* Listed flag. */
-BOOL listedsave;
-
-int cc; /* Column Counter (char position in line). */
-WORD16 checksum; /* Generated checksum */
-BOOL binary_data_output; /* Set true when data has been output. */
-WORD16 clc; /* Location counter */
-WORD16 cplc; /* Current page literal counter. */
-char delimiter; /* Character immediately after eval'd term. */
-int errors; /* Number of errors found so far. */
-int links; /* Number of links generated so far. */
-BOOL error_in_line; /* TRUE if error on current line. */
-int errors_pass_1; /* Number of errors on pass 1. */
-WORD16 field; /* Current field */
-WORD16 fieldlc; /* location counter without field portion. */
-BOOL fltg_input; /* TRUE when doing floating point input. */
-BOOL indirect_generated; /* TRUE if an off page address generated. */
-int last_xref_lexstart; /* Column where last xref symbol was located. */
-int last_xref_lineno; /* Line where last xref symbol was located. */
-int lexstartprev; /* Where previous lexeme started. */
-int lextermprev; /* Where previous lexeme ended. */
-int lexstart; /* Index of current lexeme on line. */
-int lexterm; /* Index of character after current lexeme. */
-BOOL literals_ok; /* Generate literals, ignore ID redefine err */
-BOOL perm_redef_error; /* Make redefining perm sym with labels error */
-int maxcc; /* Current line length. */
-BOOL overflow; /* Overflow flag for math routines. */
-int pass; /* Number of current pass. */
-BOOL print_permanent_symbols;
-WORD16 pzlc; /* Page Zero literal counter. */
-WORD16 radix; /* Default number radix. */
-WORD16 reloc; /* The relocation distance. */
-BOOL rim_mode; /* Generate rim format, defaults to bin */
-BOOL dollar_not_required; /* $ not required at end of file */
-BOOL additional_enabled; /* True if extended functions over PAL8 */
- /* enabled */
-BOOL symtab_print; /* Print symbol table flag */
-BOOL xref;
-
-FLTG_T fltg_ac; /* Value holder for evalFltg() */
-SYM_T sym_eval = { DEFINED, "", 0 }; /* Value holder for eval() */
-SYM_T sym_getexpr = { DEFINED, "", 0 }; /* Value holder for getexpr() */
-SYM_T sym_undefined = { UNDEFINED, "", 0 };/* Symbol Table Terminator */
-
-
-/******************************************************************************/
-/* */
-/* Function: main */
-/* */
-/* Synopsis: Starting point. Controls order of assembly. */
-/* */
-/******************************************************************************/
-int main( int argc, char *argv[] )
-{
- int ix;
- int space;
-
- /* Set the default values for global symbols. */
- binary_data_output = FALSE;
- fltg_input = FALSE;
- literals_ok = TRUE;
- perm_redef_error = FALSE;
- print_permanent_symbols = FALSE;
- rim_mode = FALSE;
- dollar_not_required = FALSE;
- additional_enabled = FALSE;
- symtab_print = FALSE;
- xref = FALSE;
- pathname = NULL;
-
- /* Get the options and pathnames */
- getArgs( argc, argv );
-
- /* Setup the error file in case symbol table overflows while installing the */
- /* permanent symbols. */
- errorfile = fopen( errorpathname, "w" );
- if (errorfile == NULL) {
- fprintf( stderr, "Could not open error file %s: %s\n", errorpathname, strerror(errno));
- exit( -1 );
-
- }
- errors = 0;
- save_error_count = 0;
- pass = 0; /* This is required for symbol table initialization. */
- symtab = (SYM_T *) malloc( sizeof( SYM_T ) * SYMBOL_TABLE_SIZE );
-
- if( symtab == NULL )
- {
- fprintf( stderr, "Could not allocate memory for symbol table.\n");
- exit( -1 );
- }
-
- /* Place end marker in symbol table. */
- symtab[0] = sym_undefined;
- symbol_top = 0;
- number_of_fixed_symbols = symbol_top;
- fixed_symbols = &symtab[symbol_top - 1];
-
- /* Enter the pseudo-ops into the symbol table */
- for( ix = 0; ix < DIM( pseudo ) -
- (additional_enabled ? 0 : NUMBER_ADDITIONAL_PSEUDO) ; ix++ )
- {
- defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 );
- }
-
- /* Enter the predefined symbols into the table. */
- /* Also make them part of the permanent symbol table. */
- for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ )
- {
- defineSymbol( really_permanent_symbols[ix].name,
- really_permanent_symbols[ix].val,
- really_permanent_symbols[ix].type | DEFFIX , 0 );
- }
-
- /* Enter the predefined symbols into the table. */
- /* Also make them part of the permanent symbol table. */
- for( ix = 0; ix < DIM( permanent_symbols ); ix++ )
- {
- defineSymbol( permanent_symbols[ix].name,
- permanent_symbols[ix].val,
- permanent_symbols[ix].type | DEFFIX , 0 );
- }
-
- number_of_fixed_symbols = symbol_top;
- fixed_symbols = &symtab[symbol_top - 1];
-
- /* Do pass one of the assembly */
- checksum = 0;
- pass = 1;
- page_lineno = LIST_LINES_PER_PAGE;
- onePass();
- errors_pass_1 = errors;
-
- /* Set up for pass two */
- rewind( infile );
- /*Opened in main errorfile = fopen( errorpathname, "w" );*/
- objectfile = fopen( objectpathname, "wb" );
- if (objectfile == NULL) {
- fprintf( stderr, "Could not open object file %s: %s\n", objectpathname, strerror(errno));
- exit( -1 );
-
- }
- objectsave = objectfile;
-
- listfile = fopen( listpathname, "w" );
- if (listfile == NULL) {
- fprintf( stderr, "Could not open list file %s: %s\n", listpathname, strerror(errno));
- exit( -1 );
-
- }
- listsave = NULL;
-
- punchLeader( 0 );
- checksum = 0;
-
- /* Do pass two of the assembly */
- errors = 0;
- save_error_count = 0;
- page_lineno = LIST_LINES_PER_PAGE;
-
- if( xref )
- {
- /* Get the amount of space that will be required for the concordance. */
- for( space = 0, ix = 0; ix < symbol_top; ix++ )
- {
- symtab[ix].xref_index = space; /* Index into concordance table. */
- space += symtab[ix].xref_count + 1;
- symtab[ix].xref_count = 0; /* Clear the count for pass 2. */
-
- }
- /* Allocate the necessary space. */
- xreftab = (WORD16 *) malloc( sizeof( WORD16 ) * space );
-
- /* Clear the cross reference space. */
- for( ix = 0; ix < space; ix++ )
- {
- xreftab[ix] = 0;
- }
- }
- pass = 2;
- onePass();
-
- /* Undo effects of NOPUNCH for any following checksum */
- objectfile = objectsave;
- punchChecksum();
-
- /* Works great for trailer. */
- punchLeader( 8 );
-
- /* undo effects of XLIST for any following output to listing file. */
- if( listfile == NULL )
- {
- listfile = listsave;
- }
-
- /* Display value of error counter. */
- if( errors == 0 )
- {
- fprintf( listfile, "\n %s %s %s\n", s_no, s_detected, s_errors );
- }
- else
- {
- fprintf( errorfile, "\n %d %s %s\n", errors, s_detected,
- ( errors == 1 ? s_error : s_errors ));
- fprintf( listfile, "\n %d %s %s\n", errors, s_detected,
- ( errors == 1 ? s_error : s_errors ));
- fprintf( stderr, " %d %s %s\n", errors, s_detected,
- ( errors == 1 ? s_error : s_errors ));
- }
- /* Display value of link counter. */
- if( links == 0 )
- {
- fprintf( listfile, " %s %s %s\n", s_no, s_links, s_generated );
- }
- else
- {
- fprintf( errorfile, " %d %s %s\n", links,
- ( links == 1 ? s_link : s_links ),
- s_generated);
- fprintf( listfile, " %d %s %s\n", links,
- ( links == 1 ? s_link : s_links ),
- s_generated);
- fprintf( stderr, " %d %s %s\n", links,
- ( links == 1 ? s_link : s_links ),
- s_generated);
- }
-
- if( symtab_print )
- {
- printSymbolTable();
- }
-
- if( print_permanent_symbols )
- {
- printPermanentSymbolTable();
- }
-
- if( xref )
- {
- printCrossReference();
- }
-
- fclose( objectfile );
- fclose( listfile );
- fclose( errorfile );
- if( errors == 0 && errors_pass_1 == 0 )
- {
- remove( errorpathname );
- }
-
- return( errors != 0 );
-} /* main() */
-
-/******************************************************************************/
-/* */
-/* Function: getArgs */
-/* */
-/* Synopsis: Parse command line, set flags accordingly and setup input and */
-/* output files. */
-/* */
-/******************************************************************************/
-void getArgs( int argc, char *argv[] )
-{
- int len;
- int ix, jx;
-
- /* Set the defaults */
- errorfile = NULL;
- infile = NULL;
- listfile = NULL;
- listsave = NULL;
- objectfile = NULL;
- objectsave = NULL;
- tabstops = 8;
-
- for( ix = 1; ix < argc; ix++ )
- {
- if( argv[ix][0] == '-' )
- {
- for( jx = 1; argv[ix][jx] != 0; jx++ )
- {
- switch( argv[ix][jx] )
- {
- case '$':
- dollar_not_required = TRUE;
- break;
-
- case 'd':
- symtab_print = TRUE;
- break;
-
- case 'a':
- additional_enabled = TRUE;
- break;
-
- case 'r':
- rim_mode = TRUE;
- break;
-
- case 'e':
- literals_ok = FALSE;
- break;
-
- case 'l':
- literals_ok = TRUE;
- break;
-
- case 'n':
- perm_redef_error = TRUE;
- break;
-
- case 'p':
- print_permanent_symbols = TRUE;
- break;
-
- /* Added -tN; RK 20071029 */
- /* Damn, this is ugly, we should use getopt() */
- case 't':
- if (argv [ix][jx + 1]) {
- tabstops = atoi (argv [ix] + (jx + 1));
- /* advance past numbers */
- for (jx++; argv [ix][jx]; jx++) ;
- jx--;
- } else {
- ix++;
- if (ix >= argc) {
- fprintf( stderr, "%s: missing argument for -t, expected number of tabsopts\n", argv[0] );
- exit( -1 );
- }
- for (jx = 0; argv [ix][jx]; jx++) ;
- jx--;
- tabstops = atoi (argv [ix]);
- }
- break;
-
- case 'x':
- xref = TRUE;
- break;
-
- case 'v':
- fprintf( stderr, "%s\n", release );
- fflush( stderr );
- exit( -1 );
- break;
-
- default:
- fprintf( stderr, "%s: unknown flag: %s\n", argv[0], argv[ix] );
- case 'h':
- fprintf( stderr, " -$ -- allow file to not end with $\n" );
- fprintf( stderr, " -a -- enable additional function not in PAL8\n" );
- fprintf( stderr, " -d -- dump symbol table\n" );
- fprintf( stderr, " -e -- error if link generated\n" );
- fprintf( stderr, " -h -- show this help\n" );
- fprintf( stderr, " -l -- generate literal/link (default)\n" );
- fprintf( stderr, " -n -- no redefining with label permanent symbols\n" );
- fprintf( stderr, " -p -- output permanent symbols to file\n" );
- fprintf( stderr, " -r -- output rim format file\n" );
- fprintf( stderr, " -t N -- set tab stops to N\n" );
- fprintf( stderr, " -v -- display version\n" );
- fprintf( stderr, " -x -- output cross reference to file\n" );
- fflush( stderr );
- exit( -1 );
- } /* end switch */
- } /* end for */
- }
- else
- {
- if( pathname != NULL )
- {
- fprintf( stderr, "%s: too many input files\n", argv[0] );
- exit( -1 );
- }
- pathname = &argv[ix][0];
- }
- } /* end for */
-
- if( pathname == NULL )
- {
- fprintf( stderr, "%s: no input file specified\n", argv[0] );
- exit( -1 );
- }
-
- len = strlen( pathname );
- if( len > NAMELEN - 5 )
- {
- fprintf( stderr, "%s: pathname \"%s\" too long\n", argv[0], pathname );
- exit( -1 );
- }
-
- /* Now open the input file. */
- if(( infile = fopen( pathname, "r" )) == NULL )
- {
- fprintf( stderr, "%s: cannot open \"%s\": %s\n", argv[0], pathname, strerror(errno) );
- exit( -1 );
- }
-
- /* Now make the pathnames */
- /* Find last '.', if it exists. */
- jx = len - 1;
- while( pathname[jx] != '.' && pathname[jx] != '/'
- && pathname[jx] != '\\' && jx >= 0 )
- {
- jx--;
- }
-
- switch( pathname[jx] )
- {
- case '.':
- break;
-
- case '/':
- case '\\':
- jx = len;
- break;
-
- default:
- break;
- }
-
- /* Add the pathname extensions. */
- strncpy( objectpathname, pathname, jx );
- objectpathname[jx] = '\0';
- strcat( objectpathname, rim_mode ? ".rim" : ".bin" );
-
- strncpy( listpathname, pathname, jx );
- listpathname[jx] = '\0';
- strcat( listpathname, ".lst" );
-
- strncpy( errorpathname, pathname, jx );
- errorpathname[jx] = '\0';
- strcat( errorpathname, ".err" );
-
- strncpy( permpathname, pathname, jx );
- permpathname[jx] = '\0';
- strcat( permpathname, ".prm" );
-
- /* Extract the filename from the path. */
- if( isalpha( pathname[0] ) && pathname[1] == ':' && pathname[2] != '\\' )
- {
- pathname[1] = '\\'; /* MS-DOS style pathname */
- }
-
- jx = len - 1;
- while( pathname[jx] != '/' && pathname[jx] != '\\' && jx >= 0 )
- {
- jx--;
- }
- strcpy( filename, &pathname[jx + 1] );
-
-} /* getArgs() */
-
-/******************************************************************************/
-/* */
-/* Function: clearLiteralTable */
-/* */
-/* Synopsis: Clear the cp and max_page_used data storing literal */
-/* information. */
-/* */
-/******************************************************************************/
-void clearLiteralTable()
-{
- int i;
-
- for (i = 0; i < DIM(cp); i++)
- {
- cp[i].loc = 0200; /* Points to end of page for [] operands. */
- cp[i].last_punched = 0200; /* Points to end of page for [] operands. */
- }
- memset(max_page_used, 0, sizeof(max_page_used));
-}
-
-/******************************************************************************/
-/* */
-/* Function: onePass */
-/* */
-/* Synopsis: Do one assembly pass. */
-/* */
-/******************************************************************************/
-void onePass()
-{
- char name[SYMLEN];
- WORD16 newclc;
- BOOL scanning_line;
- int start;
- SYM_T *sym;
- int term;
- WORD16 val;
-
- clc = 0200; /* Default starting address is 200 octal. */
- field = 0;
- fieldlc = clc & 07777;
- reloc = 0;
- clearLiteralTable();
- listed = TRUE;
- lineno = 0;
- list_pageno = 0;
- list_lineno = 0;
- last_xref_lexstart = 0;
- last_xref_lineno = 0;
- list_title_set = FALSE;
- radix = 8; /* Initial radix is octal (base 8). */
-
- if( !rim_mode )
- {
- /* Put out initial origin if not in rim mode. */
- punchOrigin( clc );
- }
-
- while( TRUE )
- {
- readLine();
- nextLexeme();
-
- scanning_line = TRUE;
- while( scanning_line )
- {
- if( isend( line[lexstart] ))
- {
- scanning_line = FALSE;
- }
- else
- {
- switch( line[lexstart] )
- {
- case '/':
- scanning_line = FALSE;
- break;
-
- case ';':
- nextLexeme();
- break;
-
- case '$':
- endOfBinary();
- return;
-
- case '*':
- nextLexeme(); /* Skip '*', (set origin symbol) */
- newclc = ((getExpr())->val & 07777 ) | field;
- /* Do not change Current Location Counter if an error occurred. */
- if( !error_in_line )
- {
- if(( newclc & 07600 ) != ( clc & 07600 ) )
- {
- /* Current page has changed. */
- punchLiteralPool( cp, 0 );
- }
- clc = newclc - reloc;
- fieldlc = clc & 07777;
-
- if( !rim_mode )
- {
- /* Not rim mode, put out origin. */
- punchOrigin( clc );
- }
- printLine( line, 0, fieldlc, LINE_VAL );
- }
- break;
-
- default:
- switch( line[lexterm] )
- {
- case ',':
- if( isalpha( line[lexstart] ))
- {
- /* Use lookup so symbol will not be counted as reference. */
- sym = lookup( lexemeToName( name, lexstart, lexterm ));
- if( M_DEFINED( sym->type ))
- {
- if( (sym->val & 07777) != ( ( clc+reloc ) & 07777) && pass == 2 )
- {
- errorSymbol( &duplicate_label, sym->name, lexstart );
- }
- sym->type = sym->type | DUPLICATE;
- }
- /* Must call define on pass 2 to generate concordance. */
- defineLexeme( lexstart, lexterm, ( clc + reloc ), LABEL );
- }
- else
- {
- errorLexeme( &label_syntax, lexstart );
- }
- nextLexeme(); /* skip label */
- nextLexeme(); /* skip comma */
- break;
-
- case '=':
- if( isalpha( line[lexstart] ))
- {
- start = lexstart;
- term = lexterm;
- delimiter = line[lexterm];
- nextLexBlank(); /* skip symbol */
- nextLexeme(); /* skip trailing =, allow blank */
- delimiter = line[lexterm];
- val = getExprs();
- defineLexeme( start, term, val, DEFINED );
- printLine( line, 0, val, LINE_VAL );
- }
- else
- {
- errorLexeme( &symbol_syntax, lexstartprev );
- nextLexeme(); /* skip symbol */
- nextLexeme(); /* skip trailing = */
- getExprs(); /* skip expression */
- }
- break;
-
- default:
- if( isalpha( line[lexstart] ))
- {
- sym = evalSymbol();
- val = sym->val;
- if( M_PSEUDO( sym->type ))
- {
- nextLexeme(); /* Skip symbol */
- scanning_line = pseudoOperators( (PSEUDO_T)val & 07777 );
- }
- else
- {
- /* Identifier is not a pseudo-op, interpret as load value */
- punchOutObject( clc, getExprs() & 07777 );
- incrementClc();
- }
- }
- else
- {
- /* Identifier is a value, interpret as load value */
- punchOutObject( clc, getExprs() & 07777 );
- incrementClc();
- }
- break;
- } /* end switch */
- break;
- } /* end switch */
- } /* end if */
- } /* end while( scanning_line ) */
- } /* end while( TRUE ) */
-} /* onePass() */
-
-
-/******************************************************************************/
-/* */
-/* Function: fixMRIInstruction */
-/* */
-/* Synopsis: Now that we have the final value figure out if page 0, current */
-/* page, or indirect needed and max final instruction */
-/* */
-/******************************************************************************/
-WORD16 fixMRIInstruction(WORD16 instruction, WORD16 value)
-{
- /* Now have the address part of the MRI instruction. */
- if( value < 00200 )
- {
- instruction |= value; /* Page zero MRI. */
- }
- else if( (( fieldlc + reloc ) & 07600 ) <= value
- && value <= ((( fieldlc + reloc ) & 07600) | 0177 ))
- {
- instruction |= ( PAGE_BIT | (value & ADDRESS_FIELD )); /* Current page MRI */
- }
- else
- {
- if(( instruction & INDIRECT_BIT ) == INDIRECT_BIT )
- {
- /* Already indirect, can't generate */
- errorSymbol( &illegal_indirect, NULL, lexstartprev );
- }
- else
- {
- if( literals_ok )
- {
- /* Now fix off page reference. */
- /* Search current page literal pool for needed instruction. */
- /* Set Indirect Current Page */
- instruction |= ( 00600 | insertLiteral( cp, value, GET_PAGE_INDEX(clc) ));
- indirect_generated = TRUE;
- if (pass == 2)
- {
- links++;
- }
- }
- else
- {
- errorSymbol( &illegal_reference, NULL, lexstartprev );
- instruction |= ( value & 0177 );
- }
- }
- }
- return instruction;
-}
-/******************************************************************************/
-/* */
-/* Function: getExprs */
-/* */
-/* Synopsis: Or together a list of blank separated expressions, from the */
-/* current lexeme onward. Leave the current lexeme as */
-/* the last one in the list. */
-/* */
-/******************************************************************************/
-WORD16 getExprs()
-{
- SYM_T *symv;
- SYM_T *symt;
- WORD16 temp;
- SYMTYP temp_type;
- WORD16 value;
- SYMTYP value_type;
- BOOL MRI_held = FALSE;
- WORD16 held_value = 0;
-
- symv = getExpr();
- value = symv->val;
- value_type = symv->type;
-
- while( TRUE )
- {
- if( isdone( line[lexstart] ))
- {
- if (MRI_held)
- {
- value = fixMRIInstruction(value, held_value);
- }
- return( value );
- }
- switch( line[lexstart] )
- {
- case ')':
- case ']':
- case '<':
- if (MRI_held)
- {
- value = fixMRIInstruction(value, held_value);
- }
- return( value );
-
- default:
- break;
- }
-
- /* Interpret space as logical or */
- symt = getExpr();
- temp = symt->val & 07777;
- temp_type = symt->type;
-
- switch( value_type & (MRI | MRIFIX))
- {
- case MRI:
- case MRIFIX:
- /* Previous symbol was a Memory Reference Instruction. */
- switch( temp_type & (MRI | MRIFIX) )
- {
- case MRI:
- case MRIFIX:
- /* If we have held value don't or in more MRI's to instuction, they */
- /* are now instuction value */
- if (MRI_held)
- {
- held_value |= temp;
- }
- else
- {
- /* Current symbol is also a Memory Reference Instruction. */
- value |= temp; /* Just OR the MRI instructions. */
- }
- break;
-
- default:
- held_value |= temp;
- MRI_held = TRUE;
- break;
- }
- break;
-
- default:
- if (value_type == UNDEFINED || temp_type == UNDEFINED) {
- value = 0;
- } else {
- value |= temp; /* Normal 12 bit value. */
- }
- break;
- }
- } /* end while */
-} /* getExprs() */
-
-
-/******************************************************************************/
-/* */
-/* Function: getExpr */
-/* */
-/* Synopsis: Get an expression, from the current lexeme onward, leave the */
-/* current lexeme as the one after the expression. Expressions */
-/* contain terminal symbols (identifiers) separated by operators. */
-/* */
-/******************************************************************************/
-SYM_T *getExpr()
-{
- SYM_T *sym;
- delimiter = line[lexterm];
-
-
- if( line[lexstart] == '-' )
- {
- nextLexBlank();
- sym_getexpr = *(eval());
- sym_getexpr.val = ( - sym_getexpr.val ) & 07777;
- }
- else
- {
- if( line[lexstart] == '+' )
- {
- nextLexBlank();
- }
- sym_getexpr = *(eval());
- sym_getexpr.val = sym_getexpr.val & 07777;
- }
-
- if( is_blank( delimiter ))
- {
- return( &sym_getexpr );
- }
-
- /* Here we assume the current lexeme is the operator separating the */
- /* previous operator from the next, if any. */
- while( TRUE )
- {
- /* assert line[lexstart] == delimiter */
- if( is_blank( delimiter ))
- {
- return( &sym_getexpr );
- }
-
- switch( line[lexstart] )
- {
- case '+': /* add */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val += sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- case '-': /* subtract */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val -= sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- case '^': /* multiply */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val *= sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- case '%': /* divide */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val /= sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- case '&': /* and */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val &= sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- case '!': /* or */
- nextLexBlank(); /* skip over the operator */
- sym = eval();
- sym_getexpr.val |= sym->val;
- if (sym_getexpr.type == UNDEFINED || sym->type == UNDEFINED) {
- sym_getexpr.val = 0;
- sym_getexpr.type = UNDEFINED;
- }
- break;
-
- default:
- if( isend( line[lexstart] ))
- {
- return( &sym_getexpr );
- }
-
- switch( line[lexstart] )
- {
- case '/':
- case ';':
- case ')':
- case ']':
- case '<':
- break;
-
- case '=':
- errorMessage( &illegal_equals, lexstart );
- moveToEndOfLine();
- sym_getexpr.val = 0;
- break;
-
- default:
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- sym_getexpr.val = 0;
- break;
- }
- return( &sym_getexpr );
- }
- } /* end while */
-} /* getExpr() */
-
-
-/******************************************************************************/
-/* */
-/* Function: eval */
-/* */
-/* Synopsis: Get the value of the current lexeme, set delimiter and advance.*/
-/* */
-/******************************************************************************/
-SYM_T *eval()
-{
- WORD16 digit;
- int from;
- WORD16 loc;
- SYM_T *sym;
- WORD16 val;
-
- val = 0;
-
- delimiter = line[lexterm];
- if( isalpha( line[lexstart] ))
- {
- sym = evalSymbol();
- if( M_UNDEFINED( sym->type ) && pass == 2 )
- {
- errorSymbol( &undefined_symbol, sym->name, lexstart );
- nextLexeme();
- return( sym );
- }
- else
- {
- nextLexeme();
- return( sym );
- }
- }
- else if( isdigit( line[lexstart] ))
- {
- from = lexstart;
- val = 0;
- while( from < lexterm )
- {
- if( isdigit( line[from] ))
- {
- digit = (WORD16) line[from++] - (WORD16) '0';
- if( digit < radix )
- {
- val = val * radix + digit;
- }
- else
- {
- errorLexeme( &number_not_radix, from - 1 );
- val = 0;
- from = lexterm;
- }
- }
- else
- {
- errorLexeme( ¬_a_number, lexstart );
- val = 0;
- from = lexterm;
- }
- }
- nextLexeme();
- sym_eval.val = val;
- return( &sym_eval );
- }
- else
- {
- switch( line[lexstart] )
- {
- case '"': /* Character literal */
- if( cc + 1 <= maxcc )
- {
- val = line[lexstart + 1] | 0200;
- delimiter = line[lexstart + 2];
- cc = lexstart + 2;
- }
- else
- {
- errorMessage( &no_literal_value, lexstart );
- }
- nextLexeme();
- break;
-
- case '.': /* Value of Current Location Counter */
- val = (clc & 07777) + reloc;
- nextLexeme();
- break;
-
- case '[': /* Generate literal on page zero. */
- if( !literals_ok && LITERAL_ERROR)
- {
- errorMessage( &literal_gen_off, lexstart );
- }
- nextLexBlank(); /* Skip bracket */
- val = getExprs() & 07777;
-
- if( line[lexstart] == ']' )
- {
- nextLexBlank(); /* Skip end bracket */
- }
-
- sym_eval.val = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp , val,
- GET_PAGE_INDEX(field)) : 0;
- return( &sym_eval );
-
- case '(': /* Generate literal on current page. */
- if( !literals_ok && LITERAL_ERROR)
- {
- errorMessage( &literal_gen_off, lexstart );
- }
-
- nextLexBlank(); /* Skip paren */
- val = getExprs() & 07777;
-
- if( line[lexstart] == ')' )
- {
- nextLexBlank(); /* Skip end paren */
- }
-
- loc = (literals_ok || !LITERAL_ERROR) ? insertLiteral( cp, val, GET_PAGE_INDEX(clc) ) : 0;
- sym_eval.val = loc + (( clc + reloc ) & 077600 );
- return( &sym_eval );
-
- default:
- switch( line[lexstart] )
- {
- case '=':
- errorMessage( &illegal_equals, lexstart );
- moveToEndOfLine();
- break;
-
- default:
- errorMessage( &illegal_character, lexstart );
- break;
- }
- val = 0; /* On error, set value to zero. */
- nextLexBlank(); /* Go past illegal character. */
- }
- }
- sym_eval.val = val;
- return( &sym_eval );
-} /* eval() */
-
-
-/******************************************************************************/
-/* */
-/* Function: inputDubl */
-/* */
-/* Synopsis: Get the value of the current lexeme as a double word. */
-/* */
-/******************************************************************************/
-void inputDubl()
-{
- WORD32 dublvalue;
- BOOL scanning_line;
-
- scanning_line = TRUE;
- do
- {
- while( scanning_line )
- {
- if( isend( line[lexstart] ))
- {
- scanning_line = FALSE;
- }
- else
- {
- switch( line[lexstart] )
- {
- case '/':
- scanning_line = FALSE;
- break;
-
- case ';':
- nextLexeme();
- break;
-
- case '+':
- delimiter = line[lexterm];
- nextLexBlank();
- case '-':
- default:
- if( isdigit( line[lexstart] ) || line[lexstart] == '-' )
- {
- dublvalue = getDublExprs();
- punchOutObject( clc, (WORD16)(( dublvalue >> 12 ) & 07777 ));
- incrementClc();
- punchOutObject( clc, (WORD16)( dublvalue & 07777 ));
- incrementClc();
- }
- else
- {
- return; /* Non-numeric input, back to assembly. */
- }
- break;
- } /* end switch */
- } /* end if */
-
- if( error_in_line )
- {
- return; /* Error occurred, exit DUBL input mode. */
- }
- } /* end while( scanning_line ) */
- readLine();
- nextLexeme();
- scanning_line = TRUE;
- }
- while( TRUE );
-} /* inputDubl() */
-
-
-/******************************************************************************/
-/* */
-/* Function: getDublExprs */
-/* */
-/* Synopsis: Get a DUBL expression. */
-/* */
-/******************************************************************************/
-WORD32 getDublExprs()
-{
- WORD32 dublvalue;
-
- dublvalue = getDublExpr();
-
- while( TRUE )
- {
- if( isdone( line[lexstart] ))
- {
- return( dublvalue );
- }
- else
- {
- errorMessage( &illegal_expression, lexstart - 1 );
- return( 0 );
- }
- } /* end while */
-} /* getDublExprs() */
-
-
-/******************************************************************************/
-/* */
-/* Function: getDublExpr */
-/* */
-/* Synopsis: Get the value of the current lexeme as a double word. The */
-/* number is always considered to have a decimal radix. */
-/* */
-/******************************************************************************/
-WORD32 getDublExpr()
-{
- WORD32 dublvalue;
-
- delimiter = line[lexterm];
- if( line[lexstart] == '-' )
- {
- nextLexBlank();
- dublvalue = evalDubl( 0 );
- nextLexeme();
- /* Test for any value greater than 23 bits in length. */
- if( (unsigned long int)dublvalue > 040000000L )
- {
- errorMessage( &dubl_overflow, lexstart );
- dublvalue = 0;
- }
- dublvalue = -dublvalue;
- }
- else
- {
- dublvalue = evalDubl( 0 );
- nextLexeme();
- /* Test for any value greater than 23 bits in length. */
- if( (unsigned long int)dublvalue > 037777777L )
- {
- errorMessage( &dubl_overflow, lexstart );
- dublvalue = 0;
- }
- }
-
- if( is_blank( delimiter ))
- {
- return( dublvalue );
- }
-
- /* Here we assume the current lexeme is the operator separating the */
- /* previous operator from the next, if any. */
- while( TRUE )
- {
- /* assert line[lexstart] == delimiter */
- if( is_blank( delimiter ))
- {
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- dublvalue = 0;
- return( dublvalue );
- }
-
- switch( line[lexstart] )
- {
- case '+': /* add */
- case '-': /* subtract */
- case '^': /* multiply */
- case '%': /* divide */
- case '&': /* and */
- case '!': /* or */
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- dublvalue = 0;
- break;
-
- default:
- if( isend( line[lexstart] ))
- {
- return( dublvalue );
- }
-
- switch( line[lexstart] )
- {
- case '/':
- case ';':
- break;
-
- default:
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- dublvalue = 0;
- break;
- }
- return( dublvalue );
- }
- } /* end while */
-} /* getDublExpr() */
-
-
-/******************************************************************************/
-/* */
-/* Function: evalDubl */
-/* */
-/* Synopsis: Get the value of the current lexeme as a double word. The */
-/* number is always considered to have a decimal radix. */
-/* */
-/******************************************************************************/
-WORD32 evalDubl( WORD32 initial_value )
-{
- WORD32 digit;
- int from;
- WORD32 dublvalue;
- WORD32 olddublvalue;
-
- overflow = FALSE;
- delimiter = line[lexterm];
- from = lexstart;
- dublvalue = initial_value;
-
- while( from < lexterm )
- {
- if( isdigit( line[from] ))
- {
- olddublvalue = dublvalue;
- digit = (WORD32)( line[from++] - '0' );
- dublvalue = dublvalue * 10 + digit;
- if( dublvalue < olddublvalue )
- {
- overflow = TRUE;
- }
- }
- else
- {
- errorLexeme( ¬_a_number, from );
- dublvalue = 0;
- from = lexterm;
- }
- }
- return( dublvalue );
-} /* evalDubl() */
-
-
-/******************************************************************************/
-/* */
-/* Function: inputFltg */
-/* */
-/* Synopsis: Get the value of the current lexeme as a Floating Point const. */
-/* */
-/******************************************************************************/
-void inputFltg()
-{
- FLTG_T *fltg;
- BOOL scanning_line;
-
- fltg_input = TRUE; /* Set lexeme scanner for floating point. */
- scanning_line = TRUE;
- while( TRUE )
- {
- while( scanning_line )
- {
- if( isend( line[lexstart] ))
- {
- scanning_line = FALSE;
- }
- else
- {
- switch( line[lexstart] )
- {
- case '/':
- scanning_line = FALSE;
- break;
-
- case ';':
- nextLexeme();
- break;
-
- case '+':
- delimiter = line[lexterm];
- nextLexBlank();
- case '-':
- default:
- if( isdigit( line[lexstart] ) || line[lexstart] == '-' )
- {
- fltg = getFltgExprs();
- punchOutObject( clc, ( fltg->exponent & 07777 ));
- incrementClc();
- punchOutObject( clc, (WORD16)(( fltg->mantissa >> 12 ) & 07777 ));
- incrementClc();
- punchOutObject( clc, (WORD16)( fltg->mantissa & 07777 ));
- incrementClc();
- }
- else
- {
- fltg_input = FALSE; /* Reset lexeme scanner. */
- return; /* Non-numeric input, back to assembly. */
- }
- break;
- } /* end switch */
- } /* end if */
-
- if( error_in_line )
- {
- fltg_input = FALSE; /* Reset lexeme scanner. */
- return; /* Error occurred, exit FLTG input mode. */
- }
- } /* end while( scanning_line ) */
- readLine();
- nextLexeme();
- scanning_line = TRUE;
- }
-} /* inputFltg() */
-
-
-/******************************************************************************/
-/* */
-/* Function: getFltgExprs */
-/* */
-/* Synopsis: Get a FLTG expression. */
-/* */
-/******************************************************************************/
-FLTG_T *getFltgExprs()
-{
- FLTG_T *fltg;
-
- fltg = getFltgExpr();
-
- while( TRUE )
- {
- if( isdone( line[lexstart] ))
- {
- return( fltg );
- }
- else
- {
- errorMessage( &illegal_expression, lexstart - 1 );
- return( 0 );
- }
- } /* end while */
-} /* getFltgExprs() */
-
-
-/******************************************************************************/
-/* */
-/* Function: getFltgExpr */
-/* */
-/* Synopsis: Get the value of the current lexeme as a double word. The */
-/* number is always considered to have a decimal radix. */
-/* */
-/******************************************************************************/
-FLTG_T *getFltgExpr()
-{
- FLTG_T *fltg;
-
- delimiter = line[lexterm];
- fltg = evalFltg();
- /* Test for any value greater than 23 bits in length. */
- if( (unsigned long int)fltg->mantissa> 077777777L )
- {
- errorMessage( &fltg_overflow, lexstart );
- }
-
- if( is_blank( delimiter ))
- {
- return( fltg );
- }
-
- /* Here we assume the current lexeme is the operator separating the */
- /* previous operator from the next, if any. */
- while( TRUE )
- {
- /* assert line[lexstart] == delimiter */
- if( is_blank( delimiter ))
- {
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- fltg = 0;
- return( fltg );
- }
-
- switch( line[lexstart] )
- {
- case '+': /* add */
- case '-': /* subtract */
- case '^': /* multiply */
- case '%': /* divide */
- case '&': /* and */
- case '!': /* or */
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- fltg = NULL;
- break;
-
- default:
- if( isend( line[lexstart] ))
- {
- return( fltg );
- }
-
- switch( line[lexstart] )
- {
- case '/':
- case ';':
- break;
-
- default:
- errorMessage( &illegal_expression, lexstart );
- moveToEndOfLine();
- fltg = NULL;
- break;
- }
- return( fltg );
- }
- } /* end while */
-} /* getFltgExpr() */
-
-
-/******************************************************************************/
-/* */
-/* Function: evalFltg */
-/* */
-/* Synopsis: Get the value of the current lexeme as a floating point value. */
-/* Floating point input is alwasy considered decimal. */
-/* The general format of a floating point number is: */
-/* +-ddd.dddE+-dd where each d is a decimal digit. */
-/* */
-/******************************************************************************/
-FLTG_T *evalFltg()
-{
- int current_state;
- int current_col;
- WORD16 exponent;
- FLTG_T *fltg;
- WORD32 input_value;
- BOOL negate;
- BOOL negate_exponent;
- int next_state;
- int right_digits;
-
- /* This uses a lexical analyzer to parse the floating point format. */
- static BYTE state_table[][10] =
- {
- /* 0 1 2 3 4 5 6 Oolumn index */
- /* + - d . E sp p State Comment */
- { 2, 1, 3, 4, 10, 10, 10 }, /* 0 Initial state. */
- { 11, 11, 3, 4, 11, 11, 11 }, /* 1 - */
- { 11, 11, 3, 4, 11, 11, 11 }, /* 2 + */
- { 10, 10, 10, 4, 6, 10, 10 }, /* 3 # (+-ddd) */
- { 11, 11, 5, 11, 11, 10, 10 }, /* 4 . (+-ddd.) */
- { 11, 11, 11, 11, 6, 10, 11 }, /* 5 # (+-ddd.ddd) */
- { 8, 7, 9, 11, 11, 11, 11 }, /* 6 E (+-ddd.dddE) */
- { 11, 11, 9, 11, 11, 11, 11 }, /* 7 - (+-ddd.dddE- */
- { 11, 11, 9, 11, 11, 11, 11 }, /* 8 + (+-ddd.dddE+ */
- { 11, 11, 11, 11, 11, 10, 11 } /* 9 # (+-ddd.dddE+-dd */
- /* 10 Completion state */
- /* 11 Error state. */
- };
-
- delimiter = line[lexterm];
- fltg = &fltg_ac;
- fltg->exponent = 0;
- fltg->mantissa = 0;
- input_value = 0;
- negate = FALSE;
- negate_exponent = FALSE;
- next_state = 0;
- exponent = 0;
- right_digits = 0;
- current_state = 0;
-
- while( TRUE )
- {
- /* Classify character. This is the column index. */
- switch( line[lexstart] )
- {
- case '+':
- current_col = 0;
- break;
-
- case '-':
- current_col = 1;
- break;
-
- case '.':
- current_col = 3;
- break;
-
- case 'E': case 'e':
- current_col = 4;
- break;
-
- default:
- if( isdigit( line[lexstart] ))
- {
- current_col = 2;
- }
- else if( isdone( line[lexstart] ))
- {
- current_col = 5;
- }
- else
- {
- current_col = 6;
- }
- break;
- }
-
- next_state = state_table[current_state][current_col];
-
- switch( next_state )
- {
- case 1: /* - */
- negate = TRUE;
- case 2: /* + */
- delimiter = line[lexterm]; /* Move past the + or - character. */
- nextLexBlank();
- break;
-
- case 3: /* Number (+-ddd) */
- input_value = evalDubl( 0 ); /* Integer part of the number. */
- nextLexeme(); /* Move past previous lexeme. */
- break;
-
- case 4:
- delimiter = line[lexterm];
- nextLexBlank(); /* Move past the . character. */
- break;
-
- case 5: /* . (+-ddd.ddd) */
- /* Fractional part of the number. */
- input_value = evalDubl( input_value );
- right_digits = lexterm - lexstart;/* Digit count to right of decimal. */
- nextLexeme(); /* Move past previous lexeme. */
- break;
-
- case 6: /* E (+-ddd.dddE) */
- delimiter = line[lexterm]; /* Move past the E. */
- nextLexBlank();
- break;
-
- case 7: /* - (+-ddd.dddE-) */
- negate_exponent = TRUE;
- case 8: /* + (+-ddd.dddE+) */
- delimiter = line[lexterm]; /* Move past the + or - character. */
- nextLexBlank();
- break;
-
- case 9: /* # (+-ddd.dddE+-dd) */
- exponent = (int)evalDubl( 0 ); /* Exponent of floating point number. */
- if( negate_exponent ) { exponent = - exponent; }
- nextLexeme(); /* Move past previous lexeme. */
- break;
-
- case 10: /* Floating number parsed, convert */
- /* the number. */
- /* Get the exponent for the number as input. */
- exponent -= right_digits;
-
- /* Remove trailing zeros and adjust the exponent accordingly. */
- while(( input_value % 10 ) == 0 )
- {
- input_value /= 10;
- exponent++;
- }
-
- /* Convert the number to floating point. The number is calculated with */
- /* a 27 bit mantissa to improve precision. The extra 3 bits are */
- /* discarded after the result has been calculated. */
- fltg->exponent = 26;
- fltg->mantissa = input_value << 3;
- normalizeFltg( fltg );
-
-
- while( exponent != 0 )
- {
- if( exponent < 0 )
- {
- /* Decimal point is to the left. */
- fltg->mantissa /= 10;
- normalizeFltg( fltg );
- exponent++;
- }
- else if( exponent > 0 )
- {
- /* Decimal point is to the right. */
- fltg->mantissa *= 10;
- normalizeFltg( fltg );
- exponent--;
- }
- }
-
- /* Discard the extra precsion used for calculating the number. */
- fltg->mantissa >>= 3;
- fltg->exponent -= 3;
- if( negate )
- {
- fltg->mantissa = (- fltg->mantissa ) & 077777777L;
- }
- return( fltg );
-
- case 11: /* Error in format. */
- /* Not a properly constructued floating point number. */
- return( fltg );
- default:
- break;
- }
- /* Set state for next pass through the loop. */
- current_state = next_state;
- }
-} /* evalFltg() */
-
-
-
-/******************************************************************************/
-/* */
-/* Function: normalizeFltg */
-/* */
-/* Synopsis: Normalize a PDP-8 double precision floating point number. */
-/* */
-/******************************************************************************/
-void normalizeFltg( FLTG_T *fltg )
-{
- /* Normalize the floating point number. */
- if( fltg->mantissa != 0 )
- {
- if(( fltg->mantissa & ~0x3FFFFFFL ) == 0 )
- {
- while(( fltg->mantissa & ~0x1FFFFFFL ) == 0 )
-
- {
- fltg->mantissa <<= 1;
- fltg->exponent--;
- }
- }
- else
- {
- while(( fltg->mantissa & ~0x3FFFFFFL ) != 0 )
- {
- fltg->mantissa >>= 1;
- fltg->exponent++;
- }
- }
- }
- else
- {
- fltg->exponent = 0;
- }
- return;
-}
-
-
-/******************************************************************************/
-/* */
-/* Function: incrementClc */
-/* */
-/* Synopsis: Set the next assembly location. Test for collision with */
-/* the literal tables. */
-/* */
-/******************************************************************************/
-WORD16 incrementClc()
-{
- testForLiteralCollision( clc );
-
- /* Incrementing the location counter is not to change field setting. */
- clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 );
- fieldlc = clc & 07777;
- return( clc );
-} /* incrementClc() */
-
-
-/******************************************************************************/
-/* */
-/* Function: testForLiteralCollision */
-/* */
-/* Synopsis: Test the given location for collision with the literal tables. */
-/* */
-/******************************************************************************/
-BOOL testForLiteralCollision( WORD16 loc )
-{
- WORD16 pagelc;
- BOOL result = FALSE;
- WORD16 tmppage;
- int tmpfield;
-
- tmpfield = GET_PAGE_INDEX(loc);
- tmppage = loc & 07600;
- pagelc = loc & 00177;
-
- if ( pagelc > max_page_used[tmpfield] )
- {
- max_page_used[tmpfield] = pagelc;
- }
- if ( pagelc >= cp[tmpfield].loc )
- {
- if ( tmppage == 0 )
- {
- errorMessage( &pz_literal_overflow, -1 );
- }
- else
- {
- errorMessage( &literal_overflow, -1 );
- }
- result = TRUE;
- }
-
- return( result );
-} /* testForLiteralCollision() */
-
-
-/******************************************************************************/
-/* */
-/* Function: readLine */
-/* */
-/* Synopsis: Get next line of input. Print previous line if needed. */
-/* */
-/******************************************************************************/
-void readLine()
-{
- WORD16 ix;
- WORD16 iy;
- char inpline[LINELEN];
-
- listLine(); /* List previous line if needed. */
- lineno++; /* Count lines read. */
- indirect_generated = FALSE; /* Mark no indirect address generated. */
- listed = FALSE; /* Mark as not listed. */
- cc = 0; /* Initialize column counter. */
- lexstartprev = 0;
-
- error_in_line = FALSE;
- if(( fgets( inpline, LINELEN - 1, infile )) == NULL )
- {
- inpline[0] = '$';
- inpline[1] = '\n';
- inpline[2] = '\0';
- if (!dollar_not_required) {
- error_in_line = TRUE;
- }
- }
-
- /* Remove any tabs from the input line by inserting the required number */
- /* of spaces to simulate N character tab stops, where N defaults to 8 and */
- /* is set by the command line option -t. (RK 20071029) */
- /* Ignore \r if there is one. (DPI 20150501) */
- for( ix = 0, iy = 0; inpline[ix] != '\0' && iy < (LINELEN - 2); ix++ )
- {
- switch( inpline[ix] )
- {
- case '\t':
- do
- {
- line[iy] = ' ';
- iy++;
- }
- while(( iy % tabstops ) != 0 && iy < (LINELEN - 2));
- break;
-
- case '\r': /* dont copy the carriage return */
- break;
-
- default:
- line[iy] = inpline[ix];
- iy++;
- break;
- }
- }
- if (iy >= (LINELEN - 2)) {
- line [iy] = '\n';
- iy++;
- }
- line[iy] = '\0';
-
- maxcc = iy; /* Save the current line length. */
- /* Save the first line for possible use as the listing title. */
- if( lineno == 1 )
- {
- strcpy( list_title, line );
- }
-} /* readLine() */
-
-
-/******************************************************************************/
-/* */
-/* Function: listLine */
-/* */
-/* Synopsis: Output a line to the listing file. */
-/* */
-/******************************************************************************/
-void listLine()
-/* generate a line of listing if not already done! */
-{
- if( listfile != NULL && listed == FALSE )
- {
- printLine( line, 0, 0, LINE );
- }
-} /* listLine() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printPageBreak */
-/* */
-/* Synopsis: Output a Top of Form and listing header if new page necessary. */
-/* */
-/******************************************************************************/
-void printPageBreak()
-{
- if( page_lineno >= LIST_LINES_PER_PAGE )
- /* ( list_lineno % LIST_LINES_PER_PAGE ) == 0 ) */
- {
- if( !list_title_set )
- {
- /* strcpy( list_title, line ); */
- if( list_title[strlen(list_title) - 1] == '\n' )
- {
- list_title[strlen(list_title) - 1] = '\0';
- }
- if( strlen( list_title ) > TITLELEN )
- {
- list_title[TITLELEN] = '\0';
- }
- list_title_set = TRUE;
- }
- topOfForm( list_title, NULL );
-
- }
-} /* printPageBreak() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printLine */
-/* */
-/* Synopsis: Output a line to the listing file with new page if necessary. */
-/* */
-/******************************************************************************/
-void printLine( char *line, WORD16 loc, WORD16 val, LINESTYLE_T linestyle )
-{
- char rlc;
-
- if( listfile == NULL )
- {
- save_error_count = 0;
- return;
- }
-
- printPageBreak();
-
- list_lineno++;
- page_lineno++;
-
- if (reloc == 0)
- {
- rlc = ' ';
- }
- else
- {
- rlc = '*';
- }
-
- switch( linestyle )
- {
- default:
- case LINE:
- fprintf(listfile, "%5d ", lineno );
- fputs( line, listfile );
- listed = TRUE;
- break;
-
- case LINE_VAL:
- fprintf(listfile, "%5d %4.4o ", lineno, val );
- fputs( line, listfile );
- listed = TRUE;
- break;
-
- case LINE_LOC_VAL:
- if( !listed )
- {
- if( indirect_generated )
- {
- fprintf( listfile, "%5d %5.5o%c %4.4o@ ", lineno, loc, rlc, val );
- }
- else
- {
- fprintf( listfile, "%5d %5.5o%c %4.4o ", lineno, loc, rlc, val );
- }
- fputs( line, listfile );
- listed = TRUE;
- }
- else
- {
- fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val );
- }
- break;
-
- case LOC_VAL:
- fprintf( listfile, " %5.5o%c %4.4o\n", loc, rlc, val );
- break;
- }
- printErrorMessages();
-} /* printLine() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printErrorMessages */
-/* */
-/* Synopsis: Output any error messages from the current list of errors. */
-/* */
-/******************************************************************************/
-void printErrorMessages()
-{
- WORD16 ix;
- WORD16 iy;
-
- if( listfile != NULL )
- {
- /* If any errors, display them now. */
- for( iy = 0; iy < save_error_count; iy++ )
- {
- printPageBreak();
- fprintf( listfile, "%-18.18s", error_list[iy].mesg );
- if( error_list[iy].col >= 0 )
- {
- for( ix = 0; ix < error_list[iy].col; ix++ )
- {
- if( line[ix] == '\t' )
- {
- putc( '\t', listfile );
- }
- else
- {
- putc( ' ', listfile );
- }
- }
- fputs( "^", listfile );
- list_lineno++;
- page_lineno++;
- }
- fputs( "\n", listfile );
- }
- }
- save_error_count = 0;
-} /* printErrorMessages() */
-
-
-/******************************************************************************/
-/* */
-/* Function: endOfBinary */
-/* */
-/* Synopsis: Outputs both literal tables at the end of a binary segment. */
-/* */
-/******************************************************************************/
-void endOfBinary()
-{
- /* Punch page 0 also. */
- punchLiteralPool( cp, 1 );
- if( error_in_line )
- {
- listed = TRUE;
- clc = ( clc & 070000 ) + (( clc - 1 ) & 07777 );
- errorMessage( &end_of_file, -1 );
- clc = ( clc & 070000 ) + (( clc + 1 ) & 07777 );
- }
- else
- {
- listLine(); /* List line if not done yet. */
- }
- return;
-} /* endOfBinary() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchChecksum */
-/* */
-/* Synopsis: Output a checksum if the current mode requires it and an */
-/* object file exists. */
-/* */
-/******************************************************************************/
-void punchChecksum()
-{
- /* If the assembler has output any BIN data output the checksum. */
- if( binary_data_output && !rim_mode )
- {
- punchLocObject( 0, checksum );
- }
- binary_data_output = FALSE;
- checksum = 0;
-} /* punchChecksum() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchLeader */
-/* */
-/* Synopsis: Generate 2 feet of leader on object file, as per DEC */
-/* documentation. Paper tape has 10 punches per inch. */
-/* */
-/******************************************************************************/
-void punchLeader( int count )
-{
- int ix;
-
- /* If value is zero, set to the default of 2 feet of leader. */
- count = ( count == 0 ) ? 240 : count;
-
- if( objectfile != NULL )
- {
- for( ix = 0; ix < count; ix++ )
- {
- fputc( 0200, objectfile );
- }
- }
-} /* punchLeader() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchOrigin */
-/* */
-/* Synopsis: Output an origin to the object file. */
-/* */
-/******************************************************************************/
-void punchOrigin( WORD16 loc )
-{
- punchObject((( loc >> 6 ) & 0077 ) | 0100 );
- punchObject( loc & 0077 );
-} /* punchOrigin() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchObject */
-/* */
-/* Synopsis: Put one character to object file and include it in checksum. */
-/* */
-/******************************************************************************/
-void punchObject( WORD16 val )
-{
- val &= 0377;
- if( objectfile != NULL )
- {
- fputc( val, objectfile );
- checksum += val;
- }
- binary_data_output = TRUE;
-} /* punchObject() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchOutObject */
-/* */
-/* Synopsis: Output the current line and then then punch value to the */
-/* object file. */
-/* */
-/******************************************************************************/
-void punchOutObject( WORD16 loc, WORD16 val )
-{
- /* Adding reloc makes printout agree with PAL8 where is prints the */
- /* relocated address, not the address in the BIN file */
- printLine( line,( ( field | loc ) + reloc ), val, LINE_LOC_VAL );
- punchLocObject( loc, val );
-} /* punchOutObject() */
-
-/******************************************************************************/
-/* */
-/* Function: punchLocObject */
-/* */
-/* Synopsis: Output the word (with origin if rim format) to the object file.*/
-/* */
-/******************************************************************************/
-void punchLocObject( WORD16 loc, WORD16 val )
-{
- if( rim_mode )
- {
- punchOrigin( loc );
- }
- punchObject(( val >> 6 ) & 0077 );
- punchObject( val & 0077 );
-} /* punchLocObject() */
-
-
-/******************************************************************************/
-/* */
-/* Function: punchLiteralPool */
-/* */
-/* Synopsis: Output the current page data. */
-/* */
-/******************************************************************************/
-void punchLiteralPool( LPOOL_T *p, BOOL punch_page0 )
-{
- WORD16 loc;
- WORD16 tmplc;
- int lpool_page = 0; /* Silence false uninitialized error from GCC */
- int i;
-
- for (i = MAX_PAGES-1; i >= 0; i--) {
- lpool_page = (i << 7) & 07600;
-
- if ( p[i].loc != p[i].last_punched && (punch_page0 || lpool_page != 0) )
- {
- if( !rim_mode )
- {
- /* Put out origin if not in rim mode. */
- punchOrigin( p[i].loc | lpool_page );
- }
- /* Put the literals in the object file. */
- for( loc = p[i].loc; loc < p[i].last_punched; loc++ )
- {
- tmplc = loc + lpool_page;
- printLine( line, (field | tmplc), p[i].pool[loc], LOC_VAL );
- punchLocObject( tmplc, p[i].pool[loc] );
- }
- p[i].last_punched = p[i].loc;
- }
- }
-} /* punchLiteralPool() */
-
-
-/******************************************************************************/
-/* */
-/* Function: insertLiteral */
-/* */
-/* Synopsis: Add a value to the given literal pool if not already in pool. */
-/* Return the location of the value in the pool. */
-/* */
-/******************************************************************************/
-WORD16 insertLiteral( LPOOL_T *pool, WORD16 value, int fieldpage_index )
-{
- WORD16 ix;
- LPOOL_T *p;
-
- p = &pool[fieldpage_index];
-
- /* Search the literal pool for any occurence of the needed value. */
- ix = PAGE_SIZE - 1;
- while( ix >= p->loc && p->pool[ix] != value )
- {
- ix--;
- }
-
- /* Check if value found in literal pool. If not, then insert value. */
- if( ix < p->loc )
- {
- (p->loc)--;
- p->pool[p->loc] = value;
- ix = p->loc;
- if( max_page_used[fieldpage_index] >= p->loc ) {
- if ( (fieldpage_index & 017) == 0 )
- {
- errorMessage( &pz_literal_overflow, -1 );
- }
- else
- {
- errorMessage( &literal_overflow, -1 );
- }
- }
- }
- return( ix );
-} /* insertLiteral() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printSymbolTable */
-/* */
-/* Synopsis: Output the symbol table. */
-/* */
-/******************************************************************************/
-void printSymbolTable()
-{
- int col;
- int cx;
- char *fmt;
- int ix;
- char mark;
- int page;
- int row;
- int symbol_base;
- int symbol_lines;
-
- symbol_base = number_of_fixed_symbols;
-
- for( page=0, list_lineno=0, col=0, ix=symbol_base; ix < symbol_top; page++ )
- {
- topOfForm( list_title, s_symtable );
- symbol_lines = LIST_LINES_PER_PAGE - page_lineno;
-
- for( row = 0; page_lineno < LIST_LINES_PER_PAGE && ix < symbol_top; row++)
- {
- list_lineno++;
- page_lineno++;
- fprintf( listfile, "%5d", list_lineno );
-
- for( col = 0; col < SYMBOL_COLUMNS && ix < symbol_top; col++ )
- {
- /* Get index of symbol for the current line and column */
- cx = symbol_lines * ( SYMBOL_COLUMNS * page + col ) + row;
- cx += symbol_base;
-
- /* Make sure that there is a symbol to be printed. */
- if( number_of_fixed_symbols <= cx && cx < symbol_top )
- {
- switch( symtab[cx].type & LABEL )
- {
- case LABEL:
- fmt = " %c%-6.6s %5.5o ";
- break;
-
- default:
- fmt = " %c%-6.6s %4.4o ";
- break;
- }
-
- switch( symtab[cx].type & ( DEFINED | REDEFINED ))
- {
- case UNDEFINED:
- mark = '?';
- break;
-
- case REDEFINED:
- mark = '#';
- break;
-
- default:
- mark = ' ';
- break;
- }
- fprintf( listfile, fmt, mark, symtab[cx].name, symtab[cx].val );
- ix++;
- }
- }
- fprintf( listfile, "\n" );
- }
- }
-} /* printSymbolTable() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printPermanentSymbolTable */
-/* */
-/* Synopsis: Output the permanent symbol table to a file suitable for */
-/* being input after the EXPUNGE pseudo-op. */
-/* */
-/******************************************************************************/
-void printPermanentSymbolTable()
-{
- int ix;
- FILE *permfile;
- char *s_type;
-
- if(( permfile = fopen( permpathname, "w" )) == NULL )
- {
- exit( 2 );
- }
-
- fprintf( permfile, "/ PERMANENT SYMBOL TABLE\n/\n" );
- fprintf( permfile, " EXPUNGE\n/\n" );
- /* Print the memory reference instructions first. */
- s_type = "FIXMRI";
- for( ix = 0; ix < symbol_top; ix++ )
- {
- if( M_MRI( symtab[ix].type ))
- {
- fprintf( permfile, "%-7s %s=%4.4o\n",
- s_type, symtab[ix].name, symtab[ix].val );
- }
- }
-
- s_type = " ";
- for( ix = 0; ix < symbol_top; ix++ )
- {
- if( M_FIXED( symtab[ix].type ))
- {
- if( !M_MRI( symtab[ix].type ) && !M_PSEUDO( symtab[ix].type ))
- {
- fprintf( permfile, "%-7s %s=%4.4o\n",
- s_type, symtab[ix].name, symtab[ix].val );
- }
- }
- }
- fprintf( permfile, "/\n FIXTAB\n" );
- fclose( permfile );
-} /* printPermanentSymbolTable() */
-
-
-/******************************************************************************/
-/* */
-/* Function: printCrossReference */
-/* */
-/* Synopsis: Output a cross reference (concordance) for the file being */
-/* assembled. */
-/* */
-/******************************************************************************/
-void printCrossReference()
-{
- int ix;
- int symbol_base;
- int xc;
- int xc_index;
- int xc_refcount;
- int xc_cols;
-
- /* Force top of form for first page. */
- page_lineno = LIST_LINES_PER_PAGE;
-
- list_lineno = 0;
- symbol_base = number_of_fixed_symbols;
-
- for( ix = symbol_base; ix < symbol_top; ix++ )
- {
- list_lineno++;
- page_lineno++;
- if( page_lineno >= LIST_LINES_PER_PAGE )
- {
- topOfForm( list_title, s_xref );
- }
-
- fprintf( listfile, "%5d", list_lineno );
-
- /* Get reference count & index into concordance table for this symbol. */
- xc_refcount = symtab[ix].xref_count;
- xc_index = symtab[ix].xref_index;
- /* Determine how to label symbol on concordance. */
- switch( symtab[ix].type & ( DEFINED | REDEFINED ))
- {
- case UNDEFINED:
- fprintf( listfile, " U ");
- break;
-
- case REDEFINED:
- fprintf( listfile, " M %5d ", xreftab[xc_index] );
- break;
-
- default:
- fprintf( listfile, " A %5d ", xreftab[xc_index] );
- break;
- }
- fprintf( listfile, "%-6.6s ", symtab[ix].name );
-
- /* Output the references, 8 numbers per line after symbol name. */
- for( xc_cols = 0, xc = 1; xc < xc_refcount + 1; xc++, xc_cols++ )
- {
- if( xc_cols >= XREF_COLUMNS )
- {
- xc_cols = 0;
- page_lineno++;
- if( page_lineno >= LIST_LINES_PER_PAGE )
- {
- topOfForm( list_title, s_xref);
- }
- list_lineno++;
- fprintf( listfile, "\n%5d%-19s", list_lineno, " " );
- }
- fprintf( listfile, " %5d", xreftab[xc_index + xc] );
- }
- fprintf( listfile, "\n" );
- }
-} /* printCrossReference() */
-
-
-/******************************************************************************/
-/* */
-/* Function: topOfForm */
-/* */
-/* Synopsis: Prints title and sub-title on top of next page of listing. */
-/* */
-/******************************************************************************/
-void topOfForm( char *title, char *sub_title )
-{
- char temp[10];
-
- list_pageno++;
- strcpy( temp, s_page );
- sprintf( temp, "%s %d", s_page, list_pageno );
-
- /* Output a top of form if not the first page of the listing. */
- if( list_pageno > 1 )
- {
- fprintf( listfile, "\f" );
- }
- fprintf( listfile, "\n\n\n %-63s %10s\n", title, temp );
-
- /* Reset the current page line counter. */
- page_lineno = 3;
- if( sub_title != NULL )
- {
- fprintf( listfile, "%80s\n", sub_title );
- page_lineno++;
- }
- else
- {
- fprintf( listfile, "\n" );
- page_lineno++;
- }
- fprintf( listfile, "\n" );
- page_lineno++;
-} /* topOfForm() */
-
-
-/******************************************************************************/
-/* */
-/* Function: lexemeToName */
-/* */
-/* Synopsis: Convert the current lexeme into a string. */
-/* */
-/******************************************************************************/
-char *lexemeToName( char *name, int from, int term )
-{
- int to;
-
- to = 0;
-
- while( from < term && to < ( SYMLEN - 1 ))
- {
- name[to++] = toupper( line[from++] );
- }
-
- while( to < SYMLEN )
- {
- name[to++] = '\0';
- }
- return( name );
-} /* lexemeToName() */
-
-/******************************************************************************/
-/* */
-/* Function: defineLexeme */
-/* */
-/* Synopsis: Put lexeme into symbol table with a value. */
-/* */
-/******************************************************************************/
-SYM_T *defineLexeme( int start, /* start of lexeme being defined. */
- int term, /* end+1 of lexeme being defined. */
- WORD16 val, /* value of lexeme being defined. */
- SYMTYP type ) /* how symbol is being defined. */
-{
- char name[SYMLEN];
-
- lexemeToName( name, start, term);
- return( defineSymbol( name, val, type, start ));
-} /* defineLexeme() */
-
-
-/******************************************************************************/
-/* */
-/* Function: defineSymbol */
-/* */
-/* Synopsis: Define a symbol in the symbol table, enter symbol name if not */
-/* not already in table. */
-/* */
-/******************************************************************************/
-SYM_T *defineSymbol( char *name, WORD16 val, SYMTYP type, WORD16 start )
-{
- SYM_T *sym;
- int xref_count;
-
- if( strlen( name ) < 1 )
- {
- return( &sym_undefined ); /* Protect against non-existent names. */
- }
- sym = lookup( name );
- /* OS/8 PAL8 seems to allow permanent symbold to be redefined without error */
- if( ( M_FIXED( sym->type ) && pass == 1 && perm_redef_error ) ||
- (M_PERM_REDEFINED( sym->type ) && (sym->val != val)) )
- {
- type |= PERM_REDEFINED;
- }
-
- xref_count = 0; /* Set concordance for normal defintion. */
-
- if( M_DEFINED( sym->type ))
- {
- if( pass == 2 && ( (sym->val & 07777) != (val & 07777) || M_PERM_REDEFINED(sym->type)) )
- {
- /* Generate diagnostic if redefining a symbol. */
- if( M_PERM_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) )
- {
- errorSymbol( &illegal_redefine, sym->name, start );
- } else
- {
- /* Generate diagnostic if redefining a symbol. */
- if( M_REDEFINED( sym->type ) && (M_LABEL(sym->type) || M_LABEL(type)) )
- {
- errorSymbol( &redefined_symbol, sym->name, start );
- }
- }
- type = type | REDEFINED;
- sym->xref_count++; /* Referenced suymbol, count it. */
- xref_count = sym->xref_count;
- }
- }
-
- if( pass == 2 && xref )
- {
- /* Put the definition line number in the concordance table. */
- /* Defined symbols are not counted as references. */
- xreftab[sym->xref_index] = lineno;
- /* Put the line number in the concordance table. */
- xreftab[sym->xref_index + xref_count] = lineno;
- }
-
- /* Now set the value and the type. */
- sym->val = ( M_LABEL(type) ) ? val : val & 07777;
- sym->type = ( pass == 1 ) ? ( type | CONDITION ) : type;
- return( sym );
-} /* defineSymbol() */
-
-
-/******************************************************************************/
-/* */
-/* Function: lookup */
-/* */
-/* Synopsis: Find a symbol in table. If not in table, enter symbol in */
-/* table as undefined. Return address of symbol in table. */
-/* */
-/******************************************************************************/
-SYM_T *lookup( char *name )
-{
- int ix; /* Insertion index */
- int lx; /* Left index */
- int rx; /* Right index */
-
- /* First search the permanent symbols. */
- lx = 0;
- ix = binarySearch( name, lx, number_of_fixed_symbols );
-
- /* If symbol not in permanent symbol table. */
- if( ix < 0 )
- {
- /* Now try the user symbol table. */
- ix = binarySearch( name, number_of_fixed_symbols, symbol_top );
-
- /* If symbol not in user symbol table. */
- if( ix < 0 )
- {
- /* Must put symbol in table if index is negative. */
- ix = ~ix;
- if( symbol_top + 1 >= SYMBOL_TABLE_SIZE )
- {
- errorSymbol( &symbol_table_full, name, lexstart );
- exit( 1 );
- }
-
- for( rx = symbol_top; rx >= ix; rx-- )
- {
- symtab[rx + 1] = symtab[rx];
- }
- symbol_top++;
-
- /* Enter the symbol as UNDEFINED with a value of zero. */
- strcpy( symtab[ix].name, name );
- symtab[ix].type = UNDEFINED;
- symtab[ix].val = 0;
- symtab[ix].xref_count = 0;
- if( xref && pass == 2 )
- {
- xreftab[symtab[ix].xref_index] = 0;
- }
- }
- }
-
- return( &symtab[ix] ); /* Return the location of the symbol. */
-} /* lookup() */
-
-
-/******************************************************************************/
-/* */
-/* Function: binarySearch */
-/* */
-/* Synopsis: Searches the symbol table within the limits given. If the */
-/* symbol is not in the table, it returns the insertion point. */
-/* */
-/******************************************************************************/
-int binarySearch( char *name, int start, int symbol_count )
-{
- int lx; /* Left index */
- int mx; /* Middle index */
- int rx; /* Right index */
- int compare; /* Results of comparison */
-
- lx = start;
- rx = symbol_count - 1;
- while( lx <= rx )
- {
- mx = ( lx + rx ) / 2; /* Find center of search area. */
-
- compare = strcmp( name, symtab[mx].name );
-
- if( compare < 0 )
- {
- rx = mx - 1;
- }
- else if( compare > 0 )
- {
- lx = mx + 1;
- }
- else
- {
- return( mx ); /* Found a match in symbol table. */
- }
- } /* end while */
- return( ~lx ); /* Return insertion point. */
-} /* binarySearch() */
-
-
-/******************************************************************************/
-/* */
-/* Function: compareSymbols */
-/* */
-/* Synopsis: Used to presort the symbol table when starting assembler. */
-/* */
-/******************************************************************************/
-int compareSymbols( const void *a, const void *b )
-{
- return( strcmp( ((SYM_T *) a)->name, ((SYM_T *) b)->name ));
-} /* compareSymbols() */
-
-
-/******************************************************************************/
-/* */
-/* Function: evalSymbol */
-/* */
-/* Synopsis: Get the pointer for the symbol table entry if exists. */
-/* If symbol doesn't exist, return a pointer to the undefined sym */
-/* */
-/******************************************************************************/
-SYM_T *evalSymbol()
-{
- char name[SYMLEN];
- SYM_T *sym;
-
- sym = lookup( lexemeToName( name, lexstart, lexterm ));
-
- /* The symbol goes in the concordance iff it is in a different position in */
- /* the assembler source file. */
- if( lexstart != last_xref_lexstart || lineno != last_xref_lineno )
- {
- sym->xref_count++; /* Count the number of references to symbol. */
- last_xref_lexstart = lexstart;
- last_xref_lineno = lineno;
-
- /* Put the line number in the concordance table. */
- if( xref && pass == 2 )
- {
- xreftab[sym->xref_index + sym->xref_count] = lineno;
- }
- }
-
- return( sym );
-} /* evalSymbol() */
-
-
-/******************************************************************************/
-/* */
-/* Function: moveToEndOfLine */
-/* */
-/* Synopsis: Move the parser input to the end of the current input line. */
-/* */
-/******************************************************************************/
-void moveToEndOfLine()
-{
- while( !isend( line[cc] )) cc++;
- lexstart = cc;
- lexterm = cc;
- lexstartprev = lexstart;
-} /* moveToEndOfLine() */
-
-/******************************************************************************/
-/* */
-/* Function: nextLexeme */
-/* */
-/* Synopsis: Get the next lexical element from input line. */
-/* */
-/******************************************************************************/
-void nextLexeme()
-{
- /* Save start column of previous lexeme for diagnostic messages. */
- lexstartprev = lexstart;
- lextermprev = lexterm;
-
- while( is_blank( line[cc] )) { cc++; }
- lexstart = cc;
-
- if( isalnum( line[cc] ))
- {
- while( isalnum( line[cc] )) { cc++; }
- }
- else if( isend( line[cc] ))
- {
- /* End-of-Line, don't advance cc! */
- }
- else
- {
- switch( line[cc] )
- {
- case '"': /* Quoted letter */
- if( cc + 2 < maxcc )
- {
- cc++;
- cc++;
- }
- else
- {
- errorMessage( &no_literal_value, lexstart );
- cc++;
- }
- break;
-
- case '/': /* Comment, don't advance cc! */
- break;
-
- default: /* All other punctuation. */
- cc++;
- break;
- }
- }
- lexterm = cc;
-} /* nextLexeme() */
-
-
-/******************************************************************************/
-/* */
-/* Function: nextLexBlank */
-/* */
-/* Synopsis: Used to prevent illegal blanks in expressions. */
-/* */
-/******************************************************************************/
-void nextLexBlank()
-{
- nextLexeme();
- if( is_blank( delimiter ))
- {
- errorMessage( &illegal_blank, lexstart - 1 );
- }
- delimiter = line[lexterm];
-} /* nextLexBlank() */
-
-
-/******************************************************************************/
-/* */
-/* Function: pseudoOperators */
-/* */
-/* Synopsis: Process pseudo-ops (directives). */
-/* */
-/******************************************************************************/
-BOOL pseudoOperators( PSEUDO_T val )
-{
- int count, count2;
- int delim;
- int index;
- int ix;
- int lexstartsave;
- WORD16 newfield;
- WORD16 oldclc;
- int pack;
- BOOL status;
- SYM_T *sym;
- FILE *temp;
- int term;
- WORD16 value;
- char os8_name[8];
- int reloc_clc;
-
- status = TRUE;
- switch( (PSEUDO_T) val )
- {
- case ASCII:
- /* added 18-Jan-2003 PNT -- derived from TEXT */
- delim = line[lexstart];
- index = lexstart + 1;
- while( line[index] != delim && !isend( line[index] ))
- {
- punchOutObject( clc, (line[index] & 127) | 128 );
- incrementClc();
- index++;
- }
- if( isend( line[index] ))
- {
- cc = index;
- lexterm = cc;
- errorMessage( &text_string, cc );
- }
- else
- {
- cc = index + 1;
- lexterm = cc;
- }
- nextLexeme();
- break;
-
- case BANK:
- errorSymbol( &no_pseudo_op, "BANK", lexstartprev );
- /* should select a different 32K out of 128K */
- break;
-
- case BINPUNCH:
- /* If there has been data output and this is a mode switch, set up to */
- /* output data in BIN mode. */
- if( binary_data_output && rim_mode )
- {
- clearLiteralTable();
- punchLeader( 8 ); /* Generate a short leader/trailer. */
- checksum = 0;
- binary_data_output = FALSE;
- }
- rim_mode = FALSE;
- break;
-
- case DECIMAL:
- radix = 10;
- break;
-
- case DUBL:
- inputDubl();
- break;
-
- case EJECT:
- page_lineno = LIST_LINES_PER_PAGE; /* This will force a page break. */
- status = FALSE; /* This will force reading of next line */
- break;
-
- case ENPUNCH:
- if( pass == 2 )
- {
- objectfile = objectsave;
- }
- break;
-
- case EXPUNGE: /* Erase symbol table */
- if( pass == 1 )
- {
- symtab[0] = sym_undefined;
- symbol_top = 0;
- number_of_fixed_symbols = symbol_top;
- fixed_symbols = &symtab[symbol_top - 1];
-
- /* Enter the pseudo-ops into the symbol table. */
- for( ix = 0; ix < DIM( pseudo ); ix++ )
- {
- defineSymbol( pseudo[ix].name, pseudo[ix].val, pseudo[ix].type, 0 );
- }
- /* Enter the really permanent symbols into the table. */
- /* Also make them part of the permanent symbol table. */
- for( ix = 0; ix < DIM( really_permanent_symbols ); ix++ )
- {
- defineSymbol( really_permanent_symbols[ix].name,
- really_permanent_symbols[ix].val,
- really_permanent_symbols[ix].type | DEFFIX , 0 );
- }
- number_of_fixed_symbols = symbol_top;
- fixed_symbols = &symtab[symbol_top - 1];
-
- }
- break;
-
- case FIELD:
- /* Punch page 0 also */
- punchLiteralPool( cp, 1 );
- newfield = field >> 12;
- lexstartsave = lexstartprev;
- if( isdone( line[lexstart] ))
- {
- newfield += 1; /* Blank FIELD directive. */
- }
- else
- {
- newfield = (getExpr())->val; /* FIELD with argument. */
- }
-
- if( rim_mode )
- {
- errorMessage( &in_rim_mode, lexstartsave ); /* Can't change fields. */
- }
- else if( newfield > 7 || newfield < 0 )
- {
- errorMessage( &illegal_field_value, lexstartprev );
- }
- else
- {
- value = (( newfield & 0007 ) << 3 ) | 00300;
- punchObject( value );
- if( objectfile != NULL ) /* Only fix checksum if punching */
- {
- checksum -= value; /* Field punches are not added to checksum. */
- }
- field = newfield << 12;
- }
-
- clc = 0200 | field;
- fieldlc = clc & 07777;
-
- if( !rim_mode )
- {
- punchOrigin( clc );
- }
-
- clearLiteralTable();
-
- break;
-
- case FIXMRI:
- if( line[lexterm] == '=' && isalpha( line[lexstart] ))
- {
- lexstartsave = lexstart;
- term = lexterm;
- nextLexeme(); /* Skip symbol. */
- nextLexeme(); /* Skip trailing = */
- defineLexeme( lexstartsave, term, getExprs(), MRI );
- }
- else
- {
- errorLexeme( &symbol_syntax, lexstart );
- nextLexeme(); /* Skip symbol. */
- nextLexeme(); /* Skip trailing = */
- (void) getExprs(); /* Skip expression. */
- }
- break;
-
- case FIXTAB:
- if (pass == 1) /* Only fix on first pass, on second all are defined */
- {
- /* Mark all current symbols as permanent symbols. */
- for( ix = 0; ix < symbol_top; ix++ )
- {
- symtab[ix].type = symtab[ix].type | FIXED;
- }
- number_of_fixed_symbols = symbol_top;
- fixed_symbols = &symtab[symbol_top - 1];
-
- /* Re-sort the symbol table */
- qsort( symtab, symbol_top, sizeof(symtab[0]), compareSymbols );
- }
- break;
-
- case FLTG:
- inputFltg();
- /* errorSymbol( &no_pseudo_op, "FLTG", lexstartprev ); */
- break;
-
- case IFDEF:
- if( isalpha( line[lexstart] ))
- {
- sym = evalSymbol();
- nextLexeme();
- if( M_DEFINED_CONDITIONALLY( sym->type ))
- {
- conditionTrue();
- }
- else
- {
- conditionFalse();
- }
- }
- else
- {
- errorLexeme( &label_syntax, lexstart );
- }
- break;
-
- case IFNDEF:
- if( isalpha( line[lexstart] ))
- {
- sym = evalSymbol();
- nextLexeme();
- if( M_DEFINED_CONDITIONALLY( sym->type ))
- {
- conditionFalse();
- }
- else
- {
- conditionTrue();
- }
- }
- else
- {
- errorLexeme( &label_syntax, lexstart );
- }
- break;
-
- case IFNZERO:
- if( getExprs() == 0 )
- {
- conditionFalse();
- }
- else
- {
- conditionTrue();
- }
- break;
-
- case IFZERO:
- if( getExprs() == 0 )
- {
- conditionTrue();
- }
- else
- {
- conditionFalse();
- }
- break;
-
- case NOPUNCH:
- if( pass == 2 )
- {
- objectfile = NULL;
- }
- break;
-
- case OCTAL:
- radix = 8;
- break;
-
- case PAGE:
- reloc_clc = clc + reloc;
- punchLiteralPool( cp, 0 );
- oldclc = clc;
- if( isdone( line[lexstart] ))
- {
- clc = (( reloc_clc + 0177 ) & 077600) - reloc; /* No argumnet. */
- fieldlc = clc & 07777;
- }
- else
- {
- value = (getExpr())->val;
- clc = field + (( value & 037 ) << 7 ) - reloc;
- fieldlc = clc & 07777;
- }
- testForLiteralCollision( clc + reloc );
-
- if( !rim_mode && clc != oldclc )
- {
- punchOrigin( clc );
- }
- break;
-
- case PAUSE:
- break;
-
- case RELOC:
- if( isdone( line[lexstart] ))
- {
- reloc = 0; /* Blank RELOC directive. */
- }
- else
- {
- value = (getExpr())->val; /* RELOC with argument. */
- reloc = (value & 07777) - ( clc & 07777);
- }
- break;
-
- case RIMPUNCH:
- /* If the assembler has output any BIN data, output the literal tables */
- /* and the checksum for what has been assembled and setup for RIM mode. */
- if( binary_data_output && !rim_mode )
- {
- endOfBinary();
- clearLiteralTable();
- punchChecksum();
- punchLeader( 8 ); /* Generate a short leader/trailer. */
- }
- rim_mode = TRUE;
- break;
-
- case SEGMNT:
- punchLiteralPool( cp, 0 );
- if( isdone( line[lexstart] ))
- { /* No argument. */
- clc = ( clc & 06000 ) + 02000;
- fieldlc = clc & 07777;
- }
- else
- {
- getExpr();
- clc = ( val & 003 ) << 10;
- fieldlc = clc & 07777;
- }
- if( !rim_mode )
- {
- punchOrigin( clc );
- }
- testForLiteralCollision( clc );
- break;
-
- case TEXT:
- delim = line[lexstart];
- pack = 0;
- count = 0;
- index = lexstart + 1;
- while( line[index] != delim && !isend( line[index] ))
- {
- pack = ( pack << 6 ) | ( line[index] & 077 );
- count++;
- if( count > 1 )
- {
- punchOutObject( clc, pack );
- incrementClc();
- count = 0;
- pack = 0;
- }
- index++;
- }
-
- if( count != 0 )
- {
- punchOutObject( clc, pack << 6 );
- incrementClc();
- }
- else
- {
- punchOutObject( clc, 0 );
- incrementClc();
- }
-
- if( isend( line[index] ))
- {
- cc = index;
- lexterm = cc;
- errorMessage( &text_string, cc );
- }
- else
- {
- cc = index + 1;
- lexterm = cc;
- }
- nextLexeme();
- break;
-
- case FILENAME:
- memset(os8_name, 0, sizeof(os8_name));
- delimiter=line[lexstart];
- if (delimiter != '.')
- {
- for (index = lexstart, count = 0; index < lexterm && count < 6; index++)
- {
- os8_name[count++] = line[index];
- }
- delimiter=line[lexterm];
- if (delimiter == '.')
- {
- nextLexeme(); /* Skip . */
- }
- }
- nextLexeme();
- if (delimiter == '.')
- {
- for (index = lexstart, count = 6; index < lexterm && count < 8; index++)
- {
- os8_name[count++] = line[index];
- }
- }
-
- pack = 0;
- count = 0;
- for (count2 = 0; count2 < 8; count2++)
- {
- pack = ( pack << 6 ) | ( os8_name[count2] & 077 );
- count++;
- if( count > 1 )
- {
- punchOutObject( clc, pack );
- incrementClc();
- count = 0;
- pack = 0;
- }
- }
- nextLexeme();
- break;
-
- case DEVICE:
- memset(os8_name, 0, sizeof(os8_name));
- for (index = lexstart, count = 0; index < lexterm && count < 4; index++)
- {
- os8_name[count++] = line[index];
- }
-
- pack = 0;
- count = 0;
- for (count2 = 0; count2 < 4; count2++)
- {
- pack = ( pack << 6 ) | ( os8_name[count2] & 077 );
- count++;
- if( count > 1 )
- {
- punchOutObject( clc, pack );
- incrementClc();
- count = 0;
- pack = 0;
- }
- }
-
- nextLexeme();
- break;
-
- case TITLE:
- delim = line[lexstart];
- ix = lexstart + 1;
- /* Find string delimiter. */
- do
- {
- if( list_title[ix] == delim && list_title[ix + 1] == delim )
- {
- ix++;
- }
- ix++;
- } while( line[ix] != delim && !isend(line[ix]) );
-
- if( line[ix] == delim )
- {
- count = 0;
- ix = lexstart + 1;
- do
- {
- if( list_title[ix] == delim && list_title[ix + 1] == delim )
- {
- ix++;
- }
- list_title[count] = line[ix];
- count++;
- ix++;
- list_title[count] = '\0';
- } while( line[ix] != delim && !isend(line[ix]) );
-
- if( strlen( list_title ) > TITLELEN )
- {
- list_title[TITLELEN] = '\0';
- }
-
- cc = ix + 1;
- lexterm = cc;
- page_lineno = LIST_LINES_PER_PAGE;/* Force top of page for new titles. */
- list_title_set = TRUE;
- }
- else
- {
- cc = ix;
- lexterm = cc;
- errorMessage( &text_string, cc );
- }
-
- nextLexeme();
- break;
-
- case XLIST:
- if( isdone( line[lexstart] ))
- {
- temp = listfile; /* Blank XLIST directive. */
- listfile = listsave;
- listsave = temp;
- }
- else
- {
- if( (getExpr())->val == 0 )
- {
- if( listfile == NULL )
- {
- listfile = listsave;
- listsave = NULL;
- }
- }
- else
- {
- if( listfile != NULL )
- {
- listsave = listfile;
- listfile = NULL;
- }
- }
- }
- break;
-
- case ZBLOCK:
- value = (getExpr())->val;
- if( value < 0 )
- {
- errorMessage( &zblock_too_small, lexstartprev );
- }
- else if( value + ( clc & 07777 ) - 1 > 07777 )
- {
- errorMessage( &zblock_too_large, lexstartprev );
- }
- else
- {
- for( ; value > 0; value-- )
- {
- punchOutObject( clc, 0 );
- incrementClc();
- }
- }
-
- break;
-
- default:
- break;
- } /* end switch for pseudo-ops */
- return( status );
-} /* pseudoOperators() */
-
-
-/******************************************************************************/
-/* */
-/* Function: conditionFalse */
-/* */
-/* Synopsis: Called when a false conditional has been evaluated. */
-/* Lex should be the opening <; ignore all text until */
-/* the closing >. */
-/* */
-/******************************************************************************/
-void conditionFalse()
-{
- int level;
-
- if( line[lexstart] == '<' )
- {
- /* Invariant: line[cc] is the next unexamined character. */
- level = 1;
- while( level > 0 )
- {
- if( isend( line[cc] ))
- {
- readLine();
- }
- else
- {
- switch( line[cc] )
- {
- case '>':
- level--;
- cc++;
- break;
-
- case '<':
- level++;
- cc++;
- break;
-
- case '$':
- level = 0;
- cc++;
- break;
-
- default:
- cc++;
- break;
- } /* end switch */
- } /* end if */
- } /* end while */
- nextLexeme();
- }
- else
- {
- errorMessage( <_expected, lexstart );
- }
-} /* conditionFalse() */
-
-/******************************************************************************/
-/* */
-/* Function: conditionTrue */
-/* */
-/* Synopsis: Called when a true conditional has been evaluated. */
-/* Lex should be the opening <; skip it and setup for */
-/* normal assembly. */
-/* */
-/******************************************************************************/
-void conditionTrue()
-{
- if( line[lexstart] == '<' )
- {
- nextLexeme(); /* Skip the opening '<' */
- }
- else
- {
- errorMessage( <_expected, lexstart );
- }
-} /* conditionTrue() */
-
-
-/******************************************************************************/
-/* */
-/* Function: errorLexeme */
-/* */
-/* Synopsis: Display an error message using the current lexical element. */
-/* */
-/******************************************************************************/
-void errorLexeme( EMSG_T *mesg, int col )
-{
- char name[SYMLEN];
-
- errorSymbol( mesg, lexemeToName( name, lexstart, lexterm ), col );
-} /* errorLexeme() */
-
-
-/******************************************************************************/
-/* */
-/* Function: errorSymbol */
-/* */
-/* Synopsis: Display an error message with a given string. */
-/* */
-/******************************************************************************/
-void errorSymbol( EMSG_T *mesg, char *name, int col )
-{
- char linecol[12];
- char *s;
-
- if( pass == 2 )
- {
- s = ( name == NULL ) ? "" : name ;
- errors++;
- sprintf( linecol, "(%d:%d)", lineno, col + 1 );
- fprintf( errorfile, "%s%-9s : error: %s \"%s\" at Loc = %5.5o\n",
- filename, linecol, mesg->file, s, clc );
- saveError( mesg->list, col );
- }
- error_in_line = TRUE;
-} /* errorSymbol() */
-
-
-/******************************************************************************/
-/* */
-/* Function: errorMessage */
-/* */
-/* Synopsis: Display an error message without a name argument. */
-/* */
-/******************************************************************************/
-void errorMessage( EMSG_T *mesg, int col )
-{
- char linecol[12];
-
- if( pass == 2 )
- {
- errors++;
- sprintf( linecol, "(%d:%d)", lineno, col + 1 );
- fprintf( errorfile, "%s%-9s : error: %s at Loc = %5.5o\n",
- filename, linecol, mesg->file, clc );
- saveError( mesg->list, col );
- }
- error_in_line = TRUE;
-} /* errorMessage() */
-
-/******************************************************************************/
-/* */
-/* Function: saveError */
-/* */
-/* Synopsis: Save the current error in a list so it may displayed after the */
-/* the current line is printed. */
-/* */
-/******************************************************************************/
-void saveError( char *mesg, int col )
-{
- if( save_error_count < DIM( error_list ))
- {
- error_list[save_error_count].mesg = mesg;
- error_list[save_error_count].col = col;
- save_error_count++;
- }
- error_in_line = TRUE;
-
- if( listed )
- {
- printErrorMessages();
- }
-} /* saveError() */
-/* End-of-File */
Index: src/ptp2txt.c
==================================================================
--- src/ptp2txt.c
+++ src/ptp2txt.c
@@ -1,29 +1,24 @@
/*
- * Program to convert between POSIX ASCII text files
+ * Program to convert between linux ASCII txt files
* and the output of OS/8 PIP to the Paper Tape Punch.
* The OS/8 paper tape punch format is:
- *
- * leader: a bunch of ASCII NUL chars to be ignored.
- * ASCII with the 8th bit set, CR+LF line endings.
- * trailer: a bunch of ASCII NUL chars to be ignored.
+ * leader: a bunch of ASCII NUL chars to be ignored.
+ * ASCII with the 8th bit set.
+ * trailer: a bunch of ASCII NUL chars to be ignored.
* This program can be used as a filter from stdin to stdout or
- * it will create a new file with name ending in .txt if going to
- * POSIX text or .ptp if going to OS/8 PIP Paper Tape format.
-
- * If the program is called with the name "txt2ptp" then
- * LTCOUNT (default 100) bytes of leader is prepended to the
- * output file and LTCOUNT bytes of leader are appended.
- * The 8th bit of every output character is set, and LF-only
- * input is turned into CR+LF output. CR+LF input is passed
- * as-is.
+ * it will create a new file with name ending in .txt if going to linux txt
+ * or .ptp if going to OS/8 PIP Paper Tape format.
+
+ * If the program is called with the name "txt2ptp"
+ * 100 bytes of leader trailer is prepended and appended to the file,
+ * and the 8th bit of every character is set.
* If called by any other name, the ASCII NUL character is
* ignored anywhere in the file, and the 8th bit is cleared.
- * Line endings are untouched in this case.
* This program helps work around the issue that the
* OS/8 Paper Tape reader handler assumes the last
* character in the buffer is junk, so that when you send
* a plain text file into PDP-8 SIMH OS/8 with the
@@ -116,36 +111,25 @@
fwrite (global_ltbuf, sizeof(char), LTCOUNT, fpout);
}
void make_ptp (FILE *fpin, FILE *fpout)
{
- int inchar, outchar, prior = '\0';
+ int inchar, outchar;
int read_ct, n;
char *obuffp;
- char ibuff[BLOCK_SIZE];
- /* Every \n might add a \r to the output.
- Worst case is obuff doubles in size. */
- char obuff[2*BLOCK_SIZE];
+ char ibuff[BLOCK_SIZE], obuff[BLOCK_SIZE];
make_lt (fpout);
while ((read_ct = fread (ibuff, sizeof(char), BLOCK_SIZE, fpin))) {
obuffp = obuff;
for (n = 0; n < read_ct; n++) {
inchar = *(ibuff + n);
- if (inchar == '\n' && prior != '\r') {
- *obuffp++ = (char)('\r' | 0200);
- }
*obuffp++ = inchar | 0200;
- prior = inchar;
}
fwrite (obuff, sizeof(char), obuffp - obuff, fpout);
}
- /* If we don't already have an EOF, add one. */
- if (inchar != '\032') {
- fwrite ("\232", sizeof(char), 1, fpout);
- }
make_lt (fpout);
}
void process_file (char *fname, int flag)
Index: tools/bosi
==================================================================
--- tools/bosi
+++ tools/bosi
@@ -164,16 +164,10 @@
encpass=$(openssl passwd -1 edsonDeCastro1968)
sudo usermod -p $encpass pidp8i
sudo passwd -e pidp8i
- cl=/boot/cmdline.txt
- if ! grep -Fq ' init=' $cl
- then
- sudo sed -i -e 's#$# init=/usr/lib/raspi-config/init_resize.sh#' $cl
- fi
-
sudo poweroff
}
# Shrink the filesystem on the OS SD card we're about to image to just a
DELETED tools/cc8-tu56-update
Index: tools/cc8-tu56-update
==================================================================
--- tools/cc8-tu56-update
+++ /dev/null
@@ -1,182 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-########################################################################
-# cc8-tu56-update - Rebuilds cc8.tu56 from source code.
-#
-# It is intended to be be called manually whenever a file in src/cc8/os8
-# changes. It is not called automatically from the top-level Makefile
-# because not all end user systems will be able to run it, since our
-# dependencies (host-side cc8 and SABR) are not always present.
-#
-# Copyright © 2017 by Warren Young.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-# Bring in just the basics so we can bring in our local modules
-import os
-import sys
-sys.path.insert (0, os.path.dirname (__file__) + '/../lib')
-sys.path.insert (0, os.getcwd () + '/lib')
-
-# Our local modules
-from pidp8i import *
-from simh import *
-
-# Other global Python modules
-import glob
-import subprocess
-
-
-#### GLOBALS AND CONSTANTS #############################################
-
-# Path to the cross-compiler version of cc8.
-cc8_cross = os.path.join (dirs.build, 'bin', 'cc8')
-
-# Path to the CC8 sources
-cc8_src = os.path.join (dirs.src, 'src', 'cc8')
-
-
-#### cross_compile #####################################################
-# Cross-compile a *.c file on the local machine to a *.s file we can
-# send into the OS/8 instance. The parameter should have no extension.
-
-def cross_compile (module):
- inf = module + '.c'
- outf = module + '.s'
-
- if os.path.exists (outf) and \
- os.path.getmtime (inf) <= os.path.getmtime (outf):
- print outf + " up-to-date."
- else:
- print "Building " + outf + "..."
- rc = subprocess.call ([cc8_cross, inf])
- if rc == 0:
- print inf + " -> " + outf
- else:
- print "Failed to cross-compile the " + module.upper() + " module!"
- exit (1)
-
-
-#### main ##############################################################
-
-def main ():
- # We have to do much of the following from within the CC8 source dir
- # since the same source code is used for both versions of CC8, so the
- # compiler assumes a flat filesystem, hence no "include path", hence
- # all headers and such must be symlinked or copied into the same
- # directory as our primary inputs.
- os.chdir (os.path.join (cc8_src, 'os8'))
-
- # Cross-compile the OS/8 version of CC8's C sources to SABR. These
- # files are listed in dependency order, in case that later matters.
- modules = [ 'libc', 'c8', 'n8', 'p8' ]
- try:
- for m in modules: cross_compile (m)
- except OSError as e:
- print "Cross-compilation steps failed: " + e.strerror + '!'
- exit (1)
-
- # Create the SIMH child instance and tell it where to send log output
- try:
- s = simh (dirs.build, True)
- except (RuntimeError) as e:
- print "Could not start simulator: " + e.message + '!'
- exit (1)
- s.set_logfile (os.fdopen (sys.stdout.fileno (), 'w', 0))
-
- # Zero core before beginning. SIMH's PDP-8 simulator doesn't do it,
- # on purpose, because the actual hardware did not do that. SIMH does
- # not attempt to simulate the persistence of core memory by saving it
- # to disk between runs, but the developers are right: you cannot trust
- # the prior state of core before initializing it yourself. Rather
- # than do that in some OS/8 specific way, we tell SIMH to do it.
- s.send_cmd ('de all 0')
-
- # Attach an empty DECtape to the simulator to hold our output.
- tape = os.path.join (dirs.os8mi, 'subsys', 'cc8.tu56')
- if os.path.exists (tape): os.remove (tape)
- s.send_cmd ("att dt0 " + tape)
-
- # Find and boot the bootable OS/8 disk. Use the "patched" version
- # because that is what "make run" uses; we use that command to
- # inspect this script's work.
- rk = os.path.join (dirs.os8mo, 'os8v3d-patched.rk05')
- if not os.path.isfile (rk):
- print "Could not find " + rk + "; OS/8 media not yet built?"
- exit (1)
- print "Booting " + rk + "..."
- s.send_cmd ("att rk0 " + rk)
- s.send_cmd ("boot rk0")
-
- # Copy the SABR files produced above by the host-side cross-compiler
- # to the OS/8 environment's RK05 disk.
- for m in modules:
- source = m + '.s'
- dest = m.upper() + '.SB'
- s.os8_send_file (source, dest)
-
- # Copy example programs in as well.
- #
- # We have to modify the destination file name because the OS/8 version
- # of CC8 currently uses *.CC as its extension for some reason.
- for src in glob.glob ('../examples/*.c'):
- dest = os.path.basename (src.upper ()) + 'C'
- s.os8_send_file (src, dest)
-
- # Copy the remaining static OS/8 CC8 text files in.
- for src in [ 'bldcc8.bi', 'header.sb', 'init.pa', 'libc.h' ]:
- s.os8_send_file (src)
-
- # Build the OS/8 version of CC8 using the batch file we copied in.
- s.os8_send_cmd ('\\.', 'EXE BLDCC8.BI')
-
- # Get rid of intermediary files on DSK: so the subsequent COPY
- # commands don't add them to the DECtape image.
- s.os8_send_cmd ('\\.', 'DEL ?8.RL,?8.SB,CC.*,LIBC.SB')
-
- # Assemble COPY command source list for CC?.SV. Can't use a file name
- # pattern because that grabs CCL.SV as well, and we don't want to make
- # a hole in the tape by copying that and then deleting it.
- cc_copies = ','.join ([ 'SYS:CC{0}.SV'.format (n) for n in range (3) ])
-
- # Save all the remaining involved files to the cc8.tu56 tape, giving
- # DIR DTA0: output approximately like this:
- #
- # HEADER.SB 4 INIT .PA 4 CC .CC 3
- # LIBC .H 3 FIB .CC 1 CALC .CC 3
- # CC1 .SV 40 CC0 .SV 27 CC2 .SV 40
- # LIBC .RL 22 BASIC .CC 13 PS .CC 1
- s.os8_send_cmd ('\\.', 'ZERO DTA0:')
- s.os8_send_cmd ('\\.', 'COPY DTA0:<' + cc_copies)
- s.os8_send_cmd ('\\.', 'COPY DTA0:
-
- Compares two lz4-compressed files, reporting differences in hex form.
-
-USAGE
- exit 99
-fi
DELETED tools/diffstat-since-release
Index: tools/diffstat-since-release
==================================================================
--- tools/diffstat-since-release
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-files=$(ls | grep -v -e autosetup -e test | tr '\n' ' ')
-fossil diff --internal --from release $files | diffstat
DELETED tools/mkadrules
Index: tools/mkadrules
==================================================================
--- tools/mkadrules
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env perl
-########################################################################
-# mkadrules - Write .c.o Makefile rules that also do autodependency
-# generation to $adf for each source subdirectory named on the command
-# line to avoid the need to manually maintain these near-identical
-# Makefile rule sets.
-#
-# Each *.o file gets a *.d file generated by the compiler listing the
-# object file's dependencies as discovered by the compiler at build
-# time, using the same build options used to generate the *.o file.
-# These automatically generated dependency rule sets are therefore
-# inherently accurate and comprehensive, which hand-written rules
-# virtually never are, particularly for software that builds on
-# multiple platforms, where out-of-tree dependencies (e.g. the
-# location of stdio.h) vary from one platform to another.
-#
-# This mechanism depends on the -M feature of GCC and Clang, which
-# means our build system is probably not as widely portable as it
-# might otherwise be.
-#
-# Based on http://scottmcpeak.com/autodepend/autodepend.html
-#
-# Copyright © 2017 Warren Young
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-use strict;
-use warnings;
-
-use Cwd;
-
-# The basic rule set we generate, which is repeatedly modified and
-# written to the output file.
-my $template = <<'TEMPLATE';
-obj/%.o: SRCDIR/src/%.c
- $(CC) -c $(CFLAGS) SRCDIR/src/$*.c -o obj/$*.o
- $(CC) -MM $(CFLAGS) SRCDIR/src/$*.c > obj/$*.d
- @mv -f obj/$*.d obj/$*.d.tmp
- @sed -e 's|.*:|obj/$*.o:|' < obj/$*.d.tmp > obj/$*.d
- @sed -e 's/.*://' -e 's/\\$$//' < obj/$*.d.tmp | fmt -1 | \
- sed -e 's/^ *//' -e 's/$$/:/' >> obj/$*.d
- @rm -f obj/$*.d.tmp
-TEMPLATE
-
-# Parse command line
-die "usage: $0 \n\n" unless @ARGV >= 2;
-my $srcdir = shift @ARGV;
-die "Source tree $srcdir does not exist!\n" unless -d $srcdir;
-my @dirs = @ARGV;
-for (@dirs) {
- die "Source subdir $_ does not exist!\n" unless -d "$srcdir/$_";
-}
-
-# Create the output file
-my $adf = 'adrules.mk';
-unlink $adf;
-open my $ad, '>', $adf, or die "Could not write to $adf: $!\n";
-print $ad "## DO NOT MODIFY. GENERATED BY tools/mkadrules! ##\n";
-print $ad "## -------------------------------------------- ##\n\n";
-
-# If we're building in-tree, we can simplify $srcdir.
-my $intree = $srcdir eq getcwd;
-if ($intree) {
- $srcdir = '.';
-}
-
-# Write rule set for each dir passed
-for my $sdir (@dirs) {
- my $rule = $template;
-
- my $odir = 'obj/' . $sdir;
- $odir =~ s{/src}{};
-
- my $cflags = uc $sdir;
- $cflags =~ s{SRC}{};
- $cflags =~ s{^/}{};
- $cflags =~ s{/}{_}g;
- $cflags = $cflags ? "${cflags}_CFLAGS" : 'TOP_CFLAGS';
-
- $rule =~ s{obj/}{$odir/}g;
- $rule =~ s{src/}{$sdir/}g;
- $rule =~ s{CFLAGS}{$cflags}g;
- $rule =~ s{SRCDIR}{$srcdir}g;
- $rule =~ s{ \./}{ }g;
- print $ad $rule, "\n";
-}
-
-# If we're building out-of-tree, some of the *.c files were written
-# by autosetup from $srcdir/*.c.in, so we need an additional copy of
-# the top src dir rule set especially for them.
-unless ($intree) {
- my $rule = $template;
- $rule =~ s{SRCDIR/}{}g;
- print $ad $rule, "\n";
-}
-
-# Finish up
-close $ad;
-chmod 0440, $adf;
-print "Generated $adf for ", join(', ', @dirs), ".\n";
DELETED tools/publish-os8
Index: tools/publish-os8
==================================================================
--- tools/publish-os8
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh -e
-cd bin
-fossil uv add os8v3d-*.rk05
-fossil uv sync
Index: tools/test-mkos8
==================================================================
--- tools/test-mkos8
+++ tools/test-mkos8
@@ -41,37 +41,30 @@
use strict;
use warnings;
# Modules from CPAN
use Math::Subsets::List;
-use Parallel::Loops;
# Core modules
-use Cwd qw(getcwd abs_path);
use Digest::SHA qw(sha256_hex);
-use English;
-use File::Basename;
+use File::Compare;
use File::Copy;
use Getopt::Std;
-use List::Util qw(shuffle);
-use Term::ANSIColor;
# Perl::Critic rules we're willing to bend
## no critic (InputOutput::RequireBriefOpen )
#### GLOBALS ###########################################################
-my @tests;
my $tests_mf;
-my (%generated, %tested);
+my $currdsk = 'bin/os8v3d-bin.rk05';
+my $currdlz = 'bin/os8v3d-bin.rklz';
my $currlog = 'obj/mkos8-bin.log';
-my $cmplz = abs_path (dirname ($0)) . '/cmplz';
# Command line option values
-my ($dry_run, $existing_only, $generate_only, $single_core, $shuffle,
- $verbose);
+my ($dry_run, $generate_only);
#### sanitize_log ######################################################
# Copy the given input log file to the ouptut file, expurgating bits
# that change from one run to the next without being meaningful.
@@ -82,38 +75,23 @@
open my $if, '<', $ifile or die "Cannot read $ifile: $!\n";
open my $of, '>', $ofile or die "Cannot write $ofile: $!\n";
while (<$if>) {
- # Strip all the CRs out. We only need the LFs.
- s{\r}{}gs;
- my $original = $_; # save it post-strip
-
- # Strip variable parts of SIMH line following each Ctrl-E:
- #
- # "Simulation stopped, PC: 01210 (JMP 1207)"
- s{
- (Simulation\ stopped) # bit to preserve
- ,\ PC:\ \d+\ \([A-Z]+(\ \d+)?\) # variable bit
- }{$1.}x;
-
- # Rewrite SIMH ATTACH commands to remove pointless differences
- # in absolute paths between machines or Fossil checkouts.
- s{
- (attach\ ) # SIMH command
- (-r\ )? # optional flag
- ([a-z0-9]+\ ) # SIMH device name
- (.*test/tmp/[0-9]+/) # noise parts of image file name thru PID
- }{$1$3.../}x;
- s{
- (attach\ )
- (-r\ )?
- ([a-z0-9]+\ )
- (.*/(media/os8)/) # also squish this noise
- }{$1$3.../$5/}x;
-
- # Add cleaned line to ofile
+ # Don't care about the simulator's configuration line: as
+ # far as we know, it doesn't affect the OS/8 disks.
+ s{^PiDP-8/I .*}{PiDP-8/I [test-mkos8]}x;
+
+ # These tend to happen during OS/8's keyboard busy-wait
+ # loop, which means there's a 50/50 chance of which
+ # instruction will happen to be running at the time of the
+ # interrupt. Doesn't matter which.
+ s{Simulation stopped, .*}{Simulation stopped.}x;
+
+ # Squish configuration line in the INIT.TX output.
+ s{CONFIGURED BY .*}{CONFIGURED BY tester\@mkos8}x;
+
print $of $_;
}
close $if;
close $of;
@@ -120,251 +98,82 @@
return;
}
-#### construct_test ####################################################
-# Assembles a test record for a single permutation
+#### test ##############################################################
+# Test a single permutation
-sub construct_test
+sub test
{
my @opts = @_;
# Distill this option set to a hash value after which we will
# name the output files. We don't want to name files with a
# leading hyphen or with long variable-length names, potentially
# multiple lines long.
my $optstr = join ' ', @opts;
my $hash = sha256_hex($optstr);
- my $hdir = "test/$hash"; # test hash dir relative to our CWD
- my $rhdir = "../../$hash"; # $hdir relative to builddir test/tmp/$PID
- my $test = {
- hash => $hash,
- hdir => $rhdir,
- log => "$rhdir/last.log",
- name => '{' . substr ($hash, 0, 12) . '}',
- optstr => $optstr,
- rklz => "$rhdir/last.rklz",
- };
-
- # Skip this one if it already exists and we're in -g mode.
- if ($generate_only) {
- if (-d $hdir) {
- if (-f "$hdir/last.log") {
- if (-f "$hdir/last.rklz") {
- print "Skipping $test->{name}: already done.\n";
- return;
- }
- elsif ($verbose) {
- print "Must re-gen $hash despite -g: rklz missing!\n";
- }
- }
- elsif ($verbose) {
- print "Must re-gen $hash despite -g: log missing!\n";
- }
- }
- elsif ($verbose) {
- print "Will generate $hash.\n";
- }
- }
- elsif (-d $hdir) {
- print "Will test $optstr against $hash.\n" if $verbose;
- }
- elsif ($verbose) {
- print "Must generate missing test set $hash.\n";
- }
-
- push @tests, $test;
-
- return;
-}
-
-
-#### compare_rklz ######################################################
-# Compare two lz4-compressed RK05 disk images, returning true if they
-# are the same. If they are different, also outputs a binary difference
-# report.
-#
-# We call a separate shell script instead of use inline shell code here
-# because the helper code uses a Bash feature, and /bin/sh might not be
-# bash, as on a Raspbian box.
-
-sub compare_rklz
-{
- my ($r1, $r2) = @_;
- return system("$cmplz '$r1' '$r2'") == 0;
-}
-
-
-#### do_test ###########################################################
-# Test a single permutation
-
-sub do_test
-{
- # Set up working directory
- my $test = $_;
- print "Configuring test $test->{name}, PID $PID...\n";
- return if $dry_run;
- chdir "test/tmp" or die "Could not CD to tmp dir: $!\n";
- mkdir $PID;
- chdir $PID;
- die "Could not mkdir $test->{hdir}: $!\n"
- unless -d $test->{hdir} || mkdir($test->{hdir});
-
- # Are we building the -patched disk or the -bin disk?
- my $patched = $test->{optstr} !~ m{--disable-os8-patches}x;
- my $typestr = $patched ? 'patched' : 'bin';
- my $currdsk = "bin/os8v3d-$typestr.rk05";
- my $currdlz = substr ($currdsk, 0, length ($currdsk) - 2) . 'lz';
- my $target = 'os8-' . $typestr;
-
- # Configure the test disk image
- system "../../../configure $test->{optstr} > cfg.log 2>&1"
- and die "Failed to configure $test->{name}!\n";
- link "../../../bin/pidp8i-sim", "bin/pidp8i-sim"; # no sense rebuilding it
- open my $itf, '>', 'media/os8/init.tx' # avoid a pointless diff
- or die "Cannot overwrite init.tx with neutral version: $!\n";
- print $itf "TEST-MKOS8 BUILT THIS DISK IMAGE.\n\n";
- close $itf;
-
- # Build the test disk image
- print "Building $currdsk for test $test->{name} (PID $PID)...\n";
- system "make $target > make.log 2>&1"
+ my $hdir = "test/$hash";
+ my $testlog = "$hdir/last.log";
+ my $testdlz = "$hdir/last.rklz";
+
+ # Skip this one if it already exists and we're in -g mode.
+ if ($generate_only && -e $hdir) {
+ print "Skipping $hash; already done.\n";
+ return;
+ }
+
+ # Do the test
+ my $optdesc = $optstr || "default media";
+ print "Configuring $optdesc...\n";
+ return if $dry_run;
+ mkdir $hdir;
+ system "./configure $optstr > test/cfg.log 2>&1"
+ and die "Failed to configure $optdesc!\n";
+ print "Building...\n";
+ system "make $currdsk > test/make.log 2>&1"
and die "Failed to build $currdsk!\n";
# Quickly compress the test disk: we don't want to store all the
# "air" in an RK05 in our test corpus.
- system("lz4 -q $currdsk > $currdlz");
+ system("lz4 $currdsk > $currdlz");
+
+ if (not -f $testlog or not -f $testdlz) {
+ # This test hasn't run here yet, so blindly assume its
+ # output is correct, and thus that it should be our exemplar
+ # henceforth. Store in LZ format
+ copy ($currdlz, $testdlz);
- if (not -f $test->{log} or not -f $test->{rklz}) {
- # This test hasn't run here yet, so save it as our exemplar for
- # this optstr, to be compared to future builds.
- sanitize_log ($currlog, $test->{log});
- move ($currdlz, $test->{rklz});
+ sanitize_log ($currlog, $testlog);
# Log the mapping between the hash and the options it
# represents, so the user can reverse it.
- print $tests_mf "$test->{hash} $test->{optstr}\n";
- $generated{$test->{hash}} = 1;
- }
- elsif (compare_rklz ($currdlz, $test->{rklz})) {
- # We had this test examplar here already and on re-doing it we
- # got the same result.
- print colored(['green'], "mkos8 $test->{name} test passed."), "\n";
- $tested{$test->{hash}} = 1;
+ print $tests_mf "$hash $optdesc\n";
+ }
+ elsif (compare ($currdlz, $testdlz) == 0) {
+ print "mkos8 $optdesc test passed.\n";
}
else {
- # This build resulted in a difference, so yell and save the
- # results for manual comparison.
- my $fdiff = "$test->{hdir}/fail.diff";
- my $faillog = "$test->{hdir}/fail.log";
+ my $fdiff = "$hdir/fail.diff";
+ my $faillog = "$hdir/fail.log";
sanitize_log ($currlog, $faillog);
- move ($currdlz, $test->{hdir} . '/fail.rklz');
- system "diff -wu $test->{log} $faillog > $fdiff";
- print colored(['bold red'], 'RESULT DIFFERS! See test/',
- substr($fdiff, 6)), "\n";
- $tested{$test->{hash}} = 0;
- }
-
- system("cd .. ; rm -fr $PID"); # -f because there are read-only files
-
- return;
-}
-
-
-#### remove_missing ####################################################
-# Implements -e: given a list of mkos8 options, returns only those for
-# which we have a valid test set.
-
-sub remove_missing
-{
- my (@tests) = @_;
- my $all = @tests;
-
- # First read in the set of prebuilt tests, filtering out those that
- # refer to output files that do not exist here. (This happens when
- # copying over the manifest file but only a subset of the actual
- # test output files.)
- my %existing;
- my $genned = 0;
- my $mff = 'test/tests-manifest.txt';
- open my $mf, '<', $mff or die "Could not read from $mff: $!\n";
- while (<$mf>) {
- chomp;
- my ($hash, @opts) = split ' ';
- my $dir = 'test/' . $hash;
- if (-d $dir and -f "$dir/last.rklz" and -f "$dir/last.log") {
- $existing{join ' ', @opts} = $hash;
- }
- ++$genned;
- }
- close $mf;
-
- # Now filter the test set to remove those that do not exist
- my @filtered = grep { $existing{$_->{optstr}} } @tests;
- print "Filtered $genned of $all tests down to ", scalar(@filtered),
- " for -e.\n";
- return @filtered;
-}
-
-
-#### report* ###########################################################
-# Print on-exit status report.
-
-sub report_part
-{
- my ($partref, $kind) = @_;
-
- return unless keys %$partref;
-
- my ($successes, $tries) = (0, 0);
- for my $s (values %$partref) {
- ++$tries;
- ++$successes if $s;
- }
-
- my $extra = $successes == $tries ? '' : " of $tries";
- print colored ([
- $successes == 0 ? 'bold red' :
- $successes != $tries ?
- 'bold yellow' :
- 'green'
- ],
- "Successfully $kind $successes$extra tests.\n");
-}
-
-sub report
-{
- print "\n", '=' x 79, "\n";
- report_part (\%generated, 'generated');
- report_part (\%tested, 'built');
- print "\n";
+ system "diff -wu $testlog $faillog > $fdiff";
+ print "MKOS8 ", uc($optdesc), " DIFFERS! See $fdiff.\n";
+ }
return;
}
#### main ##############################################################
# Parse command line
my %clopts;
-getopts('egnsv1', \%clopts) or die "Failed to parse command line!\n";
+getopts('gn', \%clopts) or die "Failed to parse command line!\n";
$dry_run = $clopts{n};
-$existing_only = $clopts{e};
$generate_only = $clopts{g};
-$shuffle = $clopts{s};
-$verbose = $clopts{v};
-$single_core = $clopts{1};
-
-# Init global resources
-mkdir 'test';
-system("rm -rf test/tmp");
-mkdir 'test/tmp';
-open $tests_mf, '>>', 'test/tests-manifest.txt'
- or die "Cannot append to test manifest: $!\n";
-$SIG{INT} = $SIG{TERM} = sub { report; exit 1 };
-$SIG{PIPE} = 'IGNORE';
# Get all current --*-os8-* options, filtering out those we know should
# not be tried for this:
#
# * No --os8-minimal because that just turns on all --disable-os8-*
@@ -383,19 +192,12 @@
open my $ocmd, '-|', join('|', @cmd) or die "Failed to get os8 option set: $!\n";
my @cfgOpts = <$ocmd>;
close $ocmd;
chomp @cfgOpts;
-# Generate all possible permutations of those options. Shuffle them if
-# requested.
-subsets \&construct_test, @cfgOpts;
-@tests = remove_missing(@tests) if $existing_only;
-@tests = shuffle @tests if $shuffle;
-
-# Run the tests
-my $tdir = abs_path(dirname($0));
-my $cores = $single_core ? 1 : int(`$tdir/corecount`);
-my $pl = Parallel::Loops->new($cores);
-$pl->share (\%generated, \%tested);
-$pl->foreach ( \@tests, \&do_test);
-
-report;
+# Init global resources
+mkdir 'test';
+open $tests_mf, '>>', 'test/tests-manifest.txt'
+ or die "Cannot append to test manifest: $!\n";
+
+# Test all possible permutations of those options.
+subsets \&test, @cfgOpts;
DELETED tools/test-os8-send-file
Index: tools/test-os8-send-file
==================================================================
--- tools/test-os8-send-file
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-########################################################################
-# test-os8-send-file - Repeatedly sends random files through class simh
-# method os8_send_file() and pulls it back through os8_get_file(),
-# then checks that the file is unchanged.
-#
-# Copyright © 2017 by Warren Young.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM,
-# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
-# OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
-# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the names of the authors above
-# shall not be used in advertising or otherwise to promote the sale,
-# use or other dealings in this Software without prior written
-# authorization from those authors.
-########################################################################
-
-# Bring in just the basics so we can bring in our local modules
-import os
-import sys
-sys.path.insert (0, os.path.dirname (__file__) + '/../lib')
-sys.path.insert (0, os.getcwd () + '/lib')
-
-# Our local modules
-from pidp8i import *
-from simh import *
-
-# Other core modules we need
-import filecmp
-import os.path
-import random
-import tempfile
-
-
-#### gen_file ##########################################################
-# Generate a random text file. In order that the process be lossless
-# through the txt2ptp/ptp2txt filters and the SIMH + OS/8 terminal
-# handling, we use only printable ASCII plus CR+LF characters. Returns
-# the name of the generated file.
-
-def gen_file ():
- f = tempfile.NamedTemporaryFile (delete = False, suffix = '.tmp')
- for i in range (0, random.randint (10, 4000)):
- if random.randint (0, 10) != 0:
- # Normal case: write some number of printable ASCII characters
- # on this line.
- for j in range (0, random.randint (1, 79)):
- f.write (chr (random.randint (32, 126)))
- # else: Every now and then, just write a blank line
-
- f.write ('\r\n')
-
- f.close ()
- return f.name
-
-
-#### main ##############################################################
-
-def main ():
- # Create the SIMH child instance and tell it where to send log output
- try:
- s = simh (dirs.build)
- except (RuntimeError) as e:
- print "Could not start simulator: " + e.message + '!'
- exit (1)
- s.set_logfile (os.fdopen (sys.stdout.fileno (), 'w', 0))
-
- # Find and boot the built OS/8 bin disk
- rk = os.path.join (dirs.os8mo, 'os8v3d-bin.rk05')
- if not os.path.isfile (rk):
- print "Could not find " + rk + "; OS/8 media not yet built?"
- exit (1)
- print "Booting " + rk + "..."
- s.send_cmd ("att rk0 " + rk)
- s.send_cmd ("boot rk0")
-
- # Setup
- random.seed ()
-
- # Transfer several random files through. Beware increasing the range
- # too far: max is 99999 due to the file name length limit of OS/8 due
- # to the temporary file naming scheme we use in the loop.
- for i in range (0, 1000):
- # Build another temp file
- ifn = gen_file ()
- of = tempfile.NamedTemporaryFile (suffix = '.out', delete = False)
- of.close ()
-
- # Send it
- ofn = of.name
- tfn = 'T%05d.TX' % i
- s.os8_send_file (ifn, tfn)
- s.os8_get_file (tfn, ofn)
-
- # Did it change?
- if filecmp.cmp (ifn, ofn):
- print ifn + ' transferred successfully.'
- s.os8_send_cmd ('\\.', 'DEL ' + tfn)
- os.remove (ifn)
- os.remove (ofn)
- elif os.path.getsize (ofn) == 0:
- print "\nDifferences found: output is empty!\n"
- else:
- print "\nDifferences found:\n--------------------------------"
- os.system ('diff -wu "' + ifn + '" "' + ofn + '"')
- print 'Left ' + tfn + ' inside OS/8.'
-
-
-if __name__ == "__main__":
- main()
Index: tools/version
==================================================================
--- tools/version
+++ tools/version
@@ -30,23 +30,13 @@
########################################################################
use strict;
use warnings;
-use Cwd qw(abs_path getcwd);
+use Cwd 'abs_path';
use File::Basename;
-# Give dummy result when run via test-mkos8. A proper version string
-# isn't helpful, and fossil isn't intended to be run in parallel
-# multiple times in the same directory. We could retry several times
-# until we succeed, but again, it doesn't really help us to bother.
-my $cwd = getcwd;
-if ($cwd =~ m{/test/tmp/}x) {
- print "test:id[00000000]\n";
- exit 0;
-}
-
my $topdir = dirname($0) . '/..';
if (-e "$topdir/.fslckout") {
# Get version info from Fossil
my ($branch, $checkout, $version, $comment);
chdir $topdir; # we might be building out-of-tree