ProgressTransformDriver.java
/*
** Module : ProgressTransformDriver.java
** Abstract : runs the Progress 4GL to Progress 4GL transformation for a file or set of files
**
** Copyright (c) 2018-2021, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------------Description---------------------------------------
** 001 GES 20181023 First version.
** 002 ECF 20190221 Added blacklist (filespec + ignore list) mode.
** 003 CA 20200412 Added incremental conversion support.
** OM 20210923 Added -P<name> command line option for specifying the configuration profile.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** 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. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.convert;
import java.io.*;
import java.util.*;
import com.goldencode.ast.*;
import com.goldencode.p2j.cfg.*;
import com.goldencode.p2j.schema.*;
/**
* Provides a harness to drive the Progress 4GL to Progress 4GL transformation for a file or set
* of files.
* <p>
* This program provides a command line interface. See {@link #main} for the syntax.
*/
public class ProgressTransformDriver
extends TransformDriver
{
/** Associates mode names with detailed mode definitions. */
private static final Map<String, RunMode> modes = new HashMap<>();
/** Job title, which needs to be implemented in each subclass. */
private static final String TITLE = "Progress 4GL Transformation Driver";
/** Help text, which needs to be implemented in each subclass. */
private static final String[] helpText = new String[]
{
"--------------------" + TITLE + "--------------------",
"",
"Syntax:",
" java -DP2J_HOME=<home> ProgressTransformDriver [options]* <mode> [user_defined_rule_set] <file-specs>",
"",
"Where",
" Options (F, S, and X are mutually exclusive. If none is specified <file-specs>",
" is a list of files added to command line):",
" Dn = set DEBUG level 'n'. Must be a numeric digit between " + MSG_NONE + " (none)",
" and " + MSG_TRACE + " (trace) inclusive",
" F = <file-specs> is a <filename> containing a custom FILE-LIST",
" S = <file-specs> is composed of a root <directory> and \"<file-filter>\"",
" to select SPECIFIC files",
" X = <file-specs> is similar to S but has an additional custom EXCLUDE",
" list file \"<filename>\" to be ignored",
" N = NO recursion in <file-filter> (S/X options)",
" A = ABORT scan part of front end on an error",
" Tn = specify number of THREADS 'n' to use for front end file scan ('n'",
" must be >= 0; defaults to 1; set to 0 to use 1 thread per",
" available CPU)",
" L = LIST files to be processed only; do not perform any further task",
" I = INCREMENTAL conversion; only changed/new programs will be parsed",
" and converted",
" Pname = the <name> of the configuration PROFILE follows the option",
"",
" Mode (one or more of the following values, use '+' to delimit if there are two",
" or more values; don't insert spaces!)",
" -------------------------------- Front End --------------------------------",
" F0 = preprocessor (in honor cache mode), lexer, parser, AST persistence and",
" post-parse fixups",
" F1 = F0 + forced preprocessor execution",
" F2 = F1 + schema loader/fixups",
" F3 = F2 + call graph generation",
"",
" ----------------------------- Transformation ------------------------------",
" TR = execute a user-defined transformation ruleset (this requires the",
" user-defined rule-set to be added)",
"",
" ------------------------------ Anti-Parsing -------------------------------",
" AP = output ASTs to Progress 4GL source code",
"",
" user_defined_rule_set (only possible in TR mode)",
"",
" filelist = arbitrary list of absolute and/or relative file names to scan",
" (default approach)",
" directory = a relative or absolute path (only used when using <file-filter>,",
" S/X options)",
" file-filter= file filter specification of the filenames in the given directory",
" to scan, should be enclosed in double quotes if any of the",
" wildcard characters '*' or '?' are used (only used with S/X",
" modes)",
" filename = when used with the -F option, this is a single absolute or",
" relative name of a text file that contains a custom list of",
" absolute and/or relative file names of files to scan (i.e. the",
" file list will be read from a file instead of being hard coded",
" on the command line); there must be one file name per line in",
" the file;",
" when used with the -X option, this is a single absolute or",
" relative name of a text file that contains a custom list of",
" specifications of file names to ignore; all other files",
" specified by the primary <file-filter> are scanned.",
};
static
{
modes.put("F0", new RunMode(true , false, false, false, false, false));
modes.put("F1", new RunMode(true , true , false, false, false, false));
modes.put("F2", new RunMode(true , true , true , false, false, false));
modes.put("F3", new RunMode(true , true , true , true , false, false));
modes.put("TR", new RunMode(false, false, false, false, true , false));
modes.put("AP", new RunMode(false, false, false, false, false, true));
}
/**
* Creates an instance with a specific configuration.
*
* @param job
* The details of this driver run.
*/
ProgressTransformDriver(JobDefinition job)
{
super(job);
}
/**
* Drive the transformation process using the file list of Progress ASTs that is already
* defined in this instance. The user must have provided a TRPL rule-set to execute,
* otherwise this phase will be a NOP.
*/
protected void middle()
throws ConfigurationException,
AstException,
SchemaException,
IOException
{
if (job.transform == null || job.transform.isEmpty())
{
return;
}
// ensure that downstream processing has the proper list of files
convertSourceNamesToAstNames();
processTrees("User-Defined Transformation",
job.transform,
null,
false,
asts,
debug);
}
/**
* Drive the back end of the transformation process using the file list of Progress ASTs
* that is already defined in this instance. Each AST will be anti-parsed back to
* Progress 4GL source code.
*/
protected void back()
throws ConfigurationException,
AstException,
SchemaException,
IOException
{
// ensure that downstream processing has the proper list of files
convertSourceNamesToAstNames();
processTrees("Anti-Parsing",
"progress/anti_parser",
null,
false,
asts,
debug);
}
/**
* Provides a command line interface for an end user to drive the scanning harness.
* <p>
* The program will return a non-zero code if there is a fatal error running the conversion.
* <p>
* Syntax:
* <pre>{@code java -DP2J_HOME=<home> ProgressTransformDriver [-options]* <mode> [user_defined_rule_set] <file-specs>}</pre>
* Where:
* <ul>
* <li>Options (F, S, and X are mutually exclusive. If none is specified <file-specs> is a list of files
* added to command line):
* <ul>
* <li>Dn = set debug level 'n' (must be a numeric digit between {@code MSG_NONE} (0) and
* {@code MSG_TRACE} (3) inclusive
* <li>I = incremental conversion; only changed/new programs will be parsed and converted.
* <li>F = {@code <file-specs>} is a {@code <filename>} containing a custom FILE-LIST, instead of
* using the explicit command line file list
* <li>S = {@code <file-specs>} is composed of a root {@code <directory>} and a {@code
* "<file-filter>"}, to select SPECIFIC files instead of an explicit command line file list
* <li>X = {@code <file-specs>} is similar to S but has an additional custom EXCLUDE list file
* {@code "<filename>"} to be ignored
* <li>N = NO recursion in {@code <file-filter>} (S/X options)",
* <li>A = ABORT scan part of front end on an error
* <li>Tn = specify number of THREADS 'n' to use for front end file scan ('n' must be {@code >=}
* 0; defaults to 1; set to 0 to use 1 thread per available CPU)
* <li>L = LIST files to be processed only; do not perform any further task
* <li>Pname = the {@code <name>} of the configuration PROFILE follows the option
* </ul>
* <li>{@code mode} (one or more of the following values, use '+' to delimit if there are two or more
* values; don't insert spaces!)
* <ul>
* <li>Front End
* <ul>
* <li>F0 = preprocessor (in honor cache mode), lexer, parser, AST persistence and
* post-parse fixups
* <li>F1 = F0 + forced preprocessor execution
* <li>F2 = F1 + schema loader/fixups
* <li>F3 = F2 + call graph generation
* </ul>
* <li>Transformation
* <ul>
* <li>TR = execute a user-defined transformation ruleset (this requires an extra parameter
* after the mode and before the source file specifications)
* </ul>
* <li>Anti-Parsing
* <ul>
* <li>AP = output ASTs to Progress 4GL source code
* </ul>
* </ul>
* <li>The optional {@code user_defined_rule_set} specifies the user-defined rule-set filename to execute
* (only some modes support this, see sub-class documentation for details)
* <li>explicit command line list (default approach if none of S, P, or F are present)
* <ul>
* <li>{@code <filelist>} is arbitrary list of absolute and/or relative file names to scan, this
* list is hard coded in the command line itself
* <li>any number of files may be listed on the command line, subject to command shell limits
* </ul>
* <li>custom file list (FILE approach)
* <ul>
* <li>{@code <filename>} is a single absolute or relative filename of a text file that contains a
* custom list of absolute and/or relative file names of files to scan
* <li>in other words, the file list will be read from a file instead of being hard coded on the
* command line
* <li>there must be one filename per line in the file
* <li>there is no limit of the number of files in the list
* </ul>
* <li>file-spec mode (expressly SPECIFIED files approach)
* <ul>
* <li>{@code <directory>} is the root directory to search for files
* <li>{@code "filespec"} is the file specification that will be used to create a list of files to
* process, should be enclosed in double quotes if any of the wildcard characters '*' or '?'
* are used
* </ul>
* <li>custom ignore list (file-spec mode with additional EXCLUDE list)
* <ul>
* <li>{@code <directory>} is the root directory to search for files
* <li>{@code "filespec"}" is the file specification that will be used to create a list of files
* to process, should be enclosed in double quotes if any of the wildcard characters '*' or
* '?' are used
* <li>{@code <filename>} is a single absolute or relative filename of a text file that contains a
* custom list of specifications of file names to ignore
* <li>asterisk (*) and question mark (?) wildcards are permitted to represent zero or more and
* exactly one wildcard characters, respectively
* <li>files specified by the primary {@code filespec} which are not matched by the ignore list
* are scanned as they would be in {@code filespec} mode.
* </ul>
* </ul>
*
* @param args
* List of command line arguments.
*/
public static void main(String[] args)
{
JobDefinition job = processCommandLine(args, modes, helpText);
if (job != null)
{
ProgressTransformDriver driver = new ProgressTransformDriver(job);
driver.executeJob(TITLE);
}
}
}