issue: ellis book author: bruce ellis category: episode 7 programs [figure 18] ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: Count_frag ; Author: Billy Bitsenbites (Bruce Ellis) ; Date written: 5/5/90 ; Function: Prompts for a directory specification, ; opens the directory file, and uses the ; file id of the files cataloged in the ; directory to count the number of file ; headers and mapping pointers for each ; file. Note: no fancy wildcard processing ; was included in the interest of brevity. ; In typical Guide style, if you want it ; then add it. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;Macro to check status .macro check arg=r0,?l blbs arg,l $exit_s arg l: .endm check ;Include system macro library .library /sys$library:lib.mlb/ $dirdef ;Directory record symbolic definitions $fabdef ;File Access Block definitions $rabdef ;Record Access Block definitions $namdef ;Name Block definitions ;Fab for $PARSE to parse directory specification to fid/did fab_parse: $fab FNA=dir_spec,FOP=NAM,- NAM=dir_nam_blk ;Fab for directory file open fab1: $fab FAC=,FOP=NAM,- MRS=512,ORG=,RFM=,- SHR=,NAM=dir_nam_blk ;Rab for directory file processing RAB1: $rab FAB=FAB1,- RBF=BUF,RSZ=512,UBF=BUF,USZ=512,- ROP= ;Name block for procesing directory fid/did dir_nam_blk: $nam ESA=dir_spec_p,ESS=nam$c_maxrss ;Record buffer buf: .blkb 512 ;record number counter line_counter: .long 0,0 ;format statement for file name file_fmt: .ascid /!AC;!UW/ ;full format for output fmt: .ascid /!50AS !9UL !9UL/ ;file name descriptor file_desc: .long 255 .address 10$ 10$: .blkb 255 indexf_channel: ;Storage for indexf channel number .blkl 1 header_bias: ;Bias from first header for use with file id .blkl 1 pointer_cnt: ;count of mapping pointers .blkl 1 header_cnt: ;count of file headers .blkl 1 pmt: .ascid /Directory spec>/ ;prompt for directory spec dir_spec_d: ;storage for full directory spec .long nam$c_maxrss .address dir_spec dir_spec: .blkb nam$c_maxrss dspd: .blkl 1 .address dir_spec_p dir_spec_p: .blkb nam$c_maxrss device_name: .blkl 1 ;device name descriptor devnam_adr: .blkl 1 ;display buffer out_buf:.long 512 .address 10$ 10$: .blkb 512 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Main code ; Function: Prompts for directory spec, opens directory ; file by file id, reads each record, obtains ; the count of headers, and displays counts. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .entry file,^m<> pushal dir_spec_d ;Read with prompt pushal pmt ; directory specification pushal dir_spec_d calls #3,g^lib$get_input check movb dir_spec_d,fab_parse+fab$b_fns ;parse directory spec $parse fab=fab_parse check bbs #nam$v_exp_name,- ;Don't handle file name dir_nam_blk+nam$l_fnb,no_exp bbs #nam$v_exp_ver,- ;Don't handle versions dir_nam_blk+nam$l_fnb,no_exp bbs #nam$v_exp_type,- ;Don't handle types dir_nam_blk+nam$l_fnb,no_exp bbs #nam$v_wildcard,- ;don't handle wildcard dir_nam_blk+nam$l_fnb,no_exp brb dir_ok no_exp: movl #ss$_badirectory,r0 ;beat it ret dir_ok: movzbl dir_nam_blk+nam$b_esl,dspd ;get size of complete string subl2 #2,dspd ;skip trailer pushal dspd ;spill the directory spec calls #1,g^lib$put_output movl dir_nam_blk+nam$w_did,- ;Reset dir id to file id dir_nam_blk+nam$w_fid movw dir_nam_blk+4+nam$w_did- ;Reset rest of file id ,dir_nam_blk+nam$w_fid+4 clrl dir_nam_blk+nam$w_did ;clear the directory id clrw dir_nam_blk+nam$w_did+4 movzbl dir_nam_blk+nam$b_dev,device_name ;Build device name movl dir_nam_blk+nam$l_dev,devnam_adr ; descriptor $open fab=fab1 ;open the direcory file check $connect rab=rab1 ;connect the record stream check pushal device_name ;pass device name pushal header_bias ;pass file header bias pushal indexf_channel ;pass the channel address to store calls #3,open_indexf ;open the index file l: $get rab=rab1 ;read the first record from the dir cmpl #rms$_eof,r0 ;at end? bneq check_error ;if not check for other errors brw done ; else scram check_error: check ; moval buf,r7 ;move record address to register movzwl rab$w_rsz+rab1,r6 ;get the record size ASSUME dir$w_verlimit EQ 2 subl #,r6 ;drop count by size of fixed overhead movzbl (r7),r8 ;get the size of the file name blbc r8,skip_inc ;if even don't round incl r8 ;round to even number of bytes skip_inc: subl r8,r6 ;drop count by size of file name divl #8,r6 ;determine the number of versions addl3 r8,#,r9 ;determine the start the fids process_versions: pushal header_cnt ;push location to store header count pushal pointer_cnt ;push location to store pointer count pushal dir$w_fid(r9) ;pass file id pushal header_bias ;pass header bias pushal indexf_channel ;pass channel of indexf.sys calls #5,count_pointers ;count the pointers ediv #22,line_counter,r10,line_counter ;Printed 22 lines? tstl line_counter ;if not skip line header bneq skip_header ; else print line header jsb dump_page_header skip_header: movab ,r4 ;get size of file name ;********* ;Format the file name/header count/pointer count ;********* $fao_s ctrstr=file_fmt,outbuf=file_desc,outlen=file_desc,- p1=r4,p2=dir$w_version(r9) $fao_s ctrstr=fmt,outbuf=out_buf,outlen=out_buf,- p1=#file_desc,p2=pointer_cnt,p3=header_cnt pushal out_buf ;spill file info calls #1,g^lib$put_output incl line_counter movl #255,file_desc movl #512,out_buf ;reset buffer size addl #8,r9 ;get next version of file sobgtr r6,process_versions_br ;process next version of file brb next_file process_versions_br: brw process_versions next_file: brw l ;get next file done: movl #ss$_normal,r0 ;sayonara ret ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;Dump page header ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LF=10 CR=13 page_hdr: .ascid $File $- $ Ptr cnt. Hdr cnt.$- $____ $- $ _______ ________$ dump_page_header: pushal page_hdr calls #1,g^lib$put_output rsb ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Subroutine: open_indexf ; Function: opens the indexf.sys file ; Inputs: 4(ap) channel address ; 12(ap) device name ; Outputs: 8(ap) header bias ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fibdef ;File information block offsets $hm2def ;Home block offsets chan_arg=4 bias_arg=8 dev_arg=12 i_fid: .word 1,1,0 ;file id of indexf.sys fibd: .long fib$k_length ;file info block descriptor .address fib fib: .blkb fib$k_length ;file information block iostat: .blkq 1 ;io status block block: .blkb 512 ;home block buffer .entry open_indexf,^m ;Assign channel to device $assign_s devnam=@dev_arg(ap),chan=@chan_arg(ap) check moval fib,r6 ;get fib descriptor movl i_fid,fib$w_fid(r6) ;set up fid in fib ;****************** ;Open indexf.sys ;****************** $qiow_s chan=@chan_arg(ap),func=#,- iosb=iostat,p1=fibd check ;Check status check iostat ;**************** ;Read the home block ;**************** $qiow_s chan=@chan_arg(ap),func=#io$_readvblk,iosb=iostat,- p1=block,p2=#512,p3=#2 check ;Check status check iostat movzwl hm2$w_ibmapvbn+block,r8 ;get index bitmap VBN movzwl hm2$w_ibmapsize+block,r9 ; and size addl r8,r9 ;compute header bias decl r9 movl r9,@bias_arg(ap) ;return header bias movl #ss$_normal,r0 ;scram ret ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Subroutine: count_pointers ; Function: counts the number of mapping pointers ; and file headers in a file. ; Inputs: 4(ap) channel number address for index file ; 8(ap) header bias ; 12(ap) file id of file ; Outputs: 16(ap) count of mapping pointers ; 20(ap) count of file headers ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ $fh2def ;Base file header offsets $fiddef ;file id offsets $fm2def ;mapping pointer offsets header_num: .blkb 4 ;local storage for header number ios: .blkq 1 ;io status block header_block: ;storage for header block .blkb 512 fid_arg=12 ptr_arg=16 hdr_arg=20 .entry count_pointers,^m movl fid_arg(ap),r6 ;Get file id address movw fid$w_num(r6),header_num ;Get file header number movzbw fid$b_nmx(r6),header_num+2 addl3 @bias_arg(ap),header_num,r7 ;add biad to header number movl #1,@hdr_arg(ap) ;assume 1 header clrl @ptr_arg(ap) ;clear count of pointers ;**************** ;Read header block ;**************** $qiow_s chan=@chan_arg(ap),func=#io$_readvblk,iosb=ios,- p1=header_block,p2=#512,p3=r7 check ;check call status check ios ;check completion status cmpw header_block+fh2$w_fid_seq,fid$w_seq(r6) ;check seq # beql got_header movl #ss$_nosuchfile,r0 ;if seq # wrong abort brw err_out_counter got_header: moval header_block,r9 ;get header block buffer address next_ext_header: movzbl fh2$b_mpoffset(r9),r2 ;locate mapping pointers mull2 #2,r2 ; using word offset addl r9,r2 ; next_mapping_ptr: movw (r2)+,r3 ;get next pointer beql no_more_pointers ;if none scram extzv #fm2$v_format,#fm2$s_format,r3,r4 ;determine format mull2 #2,r4 ;skip based on word count of pointer addl r4,r2 ; incl @ptr_arg(ap) ;bump the pointer count brw next_mapping_ptr no_more_pointers: movaw fh2$w_ext_fid(r9),r6 ;get extension header file id movw fid$w_num(r6),header_num movzbw fid$b_nmx(r6),header_num+2 tstl header_num ;extension header? beql done_with_pointers ;if so calculate the VBN of addl3 @bias_arg(ap),header_num,r7 ; the header block beql done_with_pointers ;if none scram incl @hdr_arg(ap) ; else bump header count ;***************** ;Read extension header ;***************** $qiow_s chan=@chan_arg(ap),func=#io$_readvblk,iosb=ios,- p1=header_block,p2=#512,p3=r7 check ;check appropriate status check ios moval header_block,r9 ;reset header address brw next_ext_header ;get next header block done_with_pointers: movl #ss$_normal,r0 err_out_counter: ret ;Sayonara .end file