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