1	!***************************************************************&
	!								&
	!	This is a utility for extracting member file stored	&
	!	     in a DECnet virtual floppy container file.		&
	!								&
	!	1.0	Written by Rick Watson  27-Feb-86		&
	!								&
	!	2.0	Modified 12-Mar-86 to version 2.0		&
	!								&
	!		Version 2.0 reads the virtual floppy		&
	!		file and uses the DOS information		&
	!		i.e. boot block, FAT, and directory		&
	!		to perform its functions.  It should		&
	!		work with any VAX record length to 1024		&
	!		and knows about various DOS sector sizes	&
	!		and clusters.  Also, the files output		&
	!		will work with VAX utilities such as		&
	!		VMSSWEEP.					&
	!								&
	!	2.1	Fixed bug - program now deletes ' characters	&
	!		from output file name in extract function	&
	!								&
	!	2.2	Added message indicating that filename is	&
	!		being changed during extract function.		&
	!		replaced '-' character in filename with '_'	&
	!								&
	!	3.0	Added selective file extraction with wild	&
	!		card support.					&
	!								&
	!	3.1	Changed extract so null entry to filename	&
	!		prompt is illegal.  Also fixed up help menu.	&
	!								&
	!	4.0	Added support for subdirectories.		&
	!								&
	!	4.1	Fixed bug which caused program to loop if	&
	!		change directory function was used with a	&
	!		nonexistant directory.  Also changed function	&
	!		letters so dir and type can be used.		&
	!								&
	!	4.2	Added error trapping for too many 		&
	!		subdirectories. Released version		&
	!								&
	!***************************************************************&

1000	on error goto 19000

1100	print
	print	'DECnet Virtual Floppy Disk Extraction Utility  V 4.2'

1110	print
	input	'Input File  ';in_filename$

1200	open in_filename$ for input as file #2%,			&
			undefined,					&
			recordtype none

1210	map (sector_buffer)						&
				sector_buffer$		=      1024%
	map (sub_dir_buffer)						&
				sub_dir_buffer$		=      1024%
	map (boot_record)						&
		string		boot_record		=	128%
	map (boot_record)						&
		string		boot_fill		=	  3%,	&
		string		boot_id			=	  8%,	&
		word		boot_bytes_per_sector,			&
		byte		boot_sectors_per_cluster,		&
		word		boot_reserved_sectors,			&
		byte		boot_fat_copies,			&
		word		boot_root_directory_entries,		&
		word		boot_total_sectors,			&
		byte		boot_format_id,				&
		word		boot_sectors_per_fat,			&
		word		boot_sectors_per_track,			&
		word		boot_total_sides,			&
		word		boot_special_reserved_sectors

1220	map (DOS_directory)	dir_entry$		=	 32%
	map (DOS_directory)	dir_filename$		=	  8%,	&
				dir_ext$		=	  3%,	&
		byte		dir_attribute,				&
		string		dir_who_knows		=	 10%,	&
		word		dir_creation_time,			&
		word		dir_creation_date,			&
		word		dir_first_cluster,			&
		long		dir_filesize


1900	xlate_table$ =	'       ' + chr$(7%) + chr$(8%) + chr$(9%) +	&
			chr$(10%) + chr$(11%) + chr$(12%) + chr$(13%) +	&
			'             ' + chr$(27%) + '     ' +		&
			'!"#$%&' + "'" + '()*+,-./0123456789:;<=>?@' +	&
			'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`' +		&
			'abcdefghijklmnopqrstuvwxyz{|}~ ' +		&
			'                                 ' +		&
			'!"#$%&' + "'" + '()*+,-./0123456789:;<=>?@' +	&
			'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`' +		&
			'abcdefghijklmnopqrstuvwxyz{|}~ '
	month_string$ = 'JanFebMarAprMayJunJulAugSepOctNovDec'

1910	dim dir_stack_name$(1000%)
	dim dir_stack_level%(1000%)
	dim dir_stack_start_cluster%(1000%)
	dim dir_stack_parent%(1000%)
	dim sub_directories$(10%)
	dim sub_directory_case%(10%)

2000	last_record_num% = -1%
	print	
	gosub	11200
	print	'Building directory tree...'
	gosub 11600
	print
	print	'Volume label is ';volume_label$			&
		if volume_label$ <> ''
	print	'Volume is not labeled'					&
		if volume_label$ = ''

2010	print
	print	'Functions:   C [Path]               Change subdirectories'
	print	'             D [Path]File-spec      Directory display'
	print	'             E [Path]File-spec      Extract file(s)'
	print	'             H                      Help'
	print	'             L                      List file format info'
	print	'             Q                      Quit'
	print	'             R                      Reselect input file'
	print	'             S                      Show Subdirectory tree'
	print	'             T [Path]File-spec      Type file(s)'

2020	print
	input	'Function   ';function$
	function$ = edit$( function$, 189%)
	x% = instr( 1%, function$, ' ')
	parameter$ = ''
	parameter$ = right( function$, x% + 1%) if x%
	function$ = left(function$,1%)
	goto 2020 if function$ = ''
	x% = instr( 1%, 'CDEHLQRST', function$)
	goto 2020 unless x%
	parameter_entered% =0%
	parameter_entered% =1% unless parameter$ = ''
	if (function$ = 'T' or function$ = 'E') then
		if parameter_entered% = 0% then
			print
			print	'Parameter missing...Try again'
			print
			goto 2020

2030	on x% goto 3400, 3000, 3000, 2010, 3200, 32700, 1110, 3300, 3000

3000	eof_flag% = 0%
	dir_rec_num% = 0%
	end_of_directory% = 0%
	some_file_found% = 0%
	gt_files% = 0%
	gt_bytes% = 0%
	t_files% = 0%
	t_bytes% = 0%
	t_directories% = 0%
	if parameter_entered% then
		entered_file_spec$ = parameter$
		gosub 11800
		search_directory% = -1%
		if file_spec_error% then
			print
			print	'Illegal filespec entered...Try again'
			goto 2020
			end if

3010	if parameter_entered% then
		search_directory% = search_directory% + 1%
		goto 3090 if search_directory% > max_dir_stack_pointer%
		goto 3010 if not fn_directory_match% (search_directory%)
	else
		entered_filename$ ='*'
		entered_ext$ = '*'
		file_case% = 5%
		ext_case% = 5%
		search_directory% = current_directory%
		end if
	this_cluster% = dir_stack_start_cluster%(search_directory%)
	first_call% = -1%
	new_directory% = -1%

3020	gosub 11100 unless search_directory%
	gosub 11700 if search_directory%
	goto 3040 unless end_of_directory%
	if t_files% then
		gt_files% = gt_files% + t_files%
		gt_bytes% = gt_bytes% + t_bytes%
		print
		print	'Total of ';num1$(t_files%);' files, ';		&
			num1$(t_bytes%);' bytes'
		t_directories% = t_directories% + 1%
		t_files% = 0%
		t_bytes% = 0%

3030	goto 3010 if parameter_entered%
	goto 3090

3040	goto 3020 if dir_attribute and 8%
	goto 3020 if dir_attribute and 16%
	goto 3020 unless fn_name_match% (file_case%, entered_filename$,	&
				edit$(dir_filename$,191%))
	goto 3020 unless fn_name_match% (ext_case%, entered_ext$,	&
				edit$(dir_ext$,191%))
	some_file_found% = -1%
	if function$ = 'T' then
		gosub 12000
		goto 3020
		end if
	if function$ = 'E' then
		gosub 12100
		goto 3020
		end if
	if new_directory% then
		new_directory% = 0%
		print
		print	'Directory of ';
		print	edit$(volume_label$,189%); unless volume_label$ = ''
		print	'Unlabeled'; if volume_label$ = ''
		print	':';fn_dir_string$( search_directory%)
		print

3050	day% = dir_creation_date and 31%
	day$ = num1$(day%)
	day$ = ' ' + day$ if day% < 10%
	month% = (dir_creation_date / 32%)
	month% = month% and 15%
	month$ = mid( month_string$, ((month% - 1%) * 3%) + 1%, 3%)
	year% = dir_creation_date / 512%
	year$ = num1$( year% + 1980%)
	file_date$ = day$ + '-' + month$ + '-' + year$

3060	hour% = dir_creation_time / 2048%
	hour% = hour% and 31%
	hour$ = num1$( hour%)
	hour$ = '0' + hour$ if hour% < 10%
	minute% = dir_creation_time / 32%
	minute% = minute% and 63%
	minute$ = num1$(minute%)
	minute$ = '0' + minute$ if minute% < 10%
	file_time$ = hour$ + ':' + minute$

3070	print	dir_filename$;'.';dir_ext$;'   ';
	print	'    ';file_date$;'   ';file_time$;'  ';
	print using '###,###,###', dir_filesize

3080	t_files% = t_files% + 1%
	t_bytes% = t_bytes% + dir_filesize
	goto 3020

3090	if not some_file_found% then
		print
		print	'No files found in ';
		print	edit$(volume_label$,189%); unless volume_label$ = ''
		print	'Unlabeled'; if volume_label$ = ''
		print	':';fn_dir_string$( current_directory%)		&
			unless parameter_entered%
		print	':';parameter$					&
			if parameter_entered%
		print
		goto 2020

3100	goto 2020 if function$ = 'T'
	goto 2020 if function$ = 'E'
	print
	if t_directories% > 1% then
		print	'Grand total of ';num1$(gt_files%);		&
			' files, ';num1$(gt_bytes%);' bytes'
		print
		end if
	goto 2020

3200	gosub 11300
	goto 2020

3300	print
	for x% = 0% to max_dir_stack_pointer%
	print	space$(dir_stack_level%(x%) * 8%);
	print	edit$(dir_stack_name$(x%), 191%)
	next x%
	goto 2020

3400	if parameter_entered% then
		entered_file_spec$ = parameter$
	else
		print
		input	'New directory  ';entered_file_spec$

3410	entered_file_spec$ = edit$(entered_file_spec$, 191%)
	goto 3450 if entered_file_spec$ = ''
	gosub 11800
	if wild_card_entered% or file_spec_error% then
		print
		print	'Illegal filespec entered...Try again'
		goto 3400 unless parameter_entered%
		goto 2020

3420	this_level% = 0%
	if sub_dir_pointer% = 0% then
		current_directory% = 0%
		goto 3450

3430	for x% = 0% to max_dir_stack_pointer%
	this_level% = dir_stack_level%(x%)				&
		if dir_stack_level%(x%) < this_level%
	this_level% = this_level% + 1%					&
		if edit$(dir_stack_name$(x%),191%) = 			&
			edit$(sub_directories$(this_level% + 1%),191%)	&
			and dir_stack_level%(x%) = this_level% + 1%
	if this_level% = sub_dir_pointer% then
		current_directory% = x%
		goto 3450

3440	next x%
	print
	print	'Unknown directory...Try again'
	goto 3400 unless parameter_entered%
	goto 2020

3450	print
	print	'Current directory is now ';
	print	edit$(volume_label$,189%); unless volume_label$ = ''
	print	'Unlabeled'; if volume_label$ = ''
	print	':';fn_dir_string$( current_directory%)
	goto 2020

11000	!***************************************************************&
	!								&
	!		here to get a sector of data			&
	!								&
	!***************************************************************&

11010	record_num% = ((((sector_num% - 1%) * sector_size%) / 		&
			record_size%) + 1%)
	record_offset% = (sector_num% - 1%) - 				&
			(((record_num% - 1%) * record_size%) /		&
			sector_size%)
	if record_num% <> last_record_num% then
		get #2%, block record_num%
		last_record_num% = record_num%

11020	bytes_moved% = 0%

11030	field #2%,	record_offset% * record_size as record_fill$,	&
			record_size% as record_data$
	lset sector_buffer$ = left(sector_buffer$, bytes_moved%) +	&
				record_data$
	bytes_moved% = bytes_moved% + record_size%
	goto 11099 if bytes_moved% >= sector_size%
	record_num% = record_num% + 1%
	last_record_num% = record_num%
	get #2%, block record_num%
	goto 11030

11099	return

11100	!***************************************************************&
	!								&
	!		here to get next root directory entry		&
	!								&
	!***************************************************************&

11110	dir_rec_num% = dir_rec_num% + 1%
	if dir_rec_num% > max_directory_entry% then
		end_of_directory% = -1%
		goto 11199

11120	sector_num% = ((dir_rec_num% - 1%) / entries_per_sector%) +	&
			first_directory_sector%
	dir_offset% = dir_rec_num% - 					&
			(((sector_num% - first_directory_sector%) *	&
			entries_per_sector%) + 1%)
	gosub 11000
	lset dir_entry$ = mid(sector_buffer$, (dir_offset% * 32%) + 1%,	&
				32%)
	x% = ascii( dir_filename$ )
	if x% = 0% then
		end_of_directory% = -1%
		goto 11199
	else
		goto 11100 if x% = 229%
		goto 11100 if edit$(dir_filename$,191%) = '' and	&
				edit$(dir_ext$,191%) = ''

11199	return
	
11200	!***************************************************************&
	!								&
	!		here to get boot record and init		&
	!								&
	!***************************************************************&

11210	get #2%, block 1%
	record_size% = recount
	last_record_num% = 1%
	field #2%, 128% as boot_block$
	lset boot_record = boot_block$
	
11220	first_directory_sector% = boot_reserved_sectors +		&
				( boot_sectors_per_fat *		&
				  boot_fat_copies) + 1%
	fat_pointer% = boot_reserved_sectors + 1%
	cluster_size% = boot_sectors_per_cluster
	sector_size% = boot_bytes_per_sector
	max_directory_entry% = boot_root_directory_entries
	entries_per_sector% = sector_size% / 32%
	first_data_sector% = boot_reserved_sectors +			&
		(boot_sectors_per_fat * boot_fat_copies) +		&
		(boot_root_directory_entries / entries_per_sector%) +	&
		1%
11290	return

11300	!***************************************************************&
	!								&
	!		here to display boot record info		&
	!								&
	!***************************************************************&

11320	print
	disk_format$ = 'Unknown...ID = ' + num1$(bood_format_id)
	disk_format$ = 'Double Sided 8 sectors / track'			&
		if boot_format_id = -1
	disk_format$ = 'Single Sided 8 sectors / track'			&
		if boot_format_id = -2
	disk_format$ = 'Double Sided 9 sectors / track'			&
		if boot_format_id = -3
	disk_format$ = 'Single Sided 8 sectors / track'			&
		if boot_format_id = -4
	disk_format$ = 'Quad Density'					&
		if boot_format_id = -7
	print	'System ID                       : ';			&
		boot_id
	print	'Format                          : ';			&
		disk_format$
	print	'VAX record size                 : ';			&
		num1$(record_size%)
	print	'Bytes per sector                : ';			&
		num1$(boot_bytes_per_sector)
	print	'Sectors per cluster             : ';			&
		num1$(boot_sectors_per_cluster)
	print	'Number of reserved sectors      : ';			&
		num1$(boot_reserved_sectors)
	print	'Number of FAT copies            : ';			&
		num1$(boot_fat_copies)
	print	'Number of directory entries     : ';			&
		num1$(boot_root_directory_entries)
	print	'Total number of sectors         : ';			&
		num1$(boot_total_sectors)
	print	'Sectors per FAT                 : ';			&
		num1$(boot_sectors_per_fat)
	print	'Sectors per track               : ';			&
		num1$(boot_sectors_per_track)
	print	'Number of sides                 : ';			&
		num1$(boot_total_sides)
	print	'Number special reserved sectors : ';			&
		num1$(boot_special_reserved_secotrs)

11399	return

11400	!***************************************************************&
	!								&
	!		Here to read the FAT and compute the next	&
	!			file cluster				&
	!								&
	!***************************************************************&

11410	eof_flag% = 0%
	fat_byte% = ((this_cluster% * 3%) / 2%) + 1%
	fat_sector% = (fat_byte% / sector_size%) + fat_pointer%
	fat_offset% = fat_byte% - 					&
			((fat_sector% - fat_pointer%) * sector_size%)
	sector_num% = fat_sector%
	gosub 11000
	c1% = ascii(right(sector_buffer$,fat_offset%))
	c2% = ascii(right(sector_buffer$,fat_offset% + 1%))
	c1% = c1% and 255%
	c2% = c2% and 255%
	c3% = c1% + (c2% * 256%)
	if (this_cluster% and 1%) then
		this_cluster% = (c3% / 16%) and 4095%
	else
		this_cluster% = c3% and 4095%

11420	eof_flag% = -1 if this_cluster% > 4087%
	gosub 11500 unless eof_flag%
	
11499	return

11500	!***************************************************************&
	!								&
	!	Here to compute the first sector of this_sector%	&
	!								&
	!***************************************************************&

11510	this_sector% = ((this_cluster% -2%) * boot_sectors_per_cluster)	&
			+ first_data_sector%

11599	return

11600	!***************************************************************&
	!								&
	!	This procedure reads the entire directory tree		&
	!	    and fills in the directory_stack arrays		&
	!								&
	!***************************************************************&

	directory_level% = 0%
	current_directory% = 0%
	search_directory% = 0%
	current_dir_stack_pointer% = 0%
	insert_dir_stack_pointer% = 0%
	max_dir_stack_pointer% = 0%
	volume_label$ = ''
	dir_stack_name$(0%) = '<Root>     '
	dir_stack_level%(0%) = 0%
	dir_stack_parent%(0%) = -1%
	dir_stack_start_cluster%(0%) = 0%
	dir_rec_num% = 0%
	end_of_directory% = 0%

11605	gosub 11100
	goto 11615 if end_of_directory%
	if (dir_attribute and 8%) then
		volume_label$ = dir_filename$ + dir_ext$
		goto 11605 

11610	goto 11605 unless dir_attribute and 16%
	max_dir_stack_pointer% = max_dir_stack_pointer% + 1%
	if max_dir_stack_pointer% > 999% then
		print
		print	'*** Too many subdirectories...Aborting'
		print
		goto 32700
		end if
	insert_dir_stack_pointer% = insert_dir_stack_pointer% + 1%
	dir_stack_name$(max_dir_stack_pointer%) = dir_filename$ + dir_ext$
	dir_stack_level%(max_dir_stack_pointer%) = 1%
	dir_stack_start_cluster%(max_dir_stack_pointer%) = dir_first_cluster
	dir_stack_parent%(max_dir_stack_pointer%) = 0%
	goto 11605

11615	goto 11699 if max_dir_stack_pointer% = current_dir_stack_pointer%
	current_dir_stack_pointer% = current_dir_stack_pointer% + 1%
	insert_dir_stack_pointer% = current_dir_stack_pointer%
	this_cluster% = dir_stack_start_cluster%(current_dir_stack_pointer%)
	first_call% = -1%

11620	gosub 11700
	goto 11615 if end_of_directory%
	goto 11620 unless dir_attribute and 16%
	max_dir_stack_pointer% = max_dir_stack_pointer% + 1%
	if max_dir_stack_pointer% > 999% then
		print
		print	'*** Too many subdirectories...Aborting'
		print
		goto 32700
		end if
	insert_dir_stack_pointer% = insert_dir_stack_pointer% + 1%
	goto 11630 if insert_dir_stack_pointer% = max_dir_stack_pointer%
	for x% = max_dir_stack_pointer% to insert_dir_stack_pointer% step -1%
	dir_stack_name$(x%) = dir_stack_name$(x% - 1%)
	dir_stack_level%(x%) = dir_stack_level%(x% - 1%)
	dir_stack_parent%(x%) = dir_stack_parent%(x% - 1%)
	dir_stack_start_cluster%(x%) = dir_stack_start_cluster%(x% - 1%)
	next x%

11630	dir_stack_name$(insert_dir_stack_pointer%) = dir_filename$ + 	&
							dir_ext$
	dir_stack_level%(insert_dir_stack_pointer%) =			&
			dir_stack_level%(current_dir_stack_pointer%) + 1%
	dir_stack_parent%(insert_dir_stack_pointer%) =			&
			current_dir_stack_pointer%
	dir_stack_start_cluster%(insert_dir_stack_pointer%) =		&
			dir_first_cluster
	goto 11620

11699	return

11700	!***************************************************************&
	!								&
	!	procedure to get the next entry from a subdirectory	&
	!		caller set first_call and this_cluster		&
	!								&
	!***************************************************************&

11710	goto 11720 unless first_call%
	first_call% = 0%
	end_of_directory% = 0%
	sub_dir_offset% = 1%
	gosub 11500%
	sub_dir_this_cluster% = this_cluster%
	sector_num% = this_sector%
	gosub 11000
	sub_dir_sector_num% = sector_num%
	lset sub_dir_buffer$ = sector_buffer$
	sub_dir_sectors_read% = 1%

11720	sub_dir_offset% = sub_dir_offset% + 32%
	goto 11740 if sub_dir_offset% + 31% <= sector_size%
	if sub_dir_sectors_read% = cluster_size% then
		this_cluster% = sub_dir_this_cluster%
		gosub 11400
		if eof_flag% then
			end_of_directory% = -1%
			goto 11799
		else
			gosub 11500
			sub_dir_this_cluster% = this_cluster%
			sub_dir_sector_num% = this_sector% - 1%
			sub_dir_sectors_read% = 0%

11730	sub_dir_sector_num% = sub_dir_sector_num% + 1%
	sub_dir_sectors_read% = sub_dir_sectors_read% + 1%
	sector_num% = sub_dir_sector_num%
	gosub 11000
	lset sub_dir_buffer$ = sector_buffer$
	sub_dir_offset% = 1%

11740	lset dir_entry$ = mid(sub_dir_buffer$, sub_dir_offset%, 32%)
	x% = ascii( dir_filename$ )
	goto 11720 if x% = 229%
	goto 11720 if x% = 0%
	goto 11720 if edit$(dir_filename$,191%) = '' and		&
				edit$(dir_ext$,191%) = ''
	goto 11720 if edit$(dir_filename$,191%) = '..'

11799	return

11800	!***************************************************************&
	!								&
	!		here to parse a DOS filespec			&
	!								&
	!***************************************************************&

	a$ = edit$(entered_file_spec$, 191%)
	wild_card_entered% = 0%
	wild_card_entered% = -1% if instr(1%, a$, '?') or		&
					instr(1%, a$, '%') or		&
					instr(1%, a$, '*') or		&
					instr(1%, a$, '...')
	file_spec_error% = 0%
	sub_dir_pointer% = dir_stack_level%(current_directory%)
	match_at_least% = sub_dir_pointer%
	p% = sub_dir_pointer%
	d% = current_directory%

11805	goto 11810 unless p%
	sub_directory$(p%) = dir_stack_name$(d%)
	d% = dir_stack_parent%(d%)
	p% = p% - 1%
	goto 11805

11810	s% = instr(1%, a$, '[')
	e% = instr(1%, a$, ']')
	f$ = right(a$, e% + 1%)
	f$ = '*.*' if f$ = ''
	goto 11850 if s% = 0% and e% = 0%
	if s% = 0% or e% = 0% or s% <> 1% then
		file_spec_error% = -1%
		goto 11899
	else
		d$ = left( a$, e% - 1%)
		match_at_least% = 0%
		sub_dir_pointer% = 0% unless 				&
			mid(d$, 2%, 1%) = '.' or mid(d$, 2%, 1%) = '-'

11815	d$ = right(d$, 2%)
	goto 11850 if len( d$) = 0%
	next_char$ = left(d$, 1%)
	if next_char$ = '-' then
		sub_dir_pointer% = sub_dir_pointer% - 1%
		match_at_least% = sub_dir_pointer%
		if sub_dir_pointer% < 0% then
			file_spec_error% = -1%
			goto 11899
			end if
		goto 11815
		end if
	if next_char$ <> '.' then
		x% = instr(1%, d$, '.')
		sub_dir_pointer% = sub_dir_pointer% + 1%
		if sub_dir_pointer% > 9% then
			file_spec_error% = -1%
			goto 11899
			end if
		match_at_least% = sub_dir_pointer%
		if x% = 0% then
			sub_directories$( sub_dir_pointer%) = d$
			goto 11850
			end if
		sub_directories$( sub_dir_pointer%) = left(d$, x% - 1%)
		d$ = right( d$, x% - 1%)
		goto 11815
		end if
	if left(d$, 3%) <> '...' then
		if left(d$, 2%) = '..' then
			file_spec_error% = -1%
			goto 11899
			end if
		goto 11815
		end if
	sub_directories$( sub_dir_pointer%) = '...'			&
		for sub_dir_pointer% = 					&
				sub_dir_pointer% + 1% to 10%

11850	for x% = 0% to 10%
	sub_directory_case%(x%) = fn_wild_case%(sub_directories$(x%))
	if sub_directory_case%(x%) = -1% then
		file_spec_error% = -1%
		goto 11899

11860	next x%
	goto 11899 if f$ = ''
	x% = instr( 1%, f$, '.')
	entered_filename$ = left( f$, x% - 1%) if (x% > 1%)
	entered_filename$ = f$ if (x% = 0%)
	file_case% = fn_wild_case% (entered_filename$)
	entered_ext$ = right( f$, x% + 1%)				&
		if (x% < len( f$)) and (x% > 0%)
	ext_case% = fn_wild_case% (entered_ext$)
	file_spec_error% = -1% if file_case% = -1 or ext_case% = -1%

11899	return

12000	!***************************************************************&
	!								&
	!	Here to display the contents of a file			&
	!		directory entry is in the buffer		&
	!								&
	!***************************************************************&

12010	print
	a$ = '* ' + edit$(volume_label$,189%) unless volume_label$ = ''
	a$ = '* Unlabeled' if volume_label$ = ''
	a$ = a$ + ':' + fn_dir_string$( search_directory%) +		&
		edit$(dir_filename$,191%) + '.' +			&
		edit$(dir_ext$,191%) + ' *'
	b$ = string$( len(a$), ascii('*'))
	c$ = '*' + space$(len(a$) - 2%) + '*'
	d$ = space$((80%-len(a$))/2%)
	print	d$;b$
	print	d$;c$
	print	d$;a$
	print	d$;c$
	print	d$;b$
	print
	this_cluster% = dir_first_cluster
	bytes_left% = dir_filesize
	goto 12099 if this_cluster% = 0%

12020	gosub 11500
	sector_num% = this_sector%
	sectors_left% = boot_sectors_per_cluster

12030	gosub 11000
	x% = instr( 1%, sector_buffer$, chr$(26%))
	if x% then
		bytes_left% = 0%
		x% = x% - 1%
	else
		x% = sector_size%
		x% = bytes_left% if x% > bytes_left%

12040	sector_buffer$ = xlate( sector_buffer$, xlate_table$)
	print	left( sector_buffer$, x%);
	bytes_left% = bytes_left% - x%
	goto 12099 if bytes_left% <= 0%
	sectors_left% = sectors_left% - 1%
	sector_num% = sector_num% + 1%
	goto 12030 if sectors_left%
	gosub 11400
	goto 12099 if eof_flag%
	goto 12020

12099	return

12100	!***************************************************************&
	!								&
	!	Here to extract a file...Directory entry is in buffer	&
	!								&
	!***************************************************************&

12110	original_filename$ = edit$(dir_filename$,191%) + '.' +		&
				edit$(dir_ext$,191%)
	this_filename$ = original_filename$
	filename_changed% = 0%

12120	x% = instr( 1%, this_filename$, '-')
	if x% then
		this_filename$ = left( this_filename$, x% - 1%) +	&
				'_' +					&
				 right( this_filename$, x% + 1%)
		filename_changed% = -1%
		goto 12120

12130	x% = instr( 1%, this_filename$, "'")
	if x% then
		this_filename$ = left( this_filename$, x% - 1%) +	&
				 right( this_filename$, x% + 1%)
		filename_changed% = -1%
		goto 12130

12140	print	'Extracting ';original_filename$;
	print	' and changing filename to ';this_filename$;		&
		if filename_changed%
	print
	open this_filename$ for output as file #3%,			&
			sequential variable,				&
			recordtype none,				&
			map sector_buffer

12150	bytes_left% = dir_filesize
	this_cluster% = dir_first_cluster
	if this_cluster% = 0% then
		close #3%
		goto 12199

12160	gosub 11500
	sector_num% = this_sector%
	sectors_left% = boot_sectors_per_cluster

12170	gosub 11000
	put_count% = sector_size%
	put_count% = bytes_left% if bytes_left% < sector_size%
	put #3%, count put_count%
	bytes_left% = bytes_left% - put_count%
	goto 12199 if bytes_left% <= 0%
	sectors_left% = sectors_left% - 1%
	sector_num% = sector_num% + 1%
	goto 12170 if sectors_left%
	gosub 11400
	goto 12199 if eof_flag%
	goto 12160

12199	close #3%
	return

15000	!***************************************************************&
	!								&
	!	Function to compare a name with a mask (possibly	&
	!		       containing wild cards)			&
	!								&
	!***************************************************************&

15010	def fn_name_match% ( cas%, mask$, name$)

15020	result% = -1%
	if cas% = 0% then
		for x% = 1% to len( mask$)
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,x%))) and		&
				(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		result% = 0% unless len(mask$) = len(name$)
		goto 15090

15030	if cas% = 1% then
		for x% = 1% to len( mask$) - 1%
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,x%))) and		&
				(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		goto 15090

15040	if cas% = 2% then
		for x% = 2% to len( mask$)
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,			&
					x% + len(name$) - len(mask$)))) &
			    and	(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		goto 15090

15050	if cas% = 3% then
		y% = instr( 1%, mask$, '*')
		for x% = 1% to y%-1%
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,x%))) and		&
				(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		for x% = y% + 1% to len( mask$)
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,			&
					x% + len(name$) -len(mask$))))	&
			    and	(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		goto 15090

15060	if cas% = 4% then
		for y% = 1% to len(name$) - len(mask$) + 3%
		result% = -1%
		for x% = 2% to len(mask$) - 1%
		result% = 0% if (ascii(right(mask$,x%)) <> 		&
				ascii(right(name$,x% + y% - 2%))) and	&
				(ascii(right(mask$,x%)) <> ascii('%'))	&
			    and	(ascii(right(mask$,x%)) <> ascii('?'))
		next x%
		goto 15090 if result%
		next y%

15070	result% = 0% unless (cas% = 5%) or (cas% = 6%)

15090	fn_name_match% = result%

15099	fnend

15100	!***************************************************************&
	!								&
	!	Function to compute the case of a wild card construct	&
	!								&
	!		Case		      Syntax			&
	!		----		-------------------		&
	!		 -1		    Illegal syntax		&
	!		  0		       Text			&
	!		  1		       Text*			&
	!		  2		      *Text			&
	!		  3		     Text*Text			&
	!		  4		      *Text*			&
	!		  5			 *			&
	!		  6                     ...			&
	!								&
	!***************************************************************&


15101	def fn_wild_case% (case_data$)

15110	case_data$ = edit$(case_data$,191%)
	this_case% = -1%
	if case_data$ = '*' then
		this_case% = 5%
		goto 15190

15115	if case_data$ = '...' then
		this_case% = 6%
		goto 15190

15120	x1% = len( case_data$)
	x2% = instr( 1%, case_data$, '*')
	if x2% = 0% then
		this_case% = 0%
		goto 15190

15130	if x1% = x2% then
		this_case% = 1%
		goto 15190

15140	if x1% > x2% then
		x3% = instr( x2% + 1%, case_data$, '*')
		if x3% = 0% then
			this_case% = 2% if x2% = 1%
			this_case% = 3% if x2% <> 1%
		else
			goto 15190 if (x2% <> 1%) or (x1% <> x3%)
			this_case% = 4% if x3% - x2% <> 1%
			
15190	fn_wild_case% = this_case%

15199	fnend

15200	!***************************************************************&
	!								&
	!	Here to build a string showing current path		&
	!								&
	!***************************************************************&

15210	def fn_dir_string$ (dir_stack_pointer%)

15220	x% = dir_stack_pointer%
	result$ = ']'

15230	goto 15240 unless x%
	result$ = '.' + edit$(dir_stack_name$(x%) ,191%) + result$
	x% = dir_stack_parent%(x%)
	goto 15230

15240	result$ = '[' + right(result$, 2%)
	result$ = '[Root-Directory]' if result$ = '['

15290	fn_dir_string$ = result$
	fnend

15300	!***************************************************************&
	!								&
	!	function to determine if a path matches			&
	!								&
	!***************************************************************&

15310	def fn_directory_match% (dir_pointer%)
	result% = -1%
	n% = dir_pointer%
	if match_at_least% > dir_stack_level%(dir_pointer%) or		&
		sub_dir_pointer% < dir_stack_level%(dir_pointer%) then
		result% = 0%
		goto 15399

15320	goto 15399 if (n% = 0%) or (result% = 0%)
	result% = 0% unless fn_name_match% (				&
			sub_directory_case%(dir_stack_level%(n%)),	&
			edit$(sub_directories$(dir_stack_level%(n%)),191%),&
			edit$(dir_stack_name$(n%),191%))
	n% = dir_stack_parent%(n%)
	goto 15320

15399	fn_directory_match% = result%
	fnend


19000	!***************************************************************&
	!								&
	!			Here on all errors			&
	!								&
	!***************************************************************&

19010	if err = 11% and erl = 11010 then
		eof_flag% = -1%
		resume 11099

19020	if (err=2% or err=162%) and erl= 12140 then
		print
		print	"Can't open file...Bad filename"
		print
		resume 12199

19030	if err=11% and erl=1110 then
		resume 32700

19040	if erl = 1200 then
		print
		print	"Can't open input file...Try again"
		print
		resume 1110

19050	if err=11% and erl=2020 then
		resume 32700

19080	if err=11% and erl= 3400 then
		resume 2020

19998	print 'Error # ';num1$(err);' at line # ';num1$(erl);'...Aborting'

19999	on error goto 0

32700	close #i% for i% = 1% to 10%

32767	end
