BuiltinVariable.java
/*
** Module : BuiltinVariable.java
** Abstract : the pool of Progress preprocessor built-in variables
**
** Copyright (c) 2004-2023, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------------------Description------------------------------
** 001 NVS 20041124 @18757 Created. Initial implementation of the class.
** 002 GES 20070320 @32502 Changed OPSYS implementation to use the standard runtime support
** instead of a hard coded value. Added support for the 4 webspeed
** related built-in variables.
** 003 GES 20070717 @34575 Many code formatting cleanups. Additions to treat the webspeed vars
** as redefinable.
** 004 GES 20070816 @34885 Complete rewrite to simplify the implementation. Added complete
** webspeed support. Fixed sequence support so that it resets to 0 for
** each top-level file. Added complete support for all builtins which
** previously were hard coded to values for expediency. Now the built-in
** support is 100% complete through the 10.1B level.
** 005 ECF 20070912 @35050 Made definition of webspeed definitions configurable. These are only
** defined if the configuration parameter 'ws-preproc-syms' is set to
** 'true'.
** 006 CA 20140320 Fixed the FILE-NAME variable: this will be replaced with the
** base-path relative name of the file in which FILE-NAME was used.
** 007 OM 20150508 Increment &SEQUENCE only if env.isExpandBraces().
** 008 EVL 20160223 Javadoc fixes to make compatible with Oracle Java 8 for Solaris 10.
** 009 GES 20180105 Added an implicit globally defined symbol (that can be redefined by
** 4GL code if it conflicts with their usage) that allows the detection
** of FWD and the FWD version from 4GL code. This will make it easy for
** conditional preprocessing to allow inclusion of FWD-specific 4GL
** code.
** 010 CA 20180321 Added support for PROCESS-ARCHITECTURE preprocessor var.
** 011 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
*/
/*
** 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 com.goldencode.p2j.*;
import com.goldencode.p2j.cfg.*;
import com.goldencode.p2j.convert.*;
import com.goldencode.p2j.util.*;
import java.io.*;
import java.util.logging.*;
/**
* Represents the pool of Progress preprocessor builtin variables.
* A preprocessor implementation needs an instance of this class.
* The class provides methods for identifying the builtin variables
* by name and producing corresponding strings as their values.
* <p>
* As the builtin variables can be overridden using include file
* references, the scoping of their names is as important as of any
* other variable name. For this reason, all builtin variables are
* put into the global scope of a dictionary specified as a parameter
* when constructing objects of this class.
* <p>
* Producing values for some of the variables requires access to
* some information maintained by the preprocessor on a per file
* basis. This access is done through a reference to the Environment
* object.
* <p>
* Supported Progress 4GL built-in variables:
* <p>
* <pre>
* BATCH-MODE
* FILE-NAME
* LINE-NUMBER
* OPSYS
* PROCESS-ARCHITECTURE
* SEQUENCE
* WINDOW-SYSTEM
* </pre>
* <p>
* Supported WebSpeed global defines:
* <p>
* <pre>
* WEBSTREAM
* OUT
* OUT-FILE
* OUT-STREAM
* OUT-FMT
* OUT-LONG
* DISPLAY
* END
* AMP
* LT
* GT
* QUOT
* </pre>
* <p>
* WARNING: the web-speed built-in variables are not really preprocessor
* built-ins in Progress. In particular, they can be re-defined as symbols
* when the others cannot. Although the Progress documentation calls them
* built-in, it these are actually implemented in include files rather than
* in the preprocessor/runtime. We place these implementations here as a
* default, but allow any webspeed or webspeed clone code to naturally
* override these definitions when it is preprocessed.
* <p>
* Supported FWD-specific global defines:
* <p>
* <pre>
* FWD-VERSION (this will have a value defined by {@link Version#getFWDVersion})
* </pre>
* <p>
* The FWD-specific symbols are always implicitly there but they are designed to be overridden
* if needed (they are deliberately registered as a global define).
*/
public class BuiltinVariable
{
/** SpeedScript (embedded 4GL) &WEBSTREAM definition. */
private static final String WEBSTREAM = "STREAM WebStream";
/** SpeedScript (embedded 4GL) &OUT-FMT definition. */
private static final String OUT_FMT = "PUT " + WEBSTREAM;
/** SpeedScript (embedded 4GL) &OUT definition. */
private static final String OUT = OUT_FMT + " UNFORMATTED";
/** SpeedScript (embedded 4GL) &OUT-LONG definition. */
private static final String OUT_LONG = "EXPORT " + WEBSTREAM;
/** SpeedScript (embedded 4GL) &DISPLAY definition. */
private static final String DISPLAY = "DISPLAY " + WEBSTREAM;
/** SpeedScript (embedded 4GL) &END definition. */
private static final String END = ".";
/** SpeedScript (embedded 4GL) &AMP definition. */
private static final String AMP = "&~;";
/** SpeedScript (embedded 4GL) &LT definition. */
private static final String LT = "<~;";
/** SpeedScript (embedded 4GL) &GT definition. */
private static final String GT = ">~;";
/** SpeedScript (embedded 4GL) &QUOT definition. */
private static final String QUOT = ""~;";
/** FWD-VERSION global define value. */
private static final String FWD_VERSION_VALUE = Version.getFWDVersion();
/** Logger */
private static final ConversionStatus LOG = ConversionStatus.get(BuiltinVariable.class);
/**
* Adds all WebSpeed and 4GL built-in variables to the global scope of the
* given dictionary with the <code>Symbol.GLOBAL</code> or
* <code>Symbol.BUILTIN</code> as the origin respectively.
*
* @param sym
* Dictionary where the names of all the variables are added.
*/
public static void init(ScopedSymbolDictionary sym)
{
// add the webspeed definitions, since they aren't marked as builtin
// they can be redefined in user code, but only if webspeed preproc
// symbols are enabled in the configuration
if ("true".equals(Configuration.getParameter("ws-preproc-syms")))
{
sym.addSymbol(true, "webstream", new Symbol(Symbol.GLOBAL, WEBSTREAM));
sym.addSymbol(true, "out", new Symbol(Symbol.GLOBAL, OUT));
sym.addSymbol(true, "out-file", new Symbol(Symbol.GLOBAL, OUT));
sym.addSymbol(true, "out-stream", new Symbol(Symbol.GLOBAL, OUT));
sym.addSymbol(true, "out-fmt", new Symbol(Symbol.GLOBAL, OUT_FMT));
sym.addSymbol(true, "out-long", new Symbol(Symbol.GLOBAL, OUT_LONG));
sym.addSymbol(true, "display", new Symbol(Symbol.GLOBAL, DISPLAY));
sym.addSymbol(true, "end", new Symbol(Symbol.GLOBAL, END));
sym.addSymbol(true, "amp", new Symbol(Symbol.GLOBAL, AMP));
sym.addSymbol(true, "lt", new Symbol(Symbol.GLOBAL, LT));
sym.addSymbol(true, "gt", new Symbol(Symbol.GLOBAL, GT));
sym.addSymbol(true, "quot", new Symbol(Symbol.GLOBAL, QUOT));
}
// add FWD-specific global defines (always implicitly there, can be overridden)
sym.addSymbol(true, "fwd-version", new Symbol(Symbol.GLOBAL, FWD_VERSION_VALUE));
// add the real built-ins
sym.addSymbol(true, "batch-mode" , new BatchMode() );
sym.addSymbol(true, "file-name" , new FileName() );
sym.addSymbol(true, "line-number" , new LineNumber() );
sym.addSymbol(true, "opsys" , new Opsys() );
sym.addSymbol(true, "sequence" , new Sequence() );
sym.addSymbol(true, "window-system" , new WindowSystem());
sym.addSymbol(true, "process-architecture", new ProcessArchitecture());
}
/**
* Produces the BATCH-MODE value.
*/
private static class BatchMode
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The symbol's value.
*/
public String getValue(Environment env)
{
return env.getOpt().isBatchMode() ? "yes" : "no";
}
}
/**
* Produces the FILE-NAME value.
*/
private static class FileName
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The current file name as specified in command line or
* include file reference.
*/
public String getValue(Environment env)
{
ScopedSymbolDictionary sym = env.getSym();
FileScope fs = (FileScope) sym.getScope();
String normalized = null;
String base = env.getOpt().getBasepath();
try
{
// take the base-path relative part of the filename.
normalized = Configuration.normalizeFilename(fs.getFile().getCanonicalPath());
normalized = normalized.substring(base.length());
if (normalized.startsWith(File.separator))
{
normalized = normalized.substring(1);
}
}
catch (IOException e)
{
env.eprint("Exception caught in &{FILE_NAME} builtin variable",
env.getLex().getLine(),
env.getLex().getColumn());
LOG.log(Level.INFO, "", e);
normalized = fs.getFileName();
}
return normalized;
}
}
/**
* Produces the LINE-NUMBER value.
*/
private static class LineNumber
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The current line number.
*/
public String getValue(Environment env)
{
return Integer.toString(env.getLex().getLine());
}
}
/**
* Produces the OPSYS value.
*/
private static class Opsys
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The operating system name.
*/
public String getValue(Environment env)
{
return env.getOpt().getOpsys();
}
}
/**
* Produces the SEQUENCE value, incrementing the value each time it is
* referenced. The previous value is returned. The first value returned
* is always 0 and this is reset for each compilation unit (top level
* file from the perspective of the preprocessor).
*/
private static class Sequence
extends BuiltinSymbol
{
/** The current sequence counter. */
private int sequence = 0;
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The current sequence number.
*/
public String getValue(Environment env)
{
return Integer.toString(env.isExpandBraces() ? sequence++ : sequence);
}
}
/**
* Produces the WINDOW-SYSTEM value.
*/
private static class WindowSystem
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The WINDOW-SYSTEM value.
*/
public String getValue(Environment env)
{
return env.getOpt().getWindowSystem();
}
}
/**
* Produces the PROCESS-ARCHITECTURE value.
*/
private static class ProcessArchitecture
extends BuiltinSymbol
{
/**
* Gets the symbol value using the current environment to dynamically
* create the result.
*
* @param env
* The preprocessor's current environment.
*
* @return The PROCESS-ARCHITECTURE value.
*/
public String getValue(Environment env)
{
return Integer.toString(env.getOpt().getProcessArchitecture());
}
}
}