[comp.os.minix] PC-AT-386 debugger source 3 of 7

brucee@runx.ips.oz (Bruce Evans) (11/26/88)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 7)."
# Contents:  kernel/db/int88.s kernel/db/keyboard.c kernel/db/sym.c
# Wrapped by sys@besplex on Sat Nov 26 06:00:18 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'kernel/db/int88.s' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kernel/db/int88.s'\"
else
echo shar: Extracting \"'kernel/db/int88.s'\" \(6686 characters\)
sed "s/^X//" >'kernel/db/int88.s' <<'END_OF_FILE'
X| int88.s
X
X| exported routines
X
X	.define	_db
X	.define	_dbinit
X|	.define _exit		| DOS only
X|	.define	.fat		| DOS only & Minix cc only
X|	.define	_main		| DOS only
X
X| imported routines
X
X	.extern	_db_main
X
X| exported variables
X
X|	.define	begdata		| DOS only & Minix cc only
X|	.define	begbss		| DOS only & Minix cc only
X	.define	_db_stacktop	| temp exported for 386 protected mode init
X
X| imported variables
X
X	.data
X	.extern	_db_processor	| processor type 86, 186, 286, 386
X	.extern	_edata
X	.extern	_end
X	.extern	_protected
X
XBIOS_DATA_SEG	=	0x40
X  KB_FLAG	=	0x17	| byte
X    ALT_SHIFT	=	8	| state bits
X    CTL_SHIFT	=	4
X    LEFT_SHIFT	=	2
XBREAK_VECTOR	=	4*3	| offset for breakpoint interrupt vector
XCLICK_SHIFT	=	4	| log2 CLICK_SIZE
XCLICK_SIZE	=	16	| allocation unit for TSR's
XCOM_OFFSET	=	0x100	| offset of program in an MS DOS .COM file
XDB_DS		=	4	| db data seg held here in kernel code seg
XFARI1_CALL	=	0xFF	| as386 doesn't have far indirect calls yet
XFARI2_CALL	=	0x1E
XKEYBOARD_VECTOR	=	4*9	| PC BIOS hardware keyboard interrupt number
XMS_DOS		=	0x21	| MS DOS main software interrupt number
X  TSR		=	0x31
XOS		=	0x66	| operand size override for 386
XPE		=	0x00000001	| protected mode cr0 flag bit for 386
XSSTEP_VECTOR	=	4*1	| offset for single step interrupt vector
XSTACK_SIZE	=	256
XTF		=	0x0100	| trap bit in flags
XVECTOR_SEG	=	0	| segment for interrupt vectors
X
X	.text
X
X| .space	COM_OFFSET	| DOS only (COM program)
X
X| enter here for startup code (DOS only)
X
X| _main:				| DOS only
X	jmp	dos_init
X
X| call this to enter db
X| initialisation is done automatically
X
X_db:
X	call	_dbinit
X	int	BREAK_VECTOR/4
X	ret
X
X_dbinit:
X	pushf
X	push	ax
X	call	_get_processor
X	cmp	ax,#386
X	jne	db_setvect	| only support protected mode for 386
X|	push	eax
X	.byte	OS
X	push	ax
X|	mov	eax,cr0
X	.byte	0x0F,0x20,0xC0
X	andb	al,#PE
X|	pop	eax
X	.byte	OS
X	pop	ax
X	jne	over_db_setvect	| protected init is too hard here, assume it
Xdb_setvect:
X	push	ds
X	call	setvect
X	pop	ds
Xover_db_setvect:
X	pop	ax
X	popf
X	ret
X
Xsetvect:
X	mov	ax,#VECTOR_SEG
X	mov	ds,ax
X	mov	ax,#sstep_int
X	cli
X	mov	SSTEP_VECTOR,ax
X	mov	SSTEP_VECTOR+2,cs
X	mov	ax,#break_int
X	mov	BREAK_VECTOR,ax
X	mov	BREAK_VECTOR+2,cs
X	ret			| leave ds = VECTOR_SEG and cli
X
X| enter here for hardware keyboard int (DOS only)
X| do a breakpoint if CTRL - ALT - LEFT_SHIFT
X
Xkb_int:
X	pushf
X	seg	cs
X|	call	far old_kb_vector
X	.byte	FARI1_CALL
X	.byte	FARI2_CALL
X	.word	old_kb_vector
X	push	ax
X	push	ds
X	mov	ax,*BIOS_DATA_SEG
X	mov	ds,ax
X	movb	al,KB_FLAG
X	andb	al,*CTL_SHIFT+ALT_SHIFT+LEFT_SHIFT
X	cmpb	al,*CTL_SHIFT+ALT_SHIFT+LEFT_SHIFT
X	pop	ds
X	pop	ax
X	jnz	db_iret
X
X| enter here from software breakpoint int
X
Xbreak_int:
X	seg	cs
X	sarb	db_enable,*1	| test and set to 0xFF
X	jc	db_iret		| it was and remains set at 0xFF
X	seg	cs
X	movb	is_sstep,*0
X	j	db_int
X
Xdb_iret:
X	iret
X
X| enter here from hardware single step int
X
Xsstep_int:
X	seg	cs
X	sarb	db_enable,*1
X	jc	db_iret
X	seg	cs
X	movb	is_sstep,*1
X
X| common entry point
X| this code writes to the code segment, so only works in real mode (286/386)
X| it also assumes operand size == 16, again limiting it to real mode
X| but it decides if the processor is a 386 and records 32 bit registers if so
X
X| go through lots of contortions to avoid using current stack
X| an earlier version of db attempted to be reentrant by switching the
X| stack, but that is not feasible because there are too many global
X| variables (like 8K of screen buffers!) which would have to be switched too
X
Xdb_int:
X	seg	cs
X	mov	old_ds,ds
X	seg	cs
X	mov	ds,DB_DS
X	pop	old_ip		| set up sp:ss:ip:cs:f at top of local stack
X	pop	old_cs
X	pop	old_f
X	mov	old_sp,sp
X	mov	old_ss,ss
X	seg	cs
X	mov	ss,DB_DS
X	mov	sp,#stacktop
X
X	push	es		| continue setting up local stack
X	seg	cs
X	push	old_ds
X	push	zero		| place holder (prepare for not 80386)
X	push	bp
X	pushf			| test trace flag
X	pop	bp		| it should be clear (was cleared by int)
X	and	bp,*TF		| but if int is traced it will be set
X	jnz	to_db_exit	| resist attempt to trace self or breakpoint
X
X	push	ax
X	call	_get_processor
X	mov	_db_processor,ax
X	cmp	ax,#386
X	pop	ax
X	jne	save16
X
X| 386, fix up saved flags, ip, sp and bp to 32 bits
X| then save rest of (full 32 bit) regs
X
X	.byte	OS		| operand size override to 32 bits
X	pushf			| top 16 bits of old flags are current
X	add	sp,*2		| discard non-current low 16 bits
X	pop	old_f+2
X	mov	old_ip+2,*0	| it's too hard to get at ip, assume top is 0
X	.byte	OS
X	push	sp
X	add	sp,*2
X	pop	old_sp+2	| this should be 0 too
X	pop	bp
X	add	sp,*2
X	.byte	OS
X	push	bp
X
X	.byte	OS
X	push	di
X	.byte	OS
X	push	si
X	.byte	OS
X	push	dx
X	.byte	OS
X	push	cx
X	.byte	OS
X	push	bx
X	.byte	OS
X	push	ax
X	j	call_C
X
Xto_db_exit:
X	j	db_exit
X
Xsave16:
X	sub	bp,bp
X	push	bp
X	push	di
X	push	bp
X	push	si
X	push	bp
X	push	dx
X	push	bp
X	push	cx
X	push	bp
X	push	bx
X	push	bp
X	push	ax
X
Xcall_C:
X	cld			| direction UP for C
X	mov	ax,ds
X	mov	es,ax		| es == ds for C
X	seg	cs
X	push	is_sstep
X	call	_db_main
X	add	sp,*2
X
X	cmp	_db_processor,#386
X	jnz	restore16
X	.byte	OS
X	pop	ax
X	.byte	OS
X	pop	bx
X	.byte	OS
X	pop	cx
X	.byte	OS
X	pop	dx
X	.byte	OS
X	pop	si
X	.byte	OS
X	pop	di
X	.byte	OS
X	pop	bp
X	seg	cs
X	pop	old_ds
X	pop	es
X	mov	ss,old_ss
X	.byte	OS		| fatal if no longer 16 bits?
X	mov	sp,old_sp
X	j	db_1exit
X
Xrestore16:
X	pop	ax
X	add	sp,*2
X	pop	bx
X	add	sp,*2
X	pop	cx
X	add	sp,*2
X	pop	dx
X	add	sp,*2
X	pop	si
X	add	sp,*2
X	pop	di
X	add	sp,*2
Xdb_exit:
X	pop	bp
X	add	sp,*2
X	seg	cs
X	pop	old_ds
X	pop	es
X	mov	ss,old_ss
X	mov	sp,old_sp
X
Xdb_1exit:
X	push	old_f
X	push	old_cs
X	push	old_ip
X	seg	cs
X	mov	ds,old_ds
X	seg	cs
X	shlb	db_enable,*1	| unset to 0xFE
X	jmp	db_iret
X
X| some variables are in code seg for more convenient (probably faster) access
X
Xdb_enable:
X	.byte	0xFE		| special value for test-and-set flag
X	.even
X| DB_DS:				| DOS only
X	.zerow	1
Xis_sstep:
X	.word	0		| top half is constant 0
Xold_ds:
X	.zerow	1
Xold_kb_vector:
X	.zerow	2
X
X| dos_init is only used for DOS initialisation
X| it becomes a safe overflow error for the stack
X
Xdos_init:
X	mov	DB_DS,ds
X	mov	di,#_edata
X	mov	cx,#_end
X	sub	cx,di
X	subb	al,al
X	cld
X	rep
X	stob
X	call	setvect		| returns ds = VECTOR_SEG and cli
X	les	ax,KEYBOARD_VECTOR
X	seg	cs
X	mov	old_kb_vector,ax
X	seg	cs
X	mov	old_kb_vector+2,es
X	mov	ax,#kb_int
X	mov	KEYBOARD_VECTOR,ax
X	mov	KEYBOARD_VECTOR+2,cs
X	sti
X	mov	dx,#_end+CLICK_SIZE-1
X	movb	cl,*CLICK_SHIFT
X	shr	dx,cl
X	movb	ah,*TSR
X	int	MS_DOS
X	ret
X
X| _exit:				| DOS only - should never be called
X| .fat:				| DOS only - should never be called
X|	j	_exit		| DOS only
X
X	.data
X	.even
X| begdata:			| DOS only & Minix cc only
Xzero:
X	.word	0
Xstack:
X	.space	STACK_SIZE
Xstacktop:
Xold_sp:				| following "old" variables are really on stack
X	.zerow	1		| and order is important
X	.word	0
Xold_ss:
X	.zerow	1
Xold_ip:
X	.zerow	1
X	.word	0
Xold_cs:
X	.zerow	1
Xold_f:
X	.zerow	1
X	.word	0
X_db_stacktop:
X
X	.bss
X| begbss:				| DOS only & Minix cc only
END_OF_FILE
if test 6686 -ne `wc -c <'kernel/db/int88.s'`; then
    echo shar: \"'kernel/db/int88.s'\" unpacked with wrong size!
fi
# end of 'kernel/db/int88.s'
fi
if test -f 'kernel/db/keyboard.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kernel/db/keyboard.c'\"
else
echo shar: Extracting \"'kernel/db/keyboard.c'\" \(10418 characters\)
sed "s/^X//" >'kernel/db/keyboard.c' <<'END_OF_FILE'
X/* keyboard.c */
X
X#include "const.h"
X#include "keyboard.h"
X
X#define KEYBD 0x60
X#define KBIT  0x80
X#define PORTB 0x61
X
X#define FIRST_RELEASE_CODE 0x80 /* codes below this are keypresses */
X                                /* from here to 0xff are releases */
X#define PREFIX0      0xe0       /* prefix for single scan code */
X#define PREFIX1      0xe1       /* prefix for double scan code */
X#define N_SCAN_CODES 0x80
X#define RELEASE_CODE_BIT   0x80
X
X/* states, 0 is normal */
X
X#define S_PRE0  1               /* just seen PREFIX0 */
X#define S_PRE1  2               /* just seen PREFIX1 */
X#define S_PRE1A 3               /* just seen PREFIX1-LEFT_CTRL */
X#define S_PRE1B 4               /* just seen PREFIX1-LEFT_SHIFT */
X
X/*
X  Ordinary scan codes candidates for re-mapping only.
X  The other scan codes are declared in a more localized way in our tables.
X*/
X
X#define SC_DEL          0x53
X#define SC_DN           0x50
X#define SC_END          0x4f
X#define SC_ENTER        0x1c
X#define SC_HOME         0x47
X#define SC_INS          0x52
X#define SC_LEFT         0x4b
X#define SC_LEFT_ALT     0x38
X#define SC_LEFT_CTRL    0x1d
X#define SC_LEFT_SHIFT   0x2a
X#define SC_NUM_SHIFT    0x45
X#define SC_PGDN         0x51
X#define SC_PGUP         0x49
X#define SC_PRTSC        0x37
X#define SC_RIGHT        0x4d
X#define SC_SLASH        0x35
X#define SC_UP           0x48
X
X/*
X  Re-mapped scan codes from enhanced keyboard.
X  The new codes can be any unique codes < 0x80.
X  Our area map, shift map and key maps depend on the choices made.
X*/
X
X#define SC_CPAD_DEL     0x79
X#define SC_CPAD_DN      0x76
X#define SC_CPAD_END     0x75
X#define SC_CPAD_HOME    0x70
X#define SC_CPAD_LEFT    0x73
X#define SC_CPAD_INS     0x78
X#define SC_CPAD_PGDN    0x77
X#define SC_CPAD_PGUP    0x72
X#define SC_CPAD_RIGHT   0x74
X#define SC_CPAD_UP      0x71
X#define SC_NPAD_ENTER   0x7f
X#define SC_NPAD_SLASH   0x7e
X#define SC_PAUSE        0x7d  /* 0xe1-LeftCtrl-NumLock-0xe1-<release codes> */
X#define SC_PRINTSCREEN  0x7c  /* 0xe1-LeftShift-0x37-0xe0-<release codes> */
X#define SC_RIGHT_ALT    0x7a
X#define SC_RIGHT_CTRL   0x7b
X
X/*
X  Map of keyboard areas.
X    Cursor Pad  0x70 to 0x79, 0x7e to 0x7f (our re-mapping).
X    F1-F10      0x3b to 0x64
X    F11-F12     0x57 to 0x58
X    Numeric     0x47 to 0x53
X    Other       0x54 to 0x7f not C/F/N or Right Alt/Ctrl or (prefix & 0x7f)
X*/
XPRIVATE area_t area_map[N_SCAN_CODES] =
X{
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, FKEY, FKEY, FKEY, FKEY, FKEY,
X  FKEY, FKEY, FKEY, FKEY, FKEY, 0, 0, NKEY,
X  NKEY, NKEY, NKEY, NKEY, NKEY, NKEY, NKEY, NKEY,
X  NKEY, NKEY, NKEY, NKEY, OKEY, OKEY, OKEY, FKEY,
X  FKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X  0, 0, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X  OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X  CKEY, CKEY, CKEY, CKEY, CKEY, CKEY, CKEY, CKEY,
X  CKEY, CKEY, 0, 0, OKEY, OKEY, NKEY, NKEY,
X};
X
X/*
X  Map of shift scan codes.
X    Caps Lock    0x3a
X    Ins          0x52
X    Ins          0x52 preceded by 0xe0 (state kept is inadequate)
X    Left Alt     0x38
X    Left Ctrl    0x1d
X    Left Shift   0x2a
X    Num Lock     0x45
X    Right Alt    0x38 preceded by 0xe0
X    Right Ctrl   0x1d preceded by 0xe0
X    Right Shift  0x36
X    Scroll Lock  0x46
X*/
XPRIVATE shift_t shift_map[N_SCAN_CODES] =
X{
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, LEFT_CTRL, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, LEFT_SHIFT, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, RIGHT_SHIFT, 0,
X  LEFT_ALT, 0, CAPS_SHIFT, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, NUM_SHIFT, SCROLL_SHIFT, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, INS_SHIFT, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  0, 0, 0, 0, 0, 0, 0, 0,
X  INS_SHIFT, 0, RIGHT_ALT, RIGHT_CTRL, 0, 0, 0, 0,
X};
X
X/*
X  Scan codes to ASCII.
X  \000 means a special key which is handled by another table.
X  The numeric keypad '.' or DEL key is always mapped to DEL.
X  The other keypad keys are always mapped to numbers.
X  A higher level routine can remap the keypad as it likes using the
X  shift state.
X*/
X
X/* Scan codes to ASCII for unshifted keys for PC through enhanced AT */
XPRIVATE unsigned char unshifted[N_SCAN_CODES] =
X{
X     0,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b',
X  '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',
X     0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',
X     0,'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',   0, '*',
X     0, ' ',   0,
X   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
X     0,   0,
X   '7', '8', '9', '-',
X   '4', '5', '6', '+',
X   '1', '2', '3',
X   '0', 127,
X   212, 213, 214,
X   'K', 'L',
X   217, 218, 219, 220, 221, 222, 223,
X   224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,237,238,239,
X   '7', '8', '9',
X   '4', '6',
X   '1', '2', '3',
X   '0', 127,
X     0,   0, '*', 253, '/', '\r',
X};
X/*
X  The first 5 rows correspond to rows on the keyboard.
X  Function keys return 1234567890 plus their shift flags.
X  The numeric keypad returns 789-456+1230..
X  Our mapping of enhanced AT codes in disorganized order is at the end.
X*/
X
X/* Scan codes to ASCII for shifted keys for PC through enhanced AT */
XPRIVATE char shifted[N_SCAN_CODES + 1] =
X{
X     0,  27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b',
X  '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',
X     0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':','\"', '~',
X     0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',   0, '*',
X     0, ' ',   0,
X   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
X     0,   0,
X   '7', '8', '9', '-',
X   '4', '5', '6', '+',
X   '1', '2', '3',
X   '0', 127,
X   212, 213, 214,
X   'K', 'L',
X   217, 218, 219, 220, 221, 222, 223,
X   224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,237,238,239,
X   '7', '8', '9',
X   '4', '6',
X   '1', '2', '3',
X   '0', 127,
X     0,   0, '*', 253, '/', '\r',
X};
X
X/*
X  Translate a scan code from a PC-style keyboard for a given shift state.
X  All "normal" keys return an ASCII code packed with the shift state.
X*/
X
XPUBLIC void parsecode();
X
X#ifdef DEBUG_KEYBOARD
X
Xmain()
X{
X  static struct echar_s ech;
X  scancode_pt code;
X  scancode_pt oldcode;
X
X  oldcode = inportb( KEYBD );
X  while ( 1 )
X    if ( (code = inportb( KEYBD )) != oldcode )
X    {
X      parsecode( code, &ech );
X      if ( ech.area != RKEY )
X      {
X        if ( ech.ch == 3 )
X          exit( 0 );
X        printf( "%c %2d %04x %02x\n",
X                ech.ch >= 32 ? ech.ch : 'x', ech.area, ech.shift, ech.ch );
X      }
X      oldcode = code;
X    }
X}
X
X#endif /* DEBUG_KEYBOARD */
X
XPUBLIC void parsecode( code, eptr )
Xscancode_pt code;
Xregister struct echar_s *eptr;
X{
X  scancode_pt newcode;
X  shift_pt newshift;
X
X  eptr->area = RKEY;        /* prepare to return early */
X  if ( eptr->state != 0 )
X  {
X    /*
X      Re-map known special keys so rest of routine can be table-driven.
X      Hardware does it the *wrong* way for backward compatibility.
X    */
X    newcode = code & ~RELEASE_CODE_BIT;
X    switch( eptr->state )
X    {
X    case S_PRE0:
X      switch( newcode )
X      {
X      case SC_DEL: newcode = SC_CPAD_DEL; break;
X      case SC_DN: newcode = SC_CPAD_DN; break;
X      case SC_END: newcode = SC_CPAD_END; break;
X      case SC_ENTER: newcode = SC_NPAD_ENTER; break;
X      case SC_HOME: newcode = SC_CPAD_HOME; break;
X      case SC_INS: newcode = SC_CPAD_INS; break;
X      case SC_LEFT: newcode = SC_CPAD_LEFT; break;
X      case SC_LEFT_ALT: newcode = SC_RIGHT_ALT; break;
X      case SC_LEFT_CTRL: newcode = SC_RIGHT_CTRL; break;
X      case SC_PGDN: newcode = SC_CPAD_PGDN; break;
X      case SC_PGUP: newcode = SC_CPAD_PGUP; break;
X      case SC_RIGHT: newcode = SC_CPAD_RIGHT; break;
X      case SC_SLASH: newcode = SC_NPAD_SLASH; break;
X      case SC_UP: newcode = SC_CPAD_UP; break;
X      }
X      break;
X    case S_PRE1:
X      switch( newcode )
X      {
X      case SC_LEFT_CTRL: eptr->state = S_PRE1A; return;
X      case SC_LEFT_SHIFT: eptr->state = S_PRE1B; return;
X      }
X      break;
X    case S_PRE1A:
X      if ( newcode == SC_NUM_SHIFT )
X        newcode = SC_PAUSE;
X      break;
X    case S_PRE1B:
X      if ( newcode == SC_PRTSC )
X        newcode = SC_PRINTSCREEN;
X      break;
X    }
X    if ( code >= FIRST_RELEASE_CODE )
X      newcode |= RELEASE_CODE_BIT;
X    code = newcode;
X    eptr->state = 0;
X  }
X
X  if ( code == PREFIX0 )
X  {
X    eptr->state = S_PRE0;
X    return;
X  }
X  if ( code == PREFIX1 )
X  {
X    eptr->state = S_PRE1;
X    return;
X  }
X
X  if ( code >= FIRST_RELEASE_CODE )
X  {
X    /* key release, drop shift state if this is a shift key */
X    if ( (newshift = (shift_map - FIRST_RELEASE_CODE)[code]) != 0 )
X      eptr->shift &= ~newshift;
X    return;
X  }
X
X  /* key press */
X  if ( (newshift = shift_map[code]) != 0 &&
X       (code != SC_INS || !(eptr->shift & NUM_LOCK)) )
X  {
X    /* toggle if lock and keypress is new, record shift */
X    if ( newshift & (CAPS_SHIFT | INS_SHIFT | NUM_SHIFT | SCROLL_SHIFT) &&
X         !(newshift & eptr->shift) )
X      /* same ratio for all */
X      eptr->shift ^= newshift / (CAPS_SHIFT / CAPS_LOCK);
X    eptr->shift |= newshift;
X    if ( newshift != INS_SHIFT )
X    {
X      eptr->area = RKEY;
X      return;
X    }
X  }
X  if ( (eptr->area = area_map[code]) != 0 )
X  {
X    /*
X      Non-ASCII key.
X      Return it as unique ASCII with nonzero area code.
X      Caller can decode it further if required.
X      Function keys are converted to letters.
X      Numeric keypad keys are converted to numbers and punctuation.
X    */
X    eptr->ch = unshifted[code];
X    return;
X  }
X  if ( eptr->shift & (LEFT_CTRL | RIGHT_CTRL) &&
X       (eptr->ch = shifted[code] - '@') < 0x20 )
X    return;
X  if ( eptr->shift & (LEFT_SHIFT | RIGHT_SHIFT) )
X    eptr->ch = shifted[code];
X  else
X    eptr->ch = unshifted[code];
X  if ( eptr->shift & CAPS_LOCK &&
X       (eptr->ch & ~('a' - 'A')) - 'A' <= 'Z' -'A' )
X    eptr->ch ^= 'a' - 'A';
X}
X
XPUBLIC scancode_pt scan_keyboard()
X{
X  /* fetch character from keyboard hardware and acknowledge it */
X
X  scancode_pt code;
X  unsigned status;
X
X  code = inportb( KEYBD );        /* scan code */
X  status = inportb( PORTB );      /* strobe keyboard to acknowledge */
X  oportb( PORTB, status | KBIT ); /* strobe high */
X  oportb( PORTB, status );        /* strobe low */
X  return code;
X}
END_OF_FILE
if test 10418 -ne `wc -c <'kernel/db/keyboard.c'`; then
    echo shar: \"'kernel/db/keyboard.c'\" unpacked with wrong size!
fi
# end of 'kernel/db/keyboard.c'
fi
if test -f 'kernel/db/sym.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kernel/db/sym.c'\"
else
echo shar: Extracting \"'kernel/db/sym.c'\" \(7256 characters\)
sed "s/^X//" >'kernel/db/sym.c' <<'END_OF_FILE'
X/* sym.c */
X
X#include "const.h"
X#include "type.h"
X#include "var.h"
X#include "/usr/include/a.out.h"		/* full pathname to get right one! */
X
X#define SYMSIZE_MAGIC ((peekoff_t) 2)
X
X#define anticlick( off ) ((off) * CLICK_SIZE)/* good only for unsigned off's */
X#define click( off ) ((off) / CLICK_SIZE)
X#define clickrest( off ) ((unsigned) (off) % CLICK_SIZE)
X#define NSYMPROC 4		/* kernel, mm, fs, init */
X
Xextern unsigned sizes[2 * NSYMPROC];
X
Xstruct symtab_s
X{
X	char *stname;
X	segment_t stseg;
X	struct nlist *start;
X	struct nlist *end;
X	segment_t text;
X	segment_t data;
X	unsigned nsym;
X};
X
XPRIVATE struct symtab_s proc_sym[NSYMPROC] =
X{
X	{ "kernel" }, { "mm" }, { "fs" }, { "init" },
X};
X
XPUBLIC void syminit()
X{
X	static bool_t already = FALSE;
X	segment_t base;
X	int p;
X	u16_t symoff;
X	register struct symtab_s *tp;
X
X	if ( !already )
X	{
X		already = TRUE;
X		info();
X		for ( base = codeseg(), tp = &proc_sym[0], p = 0; tp < &proc_sym[NSYMPROC];
X		      base += sizes[p] + sizes[p + 1], ++tp, p += 2 )
X		{
X			if ( (symoff = peekw( base, SYMSIZE_MAGIC )) == 0 )
X				/* symbols not loaded - p should be 0 so all tables remain null */
X				break;
X			tp->text = base;
X			tp->stseg = (tp->data = base + sizes[p]) + click( symoff );
X			tp->start = (struct nlist *) clickrest( symoff );
X			tp->nsym = (anticlick( sizes[p + 1] ) - symoff) / sizeof (struct nlist);
X			tp->end = tp->start + tp->nsym;
X			/* sort on value only, name search not used much and storage a problem */
X			outstr( "Sorting " );
X			outh16( tp->nsym );
X			outspace();
X			outstr( tp->stname );
X			outstr( " symbols ... " );
X			sortsyms( tp->start, tp->end, tp->stseg );
X			outnl();
X		}
X	}
X}
X
XPRIVATE struct nlist *buildsym( sp, tableseg )
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X	static struct nlist sym;
X	register char *s;
X	register char *t;
X	char *tend;
X
X	for ( s = sp->n_name, t = sym.n_name, tend = t + sizeof sym;
X	      t < tend; ++s, ++t )
X		*t = peekb( tableseg, (peekboff_t) s );
X	return &sym;
X}
X
XPUBLIC struct nlist *findsname( name, where, allflag )
Xchar *name;
Xint where;
Xbool_pt allflag;
X{
X	struct nlist *matchsp;
X	char *s;
X	unsigned char sclass;
X	int schar;
X	char *send;
X	register struct nlist *sp;
X	segment_t tableseg;
X	register struct symtab_s *tp;
X
X	for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X		/* find process to use */
X		if ( tp->text == uptr.seg )
X		{
X			if ( allflag )
X			{
X				/* find and print all matching symbols */
X				for ( sp = tp->start, tableseg = tp->stseg; sp < tp->end; ++sp )
X				{
X					if ( symprefix( name, sp, tableseg ) )
X					{
X						matchsp = buildsym( sp, tableseg );
X						for ( s = matchsp->n_name, send = s + sizeof matchsp->n_name;
X						      *s != 0 && s < send; ++s )
X							outbyte( *s );
X						for ( ; s <= send; ++s )
X							outspace();
X						switch( matchsp->n_sclass & N_SECT )
X						{
X							case N_ABS: schar = 'a'; break;
X							case N_TEXT: schar = 't'; break;
X							case N_DATA: schar = 'd'; break;
X							case N_BSS: schar = 'b'; break;
X							default: schar = '?'; break;
X						}
X						if ( (matchsp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
X							schar += 'A' - 'a';
X						outbyte( schar );
X						outspace();
X						outh16( (u16_t) matchsp->n_value );
X						if ( !outnl() )
X							break;
X					}
X				}
X				return NULL;
X			}
X			else
X			{
X				/* find symbol by dumb linear search */
X				for ( sp = tp->start, tableseg = tp->stseg; sp < tp->end; ++sp )
X				{
X					sclass = peekw( tableseg, (peekoff_t) &sp->n_sclass ) & N_SECT;
X					if ( (where == CSEG && sclass == N_TEXT ||
X					      where != CSEG && (sclass == N_DATA || sclass == N_BSS)) &&
X							 symeq( name, sp, tableseg ) )
X						return buildsym( sp, tableseg );
X				}
X				return NULL;
X			}
X		}
X	return NULL;
X}
X
XPUBLIC struct nlist *findsval( value, where )
Xoffset_t value;
Xint where;
X{
X	int left;
X	int middle;
X	int right;
X	unsigned char sclass;
X	register struct nlist *sp;
X	segment_t tableseg;
X	register struct symtab_s *tp;
X
X	for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X		/* find process to use */
X		if ( tp->text == uptr.seg )
X		{
X			prompt = *tp->stname;
X			/* find last symbol with value <= desired one by binary search */
X			for ( left = 0, right = tp->nsym - 1, tableseg = tp->stseg;
X			      left <= right; )
X			{
X				middle = (left + right) / 2;
X				sp = tp->start + middle;
X				if ( value < peekw( tableseg, (peekoff_t) &sp->n_value ) )
X					right = middle - 1;
X				else
X					left = middle + 1;
X			}
X			if ( right >= 0 )
X				/* otherwise tp->start + right may wrap around to > tp->start !! */
X				for ( sp = tp->start + right; sp >= tp->start; --sp )
X				{
X					sclass = peekw( tableseg, (peekoff_t) &sp->n_sclass ) & N_SECT;
X					if ( (where == CSEG && sclass == N_TEXT ||
X								where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
X					return buildsym( sp, tableseg );
X				}
X			return NULL;
X		}
X	if ( where == CSEG )
X		prompt = '?';
X	return NULL;
X}
X
XPUBLIC void outsym( sp, off )
Xstruct nlist *sp;
Xoffset_t off;
X{
X	register char *s;
X	char *send;
X
X	for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
X		outbyte( *s );
X	if ( (off -= sp->n_value) != 0 )
X	{
X		outbyte( '+' );
X		if ( off >= 65536L )
X			outh32( off );
X		else if ( off >= 256 )
X			outh16( (u16_t) off );
X		else
X			outh8( (u8_pt) off );
X	}
X}
X
XPUBLIC void setproc( c, pdptr, pmptr )
Xchar_pt c;
Xstruct adr *pdptr;
Xstruct adr *pmptr;
X{
X	register struct symtab_s *tp;
X
X	for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X		if ( tp->stname[0] == c )
X		{
X			uptr.seg = tp->text;
X			pmptr->seg = pdptr->seg = tp->data;
X			prompt = c;
X			return;
X		}
X}
X
X/* shell sort symbols on value */
X
XPRIVATE void sortsyms( array, top, tableseg )
Xstruct nlist *array;
Xstruct nlist *top;
Xsegment_t tableseg;
X{
X	int gap;
X	int i;
X	int j;
X	register struct nlist *left;
X	register struct nlist *right;
X	int size;
X
X	size = top - array;
X	/* choose gaps according to Knuth V3 p95 */
X	for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
X		;
X	do
X	{
X		for ( j = gap; j < size; ++j )
X			for ( i = j - gap; i >= 0; i -= gap )
X			{
X				left = array + i; 
X				right = array + (i + gap);
X				if ( (unsigned) peekw( tableseg, (peekoff_t) &left->n_value )
X				     <= peekw( tableseg, (peekoff_t) &right->n_value ) )
X					break;
X				symswap( left, right, tableseg, sizeof *left );
X			}
X	}
X	while ( (gap /= 3) != 0 );
X}
X
XPRIVATE bool_pt symeq( t, sp, tableseg )
Xregister char *t;
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X	register char *s;
X	char *send;
X
X	for ( s = sp->n_name, send = s + sizeof sp->n_name; s < send; ++s, ++t )
X		if ( *t != peekb( tableseg, (peekboff_t) s ) )
X			return FALSE;
X	return TRUE;
X}
X
XPRIVATE bool_pt symprefix( t, sp, tableseg )
Xregister char *t;
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X	register char *s;
X	char *send;
X
X	for ( ; *t == '_'; ++t )
X		;
X	for ( s = sp->n_name, send = s + sizeof sp->n_name;
X	      s < send && peekb( tableseg, (peekboff_t) s ) == '_'; ++s )
X		;
X	for ( ; *t != 0 && s < send; ++s, ++t )
X		if ( *t != peekb( tableseg, (peekboff_t) s ) )
X			return FALSE;
X	return TRUE;
X}
X
X#ifdef LINT
X
X/* prototypes for assembler functions */
X
X/* ARGSUSED */
XPRIVATE void symswap( left, right, tableseg, length )
Xstruct nlist *left;
Xstruct nlist *right;
Xsegment_t tableseg;
Xunsigned length;        /* must be even */
X{
X}
X
X#endif
END_OF_FILE
if test 7256 -ne `wc -c <'kernel/db/sym.c'`; then
    echo shar: \"'kernel/db/sym.c'\" unpacked with wrong size!
fi
# end of 'kernel/db/sym.c'
fi
echo shar: End of archive 3 \(of 7\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 7 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

Bruce Evans
Internet: brucee@runx.ips.oz.au    UUCP: uunet!runx.ips.oz.au!brucee