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,135 @@
$title('tables for ddt86 assembler')
$date(6/15/81)
asmtab: do;
$nolist
$include(optab.lit)
$list
declare op$tab (*) byte public data (
aaa$in, 1, 037h, 0,
aad$in, 2, 0d5h, 0ah,
aam$in, 2, 0d4h, 0ah,
aas$in, 1, 03fh, 0,
adc$in, 9, 10h, 2,
add$in, 9, 0, 0,
and$in, 10, 20h, 4,
call$in, 11, 0, 0,
callf$in, 17, 0, 0,
cbw$in, 1, 098h, 0,
clc$in, 1, 0f8h, 0,
cld$in, 1, 0fch, 0,
cli$in, 1, 0fah, 0,
cmc$in, 1, 0f5h, 0,
cmp$in, 9, 38h, 7,
cmpsb$in, 1, 0a6h, 0,
cmpsw$in, 1, 0a7h, 0,
cwd$in, 1, 099h, 0,
daa$in, 1, 027h, 0,
das$in, 1, 02fh, 0,
dec$in, 7, 0, 0,
div$in, 5, 0f6h, 6,
esc$in, 13, 0d8h, 0,
hlt$in, 1, 0f4h, 0,
idiv$in, 5, 0f6h, 7,
imul$in, 5, 0f6h, 5,
in$in, 15, 0e4h, 0,
inc$in, 7, 1, 0,
int$in, 12, 0, 0,
into$in, 1, 0ceh, 0,
iret$in, 1, 0cfh, 0,
ja$in, 3, 077h, 0,
jae$in, 3, 073h, 0,
jb$in, 3, 072h, 0,
jbe$in, 3, 076h, 0,
jc$in, 3, 072h, 0,
jcxz$in, 3, 0e3h, 0,
je$in, 3, 074h, 0,
jg$in, 3, 07fh, 0,
jge$in, 3, 07dh, 0,
jl$in, 3, 07ch, 0,
jle$in, 3, 07eh, 0,
jmp$in, 11, 1, 0,
jmpf$in, 17, 1, 0,
jmps$in, 3, 0ebh, 0,
jna$in, 3, 076h, 0,
jnae$in, 3, 072h, 0,
jnb$in, 3, 073h, 0,
jnbe$in, 3, 077h, 0,
jnc$in, 3, 073h, 0,
jne$in, 3, 075h, 0,
jng$in, 3, 07eh, 0,
jnge$in, 3, 07ch, 0,
jnl$in, 3, 07dh, 0,
jnle$in, 3, 07fh, 0,
jno$in, 3, 071h, 0,
jnp$in, 3, 07bh, 0,
jns$in, 3, 079h, 0,
jnz$in, 3, 075h, 0,
jo$in, 3, 070h, 0,
jp$in, 3, 07ah, 0,
jpe$in, 3, 07ah, 0,
jpo$in, 3, 07bh, 0,
js$in, 3, 078h, 0,
jz$in, 3, 074h, 0,
lahf$in, 1, 09fh, 0,
lds$in, 6, 0c5h, 0,
lea$in, 6, 08dh, 0,
les$in, 6, 0c4h, 0,
lock$in, 0ffh, 0f0h, 0,
lodsb$in, 1, 0ach, 0,
lodsw$in, 1, 0adh, 0,
loop$in, 3, 0e2h, 0,
loope$in, 3, 0e1h, 0,
loopne$in, 3, 0e0h, 0,
loopnz$in, 3, 0e0h, 0,
loopz$in, 3, 0e1h, 0,
mov$in, 20, 0, 0,
movsb$in, 1, 0a4h, 0,
movsw$in, 1, 0a5h, 0,
mul$in, 5, 0f6h, 4,
neg$in, 5, 0f6h, 3,
nop$in, 1, 090h, 0,
not$in, 5, 0f6h, 2,
or$in, 10, 8, 1,
out$in, 16, 0e6h, 0,
pop$in, 21, 0, 0,
popf$in, 1, 09dh, 0,
push$in, 8, 1, 0,
pushf$in, 1, 09ch, 0,
rcl$in, 4, 0d0h, 2,
rcr$in, 4, 0d0h, 3,
rep$in, 0feh, 0f3h, 0,
repe$in, 0feh, 0f3h, 0,
repne$in, 0feh, 0f2h, 0,
repnz$in, 0feh, 0f2h, 0,
repz$in, 0feh, 0f3h, 0,
ret$in, 14, 0c2h, 0,
retf$in, 14, 0cah, 0,
rol$in, 4, 0d0h, 0,
ror$in, 4, 0d0h, 1,
sahf$in, 1, 09eh, 0,
sal$in, 4, 0d0h, 4,
sar$in, 4, 0d0h, 7,
sbb$in, 9, 18h, 3,
scasb$in, 1, 0aeh, 0,
scasw$in, 1, 0afh, 0,
shl$in, 4, 0d0h, 4,
shr$in, 4, 0d0h, 5,
stc$in, 1, 0f9h, 0,
std$in, 1, 0fdh, 0,
sti$in, 1, 0fbh, 0,
stosb$in, 1, 0aah, 0,
stosw$in, 1, 0abh, 0,
sub$in, 9, 28h, 5,
test$in, 18, 0, 0,
wait$in, 1, 09bh, 0,
xchg$in, 19, 0, 0,
xlat$in, 1, 0d7h, 0,
xor$in, 10, 30h, 6
);
end asm$tab;


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
;
; interface module for ddt86 assembler
; 7/15/82
;
dgroup group dats
dats segment public 'DATS'
db '?'
dats ends
;
cgroup group code
extrn asm:near
public ddtgetline
public goddt
public ddtset
;
code segment public 'CODE'
assume cs:cgroup
;
assent proc
org 2400h
jmp asm
assent endp
;
ddtgetline proc
jmp $-22fah
ddtgetline endp
;
goddt proc
jmp $-22fah
goddt endp
;
ddtset proc
jmp $-22fah
ddtset endp
;
code ends
end


View File

@@ -0,0 +1,184 @@
/****************************************************************************/
/* */
/* C P M . H */
/* --------- */
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
/* */
/* Edits: */
/* 6-Oct-83 whf Redefine reserved area in fcb for parsefn() return */
/* 25-June-83 sw Add user number to file "fd" structure. */
/* */
/* This file contains CP/M specific definitions for the CP/M */
/* C Run Time Library. */
/* This file is intended only for inclusion with those functions */
/* dealing directly with the BDOS, as well as any function which */
/* has hardware dependent code (byte storage order, for instance). */
/* */
/* <portab.h> must be included BEFORE this file. */
/* */
/****************************************************************************/
/*
* CP/M FCB definition
*/
struct fcbtab /****************************/
{ /* */
BYTE drive; /* Disk drive field */
BYTE fname[8]; /* File name */
BYTE ftype[3]; /* File type */
BYTE extent; /* Current extent number */
BYTE s1,s2; /* "system reserved" */
BYTE reccnt; /* Record counter */
BYTE fpasswd[8]; /* Parsefn passwd area */
BYTE fuser; /* Parsefn user# area */
BYTE resvd[7]; /* More "system reserved" */
LONG record; /* Note -- we overlap the */
/* current record field to */
/* make this useful. */
}; /****************************/
#define SECSIZ 128 /* size of CP/M sector */
#define _MAXSXFR 1 /* max # sectors xferrable */
#define _MAXSHFT 12 /* shift right BDOS rtn val */
/* to obtain nsecs on err */
/****************************/
/****************************************************************************/
/* */
/* Channel Control Block (CCB) */
/* */
/* One CCB is allocated (statically) for each of the 16 possible open */
/* files under C (including STDIN, STDOUT, STDERR). Permanent data */
/* regarding the channel is kept here. */
/* */
/* */
/****************************************************************************/
struct ccb /************************************/
{ /* */
WORD flags; /*sw Flags byte */
BYTE user; /*sw User # */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct fcbtab fcb; /* File FCB (may have TTY info)*/
BYTE buffer[SECSIZ]; /* Read/write buffer */
}; /************************************/
#define MAXCCBS 16 /* Maximum # CC Blocks */
extern struct ccb _fds[]; /* */ /* Declare storage */
#define FD struct ccb /* FD Type definition */
/************************************/
/* Flags word bit definitions */
/************************************/
#define OPENED 0x01 /* Channel is OPEN */
#define ISTTY 0x02 /* Channel open to TTT */
#define ISLPT 0x04 /* Channel open to LPT */
#define ISREAD 0x08 /* Channel open readonly */
#define ISASCII 0x10 /* ASCII file attached */
#define ATEOF 0x20 /* End of file encountered */
#define DIRTY 0x40 /* Buffer needs writing */
#define ISSPTTY 0x80 /* Special tty info */
#define ISAUX 0x100 /*sw Auxiliary device */
/************************************/
#define READ 0 /* Read mode parameter for open */
#define WRITE 1 /* Write mode */
/* CCB manipulation macros *************************************/
#define _getccb(i) (&_fds[i]) /* Get CCB addr */
/* Error handling *************************************/
EXTERN WORD errno; /* error place for assigning */
EXTERN WORD __cpmrv; /* the last BDOS return value */
EXTERN WORD _errcpm; /* place to save __cpmrv */
#define RETERR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
/************************************/
/****************************************************************************/
/* */
/* B D O S F u n c t i o n D e f i n i t i o n s */
/* ------------------------------------------------- */
/* */
/* Following are BDOS function definitions used by the C runtime */
/* library. */
/* */
/****************************************************************************/
/****************************/
#if CPM68K /* */
#define __OSIF(fn,arg) __BDOS((fn),(LONG)(arg)) /* CPM68K does it this way */
#else /* */
#define __OSIF(fn,arg) __BDOS((fn),(arg)) /* DRC does it this way */
#endif /* */
/****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONIN 1 /* direct echoing con input */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define C_WRITESTR 9 /* Console string output */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define SEARCHF 17 /* Search for first */
#define SEARCHN 18 /* Search for next */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define F_RENAME 23 /* Rename a disk file */
#define SETDMA 26 /* Set DMA address */
#define USER 32 /*sw Get / set user number */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#define SETMSC 44 /* Set Multi-Sector Count */
#define P_CHAIN 47 /* Program Chain */
#define SETVEC 61 /* Set exception vector */
#define C_DELIMIT 110 /* Get/Set Output Delimiter */
/****************************/
/****************************************************************************/
/* Other CP/M definitions */
/****************************************************************************/
#define TERM "CON:" /* Console file name */
#define LIST "LST:" /* List device file name */
#define EOFCHAR 0x1a /* End of file character-^Z */
/****************************/
/****************************************************************************/
/* Hardware dependencies */
/****************************************************************************/
#include "machine.h" /* For which machine? */
/****************************/
#ifdef MC68000 || Z8000 /* 68K or Z8000 */
#define HILO 1 /* used when bytes stored */
#else /* */
#define HILO 0 /* */
#endif /* */
/* */
#if HILO /* Hi/Lo storage used in */
struct { /* 68K */
BYTE lbhihi; /* Use this for accessing */
BYTE lbhilo; /* ordered bytes in 32 bit*/
BYTE lblohi; /* LONG qtys. */
BYTE lblolo; /* */
}; /* */
struct { /* Use this for accessing */
WORD lwhi; /* ordered words in 32 bit*/
WORD lwlo; /* LONG qtys. */
}; /* */
#else /****************************/
struct { /* Lo/Hi storage use on */
BYTE lblolo; /* PDP-11, VAX, 8086,... */
BYTE lblohi; /* */
BYTE lbhilo; /* */
BYTE lbhihi; /* */
}; /* */
struct { /* */
WORD lwlo; /* */
WORD lwhi; /* */
}; /* */
#endif /****************************/
/*************************** end of cpm.h ***********************************/


File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,596 @@
$title('8086 disassembler')
$date(5/14/81)
$compact
$optimize(2)
disem86: do;
declare
cr literally '0dh',
lf literally '0ah',
true literally '1',
false literally '0';
$include(optab.dat)
declare
tab$ptrs (5) address public initial (.ops2, .ops3, .ops4, .ops5, .ops6);
declare
left$bracket byte data ('['),
right$bracket byte data (']');
declare
alt$table$base address,
alt$table based alt$table$base (16) byte,
alt$table$ptrs (8) address external;
declare
mod$bits byte,
reg$bits byte,
rm$bits byte,
byte1$reg$bits byte,
d$bit byte,
s$bit byte,
v$bit byte,
w$bit byte,
z$bit byte;
declare
mnemonic$index byte, /* index into opcodes */
instr$type byte,
table$ptr address,
table$char based table$ptr byte,
disem$ptr pointer,
disem$offset address at (.disem$ptr),
disem$end address,
disem$byte based disem$ptr (1) byte,
disem$word based disem$ptr (1) address,
b$or$w$flag byte,
error$flag byte;
declare instr$table (512) byte external;
declare
ax$reg literally '0',
cx$reg literally '1',
dx$reg literally '2',
bx$reg literally '3',
sp$reg literally '4',
bp$reg literally '5',
si$reg literally '6',
di$reg literally '7';
declare
al$reg literally '0',
cl$reg literally '1',
dl$reg literally '2',
bl$reg literally '3',
ah$reg literally '4',
ch$reg literally '5',
dh$reg literally '6',
bh$reg literally '7';
declare
es$reg literally '0',
cs$reg literally '1',
ss$reg literally '2',
ds$reg literally '3';
declare
reg16 (*) byte public initial ('AX', 'CX', 'DX', 'BX', 'SP', 'BP', 'SI', 'DI'),
reg8 (*) byte public initial ('AL', 'CL', 'DL', 'BL', 'AH', 'CH', 'DH', 'BH'),
segreg (*) byte public initial ('ES', 'CS', 'SS', 'DS');
conout: procedure (c) external;
declare c byte;
end conout;
comma: procedure;
call conout (',');
end comma;
printm: procedure (a) PUBLIC;
declare a address;
declare b based a byte;
do while b <> '$';
call conout (b);
a = a + 1;
end;
end printm;
print$nibble: procedure (b);
declare b byte;
if b > 9 then call conout (b - 10 + 'A');
else call conout (b + '0');
end print$nibble;
print$byte: procedure (b);
declare b byte;
call print$nibble (shr (b, 4));
call print$nibble (b and 0fh);
end print$byte;
print$word: procedure (a) public;
declare a address;
call print$byte (high (a));
call print$byte (low (a));
end print$word;
error: procedure;
call printm (.('??= $'));
call print$byte (disem$byte (0));
disem$offset = disem$offset + 1;
end error;
set$bits: procedure;
byte1$reg$bits = disem$byte (0) and 7;
mod$bits = shr (disem$byte (1), 6);
reg$bits = shr (disem$byte (1), 3) and 7;
rm$bits = disem$byte (1) and 7;
w$bit, z$bit = disem$byte (0) and 1;
d$bit, s$bit, v$bit = shr (disem$byte (0), 1) and 1;
end set$bits;
print$b$or$w: procedure;
if w$bit then call printm (.('WORD $'));
else call printm (.('BYTE $'));
end print$b$or$w;
print$reg: procedure (reg$add, reg);
declare reg$add address, reg byte;
table$ptr = reg$add + shl (reg, 1);
call conout (table$char);
table$ptr = table$ptr + 1;
call conout (table$char);
end print$reg;
print$reg8: procedure (reg);
declare reg byte;
call print$reg (.reg8, reg);
end print$reg8;
print$reg16: procedure (reg);
declare reg byte;
call print$reg (.reg16, reg);
end print$reg16;
print$reg$8$or$16: procedure (reg$num);
declare reg$num byte;
if w$bit then call print$reg$16 (reg$num);
else call print$reg$8 (reg$num);
end print$reg$8$or$16;
print$2$reg$16: procedure (r1, r2);
declare (r1, r2) byte;
call print$reg$16 (r1);
call conout ('+');
call print$reg$16 (r2);
end print$2$reg$16;
print$A$reg: procedure;
if w$bit then call print$reg$16 (ax$reg);
else call print$reg$8 (al$reg);
end print$A$reg;
print$seg$reg: procedure (reg);
declare reg byte;
call print$reg (.seg$reg, reg);
end print$seg$reg;
print$data$8: procedure;
call print$byte (disem$byte (0));
disem$offset = disem$offset + 1;
end print$data$8;
print$data$16: procedure;
call print$word (disem$word (0));
disem$offset = disem$offset + 2;
end print$data$16;
print$data$8$or$16: procedure;
if w$bit then call print$data$16;
else call print$data$8;
end print$data$8$or$16;
print$data$sw: procedure;
if rol (disem$byte (0), 1) then call print$word (0ff00h or disem$byte (0));
else call print$word (disem$byte (0));
disem$offset = disem$offset + 1;
end print$data$sw;
print$signed$8: procedure;
declare a address;
a = disem$byte (0);
if low (a) >= 80h then a = a or 0ff00h; /* sign extend to 16 bits */
call print$word (disem$offset + a + 1);
disem$offset = disem$offset + 1;
end print$signed$8;
print$signed$16: procedure;
call print$word (disem$offset + disem$word (0) + 2);
disem$offset = disem$offset + 2;
end print$signed$16;
print$direct$addr: procedure;
call conout (left$bracket);
call print$word (disem$word (0));
call conout (right$bracket);
disem$offset = disem$offset + 2;
end print$direct$addr;
print$mod$rm: procedure;
disem$offset = disem$offset + 1; /* point past mod/reg/rm byte */
if mod$bits = 3 then
do;
call print$reg$8$or$16 (rm$bits);
return;
end;
if b$or$w$flag then call print$b$or$w;
if rm$bits = 6 and mod$bits = 0 then
do;
call print$direct$addr;
return;
end;
if mod$bits = 1 then
do;
if (rm$bits <> 6) or (disem$byte (0) <> 0)
then call print$byte (disem$byte (0));
disem$offset = disem$offset + 1;
end;
else if mod$bits = 2 then
do;
call print$word (disem$word (0));
disem$offset = disem$offset + 2;
end;
call conout (left$bracket);
do case rm$bits;
call print$2$reg$16 (3, 6);
call print$2$reg$16 (3, 7);
call print$2$reg$16 (5, 6);
call print$2$reg$16 (5, 7);
call print$reg$16 (6);
call print$reg$16 (7);
call print$reg$16 (5);
call print$reg$16 (3);
end;
call conout (right$bracket);
end print$mod$rm;
print$mod$reg$rm: procedure;
if d$bit then
do;
call print$reg$8$or$16 (reg$bits);
call conout (',');
call print$mod$rm;
end;
else
do;
call print$mod$rm;
call conout (',');
call print$reg$8$or$16 (reg$bits);
end;
end print$mod$reg$rm;
print$mnemonic: procedure;
declare (len, i) byte;
len = 2;
do while mnemonic$index >= opn$in (len - 1);
len = len + 1;
end;
table$ptr = tab$ptrs (len - 2) + (mnemonic$index - opn$in (len - 2))
* len;
do i = 1 to 7;
if i <= len then
do;
call conout (table$char);
table$ptr = table$ptr + 1;
end;
else call conout (' ');
end;
disem$offset = disem$offset + 1;
end print$mnemonic;
type1: procedure;
call print$mnemonic;
end type1;
type2: procedure;
if disem$byte (1) = 0ah then
do;
call print$mnemonic;
disem$offset = disem$offset + 1;
end;
else error$flag = true;
end type2;
type3: procedure;
call print$mnemonic;
call print$reg$16 (byte1$reg$bits);
end type3;
type4: procedure;
declare temp byte;
temp = shr (disem$byte (0), 3) and 3;
call print$mnemonic;
call print$segreg (temp);
end type4;
type5: procedure;
call print$mnemonic;
call print$signed$8;
end type5;
type6: procedure;
call print$mnemonic;
call print$signed$16;
end type6;
type8: procedure; /* 7, 9 */
call print$mnemonic;
call print$mod$rm;
end type8;
type10: procedure;
call print$mnemonic;
call print$data$8;
end type10;
type11: procedure;
call print$mnemonic;
call print$data$16;
end type11;
type12: procedure;
call print$mnemonic;
call conout ('3');
end type12;
type13: procedure;
declare temp address;
call print$mnemonic;
temp = disem$word (0);
disem$offset = disem$offset + 2;
call print$data$16;
call conout (':');
call print$word (temp);
end type13;
type14: procedure; /* 15, 16, 17 */
call print$mnemonic;
call print$mod$reg$rm;
end type14;
type18: procedure; /* 19, 20, 21 */
call print$mnemonic;
if d$bit then
do;
call print$direct$addr;
call comma;
call print$A$reg;
end;
else
do;
call print$A$reg;
call comma;
call print$direct$addr;
end;
end type18;
type22: procedure;
call print$mnemonic;
if d$bit then
do;
call print$data$8;
call comma;
call print$A$reg;
end;
else
do;
call print$A$reg;
call comma;
call print$data$8;
end;
end type22;
type23: procedure; /* 24 */
call print$mnemonic;
call print$A$reg;
call comma;
call print$data$8$or$16;
end type23;
type25: procedure; /* 26 */
call print$mnemonic;
if d$bit then
do;
call print$reg$16 (dx$reg);
call comma;
call print$A$reg;
end;
else
do;
call print$A$reg;
call comma;
call print$reg$16 (dx$reg);
end;
end type25;
type27: procedure; /* 28, 29, 30 */
call print$mnemonic;
b$or$w$flag = true;
call print$mod$rm;
call comma;
if v$bit then call print$reg$8 (cl$reg);
else call conout ('1');
end type27;
type31: procedure; /* 32 */
call setbits;
reg$bits = byte1$reg$bits;
w$bit = shr (disem$byte (0), 3) and 1;
call print$mnemonic;
call print$reg$8$or$16 (reg$bits);
call comma;
call print$data$8$or$16;
end type31;
type33: procedure;
call print$mnemonic;
call print$reg$16 (ax$reg);
call comma;
call print$reg$16 (byte1$reg$bits);
end type33;
type34: procedure; /* 35 */
call print$mnemonic;
b$or$w$flag = true;
call print$mod$rm;
call comma;
call print$data$8$or$16;
end type34;
type36: procedure; /* 37 */
w$bit = true; /* force 16 bit reg, mem */
if reg$bits > 3 then
do;
error$flag = true;
return;
end;
call print$mnemonic;
if d$bit then
do;
call print$seg$reg (reg$bits);
call comma;
call print$mod$rm;
end;
else
do;
call print$mod$rm;
call comma;
call print$seg$reg (reg$bits);
end;
end type36;
type38: procedure;
call print$mnemonic;
call print$mod$rm;
call comma;
call print$data$8;
end type38;
type39: procedure;
if mod$bits = 3 then
do;
error$flag = true;
return;
end;
call print$mnemonic;
call print$reg$16 (reg$bits);
call comma;
call print$mod$rm;
end type39;
type40: procedure; /* 41 */
if mod$bits = 3 then
do;
error$flag = true;
return;
end;
call print$mnemonic;
b$or$w$flag = true;
call print$mod$rm;
call comma;
call print$data$8$or$16;
end type40;
type42: procedure;
call print$mnemonic;
call print$byte (shl (byte1$reg$bits, 3) or reg$bits);
call comma;
call print$mod$rm;
end type42;
type44: procedure;
call print$mnemonic;
b$or$w$flag = true;
call print$modrm;
call comma;
if s$bit = 1 and w$bit = 1 then call print$data$sw;
else call print$data$8$or$16;
end type44;
type45: procedure;
b$or$w$flag = true;
call type8;
end type45;
dis: procedure;
error$flag, b$or$w$flag = false;
call set$bits;
if instr$type = 26 then
do;
alt$table$base = alt$table$ptrs (mnemonic$index);
mnemonic$index = alt$table (reg$bits * 2);
instr$type = alt$table (reg$bits * 2 + 1);
end;
if instr$type > 28 then error$flag = true;
else
do case instr$type;
error$flag = true;
call type1;
call type2;
call type3;
call type4;
call type5;
call type6;
call type8;
call type10;
call type11;
call type12;
call type13;
call type14;
call type18;
call type22;
call type23;
call type25;
call type27;
call type31;
call type33;
call type34;
call type36;
call type38;
call type39;
call type40;
call type42;
;
call type44;
call type45;
end;
if error$flag then call error;
end dis;
disem: procedure (disloc) address public;
declare disloc pointer;
declare nprefix byte;
disem$ptr = disloc;
nprefix = 0;
do while true;
mnemonic$index = instr$table (disem$byte (0) * 2);
instr$type = instr$table (disem$byte (0) * 2 + 1);
if instr$type = 0ffh and nprefix < 3 then
do;
call print$mnemonic;
nprefix = nprefix + 1;
end;
else
do;
if instr$type = 0ffh then instr$type = 1;
call dis;
return disem$offset;
end;
end;
end disem;
end disem86;


View File

@@ -0,0 +1,30 @@
;
; interface module for ddt86 disassembler
; 7/15/82
;
dgroup group dats
dats segment public 'DATS'
db '?'
dats ends
cgroup group code
extrn disem:near
public boot
public conin,conout
code segment public 'CODE'
assume cs:cgroup
disent proc
org 1500h
jmp disem
disent endp
boot proc
ret
boot endp
conin proc
jmp $-1401h
conin endp
conout proc
jmp $-1401h
conout endp
code ends
end


View File

@@ -0,0 +1,534 @@
/**************************************************************************
* G E N C C P M - generates an operating system
*
* Written by Bill Fitler Nov. 1982
*
* GENCCPM is designed to edit the system image for the operating system
* and construct an initialized, loadable image for execution.
* GENCCPM was originally designed for Concurrent CP/M-86 v2.0, and was
* modelled after the old GENSYS.
*
* Revision history:
* 10 Feb 84 whf: bug fixes: addmem, fixupxios_info, and qbuf limits (glp)
* 08 Jan 84 glp: added support for Extended DPB
* 15 Dec 83 fmb: changed ncondev,nciodev initialization
* 5 Oct 83 whf: converted to DRC, broke apart modules, added ADDRs
* 9 Sep 83 fmb: compiler bug fix for daend in gentables
* 4 Aug 83 fmb: version number -> 3.1
* 14 Jun 83 whf: fix flags & large xios bugs
* 8 Jun 83 fmb: handles Multi-User Concurrent 3.1
* 31 May 83 fmb: added sd_xpcns init for Multi-User CCP/M 3.1 .
* 23 Feb 83 whf: add patch module
* 25 Jan 83 whf: combine all modules for easier maintenance
* 20 Jan 83 whf: handles SYSDAT overflow
* 19 Nov 82 whf: added BDOS buffering generation.
*
************************************************************************/
/*******************************/
/* for serialization purposes: */
char *copynote = "COPYRIGHT (C) 1983, DIGITAL RESEARCH XXXX-0000-654321 $";
/****************************************************/
/* up front for patching: Note the internal EOS (0) */
char *clearx = "\033H\033E\0\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
/****************************************************/
/****** include files ********/
#define MAINMODULE 1
#include <genccpm.h>
/*****************************/
#ifdef CCPM
BYTE *edsysver = "GENCCPM v2.1 [2/7/84]\n";
#endif
#ifdef CMPM
BYTE *edsysver = "GENCCPM v3.1 [2/7/84]\n";
#endif
BYTE mainmtitle[50] = ""; /* room for title of main menu */
MENU *mainmenu = NULLPTRI; /* pointers to main menu items */
MENU *memmenu=NULLPTRI; /* memory management menu */
MENU *syspmenu=NULLPTRI; /* system parameters menu */
MENU *rspmenu=NULLPTRI; /* rsp edit menu */
/**************************************************************************/
/* main module */
/**************************************************************************/
main(ac,av)
WORD ac;
BYTE **av;
{
BYTE cmds[CMDSLEN]; /* input area of commands */
BOOLEAN sysvalid(); /* is the system data valid? */
fprintf(stderr,edsysver);
if( isatty(1) ) /* standard output to a tty? */
clearit = clearx; /* yes, do clear screens */
else clearit = ""; /* no, don't do clear screens */
init_sysdat(); /* initialize system data */
init_edsys(); /* initialize menus */
if( ac>1 ) { /* if any command line arguments */
copyargs(ac-1,av+1,cmds); /* simplify cmd parser */
verbose = TRUE; /* turn on wordiness by default */
domenu(cmds,mainmenu); /* do what they've asked for */
}
FOREVER { /* work with user for a while */
if(doit) { /* does user want to quit? */
if( sysvalid() ) /* has evrything been defined? */
break; /* let them if everything okay */
press_return(); /* let them view the message(s) */
}
printf("%s",clearit); /* clear the screen */
prtmenu(mainmtitle,mainmenu); /* display user options */
printf(PROMPT); /* prompt user */
if( gets(cmds)!=cmds ){ /* on end of file */
close(0); /* standard input */
open("CON:",0); /* reopen to the console */
close(1); /* standard output: assume redirection */
open("CON:",1); /* reopen to console */
clearit = clearx; /* do the clear screen routine */
continue; /* force user to input blank line */
}
if( *cmds==NULL ) /* blank line of input */
continue; /* don't bother with blank lines here */
domenu(cmds,mainmenu); /* do what they've asked for */
} /*****************************/
/* we've got user input */
make_sysfile(); /* construct system image/use old one*/
gentables(); /* generate the tables */
fixups(); /* odds and ends on the system image */
wrapup(); /* close files, etc. */
}
/* copyargs: copies args to cbuf for uniform parsing */
copyargs(ac,av,cbuf)
WORD ac;
BYTE **av;
BYTE *cbuf;
{
for( *cbuf=NULL; ac>0; --ac, ++av ) {
strcat(cbuf,*av);
strcat(cbuf," ");
}
}
/**************************************************************************/
/* init_sysdat: reads SYStem DATa info from:
/* 1. SYSFILE, if it exists
/* 2. SYSMOD, o.w. if this is the case, it also checks
/* for existence of all other required modules
/**************************************************************************/
VOID init_sysdat()
{
REG WORD sf; /* file descriptor for SysData read */
LONG grpseek(); /* seek the data group */
UWORD goffs; /* loc of group */
EXTERN DLIST *rsps, *dirsearch(); /* directory search fn */
BYTE *addmem(); /* for initializing memory */
BYTE *chkmodules(), *xlist[80]; /* list of missing modules */
printf("GENerate SYStem image for %s\n",VERLABEL);
init_sds(sdat_area); /* initialize program ptrs */
/***************************************************/
if(chkmodules(xlist)==NULLPTR && (sf=BROPEN(SYSMOD)) > 0 ) {
printf("Constructing new %s file\n",SYSFILE);
/*** procedureize this? for cmd use */
dogensys=TRUE; /* no SYSFILE, read from modules */
if(grpseek(sf,GTYPDATA)<0) /* seek start of data group */
CRASH("no data group in SYSDAT module\n");
read(sf,sdat_area,SDLEN); /* read in the data group */
/**** may have to init arbitrarily some MAX values here ****/
xtrapds = *sd_pul; /* default number of extra process descriptors */
totqcbs = *sd_qul; /* default number of qcbs */
totopen = 0x40; /* arbitrary total open files & locked recs */
qbuflen = *sd_qmalen; /* init'ed to bytes */
rsps = dirsearch("*.RSP"); /* init RSP list */
addmem("400,6000,400"); /* start out with this memory allocation */
close(sf); /* don't need it for a while */
sf=BROPEN(XIOSMOD); /* let's go read the XIOS info */
if( grpseek(sf,GTYPDATA) <= 0 ) /* if there is not a data group */
grpseek(sf,GTYPCODE); /* use the code group instead */
goffs = lseek( sf,0L,1 ); /* where did we end up? */
initxios_info(sf,goffs); /* grab info from there */
close(sf); /* don't need it for a while */
} else if( FALSE && /****** temporarily disable this option!!! ***/
(sf=BROPEN(SYSFILE)) >= 0 ){ /* does SYSFILE exist? *******/
printf("Editting %s file\n",SYSFILE);
dogensys = FALSE; /* tell them not to gen a new system */
grpseek(sf,GTYPDATA); /* get data module in OS */
read(sf,sdat_area,SDLEN); /* read in the info */
/**** may have to trace down some lists for MAX values ****/
close(sf); /* don't need it for a while */
} else { /***************************************************/
if( xlist == NULLPTR ) {
fprintf(stderr,"Can't find %s module\n",SYSMOD);
} else {
fprintf(stderr,"Can't find these modules:\n%s\n",xlist);
}
fprintf(stderr,"Please find the correct modules\n");
exit(1);
} /**** end module check ****/
if( VERSION != *sd_mpmvn ){ /* a little version number checking */
USERR("%s works on OS version %x\n",edsysver,VERSION);
USERR("Sys Data area found was from OS version %x\n",*sd_mpmvn);
USERR("Please find correct .SYS or %s files\n",MODEXT);
exit(1);
}
}
/**************************************************************************/
#define RDAC 4 /* Read Access mode for 'access' */
BYTE *
chkmodules(badbuf) /* place to put missing module names */
BYTE *badbuf;
{
*badbuf=0;
if( access(SYSMOD,RDAC) ) {strcat(badbuf,SYSMOD);strcat(badbuf," ");}
if( access(SUPMOD,RDAC) ) {strcat(badbuf,SUPMOD);strcat(badbuf," ");}
if( access(RTMMOD,RDAC) ) {strcat(badbuf,RTMMOD);strcat(badbuf," ");}
if( access(MEMMOD,RDAC) ) {strcat(badbuf,MEMMOD);strcat(badbuf," ");}
if( access(CIOMOD,RDAC) ) {strcat(badbuf,CIOMOD);strcat(badbuf," ");}
if( access(BDOSMOD,RDAC) ) {strcat(badbuf,BDOSMOD);strcat(badbuf," ");}
if( access(XIOSMOD,RDAC) ) {strcat(badbuf,XIOSMOD);strcat(badbuf," ");}
if( *badbuf )
return badbuf;
else return NULLPTR;
}
/**************************************************************************/
/* init_edsys: initializes program variables and menus
/**************************************************************************/
VOID init_edsys()
{
MENU *m; /* mainmenu pointer */
MENU *me; /* memory partitions menu */
MENU *s; /* sys params menu */
MENU *r; /* rsp menu */
MENU *bldmenu(); /* func to build the menu list */
BYTE *drvmsg; /* destination drive message */
BYTE *delmsg; /* delete old SYSFILE msg */
BYTE getdrive(); /* get default drive */
BYTE *help(); /* func to help user */
BYTE *doxios(); /* func to do xios menu */
BYTE *dosysp(); /* func to do sys param menu */
BYTE *dorsp(); /* func to display & handle RSPs */
BYTE *dolbl(); /* func to modify version label */
BYTE *domem(); /* handle memory partitions */
BYTE *doxbufs(); /* func to construct bdos buffers */
BYTE *addmem(); /* add mem part */
BYTE *delmem(); /* delete mem part */
BYTE *rspinclude(); /* include a bunch of RSPs */
BYTE *rspexclude(); /* exclude a bunch of RSPs */
BYTE *doexit(); /* exit the main menu */
sprintf(mainmtitle,"*** %s %s Main Menu ***",VERLABEL,PROGNAME);
destdrv = getdrive(); /* returns the default drive */
drvmsg = malloc(50);
sprintf(drvmsg,"%s Output To (Destination) Drive",SYSFILE);
delmsg = malloc(55);
sprintf(delmsg,"Delete (instead of rename) old %s file\n",SYSFILE);
m=NULLPTR; me=NULLPTR; s=NULLPTR; r=NULLPTR; /* init menu pointers */
/***** initialize menus *****/
m=bldmenu(m,MPROC,help,"help","GENCCPM Help");
m=bldmenu(m,MBOOL,&verbose,"verbose","More Verbose GENCCPM Messages");
m=bldmenu(m,MDRIV,&destdrv,"destdrive",drvmsg);
m=bldmenu(m,MBOOL,&doclean,"deletesys",delmsg);
m=bldmenu(m,MPROC,dosysp,"sysparams","Display/Change System Parameters");
s=bldmenu(s,MDRIV,sd_srchdisk,"sysdrive","System Drive");
s=bldmenu(s,MDRIV,sd_tempdisk,"tmpdrive","Temporary File Drive");
s=bldmenu(s,MBOOL,sd_dayfile,"cmdlogging","Command Day/File Logging at Console");
s=bldmenu(s,MBOOL,sd_cmode,"compatmode","CP/M FCB Compatibility Mode");
s=bldmenu(s,MWORD,sd_mmp,"memmax","Maximum Memory per Process (paragraphs)");
s=bldmenu(s,MBYTE,sd_popen_max,"openmax","Open Files per Process Maximum");
s=bldmenu(s,MBYTE,sd_plock_max,"lockmax","Locked Records per Process Maximum\n");
s=bldmenu(s,MWORD,sd_mpmseg,"osstart","Starting Paragraph of Operating System");
s=bldmenu(s,MWORD,&totopen,"nopenfiles","Number of Open File and Locked Record Entries");
s=bldmenu(s,MBYTE,&xtrapds,"npdescs","Number of Process Descriptors");
s=bldmenu(s,MBYTE,&totqcbs,"nqcbs","Number of Queue Control Blocks");
s=bldmenu(s,MWORD,&qbuflen,"qbufsize","Queue Buffer Total Size in bytes");
s=bldmenu(s,MBYTE,sd_nflags,"nflags","Number of System Flags");
m=bldmenu(m,MPROC,domem,"memory","Display/Change Memory Allocation Partitions");
me=bldmenu(me,MPROC,addmem,"add","ADD Memory Partition(s)");
me=bldmenu(me,MPROC,delmem,"delete","DELETE Memory Partition(s)");
m=bldmenu(m,MPROC,doxbufs,"diskbuffers","Display/Change Disk Buffer Allocation");
if( dogensys )
m=bldmenu(m,MPROC,dolbl,"oslabel","Display/Change Operating System Label");
m=bldmenu(m,MPROC,dorsp,"rsps","Display/Change RSP list\n");
r=bldmenu(r,MPROC,rspinclude,"include","Include RSPs");
r=bldmenu(r,MPROC,rspexclude,"exclude","Exclude RSPs");
m=bldmenu(m,MPROC,doexit,"gensys","I'm finished changing things, go GEN a SYStem\n");
mainmenu=m; /* assign now to longer name */
memmenu=me; /* yah yah */
syspmenu=s; /* " " */
rspmenu=r; /* " " */
}
BYTE *
doexit() /* this is really a boolean... */
{
doit = TRUE;
return NULLPTR;
}
/**************************************************************************/
/* sysvalid: validates system data.
/* also calculates certain SYSDAT variables, in the course of validation.
/**************************************************************************/
#define BYTE_ADJUST(xx) if( xx > 0xFF ) xx = 0xFF
#define ALIGN(xx) (((xx)+0xF) & 0xFFF0)
BOOLEAN
sysvalid()
{
REG BOOLEAN isv; /* is valid? */
BOOLEAN xiosvalid(); /* check xios info */
LOCAL WORD nmparts; /* number of memory partitions */
isv = TRUE; /* innocent until proven guilty */
if( totopen < *sd_popen_max ) {
USERR("'nopenfiles' is less than 'openmax'. Please adjust.\n");
isv = FALSE;
}
if( totopen < *sd_plock_max ) {
USERR("'nopenfiles' is less than 'lockmax'. Please adjust.\n");
isv = FALSE;
}
if( (nmparts=cntmlist(memroot)) <= 0 ) {
USERR("Memory Partitions need to be adjusted\n");
isv = FALSE;
}
if( !xiosvalid() ) { /* xios info needs work? */
USERR("Disk Performance Buffers need to be adjusted\n");
isv=FALSE;
}
if( !isv )
USERR("Please correct the System Parameters\n");
return isv;
}
/**************************************************************************/
/* make_sysfile: responsible for preparing SYSfile image for table generation
/* and
/* if( dousesys )
/* doctors up SYSFILE for appropriate table generation and fixups
/* else constructs a SYSfile from assembled modules
/**************************************************************************/
VOID make_sysfile()
{
BYTE fbuf[20]; /* file name buffer */
PUTDRV(fbuf,NEWSYS);
unlink(fbuf); /* this is the file we'll be using */
if( (fns=BWCREAT(fbuf))<0 ) { /* try to open for output */
USERR("can't open new .SYS file (%s)\n",fbuf);
exit(1);
}
if( dogensys )
gensys(); /* make a new SYS file from modules */
else edsys(); /* edit the old SYS file */
}
/**************************************************************************/
/* gensys: generates a new SYS file image from modules
/**************************************************************************/
VOID
gensys()
{
WORD fxm; /* file descriptor for xios mod */
BYTE fbuf[20];
if( doclean ) { /* clean up the SYSFILE first? */
PUTDRV(fbuf,SYSFILE);
unlink(fbuf); /* delete if there... */
}
if(verbose) printf("Generating new SYS file\n");
FCHECK(fns); /* File error check */
write(fns,cmdhdr,SECSIZ); /* write out a (dummy) command hdr */
genfix(); /* remember the sysdat & sup fixups */
clsup = xfergrp(SUPMOD,GTYPCODE);
clos_label = writelbl(); /* write the OS label (returns 0 if none exists) */
if( clos_label != 0 )
*sd_verptr = clsup<<4; /* fill in offset of label rel sup code seg */
genfix(); clrtm = xfergrp(RTMMOD,GTYPCODE);
genfix(); clmem = xfergrp(MEMMOD,GTYPCODE);
genfix(); clcio = xfergrp(CIOMOD,GTYPCODE);
genfix(); clbdos= xfergrp(BDOSMOD,GTYPCODE);
clnet = 0;
fxm = BROPEN(XIOSMOD); /* look at XIOS module */
if( grpseek(fxm,GTYPDATA) >= 0){ /* is there a data group?*/
USERR("XIOS has separate code and data (small model)");
USERR("This is not supported in this O.S.: use 8080 model.");
exit(1);
} else {
pure_xios = FALSE;
clxios = 0;
}
cltotal = clsup+clos_label+clrtm+clmem+clcio+clbdos+clnet+clxios;
/*** finished writing the code portion of NEWSYS ***/
fldstart = lseek(fns,0L,1); /* where in file SYSDAT gets written */
dsstart = *sd_mpmseg + cltotal; /* where in memory SYSDAT gets loaded */
dlsysdat = xfergrp(SYSMOD,GTYPDATA); /* system data area, fixed later */
if( pure_xios )
dlxios = xferpart_grp(fxm,GTYPDATA,dlsysdat);
else { genfix(); dlxios = xferpart_grp(fxm,GTYPCODE,dlsysdat); }
close(fxm); /* don't need this file descriptor */
dltotal = dlsysdat+dlxios; /* this will change later */
/*** finished writing STATIC data portion of NEWSYS ***/
/*** fill in sysdat here ***/
sd_supmod->ep_eseg = sd_supmod->ep_iseg = *sd_mpmseg;
sd_rtmmod->ep_eseg = sd_rtmmod->ep_iseg = sd_supmod->ep_eseg+clsup+clos_label;
sd_memmod->ep_eseg = sd_memmod->ep_iseg = sd_rtmmod->ep_eseg+clrtm;
sd_ciomod->ep_eseg = sd_ciomod->ep_iseg = sd_memmod->ep_eseg+clmem;
sd_bdosmod->ep_eseg = sd_bdosmod->ep_iseg = sd_ciomod->ep_eseg+clcio;
sd_xiosmod->ep_eseg = sd_xiosmod->ep_iseg = sd_bdosmod->ep_eseg+clbdos;
if( pure_xios ) /* compute xios offsets */
sd_xiosmod->ep_ioff = 0; /* separate code */
else sd_xiosmod->ep_ioff = dlsysdat<<4; /* mixed code & data, after sysdat */
sd_xiosmod->ep_eoff = sd_xiosmod->ep_ioff + 3;
}
/****************************************************************************/
genfix() /* subroutine to remember SYSDAT & Super fixups */
{
LONG fa;
fa = lseek(fns,0L,1); /* where are we in this file? */
fixlater(fa+6,F_PUT,&dsstart); /* fix the SYSDAT address */
fixlater(fa+8,F_PUT,&(sd_supmod->ep_eoff)); /* Supervisor entry offset */
fixlater(fa+10,F_PUT,&(sd_supmod->ep_eseg)); /* " " segment */
}
/**************************************************************************/
/* edsys: edit the old SYS file image.
/* - copies old sys file into new
/* - if( donew_xios ) will patch in a new XIOS from module
/**************************************************************************/
VOID
edsys()
{
if(verbose) printf("Editting old SYS file\n");
write(fns,cmdhdr,SECSIZ); /* leave room for command hdr */
cltotal = xfergrp(SYSFILE,GTYPCODE);
dltotal = xfergrp(SYSFILE,GTYPDATA);
if( donew_xios ) {
; /* need to read 'xt' from XIOS module */
} else {
; /* need to init 'xt' from sysdat */
}
}
/**************************************************************************/
/* fixups: inserts updated SYSDAT page into NEWSYS file, and does some
/* address fixups
/**************************************************************************/
VOID fixups()
{
REG WORD ii; /* counter */
ADDR gg; /* temp var */
GROUP *cg, *dg; /* group ptrs */
UWORD genmfl(); /* (re)Gen Memory Free List */
if(verbose) printf("Doing fixups\n");
FCHECK(fns); /* File error check */
/*** fixup the memory list ***/
if(verbose) {
printf("SYS image load map:\n");
printf(" Code starts at %4.4x\n",*sd_mpmseg);
printf(" Data starts at %4.4x\n",dsstart);
printf(" Tables start at %4.4x\n",(dsotables>>4)+dsstart);
printf(" RSPs start at %4.4x\n",(dsotables>>4)+dsstart+dltables);
printf(" XIOS buffers start at %4.4x\n",rsvd_seg);
printf(" End of OS at %4.4x\n",*sd_endseg);
}
if( trimlist(*sd_mpmseg,*sd_endseg) ) { /* mem part list trimmed? */
printf("Trimming memory partitions. New list:");
dspmlist(memroot);
lseek( fns, locmfl, 0 );
gg = (dlsysdat+dlxios)<<4;
genmfl(gg); /*****/
}
/*** fixup XIOS info ***/
fixupxios_info(); /* fixes the buffer info (DPH info) */
/*** fixup the command header ***/
for( ii=0; ii<SECSIZ; ii++ ) /* zero out command header */
cmdhdr[ii] = '\0';
cg = cmdhdr; /* code group first */
cg->gtype = GTYPCODE; /* init all code vars */
cg->glen = cltotal; /* total length of code groups */
cg->gmin = cltotal; /* min length of code group */
cg->gabase = *sd_mpmseg; /* loads at absolute address */
dg = cmdhdr + sizeof(*cg); /* data group next */
dg->gtype = GTYPDATA; /* init all data vars */
dg->glen = dltotal; /* total length of data group+tables */
dg->gmin = dltotal; /* min length of data group */
dg->gabase = cg->gabase+cltotal;/* abs addr of start of system data */
lseek( fns, 0L, 0 ); /* seek the beginning of NEWSYS */
write(fns,cmdhdr,SECSIZ); /* write out the command header */
/*** fixup the sysdat page ***/
lseek(fns,fldstart,0); /* seek there in file */
write(fns,sdat_area,SDLEN); /* put it into the file */
/*** take care of the little fixes ***/
fixfile(); /* fixes from the list */
}
/**************************************************************************/
/* wrapup: closes files
/**************************************************************************/
VOID wrapup()
{
BYTE buf1[20], buf2[20];
if(verbose) printf("Wrapping up\n");
FCHECK(fns); /* File error check */
lseek(fns,0L,2); /* flush NEWSYS buffers? */
if(strlen(edsysver) != write(fns,edsysver,strlen(edsysver))) {
USERR("WRITE FAILURE - the disk may be too full\n");
exit(1);
}
close(fns); /* all finished with NEWSYS */
PUTDRV(buf1,OLDSYS); unlink(buf1);
PUTDRV(buf2,SYSFILE); rename(buf2,buf1);
PUTDRV(buf1,NEWSYS); rename(buf1,buf2);
}


View File

@@ -0,0 +1,747 @@
/***************************************************************/
/***************************************************************/
/* genc2.c: more genccpm.cc, broken up for shorter compiles */
/***************************************************************/
/***************************************************************/
#ifndef MAINMODULE
#include <genccpm.h>
#endif
/**************************************************************************/
/* init_sds: points the system data pointers to the right place
/**************************************************************************/
VOID
init_sds(sysdat)
BYTE *sysdat; /* ptr to system data buffer */
{
sd_supmod = sysdat + 0x00; /* (4) */
sd_rtmmod = sysdat + 0x08; /* (4) */
sd_memmod = sysdat + 0x10; /* (4) */
sd_ciomod = sysdat + 0x18; /* (4) */
sd_bdosmod = sysdat + 0x20; /* (4) */
sd_xiosmod = sysdat + 0x28; /* (4) */
sd_netmod = sysdat + 0x30; /* (4) */
sd_mpmseg = sysdat + 0x40;
sd_rspseg = sysdat + 0x42;
sd_endseg = sysdat + 0x44;
sd_module_map = sysdat + 0x46;
sd_ncns = sysdat + 0x47;
sd_nlst = sysdat + 0x48;
sd_nccb = sysdat + 0x49;
sd_nflags = sysdat + 0x4A;
sd_srchdisk = sysdat + 0x4B;
sd_mmp = sysdat + 0x4C;
sd_nslaves = sysdat + 0x4E;
sd_dayfile = sysdat + 0x4F;
sd_tempdisk = sysdat + 0x50;
sd_tickspsec = sysdat + 0x51;
sd_lul = sysdat + 0x52;
sd_ccb = sysdat + 0x54;
sd_flags = sysdat + 0x56;
sd_mdul = sysdat + 0x58;
sd_nxmds = sysdat + 0x58;
sd_mfl = sysdat + 0x5A;
sd_nmparts = sysdat + 0x5A;
sd_pul = sysdat + 0x5C;
sd_nxpd = sysdat + 0x5C;
sd_qul = sysdat + 0x5E;
sd_nqds = sysdat + 0x5D;
sd_qmau = sysdat + 0x60; /* (4) */
sd_qmastart = sysdat + 0x62;
sd_qmalen = sysdat + 0x64;
sd_verptr = sysdat + 0x78;
sd_vn = sysdat + 0x7A;
sd_mpmvn = sysdat + 0x7C;
sd_ncondev = sysdat + 0x83;
sd_nlstdev = sysdat + 0x84;
sd_nciodev = sysdat + 0x85;
sd_lcb = sysdat + 0x86;
sd_popen_max = sysdat + 0x8A;
sd_plock_max = sysdat + 0x8B;
sd_cmode = sysdat + 0x90;
sd_xpcns = sysdat + 0x9f;
}
/************************************************************************/
/* doxios: gets miscellaneous XIOS values from user */
/************************************************************************/
BYTE *
doxios(bb,xmtitle) /* submenu for XIOS value mods */
BYTE *bb; /* value passed in from menu */
BYTE *xmtitle;
{
BYTE cmds[CMDSLEN]; /* space for additional commands */
EXTERN BYTE *clearit;
if( bb != NULLPTR ) { /* if any "command line" arguments */
domenu(bb); /* do what they've asked for */
} else FOREVER { /* work with user for a while */
printf("%s",clearit); /* clear screen */
prtmenu(xmtitle); /* display user options */
printf(PROMPT); /* prompt user */
if( gets(cmds)!=cmds || /* on end of file */
*cmds==NULL ) /* or blank line of input */
break; /* exit interaction with user */
domenu(cmds); /* do what they've asked for */
} /*****************************/
return NULLPTR; /* standard return... */
}
/************************************************************************/
/* dosysp: gets miscellaneous system paramaters from user */
/************************************************************************/
BYTE *
dosysp(bb,smtitle) /* submenu for SYSP value mods */
BYTE *bb; /* value passed in from menu */
BYTE *smtitle;
{
BYTE cmds[CMDSLEN]; /* space for additional commands */
EXTERN MENU *syspmenu; /* list of menu items for sysp menu */
EXTERN BYTE *clearit;
if( bb != NULLPTR ) { /* if any "command line" arguments */
domenu(bb,syspmenu); /* do what they've asked for */
} else FOREVER { /* work with user for a while */
printf("%s",clearit); /* clear screen */
prtmenu(smtitle,syspmenu); /* display user options */
printf(PROMPT); /* prompt user */
if( gets(cmds)!=cmds || /* on end of file */
*cmds==NULL ) /* or blank line of input */
break; /* exit interaction with user */
domenu(cmds,syspmenu); /* do what they've asked for */
} /*****************************/
return NULLPTR; /* standard return... */
}
/*************************************************************************/
/* dorsp: handles rsp editting */
/*************************************************************************/
BYTE *
dorsp(parm,xmtitle) /* handle RSP list editting */
BYTE *parm; /* command value parameter */
BYTE *xmtitle;
{
BYTE cmds[CMDSLEN]; /* space for additional commands */
EXTERN MENU *rspmenu; /* list of menu items for rsp menu */
EXTERN BYTE *clearit;
if( parm != NULLPTR ) { /* if any "command line" arguments */
domenu(parm,rspmenu); /* do what they've asked for */
} else FOREVER { /* work with user for a while */
printf("%s",clearit); /* clear screen */
rsp_display(rsps); /* display what they have to work with */
prtmenu(xmtitle,rspmenu); /* display user options */
printf(PROMPT); /* prompt user */
if( gets(cmds)!=cmds || /* on end of file */
*cmds==NULL ) /* or blank line of input */
break; /* exit interaction with user */
domenu(cmds,rspmenu); /* do what they've asked for */
} /*****************************/
return NULLPTR; /* standard return... */
}
/*************************************************************************/
BYTE *
rspinclude(rs)
BYTE *rs;
{
BYTE *bp, *cp, *ep; /* ptrs to take apart command str */
DLIST *dd;
if( rs==NULLPTR || *rs==NULL )
return "You need to say 'include=xx.rsp,yy.rsp,zz.rsp'";
for( ep=rs; *ep; ++ep ) ; /* end of string pointer */
for( bp=rs; bp<ep; bp=cp+1 ){ /* process each rsp spec */
for( cp=bp; *cp && *cp!=','; ++cp ) ; /* find eos or comma */
if( *cp == ',' ) *cp = '\0'; /* null terminate the spec */
if( (dd=dirsearch(bp)) == NULLPTR )
return "Can't find RSP to include";
rspjoin(dd);
}
return NULLPTR;
}
rspjoin(dd)
DLIST *dd;
{
DLIST *rs;
if( rsps == NULLPTR )
rsps = dd;
else {
for( rs=rsps; rs->dlnext != NULLPTR; rs=rs->dlnext ) ;
rs->dlnext = dd;
}
}
/*************************************************************************/
BYTE *
rspexclude(rs)
BYTE *rs;
{
BYTE *bp, *cp, *ep;
BOOLEAN rspzap();
if( rs==NULLPTR || *rs==NULL )
return "You need to say 'exclude=aa.rsp,bb.rsp,cc.rsp'";
for( ep=rs; *ep; ++ep ) ; /* find eos */
for( bp=rs; bp<ep; bp=cp+1 ){ /* process each rsp spec */
for( cp=bp; *cp && *cp!=','; ++cp ) ; /* find eos or comma */
if( *cp == ',' ) *cp = '\0'; /* null terminate the spec */
if( !rspzap(bp) )
return "Can't find RSP to exclude";
}
return NULLPTR;
}
BOOLEAN
rspzap(nm)
BYTE *nm;
{
DLIST **qs, *ps, *rs;
if( *nm == '*' ) { /* zap entire list? */
for( ps=rsps; ps!=NULLPTR; ps=rs ) {
rs = ps->dlnext;
free(ps);
}
rsps = NULLPTR;
return TRUE;
}
for( qs= &rsps; *qs!=NULLPTR; qs = &rs->dlnext ) { /* zap part of list */
rs = *qs;
if( namematch(nm,rs->dlname) ) {
*qs = rs->dlnext;
free(rs);
return TRUE;
}
}
return FALSE; /* thru loop, can't find it */
}
namematch(s1,s2)
BYTE *s1, *s2;
{
for( ; *s1 && *s2; ++s1, ++s2 )
if( toupper(*s1) != toupper(*s2) )
return FALSE;
if( *s1 || *s2 )
return FALSE;
else return TRUE;
}
/**************************************************************************/
#define PAGEWIDTH 72
rsp_display(rp)
DLIST *rp;
{
WORD ii;
printf("\nRSPs to be included are:\n");
for( ii=0; rp!=NULLPTR; rp = rp->dlnext ) {
if( (ii += 15) > PAGEWIDTH ) {
printf("\n");
ii=15;
}
printf(" %12.12s",rp->dlname);
}
printf("\n");
}
/**************************************************************************/
/* grpseek: seeks in MOD file 'fd' to the start of a code/data group, */
/* returns length (in bytes) of that group */
/*************************************************************************/
LONG
grpseek(fde,gt)
WORD fde; /* file descriptor */
WORD gt; /* group type to look for */
{
WORD gc; /* group counter */
LONG dps; /* pgphs to group base in file */
GROUP grp; /* structure for Cmd Hdr info */
if( lseek(fde,0L,0) < 0 ) /* seek to beginning of file */
CRASH("grp cmd header seek failed\n");
dps=8; /* pgphs to start of load group */
for( gc=0; gc<8; gc++ ) { /* search up to 8 groups in cmd hdr */
read(fde,&grp,sizeof(grp)); /* read each group in header */
if( grp.gtype == gt ) /* the group we want */
break;
dps += grp.glen; /* add in size of previous group */
}
if( grp.gtype != gt ) /* did we find the group? */
return ((LONG) FAILURE); /* nope, so fail */
dps = dps << 4; /* pgphs xfm to bytes */
if( lseek(fde,dps,0) < 0 ) /* seek to start of data group */
CRASH("grp group seek failed\n");
return ((LONG)((grp.glen)<<4)); /* return group size in bytes */
}
/**************************************************************************/
/* xfer rtns: transfer a group from file 'module' to file NEWSYS (fns)
/* returns number of paragraphs in the group
/**************************************************************************/
UWORD
xfergrp(module,group_type)
BYTE *module; /* module name */
WORD group_type; /* code? or data? */
{
REG WORD fm; /* file descriptor for module */
REG UWORD rv,xferpart_grp(); /* return value */
if( (fm=BROPEN(module)) < 0 ) /* open the module for binary reading */
CRASH("can't find a system module\n");
rv = xferpart_grp(fm,group_type,0);
close(fm);
return rv;
}
/**************************************************************************/
UWORD
xferpart_grp(fm,gt,skip)
WORD fm; /* file descriptor for module */
WORD gt; /* group type: code or data */
UWORD skip; /* num pgphs to skip in this group */
{
REG WORD ii; /* counter */
REG LONG xx, yy; /* long counters */
BYTE xferbuf[BUFSIZ]; /* a transfer buffer */
GROUP grp; /* a group area */
if( lseek(fm,0L,0) < 0 ) /* seek to beginning of file */
CRASH("grp cmd header seek failed\n");
yy = skip+8; /* num pgphs to skip + in cmd hdr */
for( ii=0; ii<8; ++ii ) { /* read group hdrs in cmd hdr */
read(fm,&grp,sizeof(grp));
if( grp.gtype == gt )
break;
yy += grp.glen; /* count #pgphs in this group to skip */
}
if( grp.gtype!=gt ) CRASH("module doesn't have group\n");
xx = yy << 4; /* cvt to bytes */
if( lseek(fm,xx,0)<0 ) CRASH("couldn't seek in module\n");
xx = grp.glen; xx -= skip; /* pgphs to xfer */
for( yy=xx<<4; yy>0; yy-=ii ){ /* xfer bytes to NEWSYS */
ii = ( yy > BUFSIZ ? BUFSIZ : yy ); /* num bytes per xfer */
if( read(fm,xferbuf,ii) != ii ) CRASH("not enough bytes in module\n");
write(fns,xferbuf,ii);
}
return (UWORD)(xx); /* convert to pgphs */
}
/**************************************************************************/
/* help: prints out a help message */
/**************************************************************************/
BYTE *helpm1[] = {
"\n\n",
#ifdef MCPM
"\t\t*** GENCMPM Help Function ***",
"\t\t=============================",
" GENCMPM lets you edit and/or generate a system image from",
#else
"\t\t*** GENCCPM Help Function ***",
"\t\t============================",
" GENCCPM lets you edit and/or generate a system image from",
#endif
"operating system modules on the default drive. A detailed",
"explanation of each parameter may be found in the Concurrent CP/M-86",
"System Guide, Section 2.\n",
#ifdef MCPM
" GENCMPM assumes the default values shown within square",
#else
" GENCCPM assumes the default values shown within square",
#endif
"brackets. All numbers are Hexadecimal. To change a parameter,",
"enter the parameter name followed by '=' and the new value. Type",
"<CR> (a carriage return) to enter the assignment. You can make",
"multiple assignments if you separate them by a space. No spaces",
"are allowed within an assignment. Example:\n",
"CHANGES? verbose=N sysdrive=A: openmax=1A <CR>\n",
"Parameter names may be shortened to the minimum combination of",
"letters unique to the currently displayed menu. Example:\n",
"CHANGES? v=N sysd=A: op=1a <CR>\n",
NULLPTRI
};
BYTE *helpm2[] = {
"\n\n",
"Sub-menus (the last few options without default values) are accessed",
"by typing the sub-menu name followed by <CR>. You may enter",
"multiple sub-menus, in which case each sub-menu will be displayed",
"in order. Example:\n",
"CHANGES? help sysparams rsps <CR>\n",
"Enter <CR> alone to exit a menu, or a parameter name, '=' and the",
"new value to assign a parameter. Multiple assignments may be",
"entered, as in response to the Main Menu prompt.\n",
NULLPTRI
};
BYTE *
help(tx) /* print a helpful message to user */
BYTE *tx;
{
REG BYTE **cpp; /* pointer to help strings */
for( cpp=helpm1; *cpp != NULLPTR; cpp++ )
printf("%s\n",*cpp);
press_return();
for( cpp=helpm2; *cpp != NULLPTR; cpp++ )
printf("%s\n",*cpp);
press_return();
return NULLPTR;
}
/************************************************************************/
/* memory list allocation */
/**************************************************************************/
BYTE *
domem(cmdval,memtitle)
BYTE *cmdval;
BYTE *memtitle;
{
WORD cntmlist(); /* does list validation */
BOOLEAN okl; /* okay list */
BYTE cmds[CMDSLEN]; /* place to put input */
EXTERN MLIST *memroot; /* memory list root */
EXTERN MENU *memmenu; /* memory edit menu */
EXTERN BYTE *clearit;
okl = (cntmlist(memroot) > 0); /* overlap chk & condense */
if(cmdval!=NULLPTR) {
domenu(cmdval,memmenu); /* do the commands */
okl = (cntmlist(memroot)>0);/* check the results */
}
if( !okl || cmdval==NULLPTR ) /* do we need to interact with user? */
FOREVER { /* display, the edit */
printf("%s",clearit); /* clear the screen (maybe) */
dspmlist(memroot); /* here's what it looks like */
prtmenu(memtitle,memmenu); /* here's how to edit */
printf(PROMPT); /* what to do? */
if( gets(cmds)!=cmds || *cmds==NULL ) { /* see if the want to get out */
if(okl)
break;
else {
printf("Please adjust memory partitions\n");
press_return();
continue;
}
}
domenu(cmds,memmenu); /* edit the memory list */
okl = (cntmlist(memroot)>0);/* validate the memory list */
}
return NULLPTR; /* standard return */
}
/**************************************************************************/
BYTE *
addmem(ms) /* add memory partitions */
BYTE *ms; /* memory partition spec */
{
REG BYTE *pl; /* pointer to last addr spec */
REG BYTE *ps; /* pointer to size spec */
UWORD f, l, qq, s; /* values of spec */
MLIST *intomlist(), *mnew; /* where to put them */
EXTERN MLIST *memroot; /* memory partitions list */
BYTE *badspec = "Add memory partition spec should look like:\n\tadd=first,last,size";
BYTE *badval = "Spec: add=first,last,size\n\twhere last>first, size>80";
BYTE *warnbig = "Warning: size too big, it will be truncated";
BYTE *warnleft = "Warning: region not evenly divided by size, will adjust last partition";
BYTE *rval;
BYTE *index();
rval = NULLPTR; /* default return value */
if( (pl=index(ms,','))==0) /* look for ptr to last addr */
return badspec;
else *pl++ = NULL; /* terminate first addr spec */
if( (ps=index(pl,','))==0) /* look for ptr to size */
return badspec;
else *ps++ = NULL;
f=atoih(ms); /* convert first addr spec */
s=atoih(ps); /* convert size spec */
if( *pl=='+' ) /* last addr relative to first? */
l=atoih(pl+1)+f; /* yes, so calculate */
else if( *pl==NULL || *pl=='*' ) {
if( *pl=='*' ) /* last addr multiple of size? */
l=atoih(pl+1); /* spec multiple */
else l=1; /* default multiple=1 */
l = f+l*s; /* s in paragraphs */
} else l=atoih(pl); /* no, it's absolute address */
if( l<=f || s==0 ) /* 1st validation check */
return badval;
if( s > l-f ) { /* 2nd validation check */
rval = warnbig;
s = l-f;
}
if( s<MINKMEM ) /* 3rd validation check */
return "Memory partition must be at least 80 paragraphs";
qq = ((l-f)/s)*s; /* make sure last == first + xx * s */
if( qq != (l-f) ) { /* 4th validation check */
rval = warnleft;
l = f+qq;
}
mnew = (MLIST *)malloc(sizeof(*mnew)); /* make room */
mnew->mlfirst = f;
mnew->mllast = l;
mnew->mlsize = s;
memroot=intomlist(memroot,mnew); /* sorted insertion into list */
return rval; /* everything okay */
}
/**************************************************************************/
BYTE *
delmem(ms) /* delete memory partition */
BYTE *ms;
{
REG WORD df, dl; /* delete first, last */
MLIST **mm, **mn, *mo, *mp, *mq; /* necessary list ptrs */
EXTERN MLIST *memroot; /* memory partitions list */
BYTE *pl;
WORD i;
BYTE *badspec="To delete a memory partition, say\n\tdelete=1 or delete=1-3\n";
if( *ms == '*' ) { /* delete all? */
for( mp=memroot; mp!=NULLPTR; mp=mq ) {
mq = mp->mlnext; /* save the pointer before we free it */
free(mp);
}
memroot = NULLPTR;
return NULLPTR; /* everything okay */
}
if( (pl=index(ms,'-')) == 0 )
pl=ms; /* point last to first */
else *pl++ = NULL; /* else point to after 'dash' */
df=atoi(ms); /* decimal conversion */
dl=atoi(pl);
for( i=1, mm=&memroot, mn=NULLPTR, mo=memroot;
i<=dl && mo!=NULLPTR;
++i ) {
if( i==df ) mn=mm; /* found first, pt to ptr to */
mm = &mo->mlnext; /* ptr to ptr */
mo = mo->mlnext;
}
if( mn==NULLPTR || i<=dl ) /* check range of deletions */
return badspec;
mp = *mn; /* save ptr to deleted list */
*mn = mo; /* cut them suckers out of the list */
for( ; mp!=mo; mp=mq ) {
mq = mp->mlnext;
free(mp);
}
return NULLPTR; /* everything ok */
}
/**************************************************************************/
dspmlist(mroot)
MLIST *mroot;
{
MLIST *mn, *mo;
REG WORD i, nump;
printf("\n\n");
printf(" Addresses Partitions (in paragraphs)\n");
printf(" # Start Last Size Qty \n");
for( i=1, mn=mroot; mn!=NULLPTR; ++i, mn=mo ) {
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
printf("%2.2d. %4.4xh %4.4xh %4.4xh %4.4xh ",
i,mn->mlfirst,mn->mllast,mn->mlsize,nump);
if( (mo=mn->mlnext) != NULLPTR ) { /* do some checking */
if( mn->mllast > mo->mlfirst )
printf("**overlaps** ");
if( mn->mlsize > mn->mllast-mn->mlfirst )
printf("**partition too big** ");
}
printf("\n");
}
}
/**************************************************************************/
WORD
cntmlist(mroot) /* check for overlaps, condense if possible */
MLIST *mroot; /* returns number mem partitions, 0 if bad list */
{
MLIST *mn, *mo; /* ptr within list */
REG BOOLEAN olap; /* partitions overlap or bad size */
REG WORD nump; /* number of partitions this block */
REG WORD totnump; /* keep the count going */
totnump = 0; /* total number partitions */
olap = FALSE; /* innocent until proven guilty */
for( mn=mroot; mn!=NULLPTR && (mo=mn->mlnext)!=NULLPTR; ) {
if( mn->mlsize==mo->mlsize ){ /* partitions same size? */
if( mn->mlfirst==mo->mlfirst && /* same partitions? */
mn->mllast==mo->mllast ) {
mn->mlnext=mo->mlnext;
free(mo); /* mo is redundant, zap it */
continue;
} else
if( mn->mllast==mo->mlfirst || /* adjacent partition? */
mn->mllast==(mo->mlfirst-1) ) {
mn->mllast=mo->mllast; /* make 1st partition bigger */
mn->mlnext=mo->mlnext; /* zap out mo from list */
free(mo); /* we don't need it any more */
continue;
}
}
if( mn->mllast > mo->mlfirst )
olap=TRUE; /* partitions overlap */
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
if( nump<=0 )
olap=TRUE; /* size > partition */
else totnump += nump; /* incr this count */
mn=mo; /* continue through loop */
}
if( mn!=NULLPTR ) { /* catch the last in the loop */
nump = (mn->mllast-mn->mlfirst) / mn->mlsize;
if( nump<=0 )
olap=TRUE; /* size > partition */
else totnump += nump; /* incr this count */
}
if( olap )
return 0; /* boo boo, return 0 */
else return totnump; /* return num partitions */
}
/**************************************************************************/
MLIST *
intomlist(mroot,mi) /* insert mi into list mroot sorted */
MLIST *mroot;
MLIST *mi;
{
MLIST **mm; /* ptr to ptr to list */
MLIST *mn; /* ptr to list */
for( mm=&mroot, mn=mroot;
mn != NULLPTR && mi->mlfirst > mn->mlfirst; ){
mm = &mn->mlnext;
mn = mn->mlnext;
}
mi->mlnext = mn;
*mm = mi;
return mroot;
}
/**************************************************************************/
UWORD /* returns new size of partition, 0 if not enough room */
trimit(start,last,olds)
UWORD start; /* start address of partition */
UWORD last; /* end address of partition */
UWORD olds; /* old partition size */
{
REG UWORD ss;
ss = last-start; /* size is in paragraphs */
if( ss<MINKMEM ) return 0; /* sorry, too small */
else if( ss<olds ) return ss-1; /* needs to be smaller */
else return olds; /* fine just the way it is */
}
WORD
onbounds(start,size,nst)
UWORD start; /* original starting boundary */
UWORD size; /* partition size */
UWORD nst; /* new starting address */
{ /* returns addr>nst multiple of size from start */
REG UWORD rr;
for( rr=start; rr<nst; rr += size )
;
return rr;
}
/**************************************************************************/
/* trimlist: trims the memory list according to OS bounds */
/**************************************************************************/
BOOLEAN /* returns TRUE iff any adjustments */
trimlist(osstart,osend)
UWORD osstart; /* starting pgph */
UWORD osend; /* ending pgph */
{
EXTERN MLIST *memroot;
REG MLIST **mm, *mn, *mo; /* ptrs into memlist */
REG UWORD ss, zz; /* temp vars */
LOCAL WORD adjusts; /* number of collisions */
adjusts = 0; /* we haven't adjusted anything yet */
for( mm=&memroot, mn=memroot; mn!=NULLPTR; mn=*mm ) {
if( mn->mlfirst < osstart ) {
if( mn->mllast >= osstart ) { /** collision **/
++adjusts; /* we're doing some adjusting */
if( mn->mllast > osend ) { /* real big mem part? */
mo = (MLIST *)malloc(sizeof *mo); /* set it up now, adjust it later */
mo->mlfirst = onbounds(mn->mlfirst,mn->mlsize,osstart);
mo->mllast = mn->mllast;
mo->mlsize = mn->mlsize;
mo->mlnext = mn->mlnext;
mn->mlnext = mo;
}
if( (zz=trimit(mn->mlfirst,osstart-1,mn->mlsize)) > 0 ) {
mn->mllast = osstart-1;
mn->mlsize = zz; /* in case it was trimmed */
} else { /* partitions too small, delete it */
*mm = mn->mlnext;
free(mn);
continue; /* don't increment list ptr */
}
} /**** end collision ****/
} else if( mn->mlfirst < osend ) { /** collision **/
++adjusts; /* we're doing some adjusting */
if( mn->mllast <= osend ) { /* does part cross past os? */
*mm = mn->mlnext; /* no, delete it */
free(mn);
continue;
}
ss = onbounds(mn->mlfirst,mn->mlsize,osend);
if( (zz=trimit(osend,ss,mn->mlsize)) > 0 ){/* set up a smaller mem part */
mo = (MLIST *)malloc(sizeof *mo);
mo->mlfirst = osend+1;
mo->mllast = ss;
mo->mlsize = zz;
mo->mlnext = mn;
*mm = mo;
mm = &mo->mlnext;
}
if( (zz=trimit(ss,mn->mllast,mn->mlsize)) > 0 ){
mn->mlfirst = ss;
mn->mlsize = zz;
} else { /* partition too small, delete */
*mm = mn->mlnext;
free(mn);
continue; /* don't bottom out on this loop */
}
} /**** end collision ****/
mm = &mn->mlnext; /* set up for next partition check */
} /**** end FOR loop ***/
return adjusts>0; /* returns TRUE if we adjusted */
}


View File

@@ -0,0 +1,569 @@
/*********************************************************************/
/*********************************************************************/
/* genc3.c
/* EXPORTS gentable() - the routine which builds all the tables
/*********************************************************************/
/*********************************************************************/
#ifndef MAINMODULE
#include <genccpm.h>
#endif
MLOCAL UWORD rsp_last; /* link to previous RSP */
MLOCAL UWORD rsp_seg; /* where next RSP seg gets written */
#define ALIGN(xx) (((xx)+0xF)&0xFFF0)
#define BYTE_ADJUST(yy) if(yy>0xFF) yy=0xFF
/*************************************************************************/
UWORD /* return new offset */
segwrite(nbs) /* pad to paragraph boundary */
UWORD nbs; /* old offset */
{
REG UWORD nps;
if( nbs & 0xF ) { /* does it need padding? */
nps = 0x10 - (nbs & 0xF); /* number pad bytes needed */
write(fns,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",nps);
return (nbs+nps);
} else return nbs;
}
UWORD /* return num paragraphs */
padwrite(nbs) /* pad to paragraph boundary */
UWORD nbs; /* num bytes needing padding */
{
return segwrite(nbs) >> 4; /* convert to pgphs */
}
UWORD
datwrite(from,size)
BYTE *from;
WORD size;
{
if( write(fns,from,size) != size ) {
fprintf(stderr,"ERROR: Write to new SYS file failed\n");
fprintf(stderr,"Out of room on disk?\n");
exit(1);
}
return size;
}
/**************************************************************************/
MLOCAL LONG oldladdr=0; /* save previous address for comparison */
#define BIGWORD 0x0000ffffL
chkaddr(uaddr) /* check for SYSDAT overflow */
UWORD uaddr;
{
LONG laddr;
laddr = BIGWORD & uaddr;
if( laddr < oldladdr ) {
USERR("ERROR - System Data Area has grown too large\n");
USERR("Try reducing the size of some of the tables\n");
exit(1);
}
oldladdr = laddr; /* save for wrap around compare */
}
/* this is a kluge: I did it because I couldn't get the LONG cast */
/* to work without doing sign extension... whf 1/20/83 */
/**************************************************************************/
/* EXPORT gentables: generates various tables in system data area,
/* and handles RSPs
/**************************************************************************/
VOID gentables()
{
LOCAL WORD nmparts; /* number of memory partitions */
LOCAL WORD nsat_items; /* number of SAT items in qmau */
LOCAL UWORD damds; /* offset of beginning of tables */
LOCAL UWORD daqbuf; /* offset of beginning of qbuf */
LOCAL LONG daend; /* sys data offset: end of data area */
LOCAL UWORD doffset; /* current offset into data area */
LOCAL UWORD lastlink; /* helps link lists together */
LOCAL WORD count; /* counts num list items being generated */
LOCAL UWORD ucount; /* unsigned counter */
LOCAL MLIST *mn; /* for trapsing down memroot */
LOCAL WORD nump; /* local number partitions */
LOCAL UWORD saddr; /* local starting addr */
LOCAL WORD length; /* local partition length */
BYTE buf[SECSIZ]; /* an area for writing */
LOCAL LONG dmagic; /* fixup location for xt_alloc info */
UWORD genmfl(); /* gen a memory free list */
UWORD genxios(); /* go gen the xios disk buffers */
DLIST *rs; /* ptr to rsp list */
MD md; /* sample memory descriptor */
PD pd; /* " process descriptor */
QCB qcb; /* " queue control block */
CCB ccb; /* " channel control block */
LOCK lock; /* " lock list item */
FLAG flg; /* " flag item */
SATITEM sat; /* " sub allocation table item */
if(verbose) printf("Generating tables\n");
FCHECK(fns); /* File error check */
/* pre-calculate certain vars */
bufs_seg = 0; /* total buf segs allocated in rsvd_seg */
if( (nmparts=cntmlist(memroot)) <= 0 )
CRASH("invalid memory list, aborting\n");
totpds = xtrapds + nmparts; /* 1 pd per memory partition, plus xtras */
BYTE_ADJUST(totpds);
totmds = (3*totpds) + nmparts + (nmparts>>1); /* 3 mds per process, plus */
/* 1 per partition, plus extra for */
/* memory allocator worst case */
BYTE_ADJUST(totmds);
nsat_items = (1+ (1+2*totqcbs)); /* 1 for header entry plus worst case */
dltotal = dlsysdat+dlxios; /* keep track of total data length in pgphs */
doffset = dltotal << 4; /* calculate current data offset */
dsotables = doffset; /* mark the start of tables */
chkaddr(doffset); /* init the function */
/* MEMORY FREE LIST */
locmfl = lseek(fns,0L,1); /* remember where we are writing this */
doffset = genmfl(doffset); /* gen the mem free list */
lastlink = 0; /* UNUSED MEMORY DESCRIPTOR LIST */
zfill(&md,sizeof md); /* init the mem descriptor */
for( count=totmds-nmparts; count>0; --count ) { /* generate rest of mds */
md.md_link = lastlink;
lastlink = doffset;
doffset += datwrite(&md,sizeof(md));
}
*sd_mdul = lastlink; /* store ptr to mds unused */
lastlink = 0; /* UNUSED PROCESS DESCRIPTOR LIST */
zfill(&pd,sizeof(pd));
for( count=totpds; count>0; --count ) {
pd.pd_link = lastlink;
lastlink = doffset;
doffset += datwrite(&pd,sizeof(pd));
}
*sd_pul = lastlink; /* store ptr to pds unused */
lastlink = 0; /* UNUSED QUEUE CONTROL BLOCKS */
zfill(&qcb,sizeof(qcb));
for( count=totqcbs; count>0; --count ) {
qcb.qc_link = lastlink;
lastlink = doffset;
doffset += datwrite(&qcb,sizeof(qcb));
}
*sd_qul = lastlink; /* store ptr to unused qcb list */
lastlink = 0; /* UNUSED LOCKED ITEMS LIST */
zfill(&lock,sizeof(lock));
for( count=totopen; count>0; --count ) {
lock.lo_link = lastlink;
lastlink = doffset;
doffset += datwrite(&lock,sizeof(lock));
}
*sd_lul = lastlink; /* store ptr to unused lock items list */
*sd_ncns = xt.xt_nvcns; /* transfer info from XIOS to SYSDAT*/
*sd_ncondev = xt.xt_nccbs;
*sd_ccb = xt.xt_ccb;
*sd_nlst = xt.xt_nlcbs;
*sd_nlstdev = xt.xt_nlcbs;
*sd_lcb = xt.xt_lcb;
*sd_nciodev = *sd_ncondev + *sd_nlstdev;
*sd_tickspsec = xt.xt_ticks_sec;
*sd_xpcns = xt.xt_xpcns; /* # physical consoles;FMB */
*sd_flags = doffset; /* FLAG TABLE */
flg.fl_status = -1;
flg.fl_pd = -1;
for( count= *sd_nflags; count>0; --count ) {
doffset += datwrite(&flg,sizeof(flg));
}
doffset = genxios(doffset); /* go gen the xios buffering info */
chkaddr(doffset); /* is table space too big? */
doffset = segwrite(doffset); /* Q Sub Alloc Tab HEADER */
*sd_qmastart = dsstart + (doffset>>4); /* fill in seg addr */
daqbuf = doffset + sizeof(sat)*nsat_items;
zfill(&sat,sizeof(sat));
sat.sa_start = --nsat_items; /* decr before write */
doffset += datwrite(&sat,sizeof(sat)); /* write the header */
/* Q Sub Alloc Tab ENTRIES */
sat.sa_start = daqbuf;
sat.sa_length = qbuflen; /* byte value */
*sd_qmalen = qbuflen>>4; /* pgph value */
doffset += datwrite(&sat,sizeof(sat)); /* write the first sat entry */
zfill(&sat,sizeof(sat));
for( count= --nsat_items; count>0; --count ) {
doffset += datwrite(&sat,sizeof(sat));/* write the rest of the sat entries */
}
zfill(buf,SECSIZ); /* Q BUFFER AREA */
for( ucount=qbuflen; ucount>0; ucount -= length ) {
length = (ucount>SECSIZ ? SECSIZ : ucount);
doffset += datwrite(buf,length);
}
chkaddr(doffset); /* too big? */
daend = padwrite(doffset); /* end Q BUF AREA and TABLES */
dltables = daend - dltotal; /* compute length of tables in pgphs */
dltotal = daend; /* keep track of total data length */
/*** now fill in the rsps ***/
if(verbose) printf("Appending RSPs to system file\n");
FCHECK(fns); /* File error check */
rsp_last = 0;
rsp_seg = dsstart + daend;
for( rs=rsps; rs!=NULLPTR; rs=rs->dlnext ) /* follow the rsp list */
xfer_rsp(rs->dlname);
*sd_rspseg = rsp_last;
dlrsps = rsp_seg - (dsstart + daend);
dltotal += dlrsps;
rsvd_seg = rsp_seg;
length = xt.xt_alloc; /* how much memory is XIOS requesting */
xt.xt_alloc = rsvd_seg+bufs_seg; /* this is the place they can use */
dmagic = fldstart; /* location of SYSDAT in SYS file */
dmagic += XTABALLOC; /* add in where xt_alloc goes to */
fixlater(dmagic,F_PUT,&(xt.xt_alloc)); /* fix this number later on */
bufs_seg += length; /* allocate requested space */
*sd_endseg = rsvd_seg+bufs_seg; /* this is where we reserve to */
}
/**************************************************************************/
/* genmfl: writes out a memory free list, assuming file 'fns' is seeking
/* correctly into file.
/**************************************************************************/
UWORD
genmfl(doffset)
UWORD doffset;
{
REG MLIST *mn; /* ptr into EDSYS mem list */
LOCAL WORD nump;
LOCAL UWORD lastlink, length, saddr; /* counter vars */
MD md; /* mem desc struct */
*sd_mfl = doffset; /* gen this list forward */
zfill(&md,sizeof(md)); /* init the data structure */
for( mn=memroot; mn!=NULLPTR; mn=mn->mlnext ) {
nump = (mn->mllast - mn->mlfirst) / mn->mlsize;
saddr = mn->mlfirst; /* use this starting address */
length = md.md_length = mn->mlsize; /* size in pgphs */
for( ; nump>0; --nump ) { /* for each partition */
doffset += sizeof(md); /* incr by sizeof object */
lastlink = doffset; /* record address of where this will go */
if( nump == 1 ) { /* on this group's last partition */
length = md.md_length = mn->mllast-saddr; /* stick in rmdr */
if( mn->mlnext == NULLPTR ) /* on the very last partition */
lastlink=0; /* set end of list */
}
md.md_link = lastlink; /* thread the list */
md.md_start = saddr; /* set the starting addr */
write(fns,&md,sizeof(md)); /* put it into the NEWSYS file */
saddr += length; /* next md starts here */
}
} /* finished with memory partitions */
return doffset;
}
/**************************************************************************/
VOID
zfill(addr,num)
BYTE *addr;
WORD num;
{
for( ; num>0; --num )
*addr++ = '\0';
}
/**************************************************************************/
/**************************************************************************/
#define RSPHDR struct rsp_header
RSPHDR {
UWORD rs_link; /* link to other RSPs */
WORD rs_sdatvar; /* SYSDAT offset: num copies */
BYTE rs_ncopies; /* local: num copies */
BYTE rs_space[11]; /* fill up rest of header */
};
RSPHDR *rhdr; /* RSP's header */
PD *rpd; /* RSP's process descriptor area */
UDA *ruda; /* RSP's uda area */
#define RHDRSIZE (sizeof(RSPHDR)+sizeof(PD)+sizeof(UDA))
#define RHDRPGPHS (RHDRSIZE>>4)
MLOCAL BYTE rh[RHDRSIZE]; /* where to read the RSP header */
MLOCAL BYTE rspnbuf[9]; /* room for copy of pd name */
MLOCAL BYTE *rspname; /* name of RSP */
/**************************************************************************/
xfer_rsp(rspnm)
BYTE *rspnm; /* name of rsp */
{
LOCAL WORD fr; /* rsp file descriptor */
LOCAL WORD ncs; /* number of copies */
rhdr = rh; /* init these vars */
rpd = rh+sizeof(*rhdr); /* points to process descriptor */
ruda = rh+sizeof(*rhdr)+sizeof(*rpd); /* points to user data area */
if( (fr=BROPEN(rspnm)) < 0 ) {
printf("can't open RSP %s\n",rspnm);
exit(1);
}
if( grpseek(fr,GTYPDATA) > 0L){ /* is there a data group? */
ncs = grab_hdr(fr);
if( rpd->pd_mem == 0 )
xfer_separate_rsp(fr,ncs);
else xfer_pure_rsp(fr,ncs);
} else {
grpseek(fr,GTYPCODE);
ncs = grab_hdr(fr);
if( rpd->pd_mem == 0 )
xfer_mixed_rsp(fr,ncs);
else {
USERR("RSP %s has non zero MEM field and no data group\n",
rspnm);
}
}
close(fr);
}
/**************************************************************************/
WORD
grab_hdr(fr)
WORD fr;
{
REG WORD rv; /* return val */
EXTERN BYTE sdat_area[];
rspname = NULLPTR; /* blank out this name */
read(fr,rh,RHDRSIZE);
strncpy(rspnbuf,rpd->pd_name,8);/* store this in case we need it */
if( rhdr->rs_sdatvar != 0 ) {
rspname = rspnbuf;
rv = sdat_area[rhdr->rs_sdatvar] - 1;
} else {
if( rhdr->rs_ncopies > 0 )
rspname = rspnbuf;
rv = rhdr->rs_ncopies;
}
return rv;
}
/**************************************************************************/
xfer_separate_rsp(fr,ncs) /* (many) data and (many) code segs */
WORD fr; /* file desc of RSP file */
WORD ncs; /* number of copies */
{
WORD ii; /* counter */
for( ii=0; ii<=ncs; ++ii) {
ruda->ud_dsinit = ruda->ud_esinit = ruda->ud_ssinit = rsp_seg;
ruda->ud_csinit = rsp_seg + (grpseek(fr,GTYPDATA)>>4);
rhdr->rs_ncopies = ii;
if( rspname ) /* do we need to insert a modfied name? */
putname(rpd->pd_name,rspname,ii);
rhdr->rs_link = rsp_last; /* link together the list */
rsp_last = rsp_seg; /* remember this for next time */
write(fns,rh,RHDRSIZE); /* write out the RSP header */
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPDATA,RHDRPGPHS);
rsp_seg += xferpart_grp(fr,GTYPCODE,0);
}
}
/**************************************************************************/
xfer_pure_rsp(fr,ncs) /* (many) data segs and one code segs */
WORD fr; /* file desc of RSP file */
WORD ncs; /* number of copies */
{
WORD ii; /* counter */
ruda->ud_csinit = rsp_seg + (1+ncs) * (grpseek(fr,GTYPDATA) >> 4);
for( ii=0; ii<=ncs; ++ii) {
ruda->ud_dsinit = ruda->ud_esinit = ruda->ud_ssinit = rsp_seg;
rhdr->rs_ncopies = ii;
if( rspname ) /* do we need to insert a modfied name? */
putname(rpd->pd_name,rspname,ii);
rpd->pd_mem = 8; /* magic ptr to md in rsphdr */
rhdr->rs_link = rsp_last; /* link together the list */
rsp_last = rsp_seg; /* remember this for next time */
write(fns,rh,RHDRSIZE); /* write out the RSP header */
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPDATA,RHDRPGPHS);
}
rsp_seg += xferpart_grp(fr,GTYPCODE,0);
}
/**************************************************************************/
xfer_mixed_rsp(fr,ncs) /* (many) mixed code/data segs */
WORD fr; /* file desc of RSP file */
WORD ncs; /* number of copies */
{
WORD ii; /* counter */
for( ii=0; ii<=ncs; ++ii) {
ruda->ud_csinit = ruda->ud_dsinit = ruda->ud_esinit =
ruda->ud_ssinit = rsp_seg;
rhdr->rs_ncopies = ii;
if( rspname ) /* do we need to insert a modfied name? */
putname(rpd->pd_name,rspname,ii);
rhdr->rs_link = rsp_last; /* link together the list */
rsp_last = rsp_seg; /* remember this for next time */
write(fns,rh,RHDRSIZE); /* write out the RSP header */
rsp_seg += RHDRPGPHS + xferpart_grp(fr,GTYPCODE,RHDRPGPHS);
}
}
/**************************************************************************/
putname(to,from,num)
BYTE *to;
BYTE *from;
WORD num;
{
BYTE buf[15];
BYTE *bp;
WORD jj;
for( bp=buf, jj=0; *from && *from != ' ' && jj<8; ++jj )
*bp++ = *from++;
if( jj>6 )
bp = buf+7;
sprintf(bp,"%x ",num);
for( bp=buf, jj=0; jj<8; jj++ )
*to++ = *bp++;
}
/************************************************************************/
/* dolbl: modify operating system version label */
/************************************************************************/
#define MAXLBL 83
BYTE *
dolbl(txt,lbtitle)
BYTE *txt; /* cmd val */
BYTE *lbtitle;
{
DLIST *sl, *psl; /* ptrs to system labels */
BYTE mb[MAXLBL]; /* max size of each line */
EXTERN BYTE *clearit;
sl = psl = syslbls; /* init ptrs */
printf("%s\n%s\n",clearit,lbtitle);
printf("Current message is:\n");
if( syslbls==NULLPTR )
printf("<null>\n");
else for( ; sl != NULLPTR; sl = (psl=sl)->dlnext )
printf("%s\n",sl->dlname);
printf("\nAdd lines to message. Terminate by entering only RETURN:\n");
FOREVER {
if( gets(mb) != mb || *mb==NULL )
break;
sl = (DLIST *)malloc(sizeof(*sl)); /* alloc a list item */
sl->dlname = malloc(sizeof(mb));
strcpy(sl->dlname,mb); /* copy message to new space */
sl->dlnext = NULLPTR;
if( psl==NULLPTR ) /* new list? */
syslbls = psl = sl; /* this will be the first line */
else {
psl->dlnext = sl;
psl = psl->dlnext;
}
}
return NULLPTR;
}
/************************************************************************/
/* writelbl: writes the OS label to the NEWSYS file, returning the length
/* of the label (in pgphs)
/************************************************************************/
WORD
_wrlbl(str) /* subroutine to writelbl */
BYTE *str;
{
REG WORD slen;
slen=strlen(str); /* length of string to be written */
write(fns,str,slen); /* write string to file NEWSYS */
write(fns,"\015\012",2); /* cr,lf */
return slen+2;
}
WORD
writelbl() /* returns num pgphs written */
{
REG WORD cc; /* count of chars output */
DLIST *sl; /* list ptr */
cc = 0;
cc += _wrlbl(""); /* crlf */
cc += _wrlbl(version); /* write out the version label */
cc += _wrlbl(copyright); /* followed by copyright notice */
for( sl=syslbls; sl!=NULLPTR; sl=sl->dlnext )
cc += _wrlbl(sl->dlname); /* followed by all lines in OS label */
cc += _wrlbl("$"); /* terminate message for printstr fn */
return padwrite(cc); /* writes enough zeroes to pad to pgph bdry */
}
/***************************************************************************/
/* fixup routines: remembers and posthumously patches the SYS file
/***************************************************************************/
FIX *fixroot = NULLPTRI; /* list of fixes */
fixlater(fa,ft,fp) /* records the fix in the list */
LONG fa; /* addr within NEWSYS to fix */
WORD ft; /* type of fix: F_ADD or F_PUT */
WORD *fp; /* ptr to val used in fixing */
{
FIX *fx;
fx = (FIX *)malloc(sizeof *fx); /* alloc a list item */
fx->f_addr = fa;
fx->f_type = ft;
fx->f_ptr = fp;
fx->f_next = fixroot; /* insert at head of list */
fixroot = fx;
}
fixfile() /* does the fixes in the file */
{
FIX *fx;
WORD fval; /* the value to stuff */
LONG lastval;
lastval=lseek(fns,0L,2); /* end of file */
for( fx=fixroot; fx!=NULLPTR; fx = fx->f_next ) {
if(fx->f_addr > lastval) { /* oops! past eof */
printf("fixup addressing internal error: %X %x %x\n",fx->f_addr,fx->f_type,fx->f_ptr);
continue;
}
if( lseek(fns,fx->f_addr,0) < 0L )
CRASH("fixup seek failure\n");
if( fx->f_type == F_ADD ) { /* F_ADD the value to what's there */
read(fns,&fval,2);
fval += *(fx->f_ptr);
lseek(fns,-2L,1); /* backup to write */
} else /* must be a F_PUT */
fval = *(fx->f_ptr);
write(fns,&fval,2);
}
}


View File

@@ -0,0 +1,766 @@
/************************************************************************/
/************************************************************************/
/* genc4.c - This module exports the following routines:
/*
/* initxios_info(xf,goff) 'xf' is XIOSMOD file descriptor, 'goff'
/* is offset of data group in XIOSMOD (including header);
/* this module inits the buffering info questions.
/* doxbufs(txt,title) 'txt' is a command, 'title' is the prompt for this fn;
/* this routine is called within the MENU module, and prompts user
/* for xios info.
/* xiosvalid() returns a BOOLEAN value indicating whether the xios info
/* is valid.
/* genxios(doffset) generates the buffers for the xios, starting at 'doffset'
/* in the system data area.
/* fixupxios_info() writes DPH fixups required by genxios
/**************************************************************************/
/**************************************************************************/
#ifndef MAINMODULE
#include <genccpm.h>
#endif
/**************************************************************************/
/* edsdisk.h : defines the data structures used in this module
/**************************************************************************/
#define ADDR UWORD /* Address (offset) within SysDat */
#define SEG UWORD /* Segment address (may be outside SysDat) */
#define DPH struct dph_item
DPH { /* Disk Parameter Header structure */
ADDR dph_xlt; /* Translation Table Address */
BYTE dph_space[6]; /* reserved & Media Flag */
ADDR dph_dpb; /* Disk Parameter Block Address */
ADDR dph_csv; /* CheckSum Vector Address */
ADDR dph_alv; /* Allocation Vector Address */
ADDR dph_dirbcb; /* Dir Buffer Control Block Header Address */
ADDR dph_datbcb; /* Data Buffer Control Block Header Address */
SEG dph_hstbl; /* Hash Table Segment */
};
#define EDPB struct edbp_item
EDPB { /* Extended Disk Parameter Block entries */
WORD edpb_extflag; /* Extended DPB flag */
WORD edpb_nfats; /* Number of FATS */
WORD edpb_nfatrecs; /* Number of records per FAT */
WORD edpb_nclstrs; /* Number of clusters */
WORD edpb_clsize; /* Cluster size */
WORD edpb_fatadd; /* FAT address */
};
#define DPB struct dpb_item
DPB { /* Disk Parameter Block structure */
WORD dpb_spt; /* Sectors Per Track */
BYTE dpb_bsh; /* Allocation Block Shift Factor */
BYTE dpb_blm; /* Allocation Block Mask */
BYTE dpb_exm; /* Extent Mask */
WORD dpb_dsm; /* Disk Storage Maximum */
WORD dpb_drm; /* Directory Maximum */
WORD dpb_dav; /* Directory Allocation Vector */
WORD dpb_cks; /* Checksum Vector Size */
WORD dpb_off; /* Track Offset */
WORD dpb_psh; /* Physical Record Shift Factor */
WORD dpb_phm; /* Physical Record Mask */
};
#define BCBH struct bcbh_item
BCBH { /* Buffer Control Block Header structure */
ADDR bcbh_lr; /* BCB List Root */
BYTE bcbh_pm; /* BCB Process Max */
};
#define BCB struct bcb_item
BCB { /* Buffer Control Block structure */
BYTE bcb_drv; /* Drive */
BYTE bcb_record[3]; /* Record Number */
BYTE bcb_wflg; /* Write Pending Flag */
BYTE bcb_seq; /* Sequential Access Counter */
WORD bcb_track; /* Logical Track Number */
WORD bcb_sector; /* Logical Translated Sector Number */
UWORD bcb_bufptr; /* Buffer Offset (for DIRBCB) / Segment (for DATBCB) */
ADDR bcb_link; /* Link to next BCB */
WORD bcb_pdadr; /* Process Descriptor Address */
};
#define DINFO struct dirbuf_information
DINFO {
BOOLEAN d_modified; /* DPH was modified? */
BOOLEAN d_hashing; /* user wants hashing? */
WORD d_ndirbs; /* Num dir buffers */
WORD d_sdirbs; /* Size dir buffers */
WORD d_pmdirbs; /* Process Max Number Dir Buffs */
WORD d_ndatbs; /* Num data buffers */
WORD d_sdatbs; /* Size data buffers */
WORD d_pmdatbs; /* Process Max Number Dir Buffs */
WORD d_shash; /* Size of hash table */
WORD d_alvsize; /* size of Alloc Vector area (in bytes ) */
WORD d_blksize; /* size of disk Allocation Block */
WORD d_csvsize; /* size of Checksum Vector area */
};
/* end of edsdisk.h ********************************************************/
/***************************************************************************/
WORD csfd; /* command file descriptor */
WORD csgoff; /* group offset within command file */
cseek(offs) /* seek offset within Command File */
ADDR offs;
{
lseek(csfd,(LONG) offs+csgoff, 0); /* compensate for cmd header */
}
/***************************************************************************/
/* Put special byte for buffer fills */
#define ZBYTE (doffset&0xFF) /* the byte usually passed in */
WORD
bufwrite(size,byt)
WORD size;
BYTE byt;
{
WORD ss;
for( ss=size; ss>0; --ss )
write(fns,&byt,1);
return size;
}
/***************************************************************************/
/* Module local variables */
#define DPHNUM 16 /* number of possible disks */
ADDR *dphtab; /* table of offsets of Disk Parm Hdrs */
DPH *dh[DPHNUM]; /* table of Disk Parm Hdrs */
DINFO *di[DPHNUM]; /* table of info on DPHs */
/* Module local predicates */
#define ASKFOR(aa) ((aa) == 0xFFFF) /* Is this one we're sposed to ask for? */
#define SHRMSK 0x8000 /* Is this shared with another drive? */
#define SHARED(bb) ((bb)!=0xFFFF && (bb) & SHRMSK) /* Is this nd??bs field shared with another disk? */
#define GETSHARED(cc) ((cc) & ~SHRMSK) /* Get the drive we share with */
/***************************************************************************/
/* EXPORT
/* initxios_info: gets whatever information GENSYS needs from xios
/***************************************************************************/
initxios_info(xf,goff) /* get info from xios file */
WORD xf; /* xios file descriptor */
WORD goff; /* group offset within xios file */
{
REG WORD ii; /* counter */
DPB dd; /* a place to keep this info */
EDPB ee; /* a place to keep this info */
DPH *dph;
DINFO *dinf;
csfd = xf; /* assign to global: set up cseek */
csgoff = goff; /* assign to global */
cseek(XTABLOC); /* go to where the XIOSTAB info is */
read(xf,&xt,sizeof xt); /* read in the xios info */
dphtab = xt.xt_dphtab; /* point to disk parm header table */
for( ii=0; ii<DPHNUM; ++ii ) { /* for each dph pointer */
if( dphtab[ii] == 0 ) { /* is there a dph? */
dh[ii]=NULLPTR;
di[ii]=NULLPTR; /* no tickee, no washee */
} else { /* aha! let's set up this info */
dh[ii] = (DPH *)malloc(sizeof(DPH));
di[ii] = (DINFO *)malloc(sizeof(DINFO));
zfill(di[ii],sizeof(DINFO));
cseek(dphtab[ii]);
read(xf,dh[ii],sizeof(DPH));
}
} /* end of reading dph */
for( ii=0; ii<DPHNUM; ++ii ) /* let's go thru it again */
if( dh[ii] ) { /* if there's something there */
dph = dh[ii];
dinf = di[ii];
cseek(dph->dph_dpb); /* point to the disk parm block */
read(xf,&ee,sizeof(EDPB)); /* Read as though EDPB */
if (ee.edpb_extflag == 0xFFFF) { /* Extended DPB */
cseek(dph->dph_dpb+12); /* seek past extended info */
} else {
cseek(dph->dph_dpb);
}
read(xf,&dd,sizeof(DPB)); /* read DPH */
dinf->d_blksize = 128 << dd.dpb_psh;
dinf->d_csvsize = 0x7FFF & dd.dpb_cks;
dinf->d_alvsize = (dd.dpb_dsm/8 + 1) * 2;
dinf->d_shash = 4 * (1 + dd.dpb_drm);
dinf->d_ndirbs = -1; /* ask for these by name! */
dinf->d_ndatbs = -1;
dinf->d_hashing = TRUE; /* default to hashing */
} /* end of drive info init */
}
/************************************************************************/
/* EXPORT
/* doxbufs: queries user for BDOS buffering info;
/* exits only when all data valid
/************************************************************************/
BYTE *
doxbufs(txt,bdtitle)
BYTE *txt;
BYTE *bdtitle;
{
BYTE cmds[CMDSLEN];
BOOLEAN xiosvalid();
EXTERN BYTE *clearit;
FOREVER {
printf("%s",clearit); /* clear screen */
printf("%s\n",bdtitle);
dbufs_display(); /* display */
printf("Drive (<CR> to exit) ? ");
if( gets(cmds)!=cmds || *cmds==NULL ) { /* they hit <CR>? */
if( xiosvalid() ) break;
USERR("Please correct drive buffers information\n");
press_return();
continue;
}
askabout(cmds); /* go do what they want */
}
return NULLPTR; /* error msg for menu handler */
}
/************************************************************************/
/* dbufs_display: display disk buffering info
/************************************************************************/
dbufs_display()
{
REG UWORD ii, jj, tot; /* counters */
DPH *dph;
DINFO *dinf;
tot = 0; /* init this */
dcalcsizes(); /* check all the sizes */
printf("\n\t*** Disk Buffering Information ***\n");
printf(" Dir Max/Proc Data Max/Proc Hash Specified\n");
printf("Drv Bufs Dir Bufs Bufs Dat Bufs -ing Buf Pgphs\n");
printf("=== ==== ======== ==== ======== ==== =========\n");
for( ii=0; ii<DPHNUM; ++ii ) { /*** for each drive ***/
if( dphtab[ii]==0 ) continue; /* no DP Hdr for this drive */
dph = dh[ii]; dinf = di[ii];
printf(" %c: ",'A'+ii); /* print which drive */
dspdnums(dph->dph_dirbcb,dinf->d_ndirbs,dinf->d_pmdirbs);
dspdnums(dph->dph_datbcb,dinf->d_ndatbs,dinf->d_pmdatbs);
if( ! ASKFOR(dph->dph_hstbl) )
printf(" fixed ");
else if( dinf->d_hashing )
printf(" yes ");
else printf(" no ");
jj = dspdsize(dph,dinf);
if( jj == -2 )
printf(" fixed ");
else if( jj == -1 )
printf(" ?? ");
else {
printf(" %4.4x ",jj >> 4);
tot += jj;
}
printf("\n");
} /*** end for each drive ***/
printf("Total paragraphs allocated to buffers: %x\n",tot >> 4);
}
/***************************************************************************/
/* dspdsize: calculates a drive's user-requestable buffer size, in bytes
/***************************************************************************/
WORD
dspdsize(dph,dinf) /* calculate size requested */
DPH *dph; /* returns -1 if still needs info */
DINFO *dinf; /* returns -2 if pre-allocated */
{
REG WORD siz;
siz=0;
if( !ASKFOR(dph->dph_dirbcb) &&
!ASKFOR(dph->dph_datbcb) &&
!ASKFOR(dph->dph_hstbl) )
return -2; /* nothing to say here */
if( ASKFOR(dph->dph_dirbcb) ){
if( ASKFOR(dinf->d_ndirbs) )
return -1;
if( !SHARED(dinf->d_ndirbs) )
siz += dinf->d_sdirbs * dinf->d_ndirbs;
}
if( ASKFOR(dph->dph_datbcb) ){
if( ASKFOR(dinf->d_ndatbs) )
return -1;
if( !SHARED(dinf->d_ndatbs) )
siz += dinf->d_sdatbs * dinf->d_ndatbs;
}
if( ASKFOR(dph->dph_hstbl) ){
if( dinf->d_hashing )
siz += dinf->d_shash;
}
return siz;
}
/***************************************************************************/
/* dspdnums: displays the data/dir buf numbers
/***************************************************************************/
dspdnums(nfix,ninput,npm) /* display subroutine */
WORD nfix;
WORD ninput;
WORD npm;
{
if( !ASKFOR(nfix) )
printf("fixed ");
else if( SHARED(ninput) )
printf("shares %c: ",'A'+GETSHARED(ninput));
else {
if( ASKFOR(ninput) )
printf(" ?? ");
else printf(" %2.2x ",ninput);
if( ASKFOR(npm) )
printf(" ?? ");
else printf(" %2.2x ",npm);
}
}
/***************************************************************************/
/* dcalcsizes: calculates buffer sizes across shared buffers
/***************************************************************************/
dcalcsizes() /* make sure all the sizes are correct */
{
REG WORD ii, jj;
REG WORD *pkk;
DPH *dph;
DINFO *dinf;
for( ii=0; ii<DPHNUM; ++ii ) /* init all sizes to zero */
if(dphtab[ii]) {
dinf = di[ii];
dinf->d_sdirbs = dinf->d_sdatbs = 0;
}
for( ii=0; ii<DPHNUM; ++ii ) /* for each drive */
if(dphtab[ii]) {
dph = dh[ii];
dinf = di[ii];
if( ASKFOR(dph->dph_dirbcb) ) /* max out the size of a dirbuf */
if( !ASKFOR(dinf->d_ndirbs) ) { /* if it's real data there */
if( SHARED(dinf->d_ndirbs) ) {
jj = GETSHARED(dinf->d_ndirbs);
pkk = & ((di[jj])->d_sdirbs);
} else
pkk = & dinf->d_sdirbs;
if( dinf->d_blksize > *pkk ) /* assign the maximum size found */
*pkk = dinf->d_blksize;
}
if( ASKFOR(dph->dph_datbcb) ) /* max out the size of a data buf */
if( !ASKFOR(dinf->d_ndatbs) ) {
if( SHARED(dinf->d_ndatbs) ) {
jj = GETSHARED(dinf->d_ndatbs);
pkk = & ((di[jj])->d_sdatbs);
} else
pkk = & dinf->d_sdatbs;
if( dinf->d_blksize > *pkk )
*pkk = dinf->d_blksize;
}
}
}
/***************************************************************************/
/* ask user about a drive
/***************************************************************************/
askabout(drspec) /* ask user about a drive */
BYTE *drspec;
{
REG WORD dr;
DPH *dph;
DINFO *dinf;
BOOLEAN askhash();
if( *drspec == '*' ) {
askstar(); /* get info, apply to all disks */
return;
}
dr = toupper(*drspec) - 'A'; /* which drive do they want to fix? */
if( dr<0 || dr>=DPHNUM || dphtab[dr]==0 || drspec[1] != ':') {
USERR("Problem with '%s':\n",drspec);
USERR("Please specify an existing drive between 'A:' and 'P:'\n");
press_return();
return;
}
dph = dh[dr];
dinf = di[dr];
if( dspdsize(dph,dinf) == -2 ) { /* is there anything to modify? */
USERR("All buffers for %c: are fixed within the XIOS module.\n",
dr+'A');
USERR("You can't modify this fixed information in GENSYS.\n");
press_return();
return;
}
if( ASKFOR(dph->dph_dirbcb) ){
dinf->d_ndirbs = asknd(1,FALSE); /* get directory info */
dinf->d_pmdirbs = askpm(1,dinf->d_ndirbs);
}
if( ASKFOR(dph->dph_datbcb) ){
dinf->d_ndatbs = asknd(2,(128==dinf->d_blksize)); /* get data info */
dinf->d_pmdatbs = askpm(2,dinf->d_ndatbs);
}
if( ASKFOR(dph->dph_hstbl) ){
dinf->d_hashing = askhash();
}
}
/****************************************************************************/
/* askstar: asks buffering questions & applies to all ASKFOR/unanswered drives
/****************************************************************************/
askstar()
{
REG WORD dr;
DPH *dph;
DINFO *dinf;
WORD andirbs, andirpms, andatbs, andatpms;
BOOLEAN ahash, askhash();
andirbs = asknd(1,FALSE); /* Number of directory buffers? */
andirpms = askpm(1,andirbs); /* Process Max Dir Bufs? */
andatbs = asknd(2,FALSE); /* Number of data buffers? */
andatpms = askpm(2,andatbs); /* Process Max Data Bufs? */
ahash = askhash(); /* Hashing? */
for( dr=0; dr<DPHNUM; ++dr )
if( dphtab[dr] ) { /* for all existing drives */
dph = dh[dr]; dinf = di[dr];
if( ASKFOR(dph->dph_dirbcb) )
if( ASKFOR(dinf->d_ndirbs) ) {
dinf->d_ndirbs = andirbs;
dinf->d_pmdirbs = andirpms;
}
if( ASKFOR(dph->dph_datbcb) )
if( ASKFOR(dinf->d_ndatbs) ) {
dinf->d_ndatbs = andatbs;
dinf->d_pmdatbs = andatpms;
}
if( ASKFOR(dph->dph_hstbl) )
dinf->d_hashing = ahash;
}
}
/***************************************************************************/
/* asknd: ask the user for the number of dir/data buffers
/***************************************************************************/
WORD
asknd(type,zero_ok)
WORD type; /* 1=dir, 2=data */
BOOLEAN zero_ok;
{
REG WORD val, jj;
BYTE *name;
BYTE cmds[CMDSLEN];
DPH *dph;
if( type==1 ) name="directory"; else name="data";
FOREVER {
printf("Number of %s buffers, or drive to share with ? ",name);
gets( cmds );
if( cmds[1] != ':' ) {
val = atoih(cmds);
if( val > 0 && val <= 127 ) break;
if(*cmds == '0') {
if( zero_ok ) break;
USERR("Number of buffers must be greater than 0\n");
press_return();
continue;
}
} else {
val = toupper(*cmds) - 'A'; /* which drive do they want? */
if( val>=0 && val<DPHNUM && dphtab[val]!=0) { /* a drive maybe? */
dph = dh[val];
if( type==1 ) jj = dph->dph_dirbcb;
else jj = dph->dph_datbcb;
if( ASKFOR(jj) ) {
if( type==1 ) jj = di[val]->d_ndirbs;
else jj = di[val]->d_ndatbs;
if( !SHARED(jj) ) {
val |= SHRMSK; /* turn on sharing */
break;
}
}
USERR("Drive %c: is not available for sharing\n",'A'+val);
press_return();
continue;
}
}
USERR("Please input a number, or an existing drive from 'A:' to 'P:'\n");
press_return();
}
return val;
}
/************************************/
/* askpm: ask about process maximum
/************************************/
WORD
askpm(type,pmmax)
WORD type;
WORD pmmax;
{
REG WORD val;
BYTE *cmds[CMDSLEN];
BYTE *name;
switch(type) { case 1: name="directory"; break; case 2: name="data"; }
if( SHARED(pmmax) || pmmax<=0 )
return 0;
FOREVER { /* get input from user */
printf("Maximum %s buffers per process [%x]? ",name,pmmax);
gets( cmds );
if( *cmds==NULL )
val = pmmax; /* default value */
else val = atoih(cmds);
if( val > 0 && val <= pmmax ) break;
USERR("Maximum must be > zero and <= %x\n",pmmax);
press_return();
}
return val;
}
/*****************************************/
/* askhash: ask user if they'd like to hash
/*****************************************/
BOOLEAN
askhash()
{
REG WORD val;
BYTE *cmds[CMDSLEN], *cp;
FOREVER {
printf("Hashing [yes] ? ");
gets( cmds );
if( *cmds == NULL )
return TRUE;
for( cp=cmds; *cp; ++cp ) {
if( *cp==' ' || *cp=='\t' ) {
*cp = NULL;
break;
}
if( isupper(*cp) )
*cp = tolower(*cp);
}
if( (val=whichof(cmds,",yes,true,on,hashing,no,false,off")) > 0 )
break;
USERR("Please answer 'hashing', 'yes', or 'no'.\n");
press_return();
}
return val<=4; /* TRUE iff answer was one of 1st four */
}
/************************************************************************/
/* EXPORT
/* xiosvalid: validates that all the user-requestable info has been filled in
/************************************************************************/
BOOLEAN
xiosvalid()
{
REG WORD ii;
REG WORD ndph;
ndph = 0;
for( ii=0; ii<DPHNUM; ++ii )
if( dphtab[ii]!=0 ) {
if( dspdsize(dh[ii],di[ii]) == -1 )
return FALSE;
++ndph;
}
if( ndph==0 ) {
USERR("no dph information in xios header...");
exit(1);
}
return TRUE;
}
/***************************************************************************/
/* EXPORT
/* genxios: generates disk buffers (to be placed after the rest of the
/* system tables.
/*************************************************************************/
#define OFF_BCBPTR 0xA
#define OFF_DPHHTAB 0x12
ADDR locrsvd_off; /* local reserved offset, for DIRBUF fix */
ADDR /* returns final offset */
genxios(doffset) /* generate the disk buffers */
ADDR doffset; /* offset in data file */
{
REG WORD ii, jj; /* counter */
REG BOOLEAN dm; /* modified flag */
REG ADDR lastlink; /* used for threading lists */
ADDR locbufs_off; /* local buffer offset for DIRBUF grouping */
LONG dmagic; /* where word needing fix goes into file */
BCB bcb; /* place for organizing, calc for fixups */
BCBH bcbh;
DPH *dph;
DINFO *dinf;
BOOLEAN xiosvalid();
if( !xiosvalid() ) CRASH("invalid disk buffer information");
for( ii=0; ii<DPHNUM; ++ii ) /* allocate CHECK SUM VECTORS */
if( dh[ii] ) { /* if there's something to look at */
dph = dh[ii]; /* convenient ptr */
dinf = di[ii];
if( ASKFOR(dph->dph_csv) ){
dinf->d_modified = TRUE;
if( dinf->d_csvsize == 0 )
dph->dph_csv=0;
else {
dph->dph_csv = doffset;
doffset += bufwrite(dinf->d_csvsize,ZBYTE);
}
}
}
for( ii=0; ii<DPHNUM; ++ii ) /* allocate ALLOCATION TABLE VECTORS */
if( dh[ii] ) { /* if there's something to look at */
dph = dh[ii]; /* convenient ptr */
dinf = di[ii];
if( ASKFOR(dph->dph_alv) ){
dinf->d_modified = TRUE;
dph->dph_alv = doffset;
doffset += bufwrite(dinf->d_alvsize,ZBYTE);
}
}
locbufs_off = 0; /* amount (bytes) of local dir buffer*/
for( ii=0; ii<DPHNUM; ++ii ) /* allocate DIR BCBs & BUFFERS */
if( dh[ii] ) { /* if there's something to look at */
dph = dh[ii]; /* convenient ptr */
dinf = di[ii];
if( ASKFOR(dph->dph_dirbcb) ){ /* DIR BCBs */
dinf->d_modified = TRUE;
if( ! SHARED(dinf->d_ndirbs) ) { /* take care of sharing later */
lastlink=0; /* linker */
zfill(&bcb,sizeof(BCB)); /* init to zeroes */
bcb.bcb_drv = 0xFF;
for( jj=dinf->d_ndirbs; jj>0; --jj ){
bcb.bcb_link = lastlink;
/* pts to loc of buffer relative to locrsvd_off */
bcb.bcb_bufptr = locbufs_off;
locbufs_off += dinf->d_sdirbs; /* increase buf size */
/* calc where bcb will be written to, for fixlater */
dmagic = lseek(fns,0L,1) + OFF_BCBPTR;
fixlater(dmagic,F_ADD,&locrsvd_off);
/* finally, write out the bcb info */
lastlink = doffset; /* point to the bcb */
doffset += datwrite(&bcb,sizeof bcb);
}
bcbh.bcbh_lr = lastlink; /* fill in the bcb hdr */
bcbh.bcbh_pm = dinf->d_pmdirbs;
dph->dph_dirbcb = doffset; /* link to head of list */
/* write out a buffer control block hdr */
doffset += datwrite(&bcbh,sizeof bcbh);
}
}
}
for( ii=0; ii<DPHNUM; ++ii ) /* allocate DATA BCBs & BUFFERS */
if( dh[ii] ) { /* if there's something to look at */
dph = dh[ii]; /* convenient ptr */
dinf = di[ii];
/* the bufs can go out of the system page, but the bcbs need to be in */
if( ASKFOR(dph->dph_datbcb) ){ /* DATA BCBs: !!temporary!! */
dinf->d_modified = TRUE;
if( ! SHARED(dinf->d_ndatbs) ) { /* do sharing later */
lastlink=0; /* linker */
zfill(&bcb,sizeof(BCB)); /* init to zeroes */
bcb.bcb_drv = 0xFF;
for( jj=dinf->d_ndatbs; jj>0; --jj ){
bcb.bcb_link = lastlink;
bcb.bcb_bufptr = bufs_seg; /* point into reserved area */
bufs_seg += (dinf->d_sdatbs) >>4; /* cvt to pgphs */
/* calculate where the bcb.bcb_bufptr will be written in file */
dmagic = lseek(fns,0L,1) + OFF_BCBPTR;
fixlater(dmagic,F_ADD,&rsvd_seg); /* fix the bufptr */
lastlink = doffset;
/* write out a buffer control block */
doffset += datwrite(&bcb,sizeof bcb);
}
bcbh.bcbh_lr = lastlink; /* fill in the bcb hdr */
bcbh.bcbh_pm = dinf->d_pmdatbs;
dph->dph_datbcb = doffset; /* link to head of list */
/* write out a buffer control block hdr */
doffset += datwrite(&bcbh,sizeof bcbh);
}
}
}
/* now write the local directory buffers */
locrsvd_off = doffset; /* address of directory buffer area */
doffset += bufwrite(locbufs_off,ZBYTE); /* write out the buffers */
/* dmagic: magic number to add to dphtab[ii] */
dmagic = OFF_DPHHTAB + fldstart;/* where in file does SYSDAT start */
for( ii=0; ii<DPHNUM; ++ii ) /* allocate HASH TABLES */
if( dh[ii] ) { /* if there's something to look at */
dph = dh[ii]; /* convenient ptr */
dinf = di[ii];
if( ASKFOR(dph->dph_hstbl) ) { /* HASH TABLE ALLOC */
dinf->d_modified = TRUE;
if( dinf->d_hashing ) {
dph->dph_hstbl = bufs_seg; /* point into reserved area */
bufs_seg += (dinf->d_shash) >>4; /* cvt bytes to pgphs */
/* remember where the dph_hstbl word will be stored */
/* so we can adjust bufs_seg by starting loc of rsvd_seg */
fixlater(dmagic+dphtab[ii],F_ADD,&rsvd_seg);
} else dph->dph_hstbl = 0;
}
} /**** end of processing ****/
for( ii=0; ii<DPHNUM; ++ii ) /* resolve shared buffers */
if( dh[ii] ) {
if( ASKFOR(dh[ii]->dph_dirbcb) ) {
jj = GETSHARED(di[ii]->d_ndirbs);
dh[ii]->dph_dirbcb = dh[jj]->dph_dirbcb;
}
if( ASKFOR(dh[ii]->dph_datbcb) ) {
jj = GETSHARED(di[ii]->d_ndatbs);
dh[ii]->dph_datbcb = dh[jj]->dph_datbcb;
}
} /* end resolve shared buffers */
return doffset;
}
/***************************************************************************/
/* EXPORT
/* fixupxios_info: does the fixup for the dph info in the xios
/*************************************************************************/
fixupxios_info() /* call from fixups */
{
REG WORD ii; /* counter */
REG LONG dmagic; /* addr var */
for( ii=0; ii<DPHNUM; ++ii )
if( dh[ii] ) /* if there's something to look at */
if( di[ii]->d_modified ) {
dmagic = fldstart + dphtab[ii];
lseek(fns,dmagic,0); /* where to write to */
write(fns,dh[ii],sizeof(DPH)); /* what to write */
}
}


View File

@@ -0,0 +1,418 @@
/**************************************************************************/
/**************************************************************************/
/* genc5.c: M E N U handling routines
/*
/* Written by Bill Fitler
/**************************************************************************/
/**************************************************************************/
#ifndef MAINMODULE
#include <genccpm.h>
EXTERN BOOLEAN verbose; /* flag: be wordy */
#endif
MLOCAL BOOLEAN eflag = FALSE; /* user error */
/**************************************************************************/
/* bldmenu: builds a menu list from successive calls
/**************************************************************************/
MENU *
bldmenu(muroot,typ,ptr,name,description)
MENU *muroot; /* root of menu list (or NULLPTR) */
WORD typ; /* type of menu item */
BYTE *ptr; /* pointer to something... */
BYTE *name; /* command name for this menu item */
BYTE *description; /* long label for this item */
{
REG MENU *mu; /* ptr to created item */
REG MENU *tmu; /* temp ptr for linked list scan */
mu = (MENU *)malloc(sizeof(*mu)); /* allocate memory for item */
mu->mutype = typ;
mu->muiptr = ptr;
mu->muname = name;
mu->mudesc = description;
mu->munext = NULLPTR;
if( muroot == NULLPTR ) /* if NULL list */
return mu; /* return something to start with */
for( tmu=muroot; tmu->munext != NULLPTR; tmu = tmu->munext )
; /* append to end of list */
tmu->munext = mu;
return muroot; /* keep list in order */
}
/**************************************************************************/
/* domenu: executes the specified commands (in cbuf) from the menu (mnu)
/**************************************************************************/
#define CMDLEN 80
#define USERR ++eflag;printf
#define ECHK(fn) _errchk(fn,cmd,cmdval)
VOID
domenu(cbuf,mnu)
BYTE *cbuf; /* command buffer */
MENU *mnu; /* table of menu specs */
{
REG MENU *mi; /* ptr to menu item */
LOCAL BYTE cmd[CMDLEN]; /* place for command & value */
LOCAL BYTE *cmdval; /* ptr within cmd */
LOCAL BYTE *cp; /* temp char ptr */
BYTE *msetbool(); /* set a boolean value */
BYTE *msetbyte(); /* set a numeric byte value */
BYTE *msetword(); /* set an integer pointer */
BYTE *msettxt(); /* set a text value */
BYTE *(*proc)(); /* procedure pointer */
BYTE *msetdrv(); /* set a drive value */
BYTE *_nxtcmd(); /* command parser */
MENU *_fndcmd(); /* command lookup */
eflag = FALSE; /* no errors yet */
while((cbuf=_nxtcmd(cbuf,cmd))){ /* while there are commands in cbuf */
cmdval = NULLPTR; /* init value ptr for command */
for( cp=cmd; *cp; cp++ ) { /* scan command for assign op */
if( isupper(*cp) ) /* convert all commands to LOWER CASE */
*cp = tolower(*cp);
if( *cp == '=' ) { /* found? */
*cp++ = NULL; /* terminate command */
cmdval = cp; /* point value to after assign op */
break; /* and terminate loop */
}
}
if( (mi=_fndcmd(cmd,mnu)) == NULLPTR ){ /* scan menu commands */
USERR("'%s' is not a command for this menu\n",cmd);
} else { /******** cmd loop ********/
switch(mi->mutype) { /* handle cmd type */
case MBOOL: /** BOOLEAN command **/
ECHK(msetbool(mi->muiptr,cmdval));
break;
case MBYTE: /** BYTE command **/
ECHK(msetbyte(mi->muiptr,cmdval));
break;
case MWORD: /** INTEGER command **/
ECHK(msetword(mi->muiptr,cmdval));
break;
case MTEXT: /** TEXT command **/
ECHK(msettxt(mi->muiptr,cmdval));
break;
case MPROC: /** PROCEDURAL command **/
proc = mi->muiptr; /* assign to function ptr */
ECHK(((*proc)(cmdval,mi->mudesc)));
break;
case MDRIV: /** DRIVE letter command **/
ECHK(msetdrv(mi->muiptr,cmdval));
break;
} /* end switch */
} /********* end cmd loop *********/
if(eflag) { /* user error? */
press_return();
*cbuf = NULL;
} else if(verbose) /* are we being wordy? */
prtmival(mi); /* let the user know what happened */
} /**** end while loop ****/
}
/* _nxtcmd: parses cin into cout */
BYTE *
_nxtcmd(cin,cout) /* returns ptr to after next cmd */
BYTE *cin; /* command in buf */
BYTE *cout; /* command out buf */
{
/***** handle quoted strings??? *****/
while( isspace(*cin) ) /* skip leading spaces */
++cin;
if( *cin == NULL ) /* check for EOS */
return NULLPTR;
while( *cin && !isspace(*cin) ) /* scan to eos or whitespace */
*cout++ = *cin++; /* xfer to command out buf */
*cout = NULL; /* null terminate command out buf */
return cin; /* return ptr to after command */
}
/* _fndcmd: scans thru menu structure 'mu' looking for command name 'cn' */
/* returns ptr to menu item or NULLPTR */
MENU *
_fndcmd(cn,mus)
BYTE *cn; /* command name */
MENU *mus; /* ptr to menu list */
{
REG WORD cnl; /* cmd name len */
MENU *musave; /* extra ptr to menu item */
cnl = strlen(cn);
for( ; ; mus = mus->munext) { /* scan menu list */
if( mus==NULLPTR ) /* if we hit the end then fail */
return NULLPTR;
if( strncmp(cn,mus->muname,cnl) == 0 ) /* cn prefix of name?*/
break; /* yes, we have a candidate */
}
musave = mus;
for( mus=mus->munext; ; mus=mus->munext ) { /* finish scanning list */
if( mus==NULLPTR ) /* if we hit the end then succeed */
return musave; /* we reached end of list: found it! */
if( strncmp(cn,mus->muname,cnl) == 0 )
return NULLPTR; /* another match: ambiguous command */
}
}
/* _errchk: checks for error returns on functions */
VOID
_errchk(emsg,cm,cmv)
BYTE *emsg; /* error message to check */
BYTE *cm; /* command generating the error */
BYTE *cmv; /* value generating the error */
{
if( emsg ) { /* non NULL error message return? */
USERR("Error on command '%s",cm);
if(cmv)
USERR("=%s",cmv);
USERR("': %s\n",emsg);
}
}
/* msetbool: sets the BOOLEAN pointed to by 'bp' according to value in 'cvp' */
BYTE * /* return NULLPTR, or ptr to err msg */
msetbool(bp,cvp)
BYTE *bp; /* pointer to boolean to set */
BYTE *cvp; /* pointer to value to set to */
{
REG WORD bv;
REG BYTE *tp;
if( cvp==NULLPTR ) /* no val: toggle boolean */
bv = (*bp ? 4 : 1); /* toggle by setting bv index */
else {
for( tp=cvp; *tp; ++tp )
if( isupper(*tp) ) *tp=tolower(*tp);
if( (bv=whichof(cvp,",on,yes,true,off,no,false"))==0 )
return "value must be 'yes' or 'no'";
}
if( bv < 4 )
*bp = -1; /* zap to 0xFFFF */
else *bp = 0; /* zap to zero */
return NULLPTR;
}
BYTE *
msetbyte(bp,cvp) /* set numeric BYTE value */
BYTE *bp; /* ptr to BYTE to set */
BYTE *cvp; /* value to set BYTE to */
{
REG WORD val; /* temp holding place */
val=0;
if(cvp != NULLPTR) val=atoih(cvp); /* assume numbers are in HEX!! */
if( cvp==NULLPTR || (val==0 && !isdigit(*cvp)) )
return "value must be a number";
if( val > 255 )
return "value must be less than FF hex (255 decimal)";
*bp = val;
return NULLPTR;
}
BYTE *
msetword(ip,cvp)
WORD *ip; /* ptr to WORD to set */
BYTE *cvp; /* value to set WORD to */
{
REG WORD val; /* temp holding place */
val=0;
if(cvp != NULLPTR) val=atoih(cvp); /* assume numbers are in HEX!! */
if( cvp==NULLPTR || (val==0 && !isdigit(*cvp)) )
return "value must be an unsigned hex number between 0 and FFFFh";
*ip = val;
return NULLPTR;
}
WORD
atoih(cp) /* conver ascii hex to word */
BYTE *cp; /* buffer number */
{
REG WORD v; /* resulting value */
REG BYTE cv; /* character value */
BYTE *savcp; /* save orig ptr */
v = 0; savcp = cp; /* init value */
for( cv = *cp; ; cv = *++cp ){ /* for each char in cp */
if( isdigit(cv) )
v = (v<<4) + (cv-'0'); /* convert digit and add */
else { /* maybe it's a letter */
if( isupper(cv) ) /* upper case letter? */
cv = tolower(cv); /* convert it */
if( cv<'a' || cv>'f') /* range check */
break; /* terminate loop if failed */
v = (v<<4)+(10+cv-'a'); /* convert letter and add */
}
}
if( cp-savcp <= 4 )
return v; /* return the value */
else {
*savcp |= 0x80;
return 0; /* turn on hi bit, make isdigit test fail */
}
}
BYTE *
msettxt(tp,cvp)
BYTE **tp; /* place to store ptr to value */
BYTE *cvp; /* value to set BYTEs to */
{
REG BYTE *tmp; /* temp ptr for allocated storage */
if( cvp==NULLPTR )
cvp=""; /* point to null string, instead */
tmp = malloc(1+strlen(cvp)); /* get space for string */
strcpy(tmp,cvp); /* copy to allocated space */
*tp = tmp; /* assign ptr */
return NULLPTR;
}
BYTE *
msetdrv(dp,cvp)
BYTE *dp; /* place to store ptr to value */
BYTE *cvp; /* value to set DRIVE to */
{
REG WORD v; /* work place */
if( cvp!=NULLPTR ) { /* check for drive letter */
if( isupper(*cvp) )
*cvp = tolower(*cvp);
v = *cvp - 'a'; /* convert drive spec to nibble */
}
if( cvp==NULLPTR || v<0 || v>15 || cvp[1] != ':' )
return "you must specify a drive 'A:' thru 'P:'";
*dp = v; /* looks okay, set it */
return NULLPTR; /* no errors */
}
/**************************************************************************/
/* prtmenu: displays the menu labels, values and descriptors
/**************************************************************************/
VOID
prtmenu(mtitle,mnu)
BYTE *mtitle; /* title of menu */
MENU *mnu; /* table specifying menu */
{
printf("\n\n%s\n",mtitle); /* give the menu a title */
for( ; mnu!=NULLPTR; mnu = mnu->munext ) /* travel down list */
prtmival(mnu);
}
prtmival(mnu) /* return ptr to value of item */
MENU *mnu; /* item to get value of */
{
REG BYTE *ival;
BYTE ivbuf[10]; /* local buf for display */
BYTE *vbp; /* value byte ptr */
WORD *vwp; /* value word ptr */
WORD v; /* place to put value */
printf("%12.12s ",mnu->muname); /* first the name */
ival = ivbuf; *ival = NULL; /* init value */
switch(mnu->mutype) { /* now the value */
case MBOOL:
if( *(mnu->muiptr) )
ival="[Y]";
else ival="[N]";
break;
case MBYTE:
vbp = mnu->muiptr;
v = (*vbp & 0xFF);
sprintf(ivbuf,"[%2.2x]",v); /* display in hex */
break;
case MWORD:
vwp = mnu->muiptr;
v = *vwp;
sprintf(ivbuf,"[%4.4x]",v); /* display in hex */
break;
case MTEXT:
vbp = *((BYTE **)mnu->muiptr); /* go get the char ptr */
if( strlen(vbp) > 4 )
sprintf(ivbuf,"[%-4.4s>",vbp);
else sprintf(ivbuf,"[%s]",vbp);
break;
case MPROC:
/* leave blank */
break;
case MDRIV:
sprintf(ivbuf,"[%c:]",'A'+(*mnu->muiptr));
break;
}
printf("%-6s ",ival);
printf("%s\n",mnu->mudesc); /* finally the description */
}
/************************************************************************
/* whichof: scans the string 'set' (delimited by 1st char in 'set')
/* for 1st occurrence of string 'sample'.
/* Returns 0 if 'sample' not a prefix of any item in set or if
/* 'sample' is a prefix of more than one item in set;
/* delimiter# o.w.
/* E.G. if set = ",on,yes,true,off,no,false" then
/* whichof("yes",set) == 2;
/* whichof("y",set) == 2;
/* whichof("o",set) == 0;
/* whichof("x",set) == 0;
/* NOTE: results not guaranteed if item delimiter (*set) is in string 'sample',
/* or if null item is in set (adjacent delimiters).
/*************************************************************************/
/* first, a subroutine: */
/* _wget: returns NULLPTR if sa not prefix of item in st; */
/* returns end of item (ptr in st) otherwise */
BYTE *_wget(sa,st,de)
BYTE *sa;
BYTE *st;
BYTE de;
{
BYTE *s2;
for( ;; ) { /* do forever */
for( s2=sa; *s2 && *s2 == *st; ){
++s2; ++st; /* try match */
}
if( *s2 == NULL ){ /* success! we've matched all of sa */
while( *st && *st != de ) ++st; /* adv to nxt delim */
return( --st ); /* backup one char */
}
while( *st && *st != de ) /* no match, look for next item */
++st; /* adv to nxt delim */
if( *st == NULL )
return( NULLPTR ); /* end of list */
++st;
}
}
WORD whichof(sample,set)
BYTE *sample;
BYTE *set;
{
WORD sx;
BYTE *sp, *np;
if( (sp=_wget(sample,set+1,*set)) == NULLPTR )
return 0; /* not found */
if( _wget(sample,sp+1,*set) != NULLPTR )
return 0; /* ambiguous */
for( sx=0, np=set; np<sp; np++ )
if( *np == *set ) sx++; /* count delimiters */
return sx;
}


View File

@@ -0,0 +1,210 @@
/*******************************************************************/
/*******************************************************************/
/* genc5.c: */
/* some miscellaneous functions which belong in the system library */
/*******************************************************************/
/*******************************************************************/
#ifndef MAINMODULE
#include <genccpm.h>
#endif
#define FCB struct fcbstruct
FCB {
BYTE fcbdr; /* drive */
BYTE fcbname[8]; /* name */
BYTE fcbext[3]; /* extension */
BYTE fcbrest[24]; /* all the rest */
};
#define FSEARCH(faddr) (__OSIF(17,faddr)&0xFF)
#define NSEARCH(faddr) (__OSIF(18)&0xFF) /* doesn't use FCB */
#define SETDMA(dma) __OSIF(26,dma) /* where to put dir info */
#define SECSIZE 128
#define AMASK 0x7F
/* dirsearch: returns a DLIST of names matching 'fs' */
DLIST * /* returns list of names found in */
dirsearch(fs) /* directory search for */
BYTE *fs; /* file spec */
{
FCB f, *fp; /* use this FCB */
REG WORD ret; /* ptr */
DLIST *_newdli(), *ls; /* list */
BYTE dmabuf[SECSIZE]; /* place for directory info */
fp = &f; /* everything else uses address */
parsefn(fs,fp); /* fill fcb with filespec */
SETDMA(dmabuf); /* tell em where to put it */
if( (ret=FSEARCH(fp)) > 3 ) /* look for first occurrence */
return NULLPTR; /* no luck */
ls=_newdli(dmabuf+(ret<<5),NULLPTR); /* start off a list */
while( (ret=NSEARCH(fp)) <= 3 ) { /* do all the search_nexts */
ls = _newdli(dmabuf+(ret<<5),ls); /* link them together */
}
return ls;
}
DLIST *
_newdli(f,lnk)
FCB *f;
DLIST *lnk;
{
REG WORD i;
BYTE *np, nb[15]; /* name buffer */
DLIST *newl; /* new list item */
/* make a pretty filename */
np = nb;
for( i=0; i<11; ++i ) /* zap out any high bits in filename */
f->fcbname[i] &= AMASK; /* mask off attribute bits */
for( i=0; i<8; ++i ) { /* handle name spec */
if( f->fcbname[i] == ' ' ) /* end of name? */
break; /* okay */
*np++ = f->fcbname[i]; /* o.w. stuff into name buffer */
}
*np++ = '.'; /* tack this on */
for( i=0; i<3; ++i ){ /* handle ext spec */
if( f->fcbext[i] == ' ' ) /* end of ext? */
break;
*np++ = f->fcbext[i];
}
*np++ = NULL; /* null terminate string */
/*************************************************************/
np = malloc(np-nb); /* save it away */
strcpy(np,nb); /* do the copy */
newl = (DLIST *)malloc(sizeof(*newl)); /* get ptr area set up */
newl->dlname = np;
newl->dlnext = lnk;
return newl;
}
parsefn(fs,f)
BYTE *fs; /* file spec */
FCB *f; /* fcb */
{
REG WORD i;
REG BYTE *cp;
for( cp=fs; *cp; cp++ ) /* make everything upper case */
if( islower(*cp) )
*cp = toupper(*cp);
for( i=0; i<24; ++i ) /* init fcb */
f->fcbrest[i] = 0;
if( *(fs+1) == ':' ) { /* drive spec? */
f->fcbdr = 1 + *fs - 'A'; /* 0=default, 1 = A:,... */
fs += 2; /* skip dr spec */
} else f->fcbdr = 0; /* default drive */
for( i=0; *fs && *fs != '.' && i<8; fs++, ++i ) { /* NAME. */
if( *fs == '*' ) { /* wildcard? */
for( ; i<8; ++i ) /* fill up rest of name */
f->fcbname[i]='?'; /* with search spec */
for( ; *fs && *fs!='.'; fs++ ) /* ignore to end or '.' */
;
break; /* terminate loop */
}
f->fcbname[i] = *fs;
}
for( ; i<8; ++i ) /* fill up rest of name */
f->fcbname[i] = ' '; /* with blanks */
for( ; *fs; fs++ ) /* skip rest of name */
if( *fs == '.' ) { /* end of name? */
fs++; break; /* yes, so exit this loop */
}
for( i=0; *fs && i<3; fs++,++i ) { /* .EXT */
if( *fs == '*' ){ /* wildcard */
for( ; i<3; ++i )
f->fcbext[i] = '?';
break;
}
f->fcbext[i] = *fs;
}
for( ; i<3; ++i ) /* fill up rest of ext */
f->fcbext[i] = ' '; /* with blanks */
}
/* access: tests for existence: return NULL if exist, -1 o.w. */
WORD
access(fn)
BYTE *fn;
{
FCB f; /* use this FCB */
BYTE dmabuf[SECSIZE]; /* place for directory info */
parsefn(fn,&f); /* fill fcb with filespec */
SETDMA(dmabuf); /* tell em where to put it */
if( FSEARCH(&f) > 3 ) /* look for first occurrence */
return -1; /* no luck */
return 0;
}
BYTE *
gets(s)
BYTE *s;
{
BYTE *sav;
if( fgets(s,32767,stdin) == NULLPTR )
return NULLPTR;
if( !isatty(0) ) /* reading from CON:? */
fputs(s,stdout); /* echo if not */
for( sav=s; *s && *s != '\n'; ++s )
;
*s = '\0';
return sav;
}
/************************************************************************/
BYTE
getdrive()
{
return __OSIF(25,0);
}
/************************************************************************/
/* press_return: let user look at screen */
press_return()
{
BYTE bitbucket[40]; /* leave room */
if( !isatty(0) ) { /* stdin from CON:? */
printf("Error in command file: terminating program\n");
exit(1);
}
printf("\07Press RETURN to continue ");
if( gets(bitbucket)!=bitbucket )
exit(1); /* eof, quit now */
}
/* patch: provides a patch area */
patch() /* should never get called */
{
int i;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
i=i+5; i=i+5; i=i+5; i=i+5; i=i+5;
return;
}
/*******************************************************************/
/*******************************************************************/
/* T H E E N D
/*******************************************************************/
/*******************************************************************/


View File

@@ -0,0 +1,507 @@
/*************************************************************************/
/*************************************************************************/
/* genccpm.h - the include module(s) for genccpm.c
/*************************************************************************/
/*************************************************************************/
/***** include files *****/
#include <portab.h>
#include <stdio.h>
#include <ctype.h>
#include <cpm.h>
/*************************/
/* New types for GENCCPM: */
#define ADDR UWORD /* offset in system image */
#define SEG UWORD /* segment in system image */
#define FPTR LONG /* pointer into file */
/*******************************************/
/* compiler differences */
/* configured for Digital Research's C */
#define BROPEN(fn) openb(fn,0) /* binary open for read */
#define BWCREAT(fn) creatb(fn,1) /* binary creat for write */
LONG lseek();
BYTE *malloc();
BYTE *gets();
#define NULLPTRI 0 /* NULLPTR initializer */
/* compile time options: assume the "-dXXX" flag is used, where XXX is: */
/* #define CCPM /* this is a CCP/M EDSYS */
#define CMPM /* this is an CMP/M EDSYS */
/**************************************************************************/
#ifndef CCPM
#ifndef CMPM
ERROR: you must specify one of 'CMPM' or 'CCPM'
#endif
#endif
#ifdef CCPM
#ifdef CMPM
ERROR: these compile options are mutually exclusive: only 1 allowed!
#endif
#endif
/**************************************************************************/
/**************************************************************************/
/* menu.h : include with progs using menu rtns
/**************************************************************************/
/**************************************************************************/
#define MENU struct menuitem
MENU {
WORD mutype; /* type of menu item */
BYTE *muiptr; /* ptr to information for menu item */
BYTE *muname; /* name of menu item */
BYTE *mudesc; /* description of menu item */
MENU *munext; /* ptr to next menu item */
};
#define MBOOL 1
#define MBYTE 2
#define MWORD 3
#define MTEXT 4
#define MPROC 5
#define MDRIV 6
/**************************************************************************/
/**************************************************************************/
/* cpm.h - support for cpm types of calls
/**************************************************************************/
/**************************************************************************/
#define SECSIZ 128
#define BUFSIZ 512 /* should be in stdio.h */
/**************************************************************************/
/* directory search support */
#define DLIST struct dliststr /* directory list structure */
DLIST {
BYTE *dlname; /* file name */
DLIST *dlnext; /* next item in list */
};
/**************************************************************************/
/* .CMD header record Group structure */
#define GROUP struct cmdgrp
GROUP { /* what a Cmd Hdr group looks like */
BYTE gtype; /* type of group (see below) */
UWORD glen; /* length in paragraphs of group */
UWORD gabase; /* pgph addr for non-relocatable grp */
UWORD gmin; /* min pgphs to alloc to group */
UWORD gmax; /* max pgphs to alloc to group */
};
#define GTYPCODE 1 /* Code Group */
#define GTYPDATA 2 /* Data Group */
/**************************************************************************/
/**************************************************************************/
/* mpm.h - data structures peculiar to MP/M & Concurrent
/**************************************************************************/
/**************************************************************************/
#define MINKMEM 80 /* minimum memory allocation in paragraphs */
#define XIOSTAB struct xios_table
XIOSTAB {
UBYTE xt_tick;
UBYTE xt_ticks_sec;
UBYTE xt_door;
UBYTE xt_rsvd;
UBYTE xt_xpcns; /* # physical consoles; FMB */
UBYTE xt_nvcns;
UBYTE xt_nccbs;
UBYTE xt_nlcbs;
UWORD xt_ccb;
UWORD xt_lcb;
UWORD xt_dphtab[16];
UWORD xt_alloc;
};
#define XTABLEN (sizeof(XIOSTAB))
#define XTABLOC (0X0c0cL)
#define XTABALLOC (0X0c38L)
#define MD struct mem_descriptor
MD {
UWORD md_link;
UWORD md_start;
UWORD md_length;
UWORD md_plist;
UWORD md_unused;
};
#define PD struct proc_descriptor
PD {
UWORD pd_link;
UWORD pd_thread;
UBYTE pd_stat;
UBYTE pd_prior;
UWORD pd_flag;
BYTE pd_name[8];
UWORD pd_uda;
UBYTE pd_dsk;
UBYTE pd_user;
UBYTE pd_ldsk;
UBYTE pd_luser;
UWORD pd_mem;
BYTE pd_restofit[24];
};
#define LOCK struct lock_item
LOCK {
UWORD lo_link;
UWORD lo_restofit[4];
};
#define UDA struct uda_item
UDA {
BYTE ud_1space[0x50];
UWORD ud_csinit;
UWORD ud_dsinit;
UWORD ud_esinit;
UWORD ud_ssinit;
BYTE ud_2space[0xA8]; /* uda is 0x100 bytes long */
};
#define QCB struct qcb_descriptor
QCB {
UWORD qc_link;
BYTE qc_restofit[26];
};
#define FLAG struct flag_item
FLAG {
UBYTE fl_status;
UWORD fl_pd;
};
#define CCB struct ccb_item
CCB {
UWORD cc_attach;
UWORD cc_queue;
UBYTE cc_flag;
UBYTE cc_startcol;
UBYTE cc_column;
UBYTE cc_nchar;
UBYTE cc_mimic;
UBYTE cc_msource;
UBYTE cc_type;
UBYTE cc_xdev;
};
#define SATITEM struct sat_item
SATITEM {
UWORD sa_start;
UWORD sa_length;
UBYTE sa_nall;
};
/**************************************************************************/
/**************************************************************************/
/* here's the body of edsys.h
/**************************************************************************/
/**************************************************************************/
#ifdef CCPM
#define PROGNAME "GENCCPM"
#define VERLABEL "Concurrent CP/M-86 2.1"
#define VERSION 0x1421
#else
#define PROGNAME "GENCCPM"
#define VERLABEL "Concurrent CP/M-86 3.1"
#define VERSION 0x1431
#endif
#define SYSFILE "CCPM.SYS"
#define NEWSYS "CCPM.$Y$"
#define OLDSYS "CCPM.OLD"
#define MODEXT ".CON"
#define SUPMOD "SUP.CON"
#define RTMMOD "RTM.CON"
#define MEMMOD "MEM.CON"
#define CIOMOD "CIO.CON"
#define BDOSMOD "BDOS.CON"
#define NETMOD "NET86.CON"
#define SYSMOD "SYSDAT.CON"
#define XIOSMOD "XIOS.CON"
/**************************************************************************/
#define USERR printf /* how to handle user errors */
#define CRASH(fn) {fprintf(stderr,fn);exit(1);}
#define FCHECK(sp) /* disable */
/* if(ferror(sp)){printf("Error on output: out of space?");exit(1);} */
#define DBGPRT printf
#define CMDSLEN 80
#define PROMPT "Changes? "
/* memory list definition */
#define MLIST struct memorylist
MLIST {
UWORD mlfirst; /* addr of 1st pgph */
UWORD mllast; /* addr of last pgph */
UWORD mlsize; /* partition size in K bytes */
MLIST *mlnext; /* ptr to next item in list */
};
/* ENTRY point structure decls */
#define ENTRY struct entrypoint
ENTRY {
UWORD ep_eoff; /* entry offset */
UWORD ep_eseg; /* entry segment */
UWORD ep_ioff; /* init offset */
UWORD ep_iseg; /* init segment */
};
/* FIXup structure decls */
#define FIX struct fixitem
FIX {
LONG f_addr; /* offset in file */
WORD f_type; /* either F_ADD or F_PUT */
WORD *f_ptr; /* ptr to value to add or put */
FIX *f_next; /* next fixup item */
};
#define F_ADD 1 /* add value of value to word in file*/
#define F_PUT 2 /* put value ... */
/**************************************************************************/
/* Program Globals:
/* Keep all the globals defined in one file, for ease of access
/* Definitions first, then declarations
/**************************************************************************/
/******** definitions for the MAINMODULE **********/
#ifdef MAINMODULE
/**************************************************************************/
/* Edsys Program Globals
/**************************************************************************/
GLOBAL BYTE *copyright = "Copyright (C) 1983, Digital Research";
GLOBAL BYTE *version = VERLABEL;
GLOBAL BYTE *clearit; /* Home cursor & erase screen */
GLOBAL BOOLEAN verbose=TRUE; /* flag to tell EDSYS to be wordy */
GLOBAL BOOLEAN doit=FALSE; /* flag: tell EDSYS to do the rest of it */
GLOBAL WORD fns = -1; /* File descriptor for New System file */
GLOBAL BOOLEAN dogensys = FALSE; /* Gen System from scratch? */
GLOBAL BOOLEAN doclean = FALSE; /* Clean SYSFILE first from destination drive? */
GLOBAL BOOLEAN donew_xios = FALSE; /* edit in a NEW XIOS? */
GLOBAL BOOLEAN pure_xios = FALSE; /* XIOS groups are pure (separate) code & data? */
GLOBAL BYTE destdrv; /* where the SYSFILE goes */
/**************************************************************************/
/* Sysfile Globals
/**************************************************************************/
GLOBAL WORD totmds; /* total number of memory descriptors */
GLOBAL WORD totpds; /* total number of process descriptors */
GLOBAL WORD xtrapds; /* number of pds wanted by user */
GLOBAL WORD totqcbs; /* tot num q control blocks */
GLOBAL UWORD qbuflen; /* length in bytes of q buf area */
GLOBAL WORD totopen; /* total open files and locked records */
GLOBAL DLIST *rsps=NULLPTRI; /* list of RSP file names */
GLOBAL DLIST *syslbls=NULLPTRI; /* lines of OS label */
GLOBAL MLIST *memroot=NULLPTRI; /* memory partitions */
GLOBAL XIOSTAB xt; /* xios info table */
#define SDLEN 0x210
GLOBAL BYTE sdat_area[SDLEN]; /* where to store the SYSDAT info */
GLOBAL BYTE cmdhdr[SECSIZ]; /* command header for NEWSYS */
/* module length information: lengths are in paragraphs */
GLOBAL UWORD clsup; /* code length: supervisor */
GLOBAL UWORD clos_label; /* code length: OS label */
GLOBAL UWORD clrtm; /* " " : real time monitor */
GLOBAL UWORD clmem; /* " " : memory manager */
GLOBAL UWORD clcio; /* " " : char i/o */
GLOBAL UWORD clbdos; /* " " : bdos */
GLOBAL UWORD clnet; /* " " : network handler */
GLOBAL UWORD clxios; /* " " : xios */
GLOBAL UWORD cltotal; /* " " of all modules */
GLOBAL UWORD dsstart; /* starting segment of system data */
GLOBAL UWORD dlsysdat; /* data length: system data */
GLOBAL UWORD dlxios; /* length of xios in data seg */
GLOBAL UWORD dltables; /* length of tables */
GLOBAL UWORD dsotables; /* starting offset of tables */
GLOBAL UWORD dlrsps; /* length of rsps */
GLOBAL UWORD dltotal; /* length of data, xios, tables & rsps */
GLOBAL UWORD rsvd_seg; /* start of OS reserved (buffer) area (not in load image) */
GLOBAL UWORD bufs_seg; /* ptr to allocated buffer at rsvd_seg */
/*** fixup locations ***/
GLOBAL LONG fldstart; /* location of SYSDAT start */
GLOBAL LONG locmfl; /* location in file of mem free list */
/**************************************************************************/
/* system data variables for MP/M-86 or Concurrent CP/M-86 */
/**************************************************************************/
GLOBAL ENTRY * sd_supmod;
GLOBAL ENTRY * sd_rtmmod;
GLOBAL ENTRY * sd_memmod;
GLOBAL ENTRY * sd_ciomod;
GLOBAL ENTRY * sd_bdosmod;
GLOBAL ENTRY * sd_xiosmod;
GLOBAL ENTRY * sd_netmod;
GLOBAL UWORD * sd_mpmseg;
GLOBAL UWORD * sd_rspseg;
GLOBAL UWORD * sd_endseg;
GLOBAL UBYTE * sd_module_map;
GLOBAL UBYTE * sd_ncns;
GLOBAL UBYTE * sd_nlst;
GLOBAL UBYTE * sd_nccb;
GLOBAL UBYTE * sd_nflags;
GLOBAL UBYTE * sd_srchdisk;
GLOBAL UWORD * sd_mmp;
GLOBAL UBYTE * sd_nslaves;
GLOBAL UBYTE * sd_dayfile;
GLOBAL UBYTE * sd_tempdisk;
GLOBAL UBYTE * sd_tickspsec;
GLOBAL UWORD * sd_lul;
GLOBAL UWORD * sd_ccb;
GLOBAL UWORD * sd_flags;
GLOBAL UWORD * sd_mdul;
GLOBAL UBYTE * sd_nxmds;
GLOBAL UWORD * sd_mfl;
GLOBAL UBYTE * sd_nmparts;
GLOBAL UWORD * sd_pul;
GLOBAL UBYTE * sd_nxpd;
GLOBAL UWORD * sd_qul;
GLOBAL UBYTE * sd_nqds;
GLOBAL UWORD * sd_qmau;
GLOBAL UWORD * sd_qmastart; /* segment start of q buffer */
GLOBAL UWORD * sd_qmalen; /* length of q buffer */
GLOBAL UWORD * sd_verptr; /* pts to SUP segment ver string */
GLOBAL UWORD * sd_vn; /* F.12 version num */
GLOBAL UWORD * sd_mpmvn; /* F.163 version num */
GLOBAL UBYTE * sd_ncondev;
GLOBAL UBYTE * sd_nlstdev;
GLOBAL UBYTE * sd_nciodev;
GLOBAL UWORD * sd_lcb;
GLOBAL UBYTE * sd_plock_max;
GLOBAL UBYTE * sd_popen_max;
GLOBAL UBYTE * sd_cmode;
GLOBAL UBYTE * sd_xpcns;
#else
/****** declarations for non MAINMODULE *******/
/**************************************************************************/
/* Program Globals
/**************************************************************************/
EXTERN BYTE *copyright;
EXTERN BYTE *version;
EXTERN BYTE *clearit; /* Home cursor & erase screen */
EXTERN BOOLEAN verbose; /* flag to tell EDSYS to be wordy */
EXTERN BOOLEAN doit; /* flag: tell EDSYS to do the rest of it */
EXTERN WORD fns; /* File descriptor for New System file */
EXTERN BOOLEAN dogensys; /* Gen System from scratch? */
EXTERN BOOLEAN doclean; /* Clean SYSFILE first from destination drive? */
EXTERN BOOLEAN donew_xios; /* edit in a NEW XIOS? */
EXTERN BOOLEAN pure_xios; /* XIOS groups are pure (separate) code & data? */
EXTERN BYTE destdrv; /* where the SYSFILE goes */
/**************************************************************************/
/* Sysfile Globals
/**************************************************************************/
EXTERN WORD totmds; /* total number of memory descriptors */
EXTERN WORD totpds; /* total number of process descriptors */
EXTERN WORD xtrapds; /* number of pds wanted by user */
EXTERN WORD totqcbs; /* tot num q control blocks */
EXTERN UWORD qbuflen; /* length in bytes of q buf area */
EXTERN WORD totopen; /* total open files & locked records */
EXTERN DLIST *rsps; /* list of RSP file names */
EXTERN DLIST *syslbls; /* lines of OS label */
EXTERN MLIST *memroot; /* memory partitions */
EXTERN XIOSTAB xt; /* xios info table */
EXTERN BYTE sdat_area[]; /* where to store the SYSDAT info */
EXTERN BYTE *cmdhdr; /* command header for NEWSYS */
EXTERN UWORD clsup; /* code length: supervisor */
EXTERN UWORD clos_label; /* code length: OS label */
EXTERN UWORD clrtm; /* " " : real time monitor */
EXTERN UWORD clmem; /* " " : memory manager */
EXTERN UWORD clcio; /* " " : char i/o */
EXTERN UWORD clbdos; /* " " : bdos */
EXTERN UWORD clnet; /* " " : network handler */
EXTERN UWORD clxios; /* " " : xios */
EXTERN UWORD cltotal; /* " " of all modules */
EXTERN UWORD dsstart; /* starting segment of system data */
EXTERN UWORD dlsysdat; /* data length: system data */
EXTERN UWORD dlxios; /* length of xios in data seg */
EXTERN UWORD dltables; /* length of tables */
EXTERN UWORD dsotables; /* starting offset of tables */
EXTERN UWORD dlrsps; /* length of rsps */
EXTERN UWORD dltotal; /* length of data, xios, tables & rsps */
EXTERN UWORD rsvd_seg; /* start of OS reserved (buffer) area (not in load image) */
EXTERN UWORD bufs_seg; /* ptr to allocated buffer at rsvd_seg */
/*** fixup locations ***/
EXTERN LONG fldstart; /* location of SYSDAT start */
EXTERN LONG locmfl; /* location in file of mem free list */
/***********************************************************/
/* system data variables for MP/M-86 or Concurrent CP/M-86 */
EXTERN ENTRY * sd_supmod;
EXTERN ENTRY * sd_rtmmod;
EXTERN ENTRY * sd_memmod;
EXTERN ENTRY * sd_ciomod;
EXTERN ENTRY * sd_bdosmod;
EXTERN ENTRY * sd_xiosmod;
EXTERN ENTRY * sd_netmod;
EXTERN UWORD * sd_mpmseg;
EXTERN UWORD * sd_rspseg;
EXTERN UWORD * sd_endseg;
EXTERN UBYTE * sd_module_map;
EXTERN UBYTE * sd_ncns;
EXTERN UBYTE * sd_nlst;
EXTERN UBYTE * sd_nccb;
EXTERN UBYTE * sd_nflags;
EXTERN UBYTE * sd_srchdisk;
EXTERN UWORD * sd_mmp;
EXTERN UBYTE * sd_nslaves;
EXTERN UBYTE * sd_dayfile;
EXTERN UBYTE * sd_tempdisk;
EXTERN UBYTE * sd_tickspsec;
EXTERN UWORD * sd_lul;
EXTERN UWORD * sd_ccb;
EXTERN UWORD * sd_flags;
EXTERN UWORD * sd_mdul;
EXTERN UBYTE * sd_nxmds;
EXTERN UWORD * sd_mfl;
EXTERN UBYTE * sd_nmparts;
EXTERN UWORD * sd_pul;
EXTERN UBYTE * sd_nxpd;
EXTERN UWORD * sd_qul;
EXTERN UBYTE * sd_nqds;
EXTERN UWORD * sd_qmau;
EXTERN UWORD * sd_qmastart; /* segment start of q buffer */
EXTERN UWORD * sd_qmalen; /* length of q buffer */
EXTERN UWORD * sd_verptr; /* pts to SUP segment ver string */
EXTERN UWORD * sd_vn; /* F.12 version num */
EXTERN UWORD * sd_mpmvn; /* F.163 version num */
EXTERN UBYTE * sd_ncondev;
EXTERN UBYTE * sd_nlstdev;
EXTERN UBYTE * sd_nciodev;
EXTERN UWORD * sd_lcb;
EXTERN UBYTE * sd_plock_max;
EXTERN UBYTE * sd_popen_max;
EXTERN UBYTE * sd_cmode;
EXTERN UBYTE * sd_xpcns;
#endif
#define PUTDRV(dd,nn) (sprintf(dd,"%c:%s",'A'+destdrv,nn))


View File

@@ -0,0 +1,8 @@
drc genc1 -h
drc genc2 -h
drc genc3 -h
drc genc4 -h
drc genc5 -h
drc genc6 -h
link86 genccpm=genc1,genc2,genc3,genc4,genc5,genc6[libsyms


View File

@@ -0,0 +1,123 @@
gentab: proc options (main);
/* generate tables for 8086 disassembler 12/23/80 */
/* modified 5/14/81 */
declare
opcnt (2:6) fixed (7) static initial (0,0,0,0,0),
sum fixed (7),
len fixed (7),
line char (100) varying,
infile file,
outfile file,
litfile file,
opcode char (10) varying,
i fixed (7),
j fixed (15),
n fixed (7),
count fixed (15),
chars (200) char (6) varying;
open file (infile) input stream title ('OP86.DAT');
open file (outfile) print title ('OPTAB.DAT');
open file (litfile) print title ('OPTAB.LIT');
on endpage (outfile) begin; end;
on endpage (litfile) begin; end;
count = 0;
/* read op86.dat file into chars array */
get file (infile) list (opcode);
do while (opcode ^= '$');
count = count + 1;
chars (count) = opcode;
get file (infile) list (opcode);
end;
/* create ascii opcode tables, 1 for each character length */
do i = 2 to 6;
line = 'declare ops' || deblank (i) || ' (*) byte initial (';
n = 0;
do j = 1 to count;
if length (chars (j)) = i then
do;
if n > 0 then line = line || ', ';
if divide (n, 5, 7) * 5 = n then
do;
put file (outfile) skip list (line);
line = '^I';
end;
n = n + 1;
line = line || '''' || chars (j) || '''';
opcnt (i) = opcnt (i) + 1;
end;
end;
line = line || ');';
put file (outfile) skip list (line);
put file (outfile) skip;
end;
/* create array containing # of opcodes of each length */
line = 'declare nops (5) byte public initial (';
do i = 2 to 6;
line = line || deblank (opcnt (i));
if i < 6 then line = line || ', ';
end;
put file (outfile) skip list (line || ');');
put file (outfile) skip;
/* create array containing starting index for each opcode length */
line = 'declare opn$in (*) byte public initial (';
sum = 0;
do i = 2 to 6;
line = line || deblank (sum) || ', ';
sum = sum + opcnt (i);
end;
put file (outfile) skip list (line || '255);');
/* create literals for starting indexes for each opcode length */
sum = 0;
put file (litfile) skip list ('declare');
do i = 2 to 6;
put skip list (deblank (opcnt (i)), deblank (i) || '-character opcodes');
line = '^I' || 'op' || deblank (i) ||
'$in literally ''' || deblank (sum) || '''';
if i = 6 then line = line || ';';
else line = line || ',';
put file (litfile) skip list (line);
sum = sum + opcnt (i);
opcnt (i) = 0;
end;
/* create literals for position in opcode tables of each opcode */
put file (litfile) skip;
put file (litfile) skip list ('declare');
do j = 1 to count;
len = length (chars (j));
if index (chars (j), ':') > 0 then
chars (j) = substr (chars (j), 1, len-1);
line = '^I' || chars (j) || '$in literally '''
|| 'op' || deblank (len) || '$in + '
|| deblank (opcnt (len)) || '''';
if j = count then line = line || ';';
else line = line || ',';
put file (litfile) skip list (line);
opcnt (len) = opcnt (len) + 1;
end;
deblank: proc (i) returns (char (10) varying);
declare i fixed (7);
declare temp char (10) varying;
temp = char (i);
return (substr (temp, verify (temp, ' ')));
end deblank;
end gentab;


View File

@@ -0,0 +1,427 @@
$title('instruction table for 8086 disassembler')
$date(10/5/80)
instr86: do;
declare
qq$in literally '0',
alt1 literally '0',
alt2 literally '1',
alt3 literally '2',
alt4 literally '3',
alt5 literally '4',
alt6 literally '5',
alt7 literally '6',
alt8 literally '7';
$include(optab.lit)
declare
type$0 literally '0',
type$1 literally '1',
type$2 literally '2',
type$3 literally '3',
type$4 literally '4',
type$5 literally '5',
type$6 literally '6',
type$7 literally '7',
type$8 literally '7',
type$9 literally '7',
type$10 literally '8',
type$11 literally '9',
type$12 literally '10',
type$13 literally '11',
type$14 literally '12',
type$15 literally '12',
type$16 literally '12',
type$17 literally '12',
type$18 literally '13',
type$19 literally '13',
type$20 literally '13',
type$21 literally '13',
type$22 literally '14',
type$23 literally '15',
type$24 literally '15',
type$25 literally '16',
type$26 literally '16',
type$27 literally '17',
type$28 literally '17',
type$29 literally '17',
type$30 literally '17',
type$31 literally '18',
type$32 literally '18',
type$33 literally '19',
type$34 literally '20',
type$35 literally '20',
type$36 literally '21',
type$37 literally '21',
type$38 literally '22',
type$39 literally '23',
type$40 literally '24',
type$41 literally '24',
type$42 literally '25',
type$43 literally '26',
type$44 literally '27',
type$45 literally '28';
declare
prefix$type literally '0ffh';
declare alt$table$ptrs (8) address public data (
.alt$1$tab,
.alt$2$tab,
.alt$3$tab,
.alt$4$tab,
.alt$5$tab,
.alt$6$tab,
.alt$7$tab,
.alt$8$tab);
declare alt$1$tab (*) byte data (
add$in, type$44,
or$in, type$34,
adc$in, type$44,
sbb$in, type$44,
and$in, type$34,
sub$in, type$44,
xor$in, type$34,
cmp$in, type$44);
declare alt$2$tab (*) byte data (
add$in, type$44,
qq$in, type$0,
adc$in, type$44,
sbb$in, type$44,
qq$in, type$0,
sub$in, type$44,
qq$in, type$0,
cmp$in, type$44);
declare alt$3$tab (*) byte data (
add$in, type$38,
qq$in, type$0,
adc$in, type$38,
sbb$in, type$38,
qq$in, type$0,
sub$in, type$38,
qq$in, type$0,
cmp$in, type$38);
declare alt$4$tab (*) byte data (
rol$in, type$29,
ror$in, type$29,
rcl$in, type$29,
rcr$in, type$29,
shl$in, type$29,
shr$in, type$29,
qq$in, type$0,
sar$in, type$29);
declare alt$5$tab (*) byte data (
rol$in, type$27,
ror$in, type$27,
rcl$in, type$27,
rcr$in, type$27,
shl$in, type$27,
shr$in, type$27,
qq$in, type$0,
sar$in, type$27);
declare alt$6$tab (*) byte data (
test$in, type$34,
qq$in, type$0,
not$in, type$45,
neg$in, type$45,
mul$in, type$45,
imul$in, type$45,
div$in, type$45,
idiv$in, type$45);
declare alt$7$tab (*) byte data (
inc$in, type$45,
dec$in, type$45,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0);
declare alt$8$tab (*) byte data (
inc$in, type$45,
dec$in, type$45,
call$in, type$9,
callf$in, type$7,
jmp$in, type$9,
jmpf$in, type$7,
push$in, type$7,
qq$in, type$0);
/*
instruction table for 8086 disassembler
instruction is index into table
there are 2 bytes per instruction:
1. index into ascii opcode table
2. instruction type (how many operands of what type, etc.)
*/
declare instr$table (512) byte public data (
add$in, type$14, /* 0 */
add$in, type$15,
add$in, type$16,
add$in, type$17,
add$in, type$23,
add$in, type$24,
push$in, type$4,
pop$in, type$4,
or$in, type$14,
or$in, type$15,
or$in, type$16,
or$in, type$17,
or$in, type$23,
or$in, type$24,
push$in, type$4,
qq$in, type$0,
adc$in, type$14, /* 10 */
adc$in, type$15,
adc$in, type$16,
adc$in, type$17,
adc$in, type$23,
adc$in, type$24,
push$in, type$4,
pop$in, type$4,
sbb$in, type$14,
sbb$in, type$15,
sbb$in, type$16,
sbb$in, type$17,
sbb$in, type$23,
sbb$in, type$24,
push$in, type$4,
pop$in, type$4,
and$in, type$14, /* 20 */
and$in, type$15,
and$in, type$16,
and$in, type$17,
and$in, type$23,
and$in, type$24,
es$in, prefix$type,
daa$in, type$1,
sub$in, type$14,
sub$in, type$15,
sub$in, type$16,
sub$in, type$17,
sub$in, type$23,
sub$in, type$24,
cs$in, prefix$type,
das$in, type$1,
xor$in, type$14, /* 30 */
xor$in, type$15,
xor$in, type$16,
xor$in, type$17,
xor$in, type$23,
xor$in, type$24,
ss$in, prefix$type,
aaa$in, type$1,
cmp$in, type$14,
cmp$in, type$15,
cmp$in, type$16,
cmp$in, type$17,
cmp$in, type$23,
cmp$in, type$24,
ds$in, prefix$type,
aas$in, type$1,
inc$in, type$3, /* 40 */
inc$in, type$3,
inc$in, type$3,
inc$in, type$3,
inc$in, type$3,
inc$in, type$3,
inc$in, type$3,
inc$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
dec$in, type$3,
push$in, type$3, /* 50 */
push$in, type$3,
push$in, type$3,
push$in, type$3,
push$in, type$3,
push$in, type$3,
push$in, type$3,
push$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
pop$in, type$3,
qq$in, type$0, /* 60 */
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
qq$in, type$0,
jo$in, type$5, /* 70 */
jno$in, type$5,
jb$in, type$5,
jnb$in, type$5,
jz$in, type$5,
jnz$in, type$5,
jbe$in, type$5,
ja$in, type$5,
js$in, type$5,
jns$in, type$5,
jp$in, type$5,
jnp$in, type$5,
jl$in, type$5,
jnl$in, type$5,
jle$in, type$5,
jg$in, type$5,
alt1, type$43, /* 80 */
alt1, type$43,
alt2, type$43,
alt2, type$43,
test$in, type$14,
test$in, type$15,
xchg$in, type$16,
xchg$in, type$17,
mov$in, type$14,
mov$in, type$15,
mov$in, type$16,
mov$in, type$17,
mov$in, type$36,
lea$in, type$39,
mov$in, type$37,
pop$in, type$9,
nop$in, type$1, /* 90 */
xchg$in, type$33,
xchg$in, type$33,
xchg$in, type$33,
xchg$in, type$33,
xchg$in, type$33,
xchg$in, type$33,
xchg$in, type$33,
cbw$in, type$1,
cwd$in, type$1,
callf$in, type$13,
wait$in, type$1,
pushf$in, type$1,
popf$in, type$1,
sahf$in, type$1,
lahf$in, type$1,
mov$in, type$18, /* A0 */
mov$in, type$19,
mov$in, type$20,
mov$in, type$21,
movsb$in, type$1,
movsw$in, type$1,
cmpsb$in, type$1,
cmpsw$in, type$1,
test$in, type$23,
test$in, type$24,
stosb$in, type$1,
stosw$in, type$1,
lodsb$in, type$1,
lodsw$in, type$1,
scasb$in, type$1,
scasw$in, type$1,
mov$in, type$31, /* B0 */
mov$in, type$31,
mov$in, type$31,
mov$in, type$31,
mov$in, type$31,
mov$in, type$31,
mov$in, type$31,
mov$in, type$31,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
mov$in, type$32,
qq$in, type$0, /* C0 */
qq$in, type$0,
ret$in, type$11,
ret$in, type$1,
les$in, type$39,
lds$in, type$39,
mov$in, type$40,
mov$in, type$41,
qq$in, type$0,
qq$in, type$0,
retf$in, type$11,
retf$in, type$1,
int$in, type$12,
int$in, type$10,
into$in, type$1,
iret$in, type$1,
alt4, type$43, /* D0 */
alt4, type$43,
alt5, type$43,
alt5, type$43,
aam$in, type$2,
aad$in, type$2,
qq$in, type$0,
xlat$in, type$1,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
esc$in, type$42,
loopne$in, type$5, /* E0 */
loope$in, type$5,
loop$in, type$5,
jcxz$in, type$5,
in$in, type$22,
in$in, type$22,
out$in, type$22,
out$in, type$22,
call$in, type$6,
jmp$in, type$6,
jmpf$in, type$13,
jmps$in, type$5,
in$in, type$25,
in$in, type$26,
out$in, type$25,
out$in, type$26,
lock$in, prefix$type, /* F0 */
qq$in, type$0,
repne$in, prefix$type,
rep$in, prefix$type,
hlt$in, type$1,
cmc$in, type$1,
alt6, type$43,
alt6, type$43,
clc$in, type$1,
stc$in, type$1,
cli$in, type$1,
sti$in, type$1,
cld$in, type$1,
std$in, type$1,
alt7, type$43,
alt8, type$43);
end instr86;


View File

@@ -0,0 +1,11 @@
/*
* Use this file to determine what kind of machine you want the
* DRC stuff to run on ....
*/
/*#define MC68000 1 /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
#define CPM 1 /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/


View File

@@ -0,0 +1,126 @@
AAA
AAD
AAM
AAS
ADC
ADD
AND
CALL
CALLF
CBW
CLC
CLD
CLI
CMC
CMP
CMPSB
CMPSW
CS:
CWD
DAA
DAS
DEC
DIV
DS:
ES:
ESC
HLT
IDIV
IMUL
IN
INC
INT
INTO
IRET
JA
JAE
JB
JBE
JC
JCXZ
JE
JG
JGE
JL
JLE
JMP
JMPF
JMPS
JNA
JNAE
JNB
JNBE
JNC
JNE
JNG
JNGE
JNL
JNLE
JNO
JNP
JNS
JNZ
JO
JP
JPE
JPO
JS
JZ
LAHF
LDS
LEA
LES
LOCK
LODSB
LODSW
LOOP
LOOPE
LOOPNE
LOOPNZ
LOOPZ
MOV
MOVSB
MOVSW
MUL
NEG
NOP
NOT
OR
OUT
POP
POPF
PUSH
PUSHF
RCL
RCR
REP
REPE
REPNE
REPNZ
REPZ
RET
RETF
ROL
ROR
SAHF
SAL
SAR
SBB
SCASB
SCASW
SHL
SHR
SS:
STC
STD
STI
STOSB
STOSW
SUB
TEST
WAIT
XCHG
XLAT
XOR
$


View File

@@ -0,0 +1,42 @@
declare ops2 (*) byte initial (
'IN', 'JA', 'JB', 'JC', 'JE',
'JG', 'JL', 'JO', 'JP', 'JS',
'JZ', 'OR');
declare ops3 (*) byte initial (
'AAA', 'AAD', 'AAM', 'AAS', 'ADC',
'ADD', 'AND', 'CBW', 'CLC', 'CLD',
'CLI', 'CMC', 'CMP', 'CS:', 'CWD',
'DAA', 'DAS', 'DEC', 'DIV', 'DS:',
'ES:', 'ESC', 'HLT', 'INC', 'INT',
'JAE', 'JBE', 'JGE', 'JLE', 'JMP',
'JNA', 'JNB', 'JNC', 'JNE', 'JNG',
'JNL', 'JNO', 'JNP', 'JNS', 'JNZ',
'JPE', 'JPO', 'LDS', 'LEA', 'LES',
'MOV', 'MUL', 'NEG', 'NOP', 'NOT',
'OUT', 'POP', 'RCL', 'RCR', 'REP',
'RET', 'ROL', 'ROR', 'SAL', 'SAR',
'SBB', 'SHL', 'SHR', 'SS:', 'STC',
'STD', 'STI', 'SUB', 'XOR');
declare ops4 (*) byte initial (
'CALL', 'IDIV', 'IMUL', 'INTO', 'IRET',
'JCXZ', 'JMPF', 'JMPS', 'JNAE', 'JNBE',
'JNGE', 'JNLE', 'LAHF', 'LOCK', 'LOOP',
'POPF', 'PUSH', 'REPE', 'REPZ', 'RETF',
'SAHF', 'TEST', 'WAIT', 'XCHG', 'XLAT');
declare ops5 (*) byte initial (
'CALLF', 'CMPSB', 'CMPSW', 'LODSB', 'LODSW',
'LOOPE', 'LOOPZ', 'MOVSB', 'MOVSW', 'PUSHF',
'REPNE', 'REPNZ', 'SCASB', 'SCASW', 'STOSB',
'STOSW');
declare ops6 (*) byte initial (
'LOOPNE', 'LOOPNZ');
declare nops (5) byte public initial (12, 69, 25, 16, 2);
declare opn$in (*) byte public initial (0, 12, 81, 106, 122, 255);


View File

@@ -0,0 +1,134 @@
declare
op2$in literally '0',
op3$in literally '12',
op4$in literally '81',
op5$in literally '106',
op6$in literally '122';
declare
AAA$in literally 'op3$in + 0',
AAD$in literally 'op3$in + 1',
AAM$in literally 'op3$in + 2',
AAS$in literally 'op3$in + 3',
ADC$in literally 'op3$in + 4',
ADD$in literally 'op3$in + 5',
AND$in literally 'op3$in + 6',
CALL$in literally 'op4$in + 0',
CALLF$in literally 'op5$in + 0',
CBW$in literally 'op3$in + 7',
CLC$in literally 'op3$in + 8',
CLD$in literally 'op3$in + 9',
CLI$in literally 'op3$in + 10',
CMC$in literally 'op3$in + 11',
CMP$in literally 'op3$in + 12',
CMPSB$in literally 'op5$in + 1',
CMPSW$in literally 'op5$in + 2',
CS$in literally 'op3$in + 13',
CWD$in literally 'op3$in + 14',
DAA$in literally 'op3$in + 15',
DAS$in literally 'op3$in + 16',
DEC$in literally 'op3$in + 17',
DIV$in literally 'op3$in + 18',
DS$in literally 'op3$in + 19',
ES$in literally 'op3$in + 20',
ESC$in literally 'op3$in + 21',
HLT$in literally 'op3$in + 22',
IDIV$in literally 'op4$in + 1',
IMUL$in literally 'op4$in + 2',
IN$in literally 'op2$in + 0',
INC$in literally 'op3$in + 23',
INT$in literally 'op3$in + 24',
INTO$in literally 'op4$in + 3',
IRET$in literally 'op4$in + 4',
JA$in literally 'op2$in + 1',
JAE$in literally 'op3$in + 25',
JB$in literally 'op2$in + 2',
JBE$in literally 'op3$in + 26',
JC$in literally 'op2$in + 3',
JCXZ$in literally 'op4$in + 5',
JE$in literally 'op2$in + 4',
JG$in literally 'op2$in + 5',
JGE$in literally 'op3$in + 27',
JL$in literally 'op2$in + 6',
JLE$in literally 'op3$in + 28',
JMP$in literally 'op3$in + 29',
JMPF$in literally 'op4$in + 6',
JMPS$in literally 'op4$in + 7',
JNA$in literally 'op3$in + 30',
JNAE$in literally 'op4$in + 8',
JNB$in literally 'op3$in + 31',
JNBE$in literally 'op4$in + 9',
JNC$in literally 'op3$in + 32',
JNE$in literally 'op3$in + 33',
JNG$in literally 'op3$in + 34',
JNGE$in literally 'op4$in + 10',
JNL$in literally 'op3$in + 35',
JNLE$in literally 'op4$in + 11',
JNO$in literally 'op3$in + 36',
JNP$in literally 'op3$in + 37',
JNS$in literally 'op3$in + 38',
JNZ$in literally 'op3$in + 39',
JO$in literally 'op2$in + 7',
JP$in literally 'op2$in + 8',
JPE$in literally 'op3$in + 40',
JPO$in literally 'op3$in + 41',
JS$in literally 'op2$in + 9',
JZ$in literally 'op2$in + 10',
LAHF$in literally 'op4$in + 12',
LDS$in literally 'op3$in + 42',
LEA$in literally 'op3$in + 43',
LES$in literally 'op3$in + 44',
LOCK$in literally 'op4$in + 13',
LODSB$in literally 'op5$in + 3',
LODSW$in literally 'op5$in + 4',
LOOP$in literally 'op4$in + 14',
LOOPE$in literally 'op5$in + 5',
LOOPNE$in literally 'op6$in + 0',
LOOPNZ$in literally 'op6$in + 1',
LOOPZ$in literally 'op5$in + 6',
MOV$in literally 'op3$in + 45',
MOVSB$in literally 'op5$in + 7',
MOVSW$in literally 'op5$in + 8',
MUL$in literally 'op3$in + 46',
NEG$in literally 'op3$in + 47',
NOP$in literally 'op3$in + 48',
NOT$in literally 'op3$in + 49',
OR$in literally 'op2$in + 11',
OUT$in literally 'op3$in + 50',
POP$in literally 'op3$in + 51',
POPF$in literally 'op4$in + 15',
PUSH$in literally 'op4$in + 16',
PUSHF$in literally 'op5$in + 9',
RCL$in literally 'op3$in + 52',
RCR$in literally 'op3$in + 53',
REP$in literally 'op3$in + 54',
REPE$in literally 'op4$in + 17',
REPNE$in literally 'op5$in + 10',
REPNZ$in literally 'op5$in + 11',
REPZ$in literally 'op4$in + 18',
RET$in literally 'op3$in + 55',
RETF$in literally 'op4$in + 19',
ROL$in literally 'op3$in + 56',
ROR$in literally 'op3$in + 57',
SAHF$in literally 'op4$in + 20',
SAL$in literally 'op3$in + 58',
SAR$in literally 'op3$in + 59',
SBB$in literally 'op3$in + 60',
SCASB$in literally 'op5$in + 12',
SCASW$in literally 'op5$in + 13',
SHL$in literally 'op3$in + 61',
SHR$in literally 'op3$in + 62',
SS$in literally 'op3$in + 63',
STC$in literally 'op3$in + 64',
STD$in literally 'op3$in + 65',
STI$in literally 'op3$in + 66',
STOSB$in literally 'op5$in + 14',
STOSW$in literally 'op5$in + 15',
SUB$in literally 'op3$in + 67',
TEST$in literally 'op4$in + 21',
WAIT$in literally 'op4$in + 22',
XCHG$in literally 'op4$in + 23',
XLAT$in literally 'op4$in + 24',
XOR$in literally 'op3$in + 68';


View File

@@ -0,0 +1,59 @@
/*****************************************************************************
*
* C P / M C R U N T I M E L I B H E A D E R F I L E
* -------------------------------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This is an include file for assisting the user to write portable
* programs for C.
*
*****************************************************************************/
#define UCHARA 1 /* if char is unsigned */
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define BOOLEAN int /* 2 valued (true/false) */
#define WORD int /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
#define DEFAULT int /* Default size */
/***************************/
#ifdef UCHARA
#define UBYTE char /* Unsigned byte */
#else
#define UBYTE unsigned char /* Unsigned byte */
#endif
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL 0 /* Null pointer value */
#define NULLPTR (char *) 0 /* */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
/*************************** end of portab.h ********************************/