$include (..\lib\compStch.ext)

/*
 *============================================================================
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
 *
 *  Permission to use for any purpose, modify, copy, and make enhancements
 *  and derivative works of the software is granted if attribution is given to
 *  R.M. Gillmore, dba the ACME Software Deli, as the author
 *
 *  While the ACME Software Deli does not work for money, there is nonetheless
 *  a significant amount of work involved.  The ACME Software Deli maintains the
 *  rights to all code written, though it may be used and distributed as long as
 *  the following conditions are maintained.
 *
 *  1.  The copyright statement at the top of each code block is maintained in
 *      your distribution.
 *  2.  You do not identify yourself as the ACME Software Deli
 *  3.  Any changes made to the software are sent to the ACME Software Deli
 *============================================================================
 */

listFilesModule:
do;
$if not noID
declare	IDString	(*) byte data
	( '@(#)$Id: dls.p86 931 2024-03-02 00:50:35Z rmgillmore $', 0 );
$endif

declare	programVersion	(*)	byte	data	( 'v2.2', 0 ),
		copyrightString	(*)	byte	data
			( '(c)Copyright 2020-2022, 2024, the ACME Software Deli', 0 );

$include (..\lib\comnDefs.ext)
$include (..\lib\sysCalls.ext)
$include (..\lib\DOSFind.ext)
$include (..\lib\curDir.ext)
$include (..\lib\fileIO.ext)
$include (..\lib\string.ext)
$include (..\lib\date.ext)
$include (..\lib\cmdArgs.ext)
$include (..\lib\videoIO.ext)
$include (..\lib\diskIO.ext)
$include (..\lib\ptrMath.ext)
$include (..\lib\dirFunct.ext)
$include (..\lib\videoIO.ext)
$include (..\lib\volInfo.ext)
$include (..\lib\changExt.ext)
$if LOGGING
$include (..\lib\logger.ext)
$endif

declare	FILESIZE_LENGTH		literally	'13',	/* 8.3 plus the space */
		NUMBER_HEADER_LINES	literally	'7';

declare help					boolean,
		pageReporting			boolean,
		nameMask	( MAX_PATH )	char,
		noSwitch1	( MAX_PATH )	char,
		recurse					boolean,
		archive					boolean,
		directory				boolean,
		hidden					boolean,
$if LOGGING
		verbose					boolean,
$endif
		searchAttribute			word;

declare	numberFilesReported		integer,
		numberColumnsPerPage	integer,
		numberLinesPerPage		integer,

		totalNumberFiles		integer,
		totalNumberDirectories	integer,
		recordSearchNumber		integer,
		totalFileSize			dword;

declare argDefinitions	(*)	commandOption_t data
(
	EXISTS,		@help,	@( '?', 0 ),	@( 'help', 0 ),
		@( '(optional) displays this information', 0 ),

	EXISTS,		@pageReporting,		@( 'p', 0 ),	@( 'page', 0 ),
		@( '(optional) print one page of the file list, then wait for ',
			'the user to press a key to continue. ''X'' and ''Q'', ',
			'<ESC> and their lowercase equivalents, will discontinue the ',
			'reporting of files and exit the program.  Without this option, ',
			'files are listed without pausing until all are listed', 0 ),

	EXISTS,		@recurse,	@( 'r', 0 ),	@( 'recurse', 0 ),
		@( '(optional) look for directory entries that match the filespec in ',
			'sub-directories, also', 0 ),

	EXISTS,		@hidden,	@( 'hid', 0 ),	@( 'hidden', 0 ),
		@( '(optional) include those files which are hidden', 0 ),

$if LOGGING
	EXISTS,		@verbose,	@( 'v', 0 ),	@( 'verbose', 0 ),
		@( '(optional) add what may be useful information to a log file', 0 ),
$endif

	NEXT_ARG,	@nameMask,	@( 'f', 0 ),	@( 'fileMask', 0 ),
		@( '(switch optional) specifies the filename mask (following the OS rules)', 0 ),

	NO_SWITCH,	@noSwitch1, 	NULL,			NULL,
		NULL
);

declare	commandOptionDef	commandOptionDefinition_t;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

shiftStringRight:
procedure ( stringInPtr ) public;
	declare	stringInPtr			pointer,
			stringIn	based	stringInPtr	(*)	char;

	/*
	 *	shift the entire string to the right one character
	 */

	declare	lastIndex			integer,
			index				integer;

	lastIndex = signed( strlen( stringInPtr ) );

	stringIn( lastIndex + 1 ) = NUL;
	index = lastIndex;

	do while ( index >= 0 );
		stringIn( index + 1 ) = stringIn( index );
		index = index - 1;
	end;
end shiftStringRight;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

fillWithCommas:
procedure ( localStringPtr ) public;
	declare	localStringPtr		pointer,
			localString		based	localStringPtr	(*)	char;

	declare	NUMBER_TEMP_STRINGS	literally	'7',
			DIGITS_PER_THOUSAND	literally	'3',
			SEGMENT_LENGTH		literally	'4';	/* DIGITS_PER_THOUSAND + 1 */

	declare	numberIterations	integer,
			stringIndex			integer;

	numberIterations = signed( strlen( localStringPtr ) ) / DIGITS_PER_THOUSAND;
	if ( numberIterations > 0 ) then
	do;
		stringIndex = signed( strlen( localStringPtr ) ) -
			( SEGMENT_LENGTH - 1 );
	end;

	adjustString:
	do;
		declare	counter			integer;

		counter = 0;
		do while ( ( counter < numberIterations ) and ( stringIndex > 0 ) );

			/*
			 *	shift the string one character to the right at the current
			 *	location, then insert the comma
			 */

			call shiftStringRight( @localString( stringIndex ) );
			localString( stringIndex ) = ',';

			counter = counter + 1;
			stringIndex = stringIndex - ( SEGMENT_LENGTH - 1 );
		end;
	end adjustString;
end fillWithCommas;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

reportFileSize:
procedure ( fileSize ) public;
	declare	fileSize				dword;

	/*
	 *	4,294,967,295 is the worst case size report
	 */

	declare	fileSizeString		( FILESIZE_LENGTH )	char,
			tempFileSizeString	( FILESIZE_LENGTH )	char;

	/*
	 *	initialize the temp string
	 *	translate the size to ASCII
	 *	insert commas into the size
	 */

	call memset( @tempFileSizeString, 0, FILESIZE_LENGTH );
	call sprintf( @tempFileSizeString, @( '%ld', 0 ), fileSize );
	call fillWithCommas( @tempFileSizeString );

	/*
	 *	now that we have the file size in ASCII, we can determine how
	 *	many leading spaces are needed
	 */

	call memset( @fileSizeString, 0, FILESIZE_LENGTH );
	call memset( @fileSizeString, ' ',
		FILESIZE_LENGTH - strlen( @tempFileSizeString ) );
	call strcat( @fileSizeString, @tempFileSizeString );

	/*
	 *	now, report the file size
	 */

	call printf( @fileSizeString );
end reportFileSize;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

findCurrentDirectory:
procedure ( inputPathPtr ) public;
	declare	inputPathPtr		pointer,

			slashDelimPtr		pointer,
			index				word,
			localDirName	( MAX_PATH )	char,
			localPathPtr		pointer,
			localPath	based	localPathPtr	(*)	char,
			chdirReturned		word;

	if ( 0 = strlen( inputPathPtr ) ) then
	do;
		/*
		 *	there is no input path specification, so we will change to the current
		 *	directory since that is all we can assume.  However, there is really
		 *	no need to do any work because we are already there
		 */
	end;
	else
	do;
		/*
		 *	the directory path MUST use the backslash, so change them
		 *	so that everything actually works
		 */

		call strcpy( @localDirName, inputPathPtr );
		index = 0;
		do while ( localDirName( index ) <> NUL );
			if ( localDirName( index ) = '/' ) then
			do;
				localDirName( index ) = '\';
			end;
			index = index + 1;
		end;
		/*
		 *	now, we need to get to the current directory, too.  However, since
		 *	the name specified could be a relative directory specification,
		 *	we need to change to that directory
		 */

		slashDelimPtr = normalizePtr( strrchr( @localDirName, '\' ) );

		if ( slashDelimPtr > NULL ) then
		do;
			/*
			 *	the last path delimiter is a slash
			 */

			localPathPtr = slashDelimPtr;
			localPath( 0 ) = NUL;
		end;

		/*
		 *	change to the path specified
		 */

		chdirReturned = chdir( @localDirName );
	end;
end findCurrentDirectory;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

reportVolume:
procedure public;
	declare	findDataRecord			findDataRecordType,
			returnCode				integer,
			currentDrive			char,
			currentDirectoryString	( MAX_PATH )	char,
			nameMask	(*)		char	data ( ' :\*.*', 0 ),
			volumeNumber			dword,
			chdirReturned			word,
			status					word,
			volumeName		( diskInfoLabelLength )	char;

	returnCode = 0;

	/*
	 *	Volume in drive C is Mike-HP
	 *	Volume Serial Number is 7486-2C5D
	 *	Directory of C:\Users\Owner\Documents\work\Plm86
	 */

	/*
	 *	if the file listing is being done for a directory which is not on the
	 *	default drive, we need to change to the specified drive, get its volume
	 *	name, and return to the default drive
	 */

	currentDrive = getCurrentDisk;
	call getcwd( @currentDirectoryString );

	if ( returnCode = 0 ) then
	do;
		call getVolumeName( toupper( currentDirectoryString( 0 ) ) - 'A', @volumeName );
		call printf( @( 'The volume in Drive %c is %s\n', 0 ),
				getCurrentDisk, @volumeName );
		call findClose( @findDataRecord );

		volumeInfoReport:
		do;
			declare volumeInfo				volumeInfoType,
					serialNumber			dword,
					serialNumberString	( 15 )	char;

			serialNumber = getDriveSerialNumber( getCurrentDisk );
			if ( serialNumber <> 0 ) then
			do;
				call sprintf( @serialNumberString, @( '%X', 0 ),
					high( serialNumber ) );
				serialNumberString( 4 ) = '-';
				call sprintf( @serialNumberString( 5 ), @( '%X', 0 ),
					low( serialNumber ) );
				serialNumberString( 9 ) = NUL;
			end;
			else
			do;
				call strcpy( @serialNumberString, @( 'N/A', 0 ) );
			end;
			call printf( @( 'Volume Serial Number is %s\n', 0 ),
				@serialNumberString );
		end volumeInfoReport;

		directoryNameReport:
		do;
			declare	localDirName	( MAX_PATH )	char;

			call findCurrentDirectory( @nameMask );
			call getcwd( @localDirName );
			call printf( @( 'Directory of %s\n', 0 ), @localDirName );
		end directoryNameReport;

		call printf( @( '\n', 0 ) );

		/*
		 *	get back to where we started
		 */

		returnCode = signed( setCurrentDisk( currentDrive ) );
		chdirReturned = chdir( @currentDirectoryString );
	end;

end reportVolume;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

$if LOGGING
reportRecord:
procedure ( searchNumber, dataRecordPtr ) public;
	declare	searchNumber		integer,
			dataRecordPtr		pointer,
			dataRecord	based	dataRecordPtr	findDataRecordType;

	call addToLog( DEBUG, __FILE__, __LINE__,
		@( '# %d  dos: "%s"  full: "%s"', 0 ), searchNumber,
			@dataRecord.dosName, @dataRecord.fullName );

end reportRecord;
$endif

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

reportInLine:
procedure ( fileAttr, fileSize, fileDate, dosFileNamePtr, fullFileNamePtr ) public;
	declare	fileAttr			dword,
			fileSize			dword,
			fileDate			dword,
			dosFileNamePtr		pointer,
			fullFileNamePtr		pointer;

	declare	fileNameLength		word,
			fileName	( MAX_PATH )	char,
			returned			word,
			fileTime			time_t,
			timeStruct			tmStruct,
			tmStructPtr			pointer,
			timeDateString	( 40 )	char,
			LONGEST_NAME		literally	'12',
			spacesString	( LONGEST_NAME )	char
										data ( '           ' ),
			dirString		(*)	char data ( '<DIR>', 0 );

	if ( ( fileAttr and DIRECTORY_BIT ) <> 0 ) then
	do;
		returned = fwrite( stdout, @spacesString,
			( FILESIZE_LENGTH - strlen( @dirString ) ) );
		returned = fwrite( stdout, @dirString, strlen( @dirString ) );
		totalNumberDirectories = totalNumberDirectories + 1;
	end;
	else
	do;
		call reportFileSize( fileSize );
		totalNumberFiles = totalNumberFiles + 1;
		totalFileSize = totalFileSize + fileSize;
	end;

	tmStructPtr = @timeStruct;
	call localtime( fileDate, @tmStructPtr );
	call strftime( @tmStructPtr, @( '%m/%d/%y %I:%M%p', 0 ), @timeDateString );

	/*
	 *	remove the 'm' from the end of the date string (we want
	 *	'a' or 'p', not 'am' or 'pm'), then report
	 */

	timeDateString( strlen( @timeDateString ) - 1 ) = 0;
	call printf( @( ' %s ', 0 ), @timeDateString );

	/*
	 *	If we have a "long" name, use it; otherwise, use the
	 *	DOS name
	 */

	if ( 0 < strlen( fullFileNamePtr ) ) then
	do;
		call strcpy( @fileName, fullFileNamePtr );
	end;
	else
	do;
		call strcpy( @fileName, dosFileNamePtr );
	end;

	call printf( @( '%s', 0 ), @fileName );
	fileNameLength = strlen( @fileName );

	if ( fileNameLength < LONGEST_NAME ) then
	do;
		returned = fwrite( stdout, @spacesString,
			( LONGEST_NAME - fileNameLength ) );
	end;

	call printf( @( '\n', 0 ) );
end reportInLine;

summaryReport:
procedure;
	declare	tempNumberString	( FILESIZE_LENGTH )	char,
			tempNumberString2	( FILESIZE_LENGTH )	char;

	if ( totalNumberFiles = 1 ) then
	do;
		call memset( @tempNumberString, 0, FILESIZE_LENGTH );
		call sprintf( @tempNumberString, @( '%ld', 0 ), totalFileSize );
		call fillWithCommas( @tempNumberString );
		call printf( @( '%s bytes in 1 file', 0 ), @tempNumberString );
	end;
	else if ( totalNumberFiles > 1 ) then
	do;
		call memset( @tempNumberString, 0, FILESIZE_LENGTH );
		call sprintf( @tempNumberString, @( '%ld', 0 ), totalFileSize );
		call fillWithCommas( @tempNumberString );

		call memset( @tempNumberString2, 0, FILESIZE_LENGTH );
		call sprintf( @tempNumberString2, @( '%d', 0 ), totalNumberFiles );
		call fillWithCommas( @tempNumberString2 );
		call printf( @( '%s bytes in %s files', 0 ), @tempNumberString,
			@tempNumberString2 );
	end;

	if ( totalNumberDirectories = 0 ) then
	do;
		/*
		 *	no directories, do nothing
		 */
	end;
	else if ( totalNumberDirectories = 1 ) then
	do;
		call printf( @( ' (1 directory)', 0 ) );
	end;
	else if ( totalNumberDirectories > 1 ) then
	do;
		/*
		 *	initialize the temp string
		 *	translate the size to ASCII
		 *	insert commas into the size
		 */

		call memset( @tempNumberString, 0, FILESIZE_LENGTH );
		call sprintf( @tempNumberString, @( '%d', 0 ), totalNumberDirectories );
		call fillWithCommas( @tempNumberString );
		call printf( @( ' (%s directories)', 0 ), @tempNumberString );
	end;
end summaryReport;


/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:
 *
 *	Description:
 *
 *	Returns:
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

/*
 *              <DIR> 10/28/20  5:12p .svn
 *              <DIR> 10/29/20  4:02p SCRIPTS
 *         91,299,318  2/19/20 11:35p 16BitTools.zip
 *                 46 10/15/19  8:14p 8dot3Path.cmd
 *             20,916 10/28/20  5:16p acmeDir.exe
 *             67,891 10/28/20  5:16p acmeDir.lst
 */

reportFiles:
procedure integer public;
	declare	returnCode				integer,
			searchStarted			boolean,
			findDataRecord			findDataRecordType;

	searchStarted = False;
	totalNumberFiles = 0;
	totalNumberDirectories = 0;
	recordSearchNumber = 0;
	totalFileSize = 0;

	call screenSize( @numberColumnsPerPage, @numberLinesPerPage );

	returnCode = 0;
	do while ( 0 = returnCode );
		if ( not searchStarted ) then
		do;
			/*
			 *	search attributes
			 */

			if ( archive ) then
				findDataRecord.fileAttr = findDataRecord.fileAttr or ARCHIVE_BIT;
			if ( directory ) then
				findDataRecord.fileAttr = findDataRecord.fileAttr or DIRECTORY_BIT;
			if ( hidden ) then
				findDataRecord.fileAttr = findDataRecord.fileAttr or HIDDEN_BIT;

			/*
			 *	filename mask (for what are we searching)
			 */

			if ( ( strlen( @noSwitch1 ) > 0 ) and
					( strlen ( @nameMask ) = 0 ) ) then
				call strcpy( @nameMask, @noSwitch1 );
			else if ( strlen( @nameMask ) = 0 ) then
				call strcpy( @nameMask, @( '*.*', 0 ) );

			if ( pageReporting ) then
			do;
				/*
				 *	if we are to report only one screen at a time, we need
				 *	to know how many lines there are on the page.  The
				 *	size is reported as # columns and # rows.  Since we don't
				 *	need the # of columns, we will ignore them
				 */

				numberFilesReported = NUMBER_HEADER_LINES;
			end;
			else
			do;
				numberFilesReported = 0;
				numberLinesPerPage = 32767;
			end;

			call reportVolume;

			returnCode = signed( findFirst( @nameMask, @findDataRecord ) );
			recordSearchNumber = recordSearchNumber + 1;
			searchStarted = True;
		end;
		else
		do;
			returnCode = signed( findNext( @findDataRecord ) );
			recordSearchNumber = recordSearchNumber + 1;
		end;

		reportBlock:
		do;
			if ( 0 = returnCode ) then
			do;
				call reportInLine( findDataRecord.fileAttr,
					findDataRecord.fileSize( 1 ), findDataRecord.modifiedTime( 0 ),
					@findDataRecord.dosName, @findDataRecord.fullName );

				returnCode = 0;
				numberFilesReported = numberFilesReported + 1;

				if ( pageReporting ) then
				do;
					pageReportingBlock:
					do;
						declare	keyCode		integer;

						if ( numberFilesReported > ( numberLinesPerPage - 2 ) ) then
						do;
							numberFilesReported = 0;

							call printf(
								@( '%c%c More %c%c \r', 0 ),
									LINE_SINGLE_HORIZONTAL, LINE_SINGLE_HORIZONTAL,
									LINE_SINGLE_HORIZONTAL, LINE_SINGLE_HORIZONTAL );
							keyCode = ci;
							if ( ( keyCode = 'X' ) or ( keyCode = 'x' ) or
								( keyCode = 'Q' ) or ( keyCode = 'q' ) ) then
							do;
								returnCode = 1;
							end;

						end;	/* are we to quit reporting? */
					end pageReportingBlock;
				end;	/*	are we pageReporting? */
			end;	/*	if there is a file to report */
		end reportBlock;
	end;	/*	while returnCode is zero	*/

	call findClose( @findDataRecord );

	call summaryReport;

	return ( returnCode );
end reportFiles;

/*
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *	Name:	main()
 *
 *	Description:
 *		Program Entry Point
 *
 *	Returns:
 *		integer exit code
 * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 */

main:
procedure ( numArgs, argStrPtrs, envPtr ) integer public;
	declare	numArgs					word,
			argStrPtrs				pointer,
			argStrs		based	argStrPtrs	(*)	pointer,
			envPtr					pointer;

	declare	returnCode				integer;

	returnCode = 0;

	/*
	 *	we want to get all directories in the specified directory
	 */

	directory = True;

	call greetUser( argStrs( 0 ), @programVersion, @copyrightString );

	/*
	 *	in C or C++, these definitions may be done in a const statement, but
	 *	in PL/M-86 data statements, there are restrictions
	 */

	commandOptionDef.numberOptions = signed( length( argDefinitions ) );
	commandOptionDef.commandOptions = @argDefinitions;
	commandOptionDef.delimiterChar = '-';
	returnCode = getCmdOptions( signed( numArgs ), argStrPtrs, @commandOptionDef );

	if ( returnCode = 0 ) then
	do;
		if ( help ) then
		do;
			call reportCmdOptions( argStrs( 0 ), @commandOptionDef );
		end;
		else
		do;
$if LOGGING
			if ( verbose ) then
			do;
				declare	logFileName	( 260 )	char;

				call strcpy( @logFileName, argStrs( 0 ) );
				call changeExtension( @logFileName, @( 'log', 0 ) );
				call openLogFile( @logFileName );
				call changeLogLevel( DEBUG );
			end;
$endif
			returnCode = reportFiles;
		end;
	end;

	return ( returnCode );
end main;

end listFilesModule;