WPCC: Wang Programmable Calculator Compiler
Compatability Note: At this time, WPCC does not work on CYGWIN. The GCC tools there
(Windows object/executable formats) do not support the assembler directives required.
Additionally, OSX development tools (GNU assembler) does not support these directives.
Linux ELF x86 and x86_64 platforms have been tested to work.
This package supports both
Wang 600 and
Wang 700
architectures.
Each program must #include "wang600.h" or "wang700.h", which determines the
architecture being compiled for.
Use of this facility requires GNU Compiler tools, and probably Linux (unless GCC
is available for your platform).
The sample Makefile targets/actions use the following common program file name suffixes:
- w?c
- (Where "?" is either "6" or "7") Source module code.
- w?t
- (Where "?" is either "6" or "7") Tape image, usable in the tape
drive of the respective simulator. This may contain
either program code or data (registers) if supported.
- txt
- Text (and numerical) data for the model 607/707 Teletype,
or other preprocessing into data images, ASCII.
- wfl
- Function Key Label file, used to load text into the
"strip" underneath the function keys 00-15.
Other suffixes are described under their respective architectures.
Some special macros allow for abstraction of statement labels and extended
register assignment. These are:
- LABEL(name)
- Declares that 'name' will be used as a statement label.
There must be a MARK(name) once in the program.
'name' is global/external and must be unique among all
source modules.
- LLABEL(name)
- Declares that 'name' will be used as a statement label, but
only within this source module ('name' need not be unique
with respect to other modules).
- FLABEL(name)
- Declares that 'name' will be used as a function subroutine
(i.e. f(x) or F(x)). There must be a MARK(name) once in the program.
'name' is global/external and must be unique among all
source modules.
- FLLABEL(name)
- Declares that 'name' will be used as a function subroutine label, but
only within this source module ('name' need not be unique
with respect to other modules).
- EXTERNAL(name)
- Declares that 'name' is a statement label that exists in
a different module and will be linked at a later stage.
This is used to force inclusion of
the module containing the specified label.
- FEXTERNAL(name)
- Declares that 'name' is a function subroutine that exists
in a different module.
This is used to force inclusion of
the module containing the specified label.
- REG_EXTERNAL(name)
- Declares that 'name' is an allocated register that exists
in a different module.
This is used to force inclusion of
the module containing (allocating) the specified register.
- UREG(name)
- Declares that 'name' is an extended register that is not
initialized as part of the program load. The register will
be assigned (allocated) from unused program steps after the end
of the program code. See also the IREG_DATA() pre-processed macro.
- LUREG(name)
- Declares that 'name' is a local extended register that is not
initialized as part of the program load. The register will
be assigned (allocated) from unused program steps after the end
of the program code. See also the LIREG_DATA() pre-processed macro.
Note, the allocated space (program steps) are not re-used by
any other module, and the 'name' is not visible in any other module.
- ENTER_LAST_REGNO()
-
Insert E0-E9 codes to enter the number of the last
long register that was unused by program code (i.e.
number of "free" registers for use, e.g., through
indirection (0 - ENTER_LAST_REGNO()).
- ENTER_REGNO(label)
-
Insert E0-E9 codes to enter the number of the register
known by 'label' (from UREG, IREG_DATA).
- FORDERED(label,tag)
-
Used for making "foo.wfl" targets (Function Key Labels).
The function subroutine will be linked in the order it appears,
resulting in assignment of the function code corresponding to the
order, with the first code being the first available on
the given platform ("00 00" for Wang 700, "10 00" or "12 00" (ROM)
for the Wang 600.
- RES_REG(label,num)
-
Assigns a register number to 'label', without observing
possible conflicts. Register number is not automatically
assigned, and thus may conflict with other registers.
This is typically used to assign labels to low-numbered
registers, and automatically assigned registers will
not normally conflict.
The special preprocessors ("w6cpp" and "w7cpp")
support the following "macros" which allow a
more convenient entry of program sequences, and convert native
expression of text into the Wang encoding.
ALPHA_STRING("string")
ALPHA_PLOT("string")
ALPHA_TTY("string")
Converts 'string' into a Wang "alpha" sequence
that will output the desired text. Characters are
converted to IBM Selectric tilt/rotate codes, or
the modified tilt/rotate coding used on the plotter or Teletype.
The sequence includes (WRITE) ALPHA and END ALPHA codes,
plus any shift up/down codes required. The case
is assumed to be un-shifted at the beginning of the
string. 'string' should be in double quotes.
Special character escapes:
- \r
- return+index
- \n
- index
- \ooo
- any octal character code (tile-rotate + plot bit)
Output Writer Only:
- \v
- reverse-index
- \[
- 1/2
- \{
- 1/4
- \^
- (cent)
- \b
- backspace
Plotter Only:
- \%
- plot (draw) line
- \/
- move pen only
- \h
- home pen to origin
- \z
- set character size
- \s
- set character spacing
- |x
- plot character 'x'
Teletype Only:
- \p
- Punch On (DC2)
- \q
- Punch Off (DC4)
Note: ALPHA_PLOT uses a subtly different character decoder.
It affects interpretation of '/', '=', '1', 'L' and adds '{', '}'.
Also, ALPHA_PLOT does not translate non-supported Selectric
punctuation and special characters, including 1/2, 1/4, and cent.
Similarly, ALPHA_TTY changes '1', '!', 'L', and 'l' and does
not support Selectric special characters.
ENTER(number)
Converts 'number' into a Wang digit-entry sequence that
results in the number being entered on the display.
Converts digits and decimal point to their respective
command code, '-' to CHG SIGN, 'e' to SET EXP, and
ignores '+'. Other characters will result in compile
errors. 'number' should not be quoted.
IREG_DATA(reg,number)
Creates an extended register that initially contains
the value 'number'. The register may be accessed with
RECALL(reg) and STORE(reg) statements (Wang 600)
or *_DIR(reg) and *_DIR100(reg) statements (Wang 700).
IREG_DATA(reg,"string")
Creates an extended register that initially contains
the value derived from 'string', which must be a 16-digit
hexadecimal string with the left-most digit representing
the value for the left-most digit on the display.
The affects of RECALL on such a string is left to the
user to discover. For example,
IREG_DATA(blank,"fffffffffffff00a")
Will result in an apparently-blank display when the
program step RECALL(blank) is executed on the Wang 600.
All IREG_DATA registers are placed after the main program, but
before the MARK end_prog END PROG sequence that is automatically
appended to every program. This ensures they are loaded with
the program from tape. UREG (un-initialized registers) are
allocated after the END PROG and are not part of the program
image.
LIREG_DATA(reg,"string")
LIREG_DATA(reg,"string")
Similar to above versions, allocates initialized registers.
However, 'reg' is local to the source module.
Note, the allocated space (program steps) are not re-used by
any other module, and the 'name' is not visible in any other module.
Note, register data can prevent proper operation of a SEARCH end_prog
(i.e. END_PROG()), as that data could appear as though it were a MARK end_prog.
To reduce this possibility, end_prog is defined as a label (14 14 on the 600)
which is a value less-likely found in a register.
Other directives may be described under their respective architectures.
Compiling:
Compiler error messages can be cryptic. One common message is:
Error: invalid character '(' in mnemonic
A common cause for this is a mis-spelled program code macro, or possibly
directive. The line number should accurately point to the source line responsible.
Undefined or multiple defined symbols are also common. A common cause of undefined
symbols is a missing *LABEL() directive or missing MARK(). Multple defined symbols are
usually caused by conflicting symbols between linked modules, which could be caused by
failure to use the "L" (local) form of *LABEL() directives.
Makefiles
Ideally one would use the implicit rules defined in
/usr/local/wpcc/include/Make.rules.user to compile programs.
Each sub-directory for programs would contain something equivalent to this:
include /usr/local/wpcc/include/Make.rules.user
...
all: myprog.w6t foo.w6t bar.w7t
Then, typing "
make
" would compile myprog.w6t, foo.w6t, and bar.w7t.
The following make variables may be used to affect dependencies:
- W6LDADD
- W7LDADD
- 'ld' flags, typically search path like "-Lfoo-dir".
- W6TLIBS
- W7TLIBS
- (these should only be appended to) link flags, typically something like "-lfoo".
- W6TLDEPS
- W7TLDEPS
- (these should only be appended to) link dependencies,
typically something like "foo-dir/foo.a".
- WPCCBIN
- WPCCLIB
- WPCCINC
- (do not modify) Locations of the wpcc system "bin", "lib", and "include" directoried.
- W6CPP
- W7CPP
- (do not modify) Pre-processor for source files.
- W6LDFIX
- W7LDFIX
- (do not modify) Post-processor for tape image files.
The following implicit make rules are defined:
- %.w6t: %.w6c $(W6TLDEPS)
- Run the "w6cpp" preprocessor on foo.w6c,
compile (for assembler code, using C preprocessing)
the result and link into foo.w6t.
- %.w6o: %.w6c
- Run the "w6cpp" preprocessor on foo.w6c,
compile (for assembler code, using C preprocessing)
leaving an ELF object file (linkable) module.
- %.w7t: %.w7c $(W7TLDEPS)
- Similar to rulse for "w6c", but using the "w7cpp" preprocessor.
- %.w7o: %.w7c
- Similar to corresponding "w6c" rule.
- %.wfl: %.w6c $(W6TLDEPS)
- Similar to the above rules, this produces two output files.
"foo.wfl" is created as a function key label file for use on the simulators
to polulate the Function Key labeling bar.
It also produces "foo.w6t" as the executable program.
This rule would be used for a source file that contained FORDERED() directives
to produce a predictable association of functions to function key codes.
- %.wfl: %.w7c $(W7TLDEPS)
- Similar to the above rule, for the Wang 700.
- %.w6x: [...] %.w6o %/*.w6o
- This set of rules produces a Wang 600 ROM image from a library of subroutines.
Consult the Wang 600 Compiler documentation, mentioned above, for more information.
See the example programs for examples of how to use both the programming
language and the Make rules.
For more information see Internal Workings
documentation.
Downloads
The wpcc package may be downloaded here.
See also The Wang 600 Simulator
and The Wang 700 Simulator
projects.