Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
.nofill
.tab stops 8,16,24,32,40,48,56,64,72,80
Chief Decision Maker
XYZ Corp.
Anywhere, USA
.bl 1
Dear xxxxxx:
.bl 1
.fill
Digital Research is pleased to announce the availability of a preliminary
release of CP/M-68K for use in preliminary development efforts for
microcomputers based on the Motorola 68000 chip.
We are actively seeking test sites, both for rehosting CP/M-68K onto different
hardware, and for applications development.
.bl 1
The present version of CP/M-68K is fully compatible with CP/M on the 8080 and
8086.
The system comes with a 68000 assembler, linker, and
librarian, plus the CP/M file management utilities. A preliminary version of
Digital Research's
C compiler and C run-time
library will be available for testing in 30-60 days. C cross compilers
that run
on PDP-11 or VAX UNIX and VAX/VMS will also be available in the same time
frame.
.bl 1
We at Digital Research are quite excited about the future of CP/M-68K. Should
you wish to get an early start on using this system by participating in our
test program, please sign and return the enclosed test system agreement.
.bl 1
Please address any questions or correspondence regarding CP/M-68K to:
.bl 1
.nofill
.lm 5
Steve Williams
Digital Research
PO Box 579
Pacific Grove, CA 93950
(408) 649-3896
.bl 1
.lm 0
.fill
Thank you for your time and cooperation. If you have any questions, please
do not hesitate to call.
.nofill
.nojustify
.bl 1
.lm 40
Sincerely,
.bl 3
Steve Williams
.br

View File

@@ -0,0 +1,6 @@
The C BIOS has been modified since publication of the System Guide.
A new #define is required in the BIOSTYPE.H file when a loader BIOS
is being generated. The #define is for a symbol called "BOOTDSK".
This should be set to the number of the disk from which the loader
bios is to read the CPM.SYS file, 0->A, 1->B, ... .
LOADBIOS.H and BIOS.C have been changed to reflect this new usage.

View File

@@ -0,0 +1,62 @@
.appendix CP/M Error Codes
.title CP/M Error Codes
.subtitle
.page
.c
CP/M Error Codes
.c
----------------
.bl 1
.i 5
The "perror" function and the "errno" external variable are used to determine
the exact cause of an error during a CP/M system call. The include file
<errno.h> contains symbolic definitions for the errors returned by CP/M.
Following is a table of error numbers, symbolic names, and messages available
from perror:
.bl 1
.lm 8
.nofill
Number Name Error Message
------ ---- -------------
0 - Error Undefined on CP/M
1 - Error Undefined on CP/M
2 ENOENT No Such File
3 - Error Undefined on CP/M
4 - Error Undefined on CP/M
5 EIO I/O Error
6 - Error Undefined on CP/M
7 E2BIG Arg List too Long
8 - Error Undefined on CP/M
9 EBADF Bad file Number
10 - Error Undefined on CP/M
11 - Error Undefined on CP/M
12 ENOMEM Not enough core
13 EACCES Permission denied
14 - Error Undefined on CP/M
15 - Error Undefined on CP/M
16 - Error Undefined on CP/M
17 - Error Undefined on CP/M
18 - Error Undefined on CP/M
19 - Error Undefined on CP/M
20 - Error Undefined on CP/M
21 - Error Undefined on CP/M
22 EINVAL Invalid argument
23 ENFILE File table overflow
24 EMFILE Too many open files
25 ENOTTY Not a typewriter
26 - Error Undefined on CP/M
27 EFBIG File too big
28 ENOSPC No space left on device
29 - Error Undefined on CP/M
30 EROFS Read-only file system
31 - Error Undefined on CP/M
32 - Error Undefined on CP/M
33 - Error Undefined on CP/M
34 - Error Undefined on CP/M
35 ENODSPC No directory space
.bl 1
.lm 0
.fill
<errno.h> also includes the UNIX defined names for all errors defined with
UNIX V7, so that programs which reference these definitions need not be
changed.

View File

@@ -0,0 +1,5 @@
.in clib
.in style
.in cerrors
.in custom
.appendix Sample C Module

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
.nofill
Memo: Vincent Alia
Ruth Driscoll
Bill Fitler
Bob Herlien
Tim McCormick
Bill Tyler
.bl 1
xc: Tom Rolander
.bl 1
Re: Minutes of CP/M-68K Status Meeting 07/06
.bl 1
From: Steve Williams
.bl 1
.fill
As we discussed this morning, the status of the CP/M-68K project is as
follows:
.bl 1
.c
BDOS
.c
----
.bl 1
The BDOS is 99% coded, lacking only the Set exception vector, program
chain and flush buffers
functions. Approximately 60% of this code is tested. Bob has
committed to a working BDOS by 7/16.
.bl 1
.c
CCP
.c
---
.bl 1
The CCP lacks BATCH processing. It is felt that this is a desirable feature,
but that the system would be usable without it. BATCH processing is therefore
a candidate for featurectomy if need be.
.bl 1
.c
Bootstrap
.c
---------
.bl 1
No progress has been made on a bootstrap loader for CP/M on the EXORmacs.
.bl 1
.c
DDT
.c
---
.bl 1
DDT lacks File I/O and program load functions. It is not usable without
program load. Bill has promised program load by 7/12. File I/O is another
candidate for featurectomy.
.bl 1
.c
Diskette Format Utility
.c
-----------------------
.bl 1
Nothing has been done about a diskette format utility for the EXORmacs.
.bl 1
.c
Utilities
.c
---------
.bl 1
A problem exists somewhere between XLINK and the Motorola linker. Initialized
data areas in the utilities do not have the right values in the right places
after the link process. Chaki will attempt to use the Alcyon linker to
correct this problem.
.bl 1
ED and STAT work completely when linked into the system. Debugging is
starting on the PIP utility. There is some problem with random I/O which
needs to be fixed to complete this debugging. Bob will coordinate with Chaki
to resolve the problem.
.bl 1
.c
Assembler / Linker
.c
------------------
.bl 1
No further work has been done on the Alcyon assembler / linker since getting
these to work on the VAX under VMS. Work will begin this week on re-hosting
this software to run under CP/M-68K.
.bl 1
.c
C Runtime Library
.c
-----------------
.bl 1
Bill Fitler joined the project team today as the C runtime library person.
A specification for this library now exists, and work will begin immediately.
Bill has promised a schedule by the end of the week.
.bl 1
.c
C Compiler
.c
----------
.bl 1
Barring unforeseen problems, we will receive the source code to the Alcyon
compiler 7/12. This will be put up on the VAX using the same interface
library used to port the assembler and linker.
.bl 1
.c
Documentation
.c
-------------
.bl 1
Ruth has promised an outline for the Programmer's Manual by 7/8, and also to
begin writing this manual on that date.
.bl 1
We will be using the Motorola 68000 book plus Bill Allen's documentation for
the assembler and linker, at least for B-testing purposes.
.bl 1
.c
Quality Assurance
.c
-----------------
.bl 1
Vincent distributed the attached assurance plan. Bob, Bill and Chaki must
coordinate with him on getting time on the EXORmacs. I will be assuming the
role of Q/A interface person.
.bl 1
.c
Other Issues
.c
------------
.bl 1
The following decisions were reached by myself and Tom Rolander 7/6:
.ls
.leb;The Pascal version of CP/M-68K must be translated into C and shipped as
a product as soon as possible following the preliminary release. This will
entail a second field test. Portable CP/M will have to wait. I will manage
this conversion project.
.leb;The C runtime documentation will be given to Motorola and HP.
.leb;The quantities in the Motorola contract will be adjusted so that CP/M-68K
pricing is in line with CP/M-86.
.els
.c
From Last Week
.c
--------------
.bl 1
No minutes were distributed from last week's meeting. Here are the key
decisions that were made:
.ls
.leb;Bob Herlien will be responsible for the CCP, BDOS, and Bootstrap
portions of the code.
.leb;Bill Tyler will be responsible for DDT, the Disk FORMAT utility, and
serialization utilities. (Serialization does not have to be ready 7/31).
.leb;I will be responsible for making the Alcyon assembler and linker
work under CP/M-68k.
.leb;Ruth Driscoll will be responsible for documentation, consisting of
a Programmer's Guide, a User's Guide, and a Quick Reference. For the 7/31
shipment, the following items have priority:
.ls
.leb;The BDOS Calls section of the Programmer's Guide.
.leb;The BIOS Calls section of the Programmer's Guide.
.leb;The description of the Base Page area and program loading from the
Programmer's Guide.
.leb;(Time permitting) A list of DDT commands.
.els
The Alcyon documentation on the assembler and linker plus the Motorola
book on the 68000 must serve for documentation on the assembler / linker
programs. The CP/M-86 User's guide must serve as documentation for user
commands.
.els
It was also decided that the ".COM" file equivalent for CP/M-68K would be
".68K". Submit files would have the extension ".SUB".
The "SUBMIT " command prefix will be optional.
.bl 1
The ability to retrieve ALL directory entries in SEARCH functions by coding
a "?" in the drive field of the FCB under CP/M 2.2 will be preserved under
CP/M-68K.

View File

@@ -0,0 +1,138 @@
.appendix Customizing the C Compiler
.title Customizing the C Compiler
.page
.c
Customizing the C Compiler
.c
--------------------------
.bl 1
.i 5
Compiling a C program requires running three compiler passes. The output of
the compiler is assembly language, which must be assembled and linked with
the C library to produce a runnable program. The amount of disk storage
required for the compiler, assembler, and linker load modules, the C library,
and the system include files is non-trivial. This appendix contains a
discussion of compiler operation, as well as some suggestions for minimizing
the disk storage requirements for the compilation process.
.subtitle Compiler operation
.hl 1 Compiler operation
.i 5
The C compiler consists of three components: the Preprocessor (CP68),
the Parser (C068), and
the Code Generator (C168). The assembler (AS68) and linker (LO68) are also
used in generating an executable program.
These components are operated as follows:
.ls
.lec'CP68'The preprocessor is invoked to take the original source file
and produce
a file with all '_#define' and '_#include' statements resolved. The command
line is:
.bl 1
.i 8
CP68 [-I d:] file.C file.I
.bl 1
The "-I" flag is used to indicate that the next argument is a CP/M
drive specification. This drive will be used for all library include
statements -- those of the form '_#include <file>'. Drive specifications
may also appear in the filename portion of a '_#include' statement, but
this procedure is not recommended. "file.C" is the source file, and "file.I"
is the output file.
.lec'C068'The parser takes the file produced by the and creates an
intermediate code file. The command line is:
.bl 1
.i 8
C068 file.I file.IC file.ST
.bl 1
"file.I" is the output from the preprocessor. "file.IC" is the intermediate
code file for use by C168. "file.ST" is a temporary file used to collect
constant data for inclusion at the end of the intermediate code file.
.lec'C168'The code generator takes the intermediate code file from C068 and
produces an assembly-language source file. The command line is:
.bl 1
.i 8
C168 file.IC file.S [-LD]
.bl 1
"file.IC" is the intermediate code output from C068. "file.S" is the
assembly language output file. The "-L" flag is used to indicate that the
compilation is to assume all address variables are 32 bits. Default is 16
bit addresses.
The "-D" flag
causes the compiler to include the line numbers from the source file (file.C)
as comments in the generated assembly language. This can be very useful for
debugging.
.lec'AS68'The assembler is used to translate the compiler output to a form
suitable for use by the linkage editor. The command line is:
.bl 1
.i 8
AS68 -L -U [-F d:] [-S d:] file.S
.bl 1
The "-L" option is used to indicate that addresses are to be considered
32 bit quantities. The "-U" option means that undefined symbols are to be
considered external references. The "-F" option specifies a drive to be used
for the assembler's temporary files. The "-S" option specifies a drive to be
used for the assembler's initialization file "AS68SYMB.DAT". "file.S" is the
output of C168, and "file.O" is produced by the assembler.
.lec'LO68'The linker is used to produce an executable file from the output of
one or more assembler runs. A startup file and the C library must also
be included when linking C programs. The linker command line is:
.bl 1
.i 8
LO68 -R [-F d:] -O file.68K S.O file.O CLIB
.bl 1
The "-R" option specifies that the file is to be relocatable. Relocatable
files may be run on any CP/M-68K system. The "-F" option allows placing the
linker temporary files on a disk drive other than the default. The
"-O file.68K" construct causes the linker to place the executable output
in "file.68K". "S.O" is the runtime startup routine. This file must be
included as the first file in every C program link. "file.O" is the
output of the assembler. Multiple files may be specified between "S.O" and
"CLIB" if separate compilation is desired. "CLIB" is the C library file.
.els
.subtitle Supplied SUBMIT files
.hl 1 Supplied SUBMIT files
.i 5
CP/M-68K includes two files, "C.SUB" and "CLINK.SUB", which may be used to
compile and link (respectively) a C program. The use of these files is
described in Chapter 1 under "Operating Instructions". It may be desirable,
however, to edit these files to specify different disk drives for any of the
following items:
.bl 1
.ls
.leb;The disk drive on which the compiler passes, assembler and linker reside.
.leb;The disk drive which is referenced by '_#include <file>' statements in
the C preprocessor.
.leb;The disk drive on which the assembler initialization file is kept.
.leb;The disk drive on which the assembler and linker create temporary files.
.leb;The disk drive on which the C library file is kept.
.els
The default drive is currently used for all of the above items.
.subtitle Disk Space Optimization
.hl 1 Disk Space Optimization
.i 5
In situations where disk space is at a premium, several things can be done
to minimize diskette shuffling:
.ls
.leb;Use the "reloc" utility on all load modules which are to be used: the
compiler, assembler, linker, and editor. This will significantly reduce file
size and load time.
.leb;Place all of the load modules on one disk, and use a second disk for
sources and temporary files. This requires at least two drives.
.leb;On single density diskette systems, it will be necessary to place
the C library file
and linker on a separate diskette, and to make a diskette swap before
linking.
.els
.subtitle Speed Optimization
.hl 1 Speed Optimization
.i 5
In addition to the items listed above, it is possible to make the compilation
process faster by:
.ls
.leb;Putting the assembler temp files on a different drive from the source
and object files.
.leb;Putting the linker temp files on a different drive from the object
input, C library, and load module output.
.leb;Using the linker "-S" (Suppress symbol table), and "-T" (absolute
load module) switches in place of the "-R" flag. Note that the resulting
program will not run on an arbitrary CP/M-68K system if this is done.
.els

View File

@@ -0,0 +1,147 @@
Customization of the CCP.
The standard CP/M-68K CCP contains four different program
modules. In order to write your own customized version of the CCP
it is only necessary to substitute your CCP for two of the four
existing modules. However it is essential to understand the inter-
facing procedures between the four different modules and their relation-
ship to the BDOS and BIOS of CP/M-68K.
The four CCP program modules are:
(1) CCPIF.O
(2) CCPBDOS.O
(3) CCPLOAD.O
(4) CCP.O
The first three modules of the CCP perform general CP/M
housekeeping functions. CCPIF.O is the coldboot and warmboot interface
between the CCP,the BDOS,and the BIOS. CCPBDOS.O is an assembly
language module that performs the BDOS function calls for the main
CCP module: CCP.O. CCPLOAD.O is the assembly language module that
performs the program load function for CCP.O. CCP.O is the main module
of the CCP. Substitute your custom CCP for modules three and four of the
standard CCP for CP/M-68K. A description of the CCP input and output
interface requirements with modules one and two as well as the BDOS
and BIOS follow.
CCP INPUT INTERFACE
-------------------
The main module of the CCP is entered via a jsr(jump to sub-
routine) instruction from CCPIF.O. Here is the exact instruction as
it appears in CCPIF.O.
jsr _main *call the CCP
The label _main contains the underscore character because
the C compiler places an underscore before every external variable
and function name. CCP.O contains the function:
main()
{
/* main CCP module */
}
which orchestrates the function of the Console Command Processor.
This jsr instruction is the only entry point to the CCP.
CCP OUTPUT INTERFACE
--------------------
The CCP needs to access the BDOS to perform its function.
The module CCPBDOS.O contains assembly language instructions to
fill registers D0 and D1 with the BDOS function number and the BDOS
parameter respectively. This module is expecting to pull off the
stack a word for the function number and a long word for the parameter.
The function is defined in the main module as follows:
EXTERN UWORD bdos();
Here are two examples of the CCP.O to CCPBDOS.O interface:
(1) userno = bdos(GET_USER_NO,(long)255);
(2) move.l #255,-(sp)
move.w #GET_USER_NO,-(sp)
jsr _bdos
tst d0 *return value in register D0
move.w d0,userno *get return value
etc.......
The bdos will return a word value for the current user number.
In the standard CP/M-68K CCP,a warmboot occurs after the
termination of every transient program. Upon warmboot,control is
transferred to the BDOS and eventually back to the CCP via that
jsr instruction. Before entrance to the main module,the system
stack is reset to its orginal starting address. CCPIF.O must be
the first module of CP/M-68K. This module also performs coldboot
startup procedures essential to coldboot loading. Any interface
to the BIOS is done through the BDOS direct BIOS call. See the
programmer's guide for details. If you experience problems with
doubly defined global variables,use the NM68 utility to get a listing
of the system symbol table. For example:
A>NM68 CPM.REL
will give you a listing of the CP/M-68K symbol table. For further
details regarding the use of NM68 see the CP/M-68K programmer's guide.
Finally it is necessary that the CCP use bdos function 10 to
read in a command line from the console if you wish to make use of
bdos function 47(chain to program). The chain to program function
traps function 10 calls and supplies the CCP with the next command
to execute from an internal buffer.

View File

@@ -0,0 +1,189 @@
.title ^^CP/M-68K Version 1.0 Release Notes
.c
CP/M-68K Version 0.1
.c
--------------------
.bl 2
.c
Release Notes
.c
-------------
.bl 2
.i 5
CP/M-68K(1) Version 0.1 is a pre-release copy of CP/M-68K for use by OEMs for
development of custom BIOS modules and applications packages. It is not
intended, and must not be used,
as a final product for distribution to end users.
This release is definitely not production quality software, but should be
adequate for early development efforts.
.bl 1
.c
Distribution Kit Contents
.c
-------------------------
.bl 1
.i 5
CP/M-68K is distributed on four standard single-density 8-inch floppy
diskettes. Three of these diskettes are readable on any
CP/M system which supports the
standard CP/M "read one skip five" interleave algorithm. The 26 sectors on
a track are read in the order: 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15,
21, 2, 8, 14, 20, 26, 6, 12, 18, 24, 4, 10, 16, and 22. Most CP/M-80 and
CP/M-86 systems which support single density diskettes use this format.
The fourth diskette is a bootstrap diskette for the Motorola EXORmacs(1)
development system.
.footnote 5
(1) CP/M, CP/M-86, and CP/M-68K are trademarks of Digital Research, Inc.
EXORmacs and MACSbug are trademarks of Motorola, Inc.
!
.bl 1
.i 5
The CP/M format diskettes contain:
.ls
.leb;The diskette labelled "Utilities I" contains the ED, PIP, and STAT file
manipulation utilities, and the AS68, NM68, and AR68 program development
utilities.
.leb;The diskette labelled "Utilities II" contains the LO68, SENDC68, and
DDT utilities. This diskette also contains sources for three BIOS modules
to be used as examples in writing new BIOS modules.
.leb;The diskette labelled "CP/M Objects" contains the relocatable objects
for linking a new version of CP/M-68K to change the load address of CP/M
and the accompanying BIOS.
This diskette also contains Motorola S-record files for two prelinked systems.
See the section on "Pre-linked Systems" for details.
.els
The accompanying documentation describes the use of these programs in detail.
.bl 1
.test page 7
.c
Running CP/M On the EXORmacs
.c
----------------------------
.bl 1
.i 5
The bootable CP/M diskette is intended to run on any EXORmacs system which
has a floppy drive unit interfaced with the Motorola Universal Disk Controller
(UDC) module. The Floppy Disk Controller (FDC) definitely will NOT work.
The system will run in 128K of memory.
To
boot CP/M, use the following procedure:
.ls
.leb;Insert the CP/M boot disk in one of the drives.
.leb;Depress the "System Reset" button on the front panel and use the
MACSbug "Boot Halt" command to load CP/M into memory. (For example, "BH 4"
loads CP/M from drive 4).
.leb;When MACSbug re-prompts, place a CP/M (or blank) diskette in drive
4.
.leb;Depress the system reset button again, and type "G 1E000". The familiar
CP/M "A>" prompt should now appear.
.els
You may now use this copy of CP/M to generate a system which, together with
a custom BIOS, will fit your target hardware.
.bl 1
.c
Pre-Linked Systems
.c
------------------
.bl 1
.i 5
The distribution kit "CP/M Objects" disk contains Motorola S-records for two
pre-linked systems:
.ls
.leb;Files "CPM68K1.SR", "RTP1.SR", and "BIOS1.SR" contain S-records for an
EXORmacs system with the system above 18000(hex) and the TPA from 400-18000.
.leb;Files "CPM68K0.SR", "RTP0.SR", and "BIOS0.SR" contain S-records for an
EXORmacs system with the system from 400-8800(hex) and the TPA from
8800-20000(hex).
.els
These files may be downloaded to MACSbug or a similar S-Record loader for
use in debugging.
.bl 1
.c
Regenerating CP/M
.c
-----------------
.bl 1
.i 5
In order to regenerate CP/M, one must first decide where the operating
system modules and the Transient Program Area (TPA) are to reside. There are
three areas of the operating system which must be so configured: The
BDOS/CCP, the Runtime Package (RTP), and the BIOS.
The size of the BDOS/CCP is presently 24K, and the runtime package
currently occupies 800 bytes. BIOS size is implementation dependent.
.bl 1
.i 5
Suppose, for instance, that the desired BDOS/CCP address is 10000(hex), the
RTP address 16000(hex), and the BIOS address 20000(hex). The procedure for
building new load modules is:
.ls
.leb;Assemble your custom BIOS module, and place the resulting object on
the CP/M Objects diskette.
.leb;Boot CP/M with the Utilities II diskette in drive 4 and the CP/M Objects
diskette in drive 5.
.leb;Type the following commands:
.ls
.leb;A>B:
.leb;B>A:LO68 -T10000 -O CPM68K 1 2 3 4 5 6 7 8 9 10
.leb;B>A:LO68 -T16000 -O RTP RTP.O
.leb;B>A:LO68 -T20000 -O BIOS BIOS.O
.els
This puts the BDOS/CCP Module in file "CPM68K", the RTP module in file "RTP",
and the BIOS module in file "BIOS".
.els
The linked load modules can be converted to Motorola S-Records by the
following commands:
.ls
.leb;B>A:SENDC68 - CPM68K >CPM68K.SR
.leb;B>A:SENDC68 - RTP >RTP.SR
.leb;B>A:SENDC68 - BIOS >BIOS.SR
.els
The resulting ".SR" files may then be serially downloaded to a target system,
or used by a custom conversion program to generate a different load file
format.
.bl 1
.i 5
The BIOS initialization routine should set up the TRAP 1 vector to point to
the base of the RTP module
TRAP 3 should be initialized to the entry
point of the BIOS.
Following initialization, the BIOS should jump to the first location in the
BDOS/CCP module.
.bl 1
.c
Other Initialization Procedures
.c
-------------------------------
.bl 1
.i 5
The assembler requires initialization before use. To do this, put the
"Utilities I" disk in drive 4 (CP/M Drive "A") and type:
.bl 1
.i 5
as68 -i as68init
.bl 1
The assembler will build a file "as68symb.dat" which will be used as the
permanent symbol table for subsequent assemblies. This procedure must be
performed each time the base (lowest address) of the TPA is changed.
.bl 1
.c
Known Bugs
.c
----------
.bl 1
.i 5
The following are known bugs with this release:
.ls
.leb;No command file support (SUBMIT) is present in this release.
.leb;The Control-H key (Backspace)
does not always function properly with the ED utility.
.leb;The Control-H key (Backspace) does not echo properly when used with
the Control-R (review) mechanism.
.leb;DDT does not have the following commands: A(ssemble), R(ead), and
W(rite).
.leb;The assembler and linker do not always delete their temporary files.
.leb;Some options of PIP, ED, and STAT do not work if the
TPA begins above 64K.
.leb;The assembler symbol table file must always be on drive "A".
.leb;The Exception Vector handler in BDOS does not clear the TRACE bit
before starting the user exception handler.
.els

View File

@@ -0,0 +1,27 @@
.subtitle blivot Function
.page
.hl 1 Blivot Function
Description:
.bl 1
.nofill
.bl 1
Calling Sequence:
.bl 1
.i 8
ret = blivot(a1,a2,...);
.bl 1
Arguments:
.bl 1
.lm 8
a1 Is the xxxx ...
.bl 1
.lm 0
Returns:
.lm 8
.bl 1
.lm 0
.fill
.bl 1
Bugs:
.bl 1

View File

@@ -0,0 +1,75 @@
.nofill
Dr. T. Ishikawa
Musashi Works of Hitachi, Ltd.
1450 Josuihon-cho Kodaira-Shi
Tokyo, 187 Japan
.bl 1
Dear Dr. Ishikawa:
.bl 1
.fill
Thank you for your letter on CP/M-68K. We certainly appreciate your effort
in helping us make CP/M-68K a better product. Here are our answers to the
issues you raised.
.bl 1
Bugs:
.bl 1
.ls
.la;Changing file attributes with STAT does cause the first letter of the
extension to disappear. This is due to the CCP not ANDing off the high-order
bit of the character before outputting it to the screen. This bug is fixed
in the 10/8 release.
.la;Non-zero user areas do not work in the 7/31 version of the system. This
bug is also fixed in the 10/8 release.
.la;Source files which do not have single-character extensions cannot be
assembled. This is a restriction imposed by the assembler.
.la;The "-s" option of lo68 with which you had trouble seems to work on
our copy of the system. The relocation bits are unaffected by this flag.
.la;The "-x" option of lo68 is used to retain LOCAL symbols of the assemblies
or compiles which make up the input to the linker. Symbols beginning with
"L" are suppressed by this flag. The C compiler uses symbols beginning with
"L" for compiler-generated temporary labels. The "-x" option removes these.
.la;Relocatable command files may be generated by using the "-r" option of
LO68. The default is to generate absolute command files.
.la;The disk change bug which you reported has been corrected in the 10/8
release. The problem stemmed from the fact that the OLD diskette directory
was retained in memory by the BIOS.
.la;Relocation bits for the data segment are not produced unless the "-r"
option is specified.
.els
.test page 10
Assembler Requirements:
.bl 1
.ls
.la;We have been promised an update to the assembler to make it compatible
with Motorola syntax. We will place this either on the present release
or on the next release of CP/M-68K, depending on when we receive the
update from Alcyon.
.la;Source file concatenation with the assembler may be accomplished using
the C preprocessor (CP68) supplied with the 10/8 release.
.els
Questions:
.bl 1
.ls
.la;Floppy disk initialization will be performed via a FORMAT utility which
uses the UDC (Univeral Device Controller) FORMAT feature.
.la;The bootstrap utility will be supported much the same as in CP/M-86:
A loader program will reside on the first two tracks of the disk. This
loader will be brought into memory by the BOOT ROM, and will load the file
CPM.SYS from drive A:. Detailed specifications will be delivered with the
10/8 release.
.la;We do not plan on generating CP/M diskettes under Versados. The
S-records for the system will be supplied on Versados diskettes, and
CP/M can be built with MBLM. The EXORmacs emulator and other debugging
tools can be used for debugging CP/M built from these S-records.
.la;We do not plan to have a file conversion utility from CP/M to Versados.
.els
Again, thank you for your efforts in helping us debug CP/M-68K.
If any other bugs or questions should arise, please do not hesitate to
contact us.
.bl 1
.nofill
Sincerely yours,
.bl 4
Steve Williams

View File

@@ -0,0 +1,16 @@
.c
Issues
.c
------
.bl 1
.ls
.leb;Already-late schedules for CP/M-68K manuals depend on present writing
resources. There is some danger that the resources will be reduced due to
elimination of contractors, and moving a writer from CP/M-68K to CP/M-86 for
the IBM PC.
.leb;Otter schedule calls for beginning 1/1/83. Resources will not be free
until after CP/M-83.
.leb;Alcyon contract amendment has not been signed and returned. Last seen
in Tom Rolander's possession.
.leb;Need more 68K machines for the ISV marketing effort.
.els

View File

@@ -0,0 +1,214 @@
.title ^^CP/M-68K Product Brief
.c
CP/M-68K Product Brief
.c
----------------------
.bl 1
.c
Features
.c
--------
.bl 1
.ls
.leb;Memory Space Efficient -- Resides in 24K bytes
.leb;Can utilize as little as 64Kb or as much as 16Mb of memory
.leb;Allows up to 8Gb of on-line disk(ette) storage
.leb;Allows multiple programs in memory
.leb;Command compatible with CP/M and CP/M-86
.leb;File structure compatible with CP/M and CP/M-86
.leb;Allows full access to the 68000 hardware features
.leb;Comes with a C language compiler and standard run-time library.
.els
.c
CP/M-68K Overview
.c
-----------------
.bl 1
CP/M-68K is a proprietary, general-purpose control program designed especially
for microcomputers built around the Motorola 68000 microprocessor family.
.bl 1
CP/M-68K is efficient and powerful. CP/M-68K systems can support application
programs that range from small to complex. It has a time-tested, modular
design. The system modules include:
.ls
.leb;The Console Command Processor (CCP) -- the human interface of the
operating system that parses and executes a user's commands.
.leb;The Basic Disk Operating System (BDOS) -- the invariant portion of the
operating system that performs system services such as managing disk
directories and files.
.leb;The Basic Input/Output System (BIOS) -- the variant portion of the
operating system that contains hardware-dependent input/output device
handlers.
.els
CP/M-68K is small, residing in about 24K bytes of memory. The exact size is
dependent on the size of the BIOS, which in turn is determined by the
number of peripheral devices in the system. Although it is compact, CP/M-68K
can give application programs the full advantage of the 68000 address space,
up to 16 megabytes (16,777,216 bytes) of main memory. CP/M-68K supports a
relocatable program file format to provide extensive compatibility among
different 68000 computers.
.bl 1
.c
CP/M and CP/M-86 Compatibility
.c
------------------------------
.bl 1
CP/M-68K files are completely compatible with CP/M Version 2.2 and CP/M-86
Version 1.1.
This simplifies conversions of CP/M and
CP/M-86 software to run on CP/M-68K.
.bl 1
The end user will notice no significant difference between CP/M-68K and
previous versions
of CP/M. Commands such as DIR, TYPE, PIP, STAT, and ED respond
the same way in both systems. The program interface is also unchanged --
CP/M-68K
calls for system services have the same function numbers as in CP/M and
CP/M-86.
.bl 1
It is easy to upgrade existing CP/M and CP/M-86 application software to run
under CP/M-68K, because CP/M-68K is so similar to its predecessors. Although
assembly language programs will require recoding, high-level language programs
will recompile with little or no modification.
.bl 1
.c
File Management
.c
---------------
.bl 1
CP/M-68K can support up to 16 logical drives, each containing up to 512
megabytes, for a maximum of 8 gigabytes of on-line storage. Any one file
can reach 32 megabytes, with space dynamically allocated and released. Each
device has a directory which maps each file's physical locations on the disk.
Disk definition tables in the BIOS translate this logical information to
the physical characteristics of the disk. This file system is identical to
the file system supported by CP/M 2 and CP/M-86.
.bl 1
.c
Development Tools
.c
-----------------
.bl 1
Digital Research offers a set of development tools for CP/M-68K
which can be run using CP/M-68K or on a
VAX-11 or PDP-11 computer under the UNIX or VMS operating systems. These
tools can be used to develop CP/M-68K applications or a custom CP/M-68K
BIOS.
The development tools include:
.ls
.leb;A C compiler and C runtime library compatible with UNIX (R) software.
.leb;An assembler, linker, and library utitilies.
.leb;A utility to convert CP/M-68K load modules to Motorola S-Record form.
.leb;A relocation utility to convert relocatable load modules to absolute
form.
.leb;A utility to list the symbol table contained in a load module file.
.leb;A utility which prints the memory size required by the load module.
.els
These tools are distributed at no extra charge
with CP/M-68K, and can be run on any
CP/M-68K system with at least 128K of memory.
.bl 1
.c
Customization
.c
-------------
.bl 1
For ease in transporting CP/M-68K to a specific hardware environment, all
hardware dependent code is located in one module, the BIOS (Basic Input/Output
System).
.bl 1
Digital Research ships CP/M-68K configured for the Motorola EXORmacs
development system. To bring up CP/M-68K on a different system, a custom
BIOS module must be developed. The custom BIOS must support a standard set
of I/O primitives on which the BDOS depends. These primitives include:
.nofill
.lm +5
.bl 1
o Console Status
o Console In
o Console Out
o List Out
o Select Drive
o Set Track
o Set Sector
o Read Sector
o Write Sector
o Return Memory Descriptor Table Address
.lm -5
.fill
.bl 1
To simplify the preparation of a custom BIOS, Digital Research supplies the
source code for a working BIOS and a skeleton source file for a customized
BIOS. Most of a customized BIOS may be written in the C language, to save
development time.
.bl 1
.c
Utilities
.c
---------
.bl 1
In addition to the development tools described previously, CP/M-68K is
supplied with a set of file management utilities:
.ls
.lec'PIP#'The Peripheral Interchange Program provides file transfer between
devices and disk files. Various reformatting and concatenation operations
may also be performed with PIP. These include: parity bit removal, case
conversion, subfile extraction, tab expansion, line number generation, and
pagination.
.lec'ED##'The CP/M-68K text editor allows creation and modification of ASCII
files using extensive commands: string substitution, string search, insert,
delete and block move. ED allows text to be located by context, line number,
or relative position. A macro command allows making extensive text changes
with a single command line.
.lec'DDT#'The CP/M-68K Dynamic Debugging Tool allows the user to test and
debug programs interactively in a CP/M-68K environment. The command set
allows users to trace program execution with a full register and status
display.
.lec'STAT'The STAT utility alters and displays I/O device and file status
including free space computations, status of online disk(ette)s and
physical-to-logical device assignment.
.lec'DUMP'The DUMP utility displays any file with a side-by-side hexadecimal
and ASCII format. Output may be redirected to a file or the listing device
if desired.
.els
.c
Hardware Requirements
.c
---------------------
.bl 1
The version of CP/M-68K that Digital Research ships and supports requires
a Motorola EXORmacs with a Motorola Universal Disk Controller. CP/M-68K
may be reconfigured for a custom hardware environment using the development
tools supplied with the system. Custom hardware environments must include:
.bl 1
.nofill
.lm +5
o A Motorola 68000, 68008, or 68010 CPU.
o At least 64K of RAM.
o One to 16 disk drives of up to 512 megabytes each.
o An ASCII console Device such as a CRT.
.lm -5
.fill
.bl 1
.c
Ordering Information
.c
--------------------
.bl 1
CP/M-68K is shipped on four 8-inch single-sided single density diskettes.
There are two CP/M-68K products available from Digital Research:
.ls
.leb;The CP/M-68K single user
system, consisting of the four diskettes plus CP/M-68K
documentation.
.leb;CP/M-68K documentation only, consisting of four manuals:
.bl 1
.nofill
.lm +5
o The CP/M-68K User's Guide
o The CP/M-68K Programmer's Guide
o The CP/M-68K System Guide
o The CP/M-68K C Language Manual
.fill
.lm -5
.els

View File

@@ -0,0 +1,214 @@
.title ^^CP/M-68K Product Brief
.c
CP/M-68K Product Brief
.c
----------------------
.bl 1
.c
Features
.c
--------
.bl 1
.ls
.leb;Memory Space Efficient -- Resides in 24K bytes
.leb;Can utilize as little as 64Kb or as much as 16Mb of memory
.leb;Allows up to 8Gb of on-line disk(ette) storage
.leb;Allows multiple programs in memory
.leb;Command compatible with CP/M and CP/M-86
.leb;File structure compatible with CP/M and CP/M-86
.leb;Allows full access to the 68000 hardware features
.leb;Comes with a C language compiler and standard run-time library.
.els
.c
CP/M-68K Overview
.c
-----------------
.bl 1
CP/M-68K is a proprietary, general-purpose control program designed especially
for microcomputers built around the Motorola 68000 microprocessor family.
.bl 1
CP/M-68K is efficient and powerful. CP/M-68K systems can support application
programs that range from small to complex. It has a time-tested, modular
design. The system modules include:
.ls
.leb;The Console Command Processor (CCP) -- the human interface of the
operating system that parses and executes a user's commands.
.leb;The Basic Disk Operating System (BDOS) -- the invariant portion of the
operating system that performs system services such as managing disk
directories and files.
.leb;The Basic Input/Output System (BIOS) -- the variant portion of the
operating system that contains hardware-dependent input/output device
handlers.
.els
CP/M-68K is small, residing in about 24K bytes of memory. The exact size is
dependent on the size of the BIOS, which in turn is determined by the
number of peripheral devices in the system. Although it is compact, CP/M-68K
can give application programs the full advantage of the 68000 address space,
up to 16 megabytes (16,777,216 bytes) of main memory. CP/M-68K supports a
relocatable program file format to provide extensive compatibility among
different 68000 computers.
.bl 1
.c
CP/M and CP/M-86 Compatibility
.c
------------------------------
.bl 1
CP/M-68K files are completely compatible with CP/M Version 2.2 and CP/M-86
Version 1.1.
This simplifies conversions of CP/M and
CP/M-86 software to run on CP/M-68K.
.bl 1
The end user will notice no significant difference between CP/M-68K and
previous versions
of CP/M. Commands such as DIR, TYPE, PIP, STAT, and ED respond
the same way in both systems. The program interface is also unchanged --
CP/M-68K
calls for system services have the same function numbers as in CP/M and
CP/M-86.
.bl 1
It is easy to upgrade existing CP/M and CP/M-86 application software to run
under CP/M-68K, because CP/M-68K is so similar to its predecessors. Although
assembly language programs will require recoding, high-level language programs
will recompile with little or no modification.
.bl 1
.c
File Management
.c
---------------
.bl 1
CP/M-68K can support up to 16 logical drives, each containing up to 512
megabytes, for a maximum of 8 gigabytes of on-line storage. Any one file
can reach 32 megabytes, with space dynamically allocated and released. Each
device has a directory which maps each file's physical locations on the disk.
Disk definition tables in the BIOS translate this logical information to
the physical characteristics of the disk. This file system is identical to
the file system supported by CP/M 2 and CP/M-86.
.bl 1
.c
Development Tools
.c
-----------------
.bl 1
Digital Research offers a set of development tools for CP/M-68K
which can be run using CP/M-68K or on a
VAX-11 or PDP-11 computer under the UNIX or VMS operating systems. These
tools can be used to develop CP/M-68K applications or a custom CP/M-68K
BIOS.
The development tools include:
.ls
.leb;A C compiler and C runtime library compatible with UNIX (R) software.
.leb;An assembler, linker, and library utitilies.
.leb;A utility to convert CP/M-68K load modules to Motorola S-Record form.
.leb;A relocation utility to convert relocatable load modules to absolute
form.
.leb;A utility to list the symbol table contained in a load module file.
.leb;A utility which prints the memory size required by the load module.
.els
These tools are distributed at no extra charge
with CP/M-68K, and can be run on any
CP/M-68K system with at least 128K of memory.
.bl 1
.c
Customization
.c
-------------
.bl 1
For ease in transporting CP/M-68K to a specific hardware environment, all
hardware dependent code is located in one module, the BIOS (Basic Input/Output
System).
.bl 1
Digital Research ships CP/M-68K configured for the Motorola EXORmacs
development system. To bring up CP/M-68K on a different system, a custom
BIOS module must be developed. The custom BIOS must support a standard set
of I/O primitives on which the BDOS depends. These primitives include:
.nofill
.lm +5
.bl 1
o Console Status
o Console In
o Console Out
o List Out
o Select Drive
o Set Track
o Set Sector
o Read Sector
o Write Sector
o Return Memory Descriptor Table Address
.lm -5
.fill
.bl 1
To simplify the preparation of a custom BIOS, Digital Research supplies the
source code for a working BIOS and a skeleton source file for a customized
BIOS. Most of a customized BIOS may be written in the C language, to save
development time.
.bl 1
.c
Utilities
.c
---------
.bl 1
In addition to the development tools described previously, CP/M-68K is
supplied with a set of file management utilities:
.ls
.lec'PIP#'The Peripheral Interchange Program provides file transfer between
devices and disk files. Various reformatting and concatenation operations
may also be performed with PIP. These include: parity bit removal, case
conversion, subfile extraction, tab expansion, line number generation, and
pagination.
.lec'ED##'The CP/M-68K text editor allows creation and modification of ASCII
files using extensive commands: string substitution, string search, insert,
delete and block move. ED allows text to be located by context, line number,
or relative position. A macro command allows making extensive text changes
with a single command line.
.lec'DDT#'The CP/M-68K Dynamic Debugging Tool allows the user to test and
debug programs interactively in a CP/M-68K environment. The command set
allows users to trace program execution with a full register and status
display.
.lec'STAT'The STAT utility alters and displays I/O device and file status
including free space computations, status of online disk(ette)s and
physical-to-logical device assignment.
.lec'DUMP'The DUMP utility displays any file with a side-by-side hexadecimal
and ASCII format. Output may be redirected to a file or the listing device
if desired.
.els
.c
Hardware Requirements
.c
---------------------
.bl 1
The version of CP/M-68K that Digital Research ships and supports requires
a Motorola EXORmacs with a Motorola Universal Disk Controller. CP/M-68K
may be reconfigured for a custom hardware environment using the development
tools supplied with the system. Custom hardware environments must include:
.bl 1
.nofill
.lm +5
o A Motorola 68000, 68008, or 68010 CPU.
o At least 64K of RAM.
o One to 16 disk drives of up to 512 megabytes each.
o An ASCII console Device such as a CRT.
.lm -5
.fill
.bl 1
.c
Ordering Information
.c
--------------------
.bl 1
CP/M-68K is shipped on four 8-inch single-sided single density diskettes.
There are two CP/M-68K products available from Digital Research:
.ls
.leb;The CP/M-68K single user
system, consisting of the four diskettes plus CP/M-68K
documentation.
.leb;CP/M-68K documentation only, consisting of four manuals:
.bl 1
.nofill
.lm +5
o The CP/M-68K User's Guide
o The CP/M-68K Programmer's Guide
o The CP/M-68K System Guide
o The CP/M-68K C Language Manual
.fill
.lm -5
.els

View File

@@ -0,0 +1,35 @@
Patch to CP/M-68K (tm) C Run-time Library
The initial shipments of CP/M-68K had a problem in writing Ascii
files using the C run-time library. The patch described below
fixes the problem.
A>AR68 X CLIB WRITE.O (extract module WRITE.O from library CLIB)
A>DDT
-RWRITE.O (read file WRITE.O into memory)
start xxxxxxxx end yyyyyyyy
-Hxxxxxxxx,164 (xxxxxxxx is the start in memory of the file)
zzzzzzzz wwwwwwww (zzzzzzzz is the sum of 164H and xxxxxxxx)
-Dzzzzzzzz (display memory at zzzzzzzz)
zzzzzzzz: 67 18 33 FC ... (memory contents)
...
...
-Szzzzzzzz
zzzzzzzz 67 60 (change byte from 67 to 60)
uuuuuuuu 18 . (display next byte -- don't change)
-WWRITE.O (write out changed file)
-^C (Control-C to exit DDT)
A>AR68 RV CLIB WRITE.O (Replace module WRITE.O in library CLIB)
... (Archiver types confirmation messages)
A>ERA WRITE.O
The effect of the above sequence is to replace one byte in the run-time
library. The byte changed is at offset 164H in object module WRITE.O,
from 67H to 60H.

View File

@@ -0,0 +1,123 @@
OEM REDISTRIBUTION GUIDE FOR CP/M-68K(tm)
OVERVIEW
This document describes how to redistribute CP/M-68K. The
CP/M-68K operating system is distributed by Digital Research as a
set of five 8" diskettes which contain the files which the end
user will receive. A sixth diskette contains a serializer pro
gram and several related files. To generate an end user copy of
CP/M-68K, the contents of the first five diskettes should be
copied to appropriate media, then serialized. In addition, the
media shipped to an end user should contain a CPM.SYS file which
has been configured for the end user's hardware, and should be
bootstrappable on the target hardware. Configuring CP/M-68K for
particular hardware is discussed in the CP/M-68K Operating System
System Guide.
COPYING CP/M-68K
The procedure for copying CP/M-68K may vary depending upon
the media which are to be distributed to the end user. Normally,
CP/M-68K will be distributed to end users on a set of disks
compatible with the target computer. These disks may be copied
from a set of masters using the COPY utility program (described
in the CP/M-68K Operating System User's Guide.) Once the copy
has been done, the disks must be serialized using the serializer
program supplied with the OEM kit. The serialized copies may
then be shipped to end users.
USING THE SERIALIZER
The serializer program is named SERIAL.REL. It may be
relocated using RELOC (see Programmer's Guide) or renamed to
SERIAL.68K. The serializer is invoked by a command line of the
form:
A>SERIAL start end
where 'start' is the first serial number to be used, and 'end' is
the last serial number to be used. The serializer will serialize
a set of disks. The first disk serialized will have 'start' as
its serial number, the second disk will have 'start' + 1 as its
serial number, ... the last disk will have 'end' as its serial
number. The serializer expects to find a file named 'SERIAL.DAT'
on the default drive. This file contains a list of the files
which must be serialized. After the serializer has been invoked,
it will prompt you for the drive letter on which the disk to be
serialized is mounted. Then, for each disk to be serialized, the
serializer will prompt you to insert the disk into the drive. As
each file is serialized, the serializer will indicate the file
being serialized and whether or not the serialization was com
plete. The completion message will include an integer whose
value varies according to which file is being serialized.
The serializer disk contains several files in addition to
the serializer program proper. There are five submit files,
named SERIAL1.SUB, SERIAL2.SUB, ... , SERIAL5.SUB, which can be
executed to serialize user disks one to five respectively. Each
submit file takes two parameters: the first and last serial
numbers to be used in serializing the disk in question. There
are also five data files, named SERIAL1.DAT, ... , SERIAL5.DAT
which list the files to serialize on user disk 1, user disk 2,
etc. All the files named in the SERIALx.DAT files MUST be
serialized. If you reorganize the way the files are placed on
the disks for shipment, you will need to create new SERIAL.DAT
files.
CP/M-68K is a trademark of Digital Research.

View File

@@ -0,0 +1,63 @@
CP/M-68K (tm) Operating System Release Notes
February 17, 1983
S-RECORD SYSTEMS
Either of the two S-record versions of CP/M-68K included in
this release may be combined with a user-supplied BIOS in order
to obtain a working CP/M-68K operating system as discussed in the
System Guide. In addition to the information given there, you
need to know the size and entry points of the S-record systems.
The two S-record system files are discussed separately in the
following paragraphs.
SR400.SYS resides in memory locations 400H to 5D43H. You
should patch it by placing the 32-bit address of your BIOS's
_init entry point at memory locations 4F42H to 4F45H. Your BIOS
can Warm Boot by jumping to 4F46H.
SR128K.SYS resides in memory locations 15000H to 1A943H.
You should patch it by placing the 32-bit address of your BIOS's
_init entry point at memory locations 19B42H to 19B45H. Your
BIOS can Warm Boot by jumping to 19B46H.
BUGS
o The CPM.SYS file on disk 2 of the distribution system was
intended to work with a floppy disk EXORmacs(tm) system. In
fact, it does not.
o AS68 will not operate properly when the disk it is using is
full.
o If you have trouble with AS68, it is likely that you did
not initialize it. See the Programmer's Guide for
more information.
o DDT sets up an incorrect command tail when the program under
test is specified on the CCP command line invoking DDT rather
than using the E and I commands in DDT.
CP/M-68K is a trademark of Digital Research.
EXORmacs is a trademark of Motorola.

View File

@@ -0,0 +1,452 @@
CP/M-68K RSX IMPLEMENTATION ON CP/M-68K V1.0
==============================
A resident system extension under CP/M-68K consists of a block
of memory permanently set aside to hold a program and an executable,
relocatable program which can be accessed via a trap call. The RSX may reside
anywhere outside the TPA(transient program area) and CP/M itself. This
block of memory is created by use of the BDOS call: Get/Set TPA limits.
The current boundries of the TPA are re-defined to leave a section of
memory available to permanently hold the RSX. Here is a typical memory
model with an existing RSX.
-------------------------------------------------
| |
| BIOS |
| |
-------------------------------------------------
| |
| BDOS |
| |
-------------------------------------------------
| |
| CCP |
| |
Old Top of -------------------------------------------------
TPA | |
| RSX |
| |
New Top of -------------------------------------------------
TPA | |
| |
| |
| |
| |
| |
| TPA |
| |
| |
| |
| |
| |
| |
Base of TPA -------------------------------------------------
| |
| Reserved for CP/M-68K |
| |
-------------------------------------------------
CP/M-68K RSX IMPLEMENTATION ON CP/M-68K V1.0
==============================
The bdos program load function is used to load the RSX program into
memory. The set exception vector function should then be used to reset a
trap vector address to the beginning of the RSX. All access to the RSX
should be done via a trap call. This type of access will allow the RSX to
operate in supervisor mode. Return from the RSX is then accomplished by
using the RTE instruction. To eliminate the RSX,use the Get/Set TPA limits
function to re-define the TPA to its original configuration. Reset the trap
vector address to its orginal value. The following is an example of a
transient program that loads other transient programs as RSX's,reconfigures
the TPA,and passes control to the new RSX for initialization. The RSX
initialization should set an exception vector address to the beginning of
the desired code segment in the RSX,and pass control back to the rsx loader
via an RTS(return from subroutine) instruction. The RSX is now accessable via
a trap call. The rsx loader can load other RSX's right below the existing RSX.
The command:
A>rsx $
will cause the rsx loader to reset the TPA boundries to their coldboot values
as specified in the BIOS. The RSX should also have a mechanism for reseting
the modified trap vector to its coldboot value.
*************************************************************************
* rsx.s Link to LOADRSX.C v1.0 *
* ================= *
* *
* Assembly Language Module Needed to *
* Assist 'C' code to Load a Program as an RSX *
* *
*************************************************************************
*
* Make All these labels GLOBAL
*
.globl _bdos
.globl _push
.globl _main
.globl _reset
.globl _openfile
.globl _prt_tpa
.globl stack
*
* Load Parameter Block Labels
* ---------------------------
.globl _LPB
.globl _lowadr
.globl _hiadr
.globl _baspag
.globl _usrstk
.globl _flags
*
* TPA Parameter Block Labels
* --------------------------
.globl _TPAB
.globl _low
.globl _high
prtstr = 9
getmemtb = 18
settpa = 63
*
* Try to open 1st parsed FCB
* --------------------------
start: link a6,#0 *link and allocate
move.l 8(a6),a0 *get basepage address
move.l #stack,a7 *set up my own stack
move.l a7,a6 *set up a6
lea $5c(a0),a1 *get 1st parsed fcb address
move.l a1,-(sp) *push fcb address
jsr _openfile *jump to open file routine
add.l #4,sp *clean off the stack
jsr _main *go to main routine
clr.l d0 *prepare to exit program
trap #2 *warmboot and return to CCP
*
*
* Push the needed addresses on to the stack
* -----------------------------------------
*
_push:
movea.l _usrstk,a7 *set up the user stack pointer
move.l _baspag,a1 *get address of user basepage
move.l a1,-(sp) *push basepage address
move.l #wboot,-(sp) *push return address
move.l 8(a1),-(sp) *push address to jump to
rts *jump to new program
*
* Call the BDOS
* -------------
_bdos:
move.w 4(sp),d0 *get the BDOS function number
move.l 6(sp),d1 *get the BDOS parameter
trap #2 *call the BDOS
rts *return to calling code
*
* Reset CP/M-68K TPA limits to original values
* --------------------------------------------
_reset:
move.l #getmemtb,d0 *bios get memory region table
trap #3 *call the bios
add.l #$2,d0 *skip the count
move.l d0,a0 *a0 now points to tpa low address
move.l (a0)+,_low *put that address in TPAB
move.l (a0),d2 *get length of tpa
add.l _low,d2 *calculate top of tpa
move.l d2,_high *put that address in TPAB
move.w #$FF,_TPAB *make this permanent
move.w #settpa,d0 *bdos function # for set tpa limits
move.l #_TPAB,d1 *d1 gets address of TPAB
trap #2 *call the bdos
move.w #prtstr,d0 *bdos function # to print a string
move.l #mesg,d1 *get address of string into d1
trap #2 *print message by calling bdos
move.l #0,-(sp) *push a FALSE value
jsr _prt_tpa *print TPA boundries
wboot:
clr.l d0 *prepare to warmboot
trap #2 *call the bdos
*
* DATA
*
.data
.even
*
* Load Parameter Block
*
_LPB: .ds.l 1
_lowadr: .ds.l 1
_hiadr: .ds.l 1
_baspag: .ds.l 1
_usrstk: .ds.l 1
_flags: .dc.w 0
*
* TPA Parameter Block
*
.even
_TPAB: .dc.w 0
_low: .ds.l 1
_high: .ds.l 1
.even
mesg: .dc.b 13,10,'TPA limits reset to COLDBOOT values:$'
.bss
.even
.ds.l 200
stack: .ds.w 1
*
* END of Assembly Language Code
*
.end
/*----------------------------------------------------------------------*\
| loadrsx.c LOAD A RESIDENT SYSTEM EXTENSION v1.0 |
| ================================ |
| |
| Description: |
| ----------- This program loads a CP/M-68K executable |
| program into high memory and reconfigures |
| the TPA. The loaded program is now a |
| Resident System Extension. Control is |
| passed to the RSX so it can do its |
| own initialization. |
| |
| Created by: Tom Saulpaugh |
| ---------- |
| Date: 11/29/82 |
| ---- |
| Last Modified: 12/01/82 |
| ------------- |
| |
| Include Files: <Stdio.h> <Portab.h> |
| ------------- |
| Link to: rsx.s |
| ------- |
| |
\*----------------------------------------------------------------------*/
/************************************************************************\
* Here are the Include Files *
\************************************************************************/
/********************************/
#include "stdio.h" /* Standard I/O library */
/********************************/
/************************************************************************\
* DEFINES for Loadrsx.c *
\************************************************************************/
/********************************/
#define CON_OUT 2 /* Bdos console output func # */
#define PRINT_STRING 9 /* Bdos print string func # */
#define OPENFILE 15 /* Bdos open file function # */
#define CLOSE_FILE 16 /* Bdos close file funciton # */
#define READSEQ 20 /* Bdos read seq function # */
#define SETDMA 26 /* Bdos set dma address func # */
#define LOAD_PROG 59 /* Bdos load program func # */
#define SET_TPA 63 /* Bdos set tpa limits func # */
#define GET_TPA 63 /* Bdos get tap limits func # */
#define CR (long)13/* Carriage Return */
#define LF (long)10/* Linefeed character */
#define DMA_OFFSET (long)0x80/* Default dma buffer offset */
#define NULLB '\0' /* Null Byte */
/********************************/
#define isupper(c) ('A' <= (c) && (c) <= 'Z')/*upper case */
#define islower(c) ('a' <= (c) && (c) <= 'z')/*lower case */
#define tolower(c) (isupper(c) ? ((c)+040):(c))/*ltrans */
#define toupper(c) (islower(c) ? ((c)-040):(c))/*utrans */
/********************************/
/************************************************************************\
* GLOBAL Variables *
\************************************************************************/
/********************************/
BYTE open = FALSE; /* Rsx file open flag */
BYTE rsxfcb[36]; /* Fcb for rsx */
BYTE buf[128]; /* buffer to hold rsx header */
BYTE *msg1 = "RSXloader Ver 1.1$"; /* Version Number message */
BYTE *msg2 = "Unable to open file$"; /* Could not open rsx on disk */
BYTE *msg3 = "Size of RSX computed$"; /* Status message to user */
BYTE *msg4 = "Unable to Load RSX$"; /* Program load error message */
BYTE *msg5 = "Current TPA Boundries:$"; /* Status of Current TPA size */
BYTE *msg6 = "New TPA Boundries:$"; /* Status after loading of RSX */
BYTE *msg7 = "Starting Address----> $"; /* Start of TPA message */
BYTE *msg8 = " Ending Address+1----> $";/* End of TPA message */
EXTERN LONG LPB,lowadr,hiadr,baspag, /* Load Parameter block */
usrstk; /* -------------------- */
EXTERN UWORD flags; /* -------------------- */
EXTERN UWORD TPAB; /* TPA Parameter Block */
EXTERN LONG low,high; /* ------------------- */
/********************************/
/************************************************************************\
* External Procedures *
\************************************************************************/
/********************************/
EXTERN UWORD bdos(); /* Calls the bdos */
/********************************/
/************************************************************************/
cr_lf()
{
bdos(CON_OUT,CR);
bdos(CON_OUT,LF);
}
illegal(fcb)
BYTE *fcb;
{
REG UWORD i;
if(*++fcb == '$')
reset();
i = 1;
while(i++ <= 11)
if(*fcb++ == '?')
return(TRUE);
return(FALSE);
}
openfile(fcb)
BYTE *fcb;
{
REG BYTE *ptr;
REG UWORD i;
if(!(illegal(fcb)))
{
if(bdos(OPENFILE,fcb) <= 3)
open = TRUE;
else
{
ptr = (long)0;
ptr = (long)(0x9 + fcb);
if(*ptr == ' ')
{
*ptr++ = '6';
*ptr++ = '8';
*ptr = 'K';
}
if(bdos(OPENFILE,fcb) <= 3)
open = TRUE;
}
if(open)
{
ptr = rsxfcb;
for(i = 0;i < 36;i++)
*ptr++ = *fcb++;
}
}
}
prtnum(num)
LONG num;
{
if(num)
{
prtnum(num/10);
bdos(CON_OUT,('0' + (num%10)));
}
}
prt_tpa(new)
BYTE new;
{
BYTE *p;
if(!(new))
p = msg5;
else
p = msg6;
cr_lf();
bdos(PRINT_STRING,p);
cr_lf();
cr_lf();
bdos(PRINT_STRING,msg7);
if(low == 0)
bdos(CON_OUT,'0');
else
prtnum(low);
bdos(PRINT_STRING,msg8);
if(high == 0)
bdos(CON_OUT,'0');
else
prtnum(high);
cr_lf();
}
main()
{
REG LONG *p1,size;
REG UWORD i;
bdos(PRINT_STRING,msg1);
cr_lf();
if(open)
{
bdos(SETDMA,buf);
bdos(READSEQ,rsxfcb);
size = 0;
p1 = &buf[2];
for(i = 0;i <= 3;i++)
size += *p1++;
size += 2048;
bdos(GET_TPA,&TPAB);
prt_tpa(FALSE);
bdos(CLOSE_FILE,rsxfcb);
for(i = 12;i < 36;i++)
rsxfcb[i] = NULLB;
bdos(OPENFILE,rsxfcb);
LPB = rsxfcb;
lowadr = high - size;
hiadr = high;
if(bdos(LOAD_PROG,&LPB) == 0)
{
high = high - size;
TPAB = 0xFF;
bdos(SET_TPA,&TPAB);
prt_tpa(TRUE);
bdos(SETDMA,(baspag + DMA_OFFSET));
push();
}
else
bdos(PRINT_STRING,msg4);
}
else
bdos(PRINT_STRING,msg2);
}

View File

@@ -0,0 +1,10 @@
#define strlen(x) aclenf(x)
#define VOID int
#define MLOCAL static
#define LOCAL auto
#define BYTE char
#define WORD short
#define LONG long
#define EXTERN extern
#define DOUBLE double
#define REG register

View File

@@ -0,0 +1,343 @@
.tab stops 8,16,24,32,40,48,56,64,72,80
.number chapter 3
.right margin 65
.fill
.chapter C Style Guide
.subtitle Disclaimer
.page
.c
Disclaimer
.c
----------
.bl 1
This document is intended to make C code under CP/M more portable and
more maintainable. There are some hard and fast rules which must be followed
to acheive these objectives. Rules, however, should not be used as
substitutes for rational thought. From time to time, there will be situations
which call for bending or breaking of the rules.
The rules should be modified as necessary in these situations.
.bl 1
This manual is not a tutorial on either the C programming language or
on the software engineering discipline. The reader is assumed to be a
professional programmer with some knowledge of the C language. We will deal
primarily with aspects of the C language as they relate to a software
engineering environment.
.subtitle Goals
.hl 1 Goals
The goals of this document fall into three areas: Portability,
Maintainability, and Readability.
.hl 2 Portability
Software written in C should be easily transported from machine to machine
without conversion. Unfortunately, due to the differences in compilers and
machines, it is possible to write C code which is hopelessly tied to a given
machine or compiler.
.bl 1
The guidelines presented here are intended to help the novice (and
experienced!) C programmer from falling into the pitfalls that exist.
We will also present ways in which efficiency may be gained using the
C constructs.
.hl 2 Maintainability
Portable software tends to have a long lifespan. The author has seen
programs written in COBOL in 1964, for instance, which underwent their
third conversion to different hardware in 1979, and are still being used
today.
.bl 1
Maintenance accounts for as much as 80% of software expenditures in some
companies. The microprocessor community is waking up to the need for more
maintainable software as old products mature and require revamping. Consider
the cost to applications software houses, for instance, to recode payroll
programs to account for the 81-83 income tax cuts. Consider again that
Congress tried to repeal the 83 tax cut, and it becomes obvious that
programs must be written in a maintainable manner.
.bl 1
This document will present guidelines which will enhance maintainability.
A great deal of maintenance
efficiency can be gained just from having all programs
written in the same style.
.hl 2 Readability
It is often said that software source code has two classes of readers:
humans and machines. The hardware / software cost ratio is approaching the
point at which the emphasis in writing software must be on the human
audience rather than the machine audience.
.subtitle Modularity
.hl 1 Modularity
Properly modular programs can go a long way in reducing porting and
maintenance costs. Programs should be modularized such that all the routines
which perform a given function (say symbol table management) are grouped
into a single module. This has two benefits: the maintenance programmer
is allowed to treated most modules as "black boxes" for modification
purposes, and the nature of data structures is "hidden" from the
rest of the program. In a properly modular program, it should be possible
to completely revamp any major data structure with changes to only one
module.
.hl 2 Module Size
Conventional software engineering wisdom states that 500 lines is a good
maximum size for modules. Perhaps a more reasonable limitation is that a
module should be as big as necessary to perform a given function AND NO
BIGGER.
.hl 2 Inter-Module Communication
Modules should communicate via procedure calls wherever possible. Global
data areas should be avoided where possible. Where one or more compilations
requires the same data structure, a header file should be used.
.hl 2 Header Files
Header files are used for files which are compiled separately, to define
types, symbolic constants, and data structures in exactly the same fashion
for all modules.
.bl 1
Some specific rules for using header files are as follows:
.ls
.leb;Use the '_#include "file.h"' format
for header files which are project-specific.
Use '_#include <file.h>' for system-wide files. NEVER hard-code device and/or
filenames in an include statement.
.leb;Do not nest include files.
.leb;Do not define variables (other than global data references) in a header
file. NEVER initialize a global variable in a header file.
.leb;In writing macro definitions, include parenthesis around each use of
the parameters, to avoid possible precedence mixups.
.els
.subtitle Mandatory Coding Conventions
.hl 1 Mandatory Coding Conventions
Following is a list of practices which MUST be followed to preserve program
portability. Specific items which these conventions are targeted to prevent
are:
.ls
.leb;The length of a C 'int' variable varies from machine to machine. This
leads to representation problems, and to problems with binary I/O involving
'int' quantities.
.leb;The byte order of multi-byte binary variables differs from machine to
machine. This leads to problems if a binary variable is ever viewed as
a byte stream by any piece of code.
.leb;Naming conventions and the maximum length of identifiers differ from
machine to machine. Upper case / lower case distinction is not always
present.
.leb;Character and short variables are sign-extended to 'int' by some
compilers during arithmetic operations. Some compilers don't do this.
.leb;The data length of constants is a problem; Some compilers view a
hex or octal constant as an 'unsigned int', some do not. In particular,
the following sequence does not always work as expected:
.bl 1
.lm +5
.nofill
LONG data;
.
.
.
printf("%ld_\n",(data _& 0xffff));
.bl 1
.fill
.lm -5
The purpose of the "printf" statement is to print the lower 16 bits of the
long data item "data". However, some compilers SIGN EXTEND the hex constant
"0xffff" (!).
.leb;One must be careful of evaluation order dependencies, particularly in
compound BOOLEAN conditions.
.els
In addition, much grief can be avoided simply by having everyone use the
same coding style.
.hl 2 Variable and constant names
Local variable names should be unique in 8 characters. Global variable
names and procedure names should be unique in 6 characters. All variable
and procedure names should be completely lower case.
.bl 1
Names defined via a "_#define" statement should normally be entirely upper
case. The only exceptions are functions which are defined as macros; e.g.,
"getc", "isascii", etc. These names should also be unique in 8 characters.
.bl 1
Global names should not be redefined as local variables within a procedure.
.hl 2 Variable Typing
Due to the differences in C compiler standard type definitions, using these
standard types is unsafe in programs which are designed to be portable. A
set of types and storage classes
defined via "typedef" or "_#define" must be used instead:
.bl 1
.test page 20
.lm 8
.nofill
Type C Base Type
---- -----------
LONG signed long (32 bits)
WORD signed short (16 bits)
UWORD unsigned short (16 bits)
BOOLEAN short (16 bits)
BYTE signed char ( 8 bits)
UBYTE unsigned char ( 8 bits)
VOID void (function return)
DEFAULT int (16/32 bits)
.bl 1
Class C Base Class
----- ------------
REG register variable
LOCAL auto variable
MLOCAL Module static variable
GLOBAL Global variable definition
EXTERN Global variable reference
.bl 1
.lm 0
.fill
In addition, global variables must be declared at the beginning of the
module. Local variables must be defined at the beginning of the function
in which they are used. The storage class and type must always be specified,
even though the C language does not require this.
.hl 2 Expressions and Constants
All expressions and constants should be written in an implementation
independent manner. Parenthesis must be used to remove any possible
ambiguities. In particular, the construct:
.bl 1
.i 5
if(c = getchar() == '_\n')
.bl 1
does NOT assign the value returned by "getchar" to c. Rather, the value
returned by "getchar" is compared to '_\n', and c receives the value 0 or
1 (the true / false output of the comparison). The value returned by
"getchar" is lost. Parenthesizing the assignment:
.bl 1
.i 5
if((c = getchar()) == '_\n')
.bl 1
fixes the problem.
.bl 1
Constants used for masking should be written in a way such that the underlying
'int' size is irrelevant. In the 'printf' example used previously, specifying
.bl 1
.i 5
printf("%ld_\n",(data _& 0xffffL);
.bl 1
(a long masking constant), fixes the problem for all compilers. Specifying
the "one's complement" often yields this effect: "_~0xff" instead of
"0xff00".
.bl 1
Character constants should consist of a single character for portability.
Multi-character constants must be placed in string variables.
.bl 1
Commas used to separate arguments in functions are not operators. Evaluation
order is not guaranteed. In particular, function calls like:
.bl 1
.i 5
printf("%d %d_\n",i++,i++);
.bl 1
may perform differently on different machines.
.hl 2 Pointer Arithmetic
Pointers should never be manipulated as 'int's or other arithmetic variables.
C allows the addition / subtraction of an integer to / from a pointer
variable. No logical operations (e.g. ANDing or ORing) should be attempted
on pointers.
A pointer to one type of object may be converted to a pointer to another
(smaller size) data type with complete generality. Conversion in the
reverse direction may yield alignment problems.
.bl 1
Pointers may be tested for equality with other pointer variables and constants
(notably NULL). Arithmetic comparisons (e.g., ">=") will not work on all
compilers and can generate machine dependent code.
.bl 1
In evaluating the size of a data structure, bear in mind that the compiler
may leave holes in a data structure to allow for proper alignment. ALWAYS
use the "sizeof" operator.
.hl 2 String Constants
Strings must be allocated in such a way as to facilitate foreign language
conversions. The preferred method is to use an array of pointers to constant
strings which is initialized in a separate file. Each string reference
would then reference the proper element of the pointer array.
.bl 1
NEVER modify a specific location in a constant string, e.g.:
.bl 1
.nofill
BYTE string_[_] = "BDOS Error On x:"
.
.
.
string[14] = 'A';
.bl 1
.fill
Foreign language equivalents are likely to be longer or shorter than the
English version of the message.
.bl 1
Never use the high-order bit of an ASCII string for bit flags, etc. Extended
character sets make extensive use of the characters above 0x7F.
.hl 2 Data and BSS Sections
.bl 1
Normally, C programs have three sections, ".text" (program instructions),
".data" (Initialized data), and ".bss" (uninitialized data). Modification of
initialized data is to be avoided if at all possible. Programs which do not
modify the ".data" segment can aid the swapping performance and disk
utilization of a multi-user system. Also, if a program does not modify the
".data" segment, the program can be placed in ROM with no conversion.
.bl 1
This means that the program should not modify static variables which are
initialized. Modification of initialized automatic variables
is not subject
to this restriction.
.hl 2 Module Layout
The layout of a module (compilation unit) should follow this basic general
organization:
.ls
.le;A comment
paragraph or two at the very beginning of the file which describe:
.ls
.la;The purpose of the module.
.la;The major (which should be the only) entry points to the module from
the outside world.
.la;Any global data areas required by the module.
.la;Any machine or compiler dependencies.
.els
.le;Include file statements.
.le;Module-specific "_#define" statements.
.le;Global variable references and definitions. Each variable should have
a comment which describes the variable's purpose.
.le;Procedure definitions. Each procedure definition should contain:
.ls
.la;A comment paragraph which describes the procedure's function,
input parameters, and return parameters. Any unusual coding techniques
should be mentioned here.
.la;The procedure header. The procedure return type MUST be explicitly
specified. Use VOID when no value is returned.
.la;Argument definitions. All arguments MUST have the storage class and
variable type EXPLICITLY declared.
.la;Local variable definitions. All local variables must be defined
before any executable code. Storage class and variable type MUST be
explicitly declared.
.la;Procedure Code.
.els
.els
Refer to "Appendix A" for a sample program.
.subtitle Suggested Coding Conventions
.hl 1 Suggested Coding Conventions
The following recommendations are actually personal prejudices of the author,
and not strictly required for program portability and maintenance.
.ls
.le;Keep source code within 80 character margins, for easier screen editing.
.le;Use a standard indention technique. The suggested standard is:
.ls
.la;Statements within a procedure should begin one tab stop (column 8)
from the left margin.
.la;Statements controlled by an "if", "else", "while", "for", or "do"
should be indented one tab stop. If multiple nested indentions are required,
use 2 spaces for each nesting level. Avoid going more than 5 levels deep.
.la;The bracket characters surrounding each compound statement should
appear on a separate line, using the indention level of the controlling
statement. For instance:
.bl 1
.lm +8
.test page 9
.nofill
for(i=0;i<MAXNUM;i++)
_{
j = compute(i);
if (j > UPPER)
j = UPPER;
output(j);
_}
.bl 1
.lm -8
.fill
.la;A null statement controlled by a "for", "while", etc. should be
placed on a separate, indented line for readability purposes.
.els
.le;Use plenty of comments, particularly for code which must be obtuse. (If
code need not be obtuse, don't make it that way). There is no such thing
as "self-documenting code". This is just wishful thinking on the part of
language designers.
.le;Put all the maintenance documentation in the source code itself. This is
the only way it has any prayer of being updated when the code is changed.
.le;Use blank lines, form feeds, etc. to improve readability.
.els

View File

@@ -0,0 +1,8 @@
main()
{
long a;
int b;
char x;
register y;
b = blivot(x,a);
}

View File

@@ -0,0 +1,428 @@
/****************************************************************************/
/* */
/* _ P r i n t f M o d u l e */
/* --------------------------- */
/* */
/* This module is called through the single entry point "_printf" to */
/* perform the conversions and output for the library functions: */
/* */
/* printf - Formatted print to standard output */
/* fprintf - Formatted print to stream file */
/* sprintf - Formatted print to string */
/* */
/* The calling routines are logically a part of this module, but are */
/* compiled separately to save space in the user's program when only */
/* one of the library routines is used. */
/* */
/* The following routines are present: */
/* */
/* _printf Internal printf conversion / output */
/* _prnt8 Octal conversion routine */
/* _prntx Hex conversion routine */
/* __conv Decimal ASCII to binary routine */
/* _putstr Output character to string routine */
/* _prnt1 Decimal conversion routine */
/* */
/* The following routines are called: */
/* */
/* strlen Compute length of a string */
/* putc Stream output routine */
/* ftoa Floating point output conversion routine */
/* */
/* */
/* This routine depends on the fact that the argument list is always */
/* composed of LONG data items. */
/* */
/* Configured for Whitesmith's C on VAX. "putc" arguments are */
/* reversed from UNIX. */
/* */
/****************************************************************************/
/*
* Include files:
*/
#include <stdio.h> /* just the standard stuff */
/*
* Local DEFINEs
*/
#define HIBIT 31 /* High bit number of LONG */
/*
* Local static data:
*/ /****************************/
MLOCAL BYTE *_ptrbf = 0; /* Buffer Pointer */
MLOCAL BYTE *_ptrst = 0; /* -> File/string (if any) */
MLOCAL BYTE *__fmt = 0; /* Format Pointer */
/****************************/
/*****************************************************************************
*
* P R I N T F I N T E R N A L R O U T I N E
* ---------------------------------------------
*
* Routine "_printf" is used to handle all "printf" functions, including
* "sprintf", and "fprintf".
*
* Calling Sequence:
*
* _printf(fd,func,fmt,arg1);
*
* Where:
*
* fd Is the file or string pointer.
* func Is the function to handle output.
* fmt Is the address of the format string.
* arg1 Is the address of the first arg.
*
*
* Returns:
*
* Number of characters output
*
* Bugs:
*
* It is assumed that args are contiguous starting at "arg1", and that
* all are the same size (LONG), except for floating point.
*
*
*****************************************************************************/
_printf(fd,f,fmt,a1) /****************************/
LONG fd; /* Not really, but ... */
LONG (*f)(); /* Function pointer */
BYTE *fmt; /* -> Format string */
LONG *a1; /* -> Arg list */
{ /****************************/
LOCAL BYTE c; /* Format character temp */
LOCAL BYTE *s; /* Output string pointer */
LOCAL BYTE adj; /* Right/left adjust flag */
LOCAL BYTE buf[30]; /* Temporary buffer */
/****************************/
LOCAL LONG *adx; /* Arg Address temporary */
LOCAL LONG x; /* Arg Value temporary */
LOCAL LONG n; /* String Length Temp */
LOCAL LONG m; /* Field Length Temporary */
LOCAL LONG width; /* Field width */
LOCAL LONG prec; /* Precision for "%x.yf" */
LOCAL LONG padchar; /* '0' or ' ' (padding) */
LOCAL DOUBLE zz; /* Floating temporary */
LOCAL DOUBLE *dblptr; /* Floating temp. address */
LOCAL LONG ccount; /* Character count */
EXTERN _putstr(); /* Reference function */
/***************************/
/***************************/
ccount = 0; /* Initially no characters */
_ptrbf = buf; /* Set buffer pointer */
adx = a1; /* Copy address variable */
_ptrst = fd; /* Copy file descriptor */
__fmt = fmt; /* Copy format address */
/***************************/
if(*__fmt == 'L' || *__fmt == 'l') /* Skip long output */
__fmt++; /* conversions */
/* */
/************************************************* */
/* This is the main format conversion loop. Load a character from the */
/* format string. If the character is '%', perform the appropriate */
/* conversion. Otherwise, just output the character. */
/************************************************* */
/* */
while( c = *__fmt++ ) /* Pick up next format char*/
{ /* */
if(c != '%') /***************************/
{ /* */
(*f)(fd,c); /* If not '%', just output */
ccount++; /* Bump character count */
} /***************************/
else /* It is a '%', */
{ /* convert */
x = *adx++; /* x = address of next arg */
/***************************/
if( *__fmt == '-' ) /* Check for left adjust */
{ /***************************/
adj = 'l'; /* Is left, set flag */
__fmt++; /* Bump format pointer */
} /* */
else /* Right adjust */
adj = 'r'; /***************************/
/* */
padchar=(*__fmt=='0') ? '0' : ' '; /* Select Pad character */
/***************************/
width = __conv(); /* Convert width (if any) */
/***************************/
if( *__fmt == '.') /* '.' means precision spec*/
{ /* */
++__fmt; /* Bump past '.' */
prec = __conv(); /* Convert precision spec */
} /* */
else /* None specified */
prec = 0; /***************************/
/* */
s = 0; /* Assume no output string */
switch ( c = *__fmt++ ) /* Next char is conversion */
{ /* */
case 'D': /* Decimal */
case 'd': /* */
_prt1(x); /* Call decimal print rtn */
break; /* Go do output */
/***************************/
case 'o': /* Octal */
case 'O': /* Print */
_prnt8(x); /* Call octal printer */
break; /* Go do output */
/***************************/
case 'x': /* Hex */
case 'X': /* Print */
_prntx(x); /* Call conversion routine */
break; /* Go do output */
/***************************/
case 'S': /* String */
case 's': /* Output? */
s=x; /* Yes, (easy) */
break; /* Go finish up */
/***************************/
case 'C': /* Character */
case 'c': /* Output? */
*_ptrbf++ = x&0377; /* Just load buffer */
break; /* Go output */
/***************************/
case 'E': /* Floating point? */
case 'e': /* */
case 'F': /* */
case 'f': /* */
dblptr = adx-1; /* Assumes 64 bit float! */
zz = *dblptr; /* Load value */
adx =+ 1; /* Bump past second word */
ftoa (zz, buf, prec, c); /* Call floating conversion*/
prec = 0; /* Fake out padding routine*/
s = buf; /* just like string print */
break; /* Go Output */
/***************************/
default: /* None of the above? */
(*f)(fd,c); /* Just Output */
ccount++; /* Count it. */
adx--; /* Fix arg address */
} /* End switch */
/***************************/
if (s == 0) /* If s = 0, string is in */
{ /* "buf", */
*_ptrbf = '\0'; /* Insure termination */
s = buf; /* Load address */
} /***************************/
/* */
n = strlen (s); /* Compute converted length*/
n = (prec<n && prec != 0) ? prec : n;/* Take min(prec,n) */
m = width-n; /* m is # of pad characters*/
/***************************/
if (adj == 'r') /* For right adjust, */
while (m-- > 0) /* Pad in front */
{ /* */
(*f)(fd,padchar); /* Thusly */
ccount++; /* Count it */
} /* */
/***************************/
while (n--) /* Output Converted */
{ /* */
(*f)(fd,*s++); /* Data */
ccount++; /* Count it */
} /* */
/***************************/
while (m-- > 0) /* If left adjust, */
{ /* */
(*f)(fd,padchar); /* Pad */
ccount++; /* Count padded characters */
} /***************************/
_ptrbf = buf; /* Reset buffer pointer */
} /* End else */
} /* End while */
if((*f) == _putstr) /* If string output, */
(*f)(fd,'\0'); /* Drop in terminator char */
/***************************/
return(ccount); /* Return appropriate value*/
} /* End _printf */
/***************************/
/****************************************************************************/
/* */
/* _ P R N T 8 P R O C E D U R E */
/* ------------------------------- */
/* */
/* Routine "_prnt8" converts a binary LONG value to octal ascii. */
/* The area at "_ptrbf" is used. */
/* */
/* Calling Sequence: */
/* */
/* _prnt8(n); */
/* */
/* "n" is the number to be converted. */
/* */
/* Returns: */
/* */
/* (none) */
/* */
/****************************************************************************/
VOID _prnt8 (n) /* */
LONG n; /* Number to convert */
{ /* */
REG WORD p; /* Counts bits */
REG WORD k; /* Temporary 3-bit value */
REG WORD sw; /* Switch 1 => output */
/****************************/
if (n==0) /* Handle 0 as special case */
{ /* */
*_ptrbf++ = '0'; /* Put in one zero */
return; /* And quit */
} /* */
/****************************/
sw = 0; /* Indicate no output yet */
/* */
for (p=HIBIT; p >= 0; p =- 3) /* Use 3 bits at a time */
/* */
if ((k = (n>>p)&07) || sw) /* Need to output yet? */
{ /* */
if (p==HIBIT) /* 1st digit has only 2 bits*/
k = k & 02; /* Mask appropriately */
*_ptrbf++ = '0' + k; /* ASCIIfy digit */
sw = 1; /* Set output flag */
} /* End if */
} /* End _prnt8 */
/****************************/
/****************************************************************************/
/* */
/* _ P r n t x F u n c t i o n */
/* ----------------------------- */
/* */
/* The "_prntx" function converts a binary LONG quantity to hex ASCII */
/* and stores the result in "*_ptrbf". Leading zeros are suppressed. */
/* */
/* Calling sequence: */
/* */
/* _prntx(n); */
/* */
/* where "n" is the value to be converted. */
/* */
/* Returns: */
/* */
/* (none) */
/* */
/****************************************************************************/
VOID _prntx (n) /* */
LONG n; /* 32 bits */
{ /****************************/
REG LONG d; /* A digit */
REG LONG a; /* Temporary value */
/****************************/
if (a = n>>4) /* Peel off low 4 bits */
_prntx ( a & 0xfffffff); /* If <> 0, print first */
d = n&017; /* Take low four bits */
*_ptrbf++ = d > 9 ? 'A'+d-10 : '0' + d;/* ASCIIfy into buffer */
} /****************************/
/****************************************************************************/
/* */
/* _ _ C o n v F u n c t i o n */
/* ----------------------------- */
/* */
/* Function "__conv" is used to convert a decimal ASCII string in */
/* the format to binary. */
/* */
/* Calling Sequence: */
/* */
/* val = __conv(); */
/* */
/* Returns: */
/* */
/* "val" is the converted value */
/* Zero is returned if no value */
/* */
/****************************************************************************/
LONG __conv() /* */
{ /****************************/
REG BYTE c; /* Character temporary */
REG LONG n; /* Accumulator */
/****************************/
n = 0; /* Zero found so far */
while(((c= *__fmt++) >= '0') /* While c is a digit */
&& (c <= '9')) /* */
n = n*10+c-'0'; /* Add c to accumulator */
__fmt--; /* Back up format pointer to*/
/* character skipped above */
return(n); /* See, wasn't that simple? */
} /****************************/
/****************************************************************************/
/* */
/* _ P u t s t r F u n c t i o n */
/* ------------------------------- */
/* */
/* Function "_putstr" is used by "sprintf" as the output function */
/* argument to "_printf". A single character is copied to the buffer */
/* at "_ptrst". */
/* */
/* Calling Sequence: */
/* */
/* _putstr(str,chr); */
/* */
/* where "str" is a dummy argument necessary because the other output */
/* functions have two arguments. */
/* */
/* Returns: */
/* */
/* (none) */
/* */
/****************************************************************************/
VOID _putstr(str,chr) /* */
REG BYTE chr; /* The output character */
BYTE *str; /* Dummy argument */
{ /****************************/
*_ptrst++ = chr; /* Output the character */
return(0); /* Go back */
} /****************************/
/****************************************************************************/
/* */
/* _ P r t 1 F u n c t i o n */
/* --------------------------- */
/* */
/* Function "_prt1" converts a LONG binary quantity to decimal ASCII */
/* at the buffer pointed to by "_ptrbf". */
/* */
/* Calling Sequence: */
/* */
/* _prt1(n); */
/* */
/* where "n" is the value to be converted. */
/* */
/* Returns: */
/* */
/* (none) */
/* */
/****************************************************************************/
VOID _prt1(n) /* */
REG LONG n; /* Conversion input */
{ /****************************/
REG LONG digs[15]; /* store digits here */
REG LONG *dpt; /* Points to last digit */
/****************************/
dpt = digs; /* Initialize digit pointer */
/****************************/
if (n >= 0) /* Fix */
n = -n; /* up */
else /* sign */
*_ptrbf++ = '-'; /* stuff */
/****************************/
for (; n != 0; n = n/10) /* Divide by 10 till zero */
*dpt++ = n%10; /* Store digit (reverse ord)*/
/****************************/
if (dpt == digs) /* Zero value? */
*dpt++ = 0; /* Yes, store 1 zero digit */
/****************************/
while (dpt != digs) /* Now convert to ASCII */
{ /* */
--dpt; /* Decrement pointer */
*_ptrbf++ = '0' - *dpt; /* Note digits are negative!*/
} /* */
} /****************************/