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.