.title six -- simple extractor .library 'six' ; registers: ; r6 = hind ptr (0=still counting down) ; r7 = fore ptr (0=eof, -1=unused) ; r8 = line number (hind ptr) ; r9 = line number (fore ptr) (last) ; constants: $clidef $rmsdef $namdef $rabdef $secdef eof_mark = ^xffff buf_len = 255 fil_len = 255 max_tests = 20 .subtitle six_data ;---------------------DATA---------------------------------------------- _lsect _six_data .align long six_in_fab:: $fab fop=, dnm=<*.*;>, - nam=, xab=, - fna=, fns= .align long six_in_nam:: $nam rsa=, rss=, - esa=, ess= .align long six_in_fhcxab:: $xabfhc .align long six_in_rab:: $rab fab=, - ubf=, - ; address of input buffer usz= ; length of input buffer .align long six_in_rsa:: .blkb fil_len .align long six_in_esa:: .blkb fil_len ;--------------------- .align long six_out_fab:: $fab fop=, dnm=<[].LIS>, nam=, - fna=, fns=, - rat= .align long six_out_nam:: $nam rsa=, rss=, - esa=, ess=, - rlf= .align long six_out_rab:: $rab fab= ; rbf and rsz will be stored at runtime .align long six_out_rsa:: .blkb fil_len .align long six_out_esa:: .blkb fil_len ;--------------------- six_crmpsc_arglst: ; arglist for CRMPSC .long 12 ; number of args .long six_inadr ; addr of quad .long six_retadr ; addr of quad .long 0 ; acmde .long sec$m_expreg ; flags .long 0 ; gsdnam .long 0 ; ident .long 0 ; relpag six_in_chan: .long 0 ; chan (must be run-time filled) .long 0 ; pagcnt .long 0 ; vbn .long 0 ; prot .long 0 ; pfc ;-------------------- ; address buffers etc six_inadr: .long 1, 1 six_retadr: .long 0, 0 six_eof: .long 0 six_countdown: .long 0 six_saved_countdown: .long 0 six_multiple: .long 0 ;-------------------- ; dcl command parsing entities six_verb: .ascid \6 \ six_p_file: .ascid \P_FILE\ six_p_range:.ascid \P_RANGE\ six_tail: .ascid \TAIL\ six_head: .ascid \HEAD\ six_range: .ascid \RANGE\ six_output: .ascid \OUTPUT\ ;-------------------- ; constant strings six_stars: .ascid /!79/ six_blank: .quad 0 ;-------------------- ; fake strings (scratch descriptors) six_xdx: .quad 0 ;-------------------- ; var length strings .long buf_len six_xstr:: _ascid len=buf_len ; scratch string .long buf_len six_buff:: _ascid len=buf_len ; input/output buffer .long fil_len ; input file name six_in_file:: _ascid len=fil_len, addr=six_in_fna, scope=gbl .long fil_len ; output file name six_out_file:: _ascid len=fil_len, addr=six_out_fna, scope=gbl ; output file name ;-------------------- .subtitle six_code ;---------------------CODE-------------------------------------------------- _esect _six_code .entry six, ^m moval six_err_handler, (fp) ; set up error handler _reslen six_buff ; get command line (exc. verb) pushaw six_buff clrl -(sp) pushaq six_buff calls #3, g^lib$get_foreign _if_err <, - <_fade #six__command>> _get_str str=, desc= _reslen six_buff pushaq six_xdx ; prefix it with the verb pushaq six_verb pushaq six_buff calls #3, g^str$concat _if_err <, - <_fade #six__command>> pushal g^lib$get_input ; parse the command line pushal g^lib$get_input pushal six_cld_table pushaq six_buff calls #4, g^cli$dcl_parse _if_err <> _get_value six_p_range, six_stack_push_range ; get ranges _get_value six_range, six_stack_push_range ; from ps + qs _get_value six_head, six_stack_push_head _get_value six_tail, six_stack_push_tail _if_eql #six_stack_stack, six_stack_ptr, - ; if no range, loop <, - ; its an error <_fade #six__norange>> ; ; NOTE: for consistency's sake, the following section should be rewritten ; to call a subroutine in the SIX_STACK module, which would return the ; countdown. Only routines in SIX_STACK are supposed to reference the ; actual stack data structures, so that they may be easily changed. ; six_get_count: ; get countdown movl #1, six_saved_countdown subl3 #4, six_stack_ptr, r2 ; r2 = addr of last entry in stac moval six_stack_stack, r0 ; r0 = ptr into stack 25$: movl (r0), r1 ; r1 = entry bneq 30$ tstl six_saved_countdown bneq 30$ movl #-1, r1 30$: cmpl r1, six_saved_countdown bgeq 35$ movl r1, six_saved_countdown 35$: acbl r2, #4, r0, 25$ tstl six_saved_countdown beql 40$ subl3 six_saved_countdown, #1, six_saved_countdown 40$: six_open_out: ; init output file _get_value six_output, desc= _if_err <> ; don't create-if if not specified movb six_out_file, $create fab= _if_err <, - <_fade #six__openout>> $connect rab= _if_err <, - <_fade #six__openout>> six_next_file:: _reslen six_in_file pushaw six_in_file ; get file name(s) pushaq six_in_file pushaq six_p_file calls #3, g^cli$get_value _if_err <<_fade #six__normal>> ; no more files -> exit cmpl r0, #cli$_comma ; set flag if part of a list bneq six_parse movl #1, six_multiple six_parse: movb six_in_file, $parse fab= _if_err <, - > bbc #nam$v_wildcard, , six_search movl #1, six_multiple ; ; SIX_SEACH is the point we come to when we want to begin a new file. ; It does a $search for another file matching the current wildcards, ; and if that fails, it transfers to SIX_NEXT_FILE to get the next name. ; ; It is a global label. ; six_search:: $search fab= _if_eql r0, #rms$_nmf, <> _if_err <, - > six_open_in: $open fab= _if_err <, - > six_org: ; get file organization cmpb , #fab$c_seq ; and go to proper section bneq 10$ cmpb , #fab$c_var bneq 10$ brw six_var_file ; var sequential 10$: brw six_misc_file ; other .subtitle six_var_file ;---------------------VARIABLE LENGTH SEQUENTIAL FILES six_var_file: tstl six_retadr ; remove old file beql six_var_map ; if this is not the first file... clrq -(sp) ; free virtual memory pushaq six_retadr calls #3, g^sys$deltva _if_err <, - <_fade r0>> six_var_map: $fab_store fab=, fop= ; open file /fop=ufo $open fab= _if_err <, - > movl , six_in_chan ; map file into virtual memory callg six_crmpsc_arglst, g^sys$crmpsc _if_err <, - > six_var_setup: clrl r6 ; r6 = hind ptr movl #-1, r7 ; r7 = fore ptr (-1=unused, 0=eof) clrq r8 ; r8 = hind ln, r9 = fore ln movl six_saved_countdown, six_countdown beql 50$ movl six_retadr, r7 ; set fore ptr only if countdown needed 50$: movl , six_eof ; calculate eof addr decl six_eof ; eof = (ebk-1)*512 + ffb + @retadr ashl #9, six_eof, six_eof movzwl , r0 addl2 r0, six_eof addl2 six_retadr, six_eof jsb six_print_header six_var_scan: jsb six_var_read ; get record _if_err <> jsb six_stack_test_rec ; test record _if_err <> movq r2, six_xdx ; print record _output six_xdx brw six_var_scan ; loop .subtitle six_misc_file ;---------------------MISC ORGANIZATION FILES ; We do not yet support file organizations other than Sequential, ; variable-length records. It will not be too hard to add, someday, ; but for now we just don't need it. The main requirement would be ; creating a circular linked list of buffers to hold the last n ; records, corresponding to the lookahead--we don't want to just read ; the file twice in case it is on tape or something equally wierd. ; We are still fine tuning this segment, trying to deal with insuff. ; virtual memory in the least costly way, so we will not include the ; code segment at this time. Instead simply don't allow it. six_misc_file: jsb six_err_org brw six_search ;---------------------EXITS----------- six_exit:: ret .subtitle jsb routines ;========================JSB ROUTINES========================================= .subtitle six_print_header ;----------------------------------------------------------------------------- ; jsb point SIX_PRINT_HEADER -- to print information between files ; if we are processing more than one. six_print_header: blbs six_multiple, 10$ ; if multiple is true, then brw 20$ 10$: _output six_blank ; print a blank line _reslen six_xstr ; format the header string _push_str fab=six_in_fab pushaq six_xstr pushaw six_xstr pushaq six_stars calls #4, g^sys$fao _output six_xstr ; print the header _output six_blank ; print a blank line 20$: rsb ; return .subtitle six_var_read ;----------------------------------------------------------------------------- ; jsb point SIX_VAR_READ -- to get a var-len record from memory-mapped file ; handles n-record look ahead with fore/hind pointers. ; r0 = (scratch) --> success t/f ; r2 = (scratch) --> len of currec (@hind) ; r3 = (scratch) --> addr of currec (@hind) ; r6 = hind ptr --> (moved up) ; r7 = fore ptr --> (moved up) (0 on eof) (-1 on unused) ; r8 = hind line number --> (incremented) ; r9 = fore line number --> (incremented) ; this is var-len-rec format: ; . . .10 9 8 7 6 5 4 3 2 1 0 = byte ; _________________________________________________ ; . . . a |length | 0 | e d c b a | 0 5 | odd len has fill 0 ; . . . a |length | f e d c b a | 0 6 | even len does not ; ------------------------------------------------- six_var_read: ; scan var len rec clrq r2 clrl r0 tstl r7 ; check for already eof bleq 15$ movzwl (r7), r0 ; move up fore pointer cmpw r0, #eof_mark ; if eofmark here, then this is beql 60$ ; an empty file, return error. addl2 #2, r0 addl2 r0, r7 incl r9 blbc r0, 10$ incl r7 ; skip fil-nul if necc. 10$: cmpl r7, six_eof ; check for eof bgeq 12$ cmpw (r7), #eof_mark ; check for eof-mark bneq 15$ 12$: clrl r7 ; on eof, clear r7 15$: tstl r6 ; shall we move up hind pt? bneq 20$ sobgtr six_countdown, 50$ ; if not ready, rsb movl six_retadr, r6 ; initialize at 1st rec brw 40$ ; and return values 20$: movzwl (r6), r0 ; move up hind ptr addl2 #2, r0 addl2 r0, r6 blbc r0, 30$ incl r6 ; skip fil-null if necc. 30$: cmpl r6, six_eof ; check for eol blss 40$ clrl r6 clrl r0 ; fail on eol rsb 40$: addl3 #2, r6, r3 ; return addr & len of currec movzwl (r6), r2 incl r8 ; increment line number 50$: movl #1, r0 ; set success rsb 60$: clrl r0 rsb ;============================================================================= .end six