Options.java
/*
** Module : Options.java
** Abstract : contains all the Progress preprocessor options
**
** Copyright (c) 2004-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------------------Description-----------------------------
** 001 NVS 20041110 @18761 Created. Initial implementation.
** 002 NVS 20041221 @19046 Added support for -lexonly option: lexonly member and setLexonly
** and isLexonly methods to the Options class.
** 003 NVS 20050511 @21150 Added support for -hints and -marker options.
** 004 GES 20070403 @32711 Added support for forcing UNIX escape sequence processing. Major
** code formatting, cleanup and docs improvement.
** 005 GES 20070816 @34886 Added support for external control over the built-in variables
** BATCH-MODE, OPSYS and WINDOW-SYSTEM.
** 006 GES 20080308 @37650 Changed the default pushback depth to 8192.
** 007 ECF 20101001 Added case sensitive include file name flag. Defaults to true.
** 008 GES 20110623 Added basepath and fallback list processing.
** 009 CA 20180321 Added support for PROCESS-ARCHITECTURE preprocessor var.
** 010 ECF 20190619 Added include file reference prefix remapping option.
** GES 20191010 Added variant of PROCESS-ARCHITECTURE() function for expression
** evaluation.
** 011 SV 20250408 Add a default option to propath so no NPE occur. ref 6859
*/
/*
** 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.preproc;
import java.io.File;
import java.util.*;
import com.goldencode.p2j.util.*;
/**
* Represents all the Progress preprocessor options. An object of this class
* has to be instantiated and configured before the preprocessor can be
* launched. Changing its configuration afterwards has no effect on the
* running instance of the preprocessor.
* <p>
* @author NVS
*/
public class Options
{
/** Array of paths in which Progress source files are to be found. */
private String[] proPath = {"."};
/** Pushback buffer depth option. Defaults to 8192. */
private int pushbackDepth = 8192;
/** Controls how escape sequences are emitted on output. */
private boolean keepTildes = false;
/** Flag to control the honoring of backslash as an escape sequence. */
private boolean unixEscapes = true;
/** File separator string */
private String fileSeparator = File.separator;
/** Path separator string */
private String pathSeparator = File.pathSeparator;
/** Generate debug output option. */
private boolean debug = false;
/** Only the lexer should run, no full preprocessing. */
private boolean lexonly = false;
/** Marker character option. */
private char marker = '\001';
/** Hints file name option. */
private String hintsFile = null;
/** Treat include file names case sensitively -- defaults to true */
private boolean caseSensitive = true;
/** BATCH-MODE preprocessor built-in variable value. */
private boolean batchMode = false;
/** OPSYS preprocessor built-in variable value. */
private String opsys = null;
/** WINDOW-SYSTEM preprocessor built-in variable value. */
private String windowSystem = "TTY";
/** Defines the top-level directory for source code in the project. */
private String basepath = ".";
/** Fallpath list of files to search when an include file can't be found. */
private String[] fallback = null;
/** PROCESS-ARCHITECTURE preprocessor built-in variable value. */
private int processArchitecture = 32;
/** Include file path prefix remappings */
private Map<String, String> includeFilePrefixMap = null;
/**
* Default constructor.
*/
public Options()
{
}
/**
* Copy constructor. Makes an independent copy based on the given
* instance.
*
* @param other
* Instance from which to copy.
*/
public Options(Options other)
{
this.proPath = other.proPath;
this.pushbackDepth = other.pushbackDepth;
this.keepTildes = other.keepTildes;
this.unixEscapes = other.unixEscapes;
this.debug = other.debug;
this.lexonly = other.lexonly;
this.marker = other.marker;
this.hintsFile = other.hintsFile;
this.batchMode = other.batchMode;
this.opsys = other.opsys;
this.windowSystem = other.windowSystem;
this.basepath = other.basepath;
this.fallback = other.fallback;
this.processArchitecture = other.processArchitecture;
}
/**
* Sets the list of paths searched for Progress source files. Corresponds
* to the <code>'-propath ...'</code> command line parameter. Plays the
* role of the PROPATH environment variable.
*
* @param proPath
* The list of paths.
*/
public void setProPath(String[] proPath)
{
this.proPath = proPath;
}
/**
* Gets the list of paths searched for Progress source files. Corresponds
* to the <code>'-propath ...'</code> command line parameter. Plays the
* role of the PROPATH environment variable.
*
* @return The list of paths.
*/
public String[] getProPath()
{
return proPath;
}
/**
* Sets the top-level directory for Progress source files in the project.
*
* @param basepath
* The new top-level directory.
*/
public void setBasepath(String basepath)
{
this.basepath = basepath;
}
/**
* Gets the top-level directory for Progress source files in the project.
*
* @return The top-level directory.
*/
public String getBasepath()
{
return basepath;
}
/**
* Gets the list of all files in the top-level directory for Progress source
* files in the project. This list is created the first time this method
* is called and then the result is cached. The <code>basepath</code> is
* used as the top-level directory specification. The search is done
* recursively down the tree.
* <p>
* If case-sensitivity is disabled, then all names in this list will have
* been forced to lowercase to make it faster to compare. Just make sure
* the comparison string is also lowercased!
*
* @return The list of all files in top-level directory tree.
*/
public synchronized String[] getFallbackList()
{
if (fallback == null)
{
File dir = new File(getBasepath());
boolean cs = isCaseSensitive();
FileSpecList fsl = new FileSpecList(dir, "*", true, cs);
fallback = fsl.listFilenames();
if (!cs)
{
// the sorting was done case-insensitively, but the names are
// still case-sensitive; make them case-neutral
for (int i = 0; i < fallback.length; i++)
{
fallback[i] = fallback[i].toLowerCase();
}
}
}
return fallback;
}
/**
* Sets the pushback depth. Corresponds to the <code>'-pushback nnn'</code>
* command line parameter. Determines the size of the pushback buffer used
* to preprocess braces <code>{...}</code> constructs. In the rare case
* one sees an error message stating there was a pushback buffer overflow,
* increasing this value would help.
*
* @param pushbackDepth
* The new value for the pushback buffer depth in bytes.
*/
public void setPushbackDepth(int pushbackDepth)
{
this.pushbackDepth = pushbackDepth;
}
/**
* Gets the pushback depth. Corresponds to the <code>'-pushback nnn'</code>
* command line parameter. Determines the size of the pushback buffer used
* to preprocess braces <code>{...}</code> constructs. In the rare case
* one sees an error message stating there was a pushback buffer overflow,
* increasing this value would help.
*
* @return The current value for the pushback buffer depth.
*/
public int getPushbackDepth()
{
return pushbackDepth;
}
/**
* Sets the mode for processing escape characters. Changes the way the
* escapes are shown on output. When set to <code>true</code>, escapes are
* kept on output. This duplicates how the Progress preprocessor emits for
* its saved preprocessor output BUT DOES NOT MATCH how the Progress
* preprocessor seems to really work with output that is passed directly
* (in memory) to the compiler.
*
* @param keepTildes
* <code>true</code> if escape characters have to be emitted on
* output.
*/
public void setKeepTildes(boolean keepTildes)
{
this.keepTildes = keepTildes;
}
/**
* Gets the mode for processing escape characters. Changes the way the
* escapes are shown on output. When set to <code>true</code>, escapes are
* kept on output. This duplicates how the Progress preprocessor emits for
* its saved preprocessor output BUT DOES NOT MATCH how the Progress
* preprocessor seems to really work with output that is passed directly
* (in memory) to the compiler.
*
* @return <code>true</code> if escape characters have to be emitted on
* output.
*/
public boolean isKeepTildes()
{
return keepTildes;
}
/**
* Sets the mode for escape sequence processing. Escape processing
* differs depending on where Progress source code is preprocessed. On
* Windows, the backslash is not treated as an escape character, but on
* UNIX the backslash is treated just like tilde. Corresponds to the
* <code>'-unixescapes'</code> command line parameter. Defaults to
* <code>true</code>.
*
* @param unixEscapes
* <code>true</code> if backslash characters are to be treated
* as escape sequences (just like tildes).
*/
public void setUnixEscapes(boolean unixEscapes)
{
this.unixEscapes = unixEscapes;
}
/**
* Gets the mode for escape sequence processing. Escape processing
* differs depending on where Progress source code is preprocessed. On
* Windows, the backslash is not treated as an escape character, but on
* UNIX the backslash is treated just like tilde. Corresponds to the
* <code>'-unixescapes'</code> command line parameter. Defaults to
* <code>true</code>.
*
* @return <code>true</code> if backslash characters are treated as
* escape sequences (just like tildes).
*/
public boolean isUnixEscapes()
{
return unixEscapes;
}
/**
* Sets the legacy file separator defined for the project (which may be
* different from the platform's file separator). Corresponds to the
* <code>'-fileseparator'</code> command line parameter. Defaults to the
* current platform's file separator.
*
* @param fileSeparator
* Project-specific file separator.
*/
public void setFileSeparator(String fileSeparator)
{
this.fileSeparator = fileSeparator;
}
/**
* Gets the legacy file separator defined for the project (which may be
* different from the platform's file separator). Corresponds to the
* <code>'-fileseparator'</code> command line parameter. Defaults to the
* current platform's file separator.
*
* @return Project-specific file separator.
*/
public String getFileSeparator()
{
return fileSeparator;
}
/**
* Sets the legacy path separator defined for the project (which may be
* different from the platform's path separator). Corresponds to the
* <code>'-pathseparator'</code> command line parameter. Defaults to the
* current platform's path separator.
*
* @param pathSeparator
* Project-specific path separator.
*/
public void setPathSeparator(String pathSeparator)
{
this.pathSeparator = pathSeparator;
}
/**
* Gets the legacy path separator defined for the project (which may be
* different from the platform's path separator). Corresponds to the
* <code>'-pathseparator'</code> command line parameter. Defaults to the
* current platform's path separator.
*
* @return Project-specific path separator.
*/
public String getPathSeparator()
{
return pathSeparator;
}
/**
* Sets the debug option. Corresponds to the <code>'-debug'</code>
* command line parameter.
*
* @param debug
* <code>true</code> if debug output is required.
*/
public void setDebug(boolean debug)
{
this.debug = debug;
}
/**
* Gets the debug option. Corresponds to the <code>'-debug'</code>
* command line parameter.
*
* @return <code>true</code> if debug output is required.
*/
public boolean isDebug()
{
return debug;
}
/**
* Sets the run lexer only option. Corresponds to the
* <code>'-lexonly'</code> command line parameter.
*
* @param lexonly
* <code>true</code> if lexer only mode required.
*/
public void setLexonly(boolean lexonly)
{
this.lexonly = lexonly;
}
/**
* Gets the run lexer only option. Corresponds to the
* <code>'-lexonly'</code> command line parameter.
*
* @return <code>true</code> if lexer only mode is in effect.
*/
public boolean isLexonly()
{
return lexonly;
}
/**
* Sets the marker character. Corresponds to the <code>'-marker n'</code>
* command line parameter.
*
* @param c
* The new marker character.
*/
public void setMarker(char c)
{
marker = c;
}
/**
* Gets the marker character. Corresponds to the <code>'-marker n'</code>
* command line parameter.
*
* @return The marker character in use.
*/
public char getMarker()
{
return marker;
}
/**
* Sets the hints file name. Corresponds to the
* <code>'-hints filename'</code> command line parameter.
*
* @param hints
* The new hints file name.
*/
public void setHintsFile(String hints)
{
hintsFile = hints;
}
/**
* Gets the hints file name. Corresponds to the
* <code>'-hints filename'</code> command line parameter.
*
* @return The hints file name.
*/
public String getHintsFile()
{
return hintsFile;
}
/**
* Sets the batch mode state. Corresponds to the <code>'-batch'</code>
* command line parameter.
*
* @param batchMode
* <code>true</code> to set batch mode on.
*/
public void setBatchMode(boolean batchMode)
{
this.batchMode = batchMode;
}
/**
* Gets the batch mode state. Corresponds to the <code>'-batch'</code>
* command line parameter.
*
* @return <code>true</code> if batch mode is on.
*/
public boolean isBatchMode()
{
return batchMode;
}
/**
* Sets the case sensitive include file name flag. Corresponds to the
* <code>'-casesensitive'</code> command line parameter.
*
* @param caseSensitive
* <code>true</code> to treat include file names case sensitively;
* else <code>false</code>
*/
public void setCaseSensitive(boolean caseSensitive)
{
this.caseSensitive = caseSensitive;
}
/**
* Gets the case sensitive include file name state. Corresponds to the
* <code>'-casesensitive'</code> command line parameter.
*
* @return <code>true</code> if include file names should be treated as
* case-sensitive, else <code>false</code>.
*/
public boolean isCaseSensitive()
{
return caseSensitive;
}
/**
* Sets the operating system name. Corresponds to the
* <code>'-opsys name'</code> command line parameter.
*
* @param opsys
* The new operating system name.
*/
public void setOpsys(String opsys)
{
this.opsys = opsys;
}
/**
* Gets the operating system name. Corresponds to the
* <code>'-opsys name'</code> command line parameter.
*
* @return The operating system name.
*/
public String getOpsys()
{
if (opsys == null)
opsys = EnvironmentOps.getOperatingSystem().toStringMessage();
return opsys;
}
/**
* Sets the window system name. Corresponds to the
* <code>'-winsys name'</code> command line parameter.
*
* @param windowSystem
* The new window system name.
*/
public void setWindowSystem(String windowSystem)
{
this.windowSystem = windowSystem;
}
/**
* Gets the window system name. Corresponds to the
* <code>'-winsys name'</code> command line parameter.
*
* @return The window system name.
*/
public String getWindowSystem()
{
return windowSystem;
}
/**
* Set the process architecture. Corresponds to the '-arch {32|64}' command line parameter.
*
* @param processArchitecture
* The process architecture bitness.
*/
public void setProcessArchitecture(int processArchitecture)
{
if (!(processArchitecture == 32 || processArchitecture == 64))
{
throw new IllegalArgumentException("The process architecture must be 32 or 64.");
}
this.processArchitecture = processArchitecture;
}
/**
* Get the process architecture. Corresponds to the '-arch {32|64}' command line parameter.
*
* @return The process architecture bitness.
*/
public int getProcessArchitecture()
{
return processArchitecture;
}
/**
* Get the process architecture. Corresponds to the '-arch {32|64}' command line parameter.
*
* @return The process architecture bitness.
*/
public integer getProcessArchitectureBDT()
{
return new integer(processArchitecture);
}
/**
* Get the custom mappings of include file prefixes to the values with which they should be
* replaced.
*
* @return Include file prefix re-mappings.
*/
public Map<String, String> getIncludeFilePrefixMap()
{
return includeFilePrefixMap;
}
/**
* Set the custom mappings of include file prefixes to the values with which they should be
* replaced.
*
* @param includeFilePrefixMap
* Include file prefix re-mappings.
*/
public void setIncludeFilePrefixMap(Map<String, String> includeFilePrefixMap)
{
this.includeFilePrefixMap = includeFilePrefixMap;
}
}