/*
 * A hack to make building other programs easier, by extracting the
 * commands needed to build the file from it's source.
 *
 *	build [name NAME] [flags COMMAND=FLAGS ...] [file] FILE [FILE ...] 
 *
 * Name defaults to "build". Flags causes the following arguments to be parsed
 * for extra flags to be added to each COMMAND. All input FILEs are scanned
 * for build lines to be issued to the system. If flags is present, file is
 * required.
 *
 * In scanning a file, build ignores all lines until it sees a line containing
 * the string "===NAME", for whatever value name has, defaulting to build. All
 * lines following are then processed until a line containing "===endNAME" is
 * encountered. Delimiter and control are set by parsing the line ===NAME line
 * as '===NAME delimiter DELIMITER control CONTROL'
 *
 * In processing the build lines, two tokens have special significance. They
 * are called delimiter and control, and are normally '%' and ';'. The line is
 * first split on the control character, into the front and back halves. If
 * there is a delimiter in the front half, any text preceding it is discarded.
 * If there is a delimiter in the back half, any text following it is discarded.
 *
 * The front half is treated as a command to be issued to the system. If the
 * first word of the front half is matched by a the command part of a flags
 * argument, then the flags part of that argument is inserted into the command
 * after the first word. I.e. the command issued is "command FLAGS rest of line".
 * The back half of the command is then checked, and the above comamnd is issued
 * if it is called for.
 *
 * The back half is assumed to be of the form 'output= FILE input= FILE ...'.
 * If any of the input files are newer than the output file, then the command
 * in the front half will be executed.  If either input or output keywords are
 * missing, the command is always issued.
 *
 * As a convenience, if the back half of a line is empty, then it will be
 * executed if the previous command was executed.
 */

/* Get the support code */
if ~show('Libraries', 'rexxsupport.library') then do
	if ~addlib('rexxsupport.library', 0, -30) then do
		say "Can't open rexxsupport.library!"
		exit
		end
	end

flags. = ''
flags = 0
name = 'build'
files = ''

/* Parse them arguments */
args = arg(1)
do i = 1 to words(args)
	select
		when upper(word(args, i)) = 'NAME' then do
			flags = 0
			i = i + 1
			name = word(args, i)
			end
		when upper(word(args, i)) = 'FILE' then do
			flags = 0
			i = i + 1
			files = word(args, i)
			end
		when upper(word(args, i)) = 'FLAGS' then flags = 1
		when flags then do
			parse value word(args, i) with command '=' flag
			if flag = '' then
				flags.currentcommand = flags.currentcommand word(args, i)
			else do
				currentcommand = command
				flags.command = flag
				end
			end
		otherwise files = files word(args, i)
		end
	end

/*
 * loop over the file names.
 */
files = expand(files)
do i = 1 to words(files)
	call buildfile(word(files, i), name)
	end

exit 0

/*
 * Scan a file, looking for the build instructions.
 */
buildfile: procedure expose flags.
	parse arg file, name

	delim = '%'
	control = ';'

	if ~open(input, file) then do
		say "Can't open file" file
		return 10
		end

	/* Search for the section with command in it */
	search = '==='upper(name)
	do until index(upper(line), search) ~= 0
		if eof(input) then do
			say "No actions found for" name "in file" file
			return 5
			end
		line = readln(input)
		end

	/* Check for control/delimter settings */
	parse var line 'control' new .
	if new ~= '' then control = new
	parse var line 'delimiter' new .
	if new ~= '' then delimiter = new

	/* Process the command lines */
	search = '===END'upper(name)
	line = readln(input)
	do while index(upper(line), search) = 0
		parse var line command (control) files

		/* Check files section */
		parse var files files (delim)
		parse var files "output=" outfile "input=" infiles
		if outfile = "" | infiles = "" then docommand = 1
		else do
			instamp = makestamp(strip(outfile))
			docommand = 0
			do i = 1 to words(infiles)
				if instamp < makestamp(word(infiles, i)) then do
					docommand = 1
					leave
					end
				end
			end

		/* Build command to execute */ 
		parse var command (delim) new flags
		if new ~= "" then command = new
		else parse var command command flags
		if command ~= "" & docommand then do
			say command flags
			address command command flags.command flags
			if rc ~= 0 then exit rc
			end
		line = readln(input)

		if eof(input) then do
			say "No end to build section"
			exit 10
			end
		end

	call close input
	return 0

/* Get a files creation date as a numeric string */
makestamp: procedure
	arg filename

	parse value statef(filename) with . . . . d m t .
	return right(d, 4, 0) || right(m, 4, 0) || right(t, 4, 0)
