JZtxtcmd

JZtxtcmd

Inhalt


Topic:.JZtxtcmd.


Topic:.JZtxtcmd.


1 Substantiation

Topic:.JZtxtcmd.subst.

Last changed: 2017-0729

JZtxtcmd is a script language with its interpreter. A JZtxtcmd script has capabilities adequate a shell script or batch file but with a well affinity to Java routines and special capability for text generation. A JZtxtcmd script will be interpreted using Java. Only a standard Java Virtual Machine (currently version 8) is necessary to run, like it is usual given on most systems. The ZBNF.jar file contains all byte code of that. Therefore it runs under Windows as well as under Linux, Macintosh and special operation systems which are supported by Java.

Note: Till 2017-03 JZtxtcmd was firmed as JZcmd. It is renamed because it can be used both as Text generator (T) and as command executer (c). The importance as text generator was not shown in the name JZcmd.

In a JZtxtcmd script you can invoke command line statements from your system. You can have local variables which can be filled by results of command line invocations or some more routines. You can have if()...elsif()...else... constructs as well as for(containerelement)... and calling of subroutines which are defined inside the own script or in included scripts.

cmd line ---------------->|<-----Invoke inside a Java application
                          |          |
Another JZtxtcmd script ->|          |  use Java data
                          |          +==>+
                       JZtxtcmd =========+===>cmd line
                          ^              +===>generate text output
                          |              +<== read files
                       Users.JZtxtcmd    +===>write files, especially text generation
                       script            +===>invoke Java routines,
                                              prepare data.

JZtxtcmd has well capabilities to access Java data. You can work with complex container (arrays, lists, trees) as well as access simple fields or invoke methods. A Java application can prepare data in a special and complex kind, and then invoke srcJava_Zbnf/org/vishia/jztxtcmd/JZtxtcmd with a given user script.jztc to generate an output text or execute somewhat with the data.

The output text from JZtxtcmd may be a XML format, a programming language's sources code, csv-Format for MS-Excel table calculation or any other. For XML the approach is similar like Wikipedia:_XSLT. But XSLT deals with XML input data only.


2 Copyright, Copyleft

Topic:.JZtxtcmd.copyleft.

Last changed: 2017-0729

This description and the software, which is described was created from Hartmut Schorrig, Pinzberg, Germany (hartmut.schorrig@vishia.de). Hartmut Schorrig holds the moral rights of this description and the software.

The software can be used with the LPGL license (Lesser General Public License, published by the Free Software Foundation).

Any citation of this text needs the declaration of the owner of the moral right and the source in the internet www.vishia.org/docuZBNF/JZtxtcmd.html.


3 Availability, test and examples

Topic:.JZtxtcmd.testExamp.

Last changed: 2017-0729

To execute a JZtxtcmd-script you need only the Java archive ZBNF-Dowload/.../zbnf.jar and a Java virtual machine currently any version 8.

Some tests and examples are contained in the ZBNF-Download/.../ZBNF.zip This is the whole archive of ZBNF available on http://sf.net/projects/zbnf too.

The capability is tested with the following script contained in ZBNF.zip:

examples_JZtxtcmd/TestAll/testAll.jz.bat.html


4 Capability and general Syntax of a JZtxtcmd script

Topic:.JZtxtcmd.genScript.

The syntax regards of 2 strategies:

The script has a

main(){
  ...statements
}

The main()-Routine can be contained in an included file too. That is proper if a special script contains a special part of the program whereby the main is given as standard in the users orbit.

For text preparation a writing style with

 <:>text<&placeholder><.>

is used. The script doesn't use the "quotation marks" for texts. Instead a text is written in the script directly inclusive all white spaces, line feed etc. See 13 Text output and text generation.

The complete syntax is shown and explained in 16 Syntax of a JZtxtcmd script.

What offers JZtxtcmd:

Command line invocation:

Program structure, control flow, variable:

Java usage:

Text generating capabilities:

Zmake approach:

The combination with Java programs offers the following strategy:

JZtxtcmd is structured but not object-oriented by itself. With usage of Java-objects it is object-oriented.

A JZtxtcmd script is parsed and translated from its textual presentation to an internal tree of execution statements while starting. In the running phase the textual script is not used. The interpreter works with its internal data. Independent of this principle a changing of the source text and re-translate to support debug facilities is planned but not implemented yet.


5 Invocation of a JZtxtcmd script

Topic:.JZtxtcmd.invoke.

A JZtxtcmd script can be started from a command line environment similar to a batch file or shell script, or it can be started from any Java application inside.


5.1 Command line invocation

Topic:.JZtxtcmd.invoke.cmd.

One needs only a standard java upto version 6 and the zbnf.jar file. The last one can be downloaded from ZBNF_on_Sourceforge or from the vishia_Downloadpage.

java -cp path/to/zbnf.jar org.vishia.zcmd.JZtxtcmd scriptfile

To shorten the invocation of JZtxtcmd and to simpify some inclusions, a batch file should be used. That batch file should be invoke-able in the operation system's PATH. Then the invocation of JZtxtcmd will be written only with

jztxtcmd scriptfile

See the template for a batch file for windows: zbnfjax/batch_template/jztxtcmd.bat and linux: zbnfjax/linux_startscript_template/jztxtcmd. This file contains the setting of some environment variable which can be used in JZtxtcmd scripts. It refers paths where other tools are found.

help and JZtxtcmd syntax:

Some more arguments can be given, especially a file path to the standard text output, some arguments for debug, and user arguments. To see a complete argument description, invoke

jztxtcmd --help

The help text is send to the stdout and contain a syntax description in ZBNF format, which is used for parsing.

Text output:

To generate a text output, you can invoke

jztxtcmd JZtxtcmdScript -t:pathTo/file.txt

That file will be written with <+> This text will be generated <.+> inside the script. You can generate for example make files, batch files, xml files etc. etc. controlled by the JZtxtcmdScript.

Another possibilities to control which text files are <+:create>filepath..., FileOpen file =filepath;.

User arguments can be given with the option

-u:anyUserArg

The textual value is stored in script-variables named $1, $2 ... $10 etc. which can be used in the script.

Debug facilities:

With the option

jztxtcmd scriptfile -debug:pathTo/debug.xml

the result of parsing of the script is written in XML format. With them it can be checked how the input was understood from the parser. It may help in complex syntactical situations.

The option

--loglevel:334 --log:pathTo/parserLog.txt

switches on a parser logging. It is only used for the ZBNF parser while parsing the script. Normally it is not necessary. But if sophisticated syntactical errors are given, it may be usefull.

Last but not least you can start the JZtxtcmd for example in a Eclipse environment for debugging. You can set a breakpoint in the Java source lines and activate it with a debug statement, see 15 Debugging possibilities. Then one can see how does it works in Java.


5.2 Start batch file in a MS-Windows and UNIX

Topic:.JZtxtcmd.invoke.jztxtcmd.bat.

It is recommended to store a batch file in the operation system's PATH to invoke JZtxtcmd simple. Such a file jztxtcmd.bat should have the following content, this file is contained in the ZBNF download in zbnfjax/batch_templat/jztxtcmd.bat:

@echo off
REM This is the start batch for JZtxtcmd execution for MS-Windows.
REM It should be copied in a directory which is referenced by the Operation system's PATH
REM and adapt with the paths to Java and the other tools.
REM All what is need to run JZtxtcmd is referenced here.
REM adapt the path to the zbnfjax folder of vishia-ZBNF tools.
REM It contains the jar archive for execution of JZtxtcmd and some JZtxtcmd scripts which may be included.
set ZBNFJAX_HOME=D:/vishia/ZBNF/zbnfjax
REM If necessary adapt the PATH for a special java version. Comment it if the standard Java installation should be used.
REM Note Java does not need an installation. It runs well if it is only present in the file system.
set JAVA_HOME=D:\Programme\JAVA\jre7
set PATH=%JAVA_HOME%\bin;%PATH%
REM adapt the path to the Java-JDK directory. That should contain bin/javac.exe.
REM The JDK is necessary for compilation of java sources. Comment it if not used.
set JAVA_JDK=D:\Programme\JAVA\jdk1.7.0_51
REM adapt the path to the Xml-Tools. See zbnfjax-readme.
REM The XML tools are necessary for some XML operations. This environment variable may be used in some JZtxtcmd scripts.
REM Comment it if not used.
set XML_TOOLS=D:\Programme\XML_Tools
REM This is the invocation of JZtxtcmd, with up to 9 arguments.
java -cp %ZBNFJAX_HOME%/zbnf.jar   org.vishia.zcmd.JZtxtcmd   %1 %2 %3 %4 %5 %6 %7 %8 %9
if errorlevel 1 pause

Up to 9 arguments are given by forwarding from calling level. Usual only 1 or 2 are necessary. A script can be invoked from command line or inside another script by simple writing:

jztxtcmd path\to\script.jztxtcmd
jztxtcmd %0

The second form uses the same script, see meaning of %0 in batch programming in MS-Windows.

The installation conditions for some tools are contained in the jztxtcmd.bat script.

The same startegy can be used for UNIX/LINUX using a shell script.


5.3 Script as part of another file (batch file, java source)

Topic:.JZtxtcmd.invoke.bat.

It is possible to write a JZtxtcmd script in a MS-Windows batchfile. The advantage: There is only one file which contains the start of the script and the script itself. Write for example:

call jztxtcmd.bat %0
pause
exit /B

==JZtxtcmd==
currdir = <:><&scriptdir>/../..<.>;

Filepath input = path/to/myFile.csv;

main(){
  execute(input);
}

The batchfile contains the start of jztxtcmd, here calling of a sub-batch which knows the calling conditions, see 5.1 Command line invocation. %0 ist the path to the batch file itself. The batch file is ended on the exit /B statement. All text after them won't be processed from the Windows command interpreter. The JZtxtcmd script starts after the label ==JZtxtcmd==.

Writing inside a java source file:

Another possibility is, writing a JZtxtcmd script on start of a Java source file. Follow the pattern:

//D:/vishia/Java/srcJava_vishiaBase/org/vishia/util/test/TestCalculatorExpr.java
//==JZtxtcmd==
//JZtxtcmd Obj a = java org.vishia.util.test.TestCalculatorExpr.testSimpleExpression();
//==endJZtxtcmd==
package org.vishia.util.test;
import org.vishia.util.Assert;
import org.vishia.util.CalculatorExpr;
public class TestCalculatorExpr
{ //any class
}

The first line is a comment line with the filename. It helps to organize the invocation.

The second line starts with //JZtxtcmd. It is a comment in the Java source file. But if this file is used as JZtxtcmd script, the following line is used as script source. In this case a script variable is initialized with a static Java method. This line causes the invocation of that static method in exactly this source, to test somewhat. To use that, in an Eclipse-IDE there is only one Debug entry named JZtxtcmd with the main class org.vishia.zcmd.JZtxtcmd. The line with the filename is sufficient as calling argument. Then this file as script is started. It is possible to set a breakpoint on start of the called Java method - to test it.

The JZtxtcmd script ends with the label //endJZtxtcmd. The text after them is not used for JZtxtcmd.


5.4 Invocation from a Java application

Topic:.JZtxtcmd.invoke.java.

See srcJava_Zbnf/org/vishia/jztxtcmd/JZtxtcmd

A parsed script can be executed invoking execute(...) in srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter. It is possible to parse a capacious script on start of an application and then invoke special routines from that for example in a graphical application.


6 Structure of a JZtxtcmd script

Topic:.JZtxtcmd.script.

A JZtxtcmd script is a textual script. It is parsed and converted to an internal representation of data and statements while starting JZtxtcmd. The user can change the scripts text before it is started. Changing while running the script has no effect. There is no representation of parsed internal data outside of the JZtxtcmd execution.

The syntax of a JZtxtcmd script is defined in ZBNF syntax language internally in the JZtxtcmd script translator engine. That syntax can be presented in the help output, see 16 Syntax of a JZtxtcmd script.

If the syntax should be shown in the following text, it is written in form:

Some examples in mono-space font without special character fonts are given additionally.

The JZtxtcmdScript can contain any other lines before, especially a command line invocation, which ends with exit. The script starts after the marker if other lines are need on start of that file:

==JZtxtcmd==

The script should contain a main(...)-routine.


6.1 Script variables

Topic:.JZtxtcmd.script.scriptvar.

All types of variables can be noted in a script outside of subroutines and outside of the main routine. The variables will be created on start time of the execution in their order in the script, independently of their position on top or between routines. One should write script variables on beginning of the script, but one can write script variables in the context of a sub routine, if they are need their especially. Script variables are existing outside of the running time of a routine, where the variable of a routine does exist only while the routine runs. Script variables can be changed in routines.

See 9 Data and variables and syntax: 16.7 Variables.


6.2 Included scripts

Topic:.JZtxtcmd.script.incl.

Syntax: 16.3 The include statement

One can include another script in the given script. All included scripts are parsed independently and after the given script. An included script part acts like it continues the current script on end. It can define more script variables, can include another script, especially it can contain some subroutines and a main().

include path/to/otherScript.jzTc

include $ENV_TO/"path/global Script.jzTc"

The path to another script is written as simple character String till a whitespace, or in "". That path starts relative from the current script. If the path starts with an environment variable $VAR especially the environment variable should contain an absolute path, where the included script can be found.

main()-Routine in an included script:

If the top level script (which includes) contains a main()-Routine, it is used. If the top level does not contain a main() the first found main() in included scripts is used. One can use a script only with special sub routines which includes the script with the main(). Therewith a special behavior can be variegated with a short special script.


6.3 The main routine

Topic:.JZtxtcmd.script.main.

A script or a included script should contain a main routine. This is used to execute the script. (The main routine is started if another routine is not specified. TODO how?)

main()
{ ##statements
}

6.4 Classes

Topic:.JZtxtcmd.script.class.

The script can be divided in classes. Each class can have sub classes. Yet the routines of classes can be seen as only static routines in comparison with Java classes.

Syntax see 16.4 Classes

To invoke a sub routine in a class one should write

classname.subroutine(...);

For future development: It is an object oriented concept which may usefull to organize the workflow with sub scripts. Each class should have class variables.


6.5 Subroutines and subtext

Topic:.JZtxtcmd.script.sub.

Syntax see 16.5 subroutine.

Calling a subroutine see 7.5 call: Invocation of sub routines.

Calling a subtext see 13.12 Insert text form a subroutine: <:subtext:...>.

Statements in a variable see 9.1.9 Subtextvar, Subroutinevar - statements to execute

It is recommended to divide the execution of a task in more as one sub routines. Any routine should be short and easy. Long shell scripts or batch files with some goto are terrible. A routine should be manageable with about one screen size, 40..50 lines.

sub mySubroutine(String arg1="example", Obj arg2 = scriptVar){
  <+out><&arg1>, <&arg2><.+n>
}

arguments and local variables:

A subroutine can have an argument list which builds local variable for the routine. For calling a subroutine with building actual arguments see 7.5 call: Invocation of sub routines.

If (use-locals) is not set then a subroutine gets a copy of all script variables if they are writeable and gets the reference to readonly script variables. If that variables are changed the value of the script variables are not influenced. A subroutine can define its own variables. All that variables are existent as long as the routine runs.

It is possible to call a subroutine which uses the same local variables as the calling level. Then that subroutine is not independent of the calling environment. It should only be called in one environment or in adequate environments. Elsewhere errors are possible if used variable are not found. Such an behaviour is only possible for script languages. It makes easy to dispers the source code without effort for definition of a lot of variables:

sub myRoutine(use-locals) { ... }
subtext myText(use-locals) <:>...<.>

Such a subroutine or subtext cannot have additional arguments. It should not define a return variable except the return variable should be used in the calling level as return.

It is possible to add all local variables of the calling level to the local variables of the subroutine. In that case the subroutine is independent but it knows all variables of the calling level. Changing a variable in the subroutine does not affect the variables of the calling level. The application of that feature may be similar to use-locals:

sub myRoutine(add-locals, String moreParameter) { ... }
subtext myText(add-locals, String moreParameter) <:>...<.>

returned values:

A subroutine can return some values stored in a variable tree. This variable tree is named return inside the subroutine:

sub mySub(String arguments){
  String return.textret = "any text";
  Obj return.objret = anyObjExpression...
}
outside:
  Map result;
  result = call mySub();
  <+out>result.textret=<&result.textret><.+n>

6.6 Statement blocks

Topic:.JZtxtcmd.script.stm.

The main routine, a sub routine or some parts of the routine consists of a statement block.

{ statements
}

Statement blocks can be nested. Especially they are used in control structures:

if(condition){ statements} else { statements}

For statements see 7 Statements


6.7 Text blocks

Topic:.JZtxtcmd.script..

See 13 Text output and text generation and 10.3 Text expression.

Syntax see Chapter: 16.14 TextExpression.

A text argument or a comprehensive part of a subroutine can be a text block. The text block is clamped either with

 <:>text block<.>

if the text block is expected as argument, or it is organized as output to any Appendable, simple

<+>text block<.+>

for output to the main output text file, given by a calling parameter, usual -t=text.file, or

<+openfile>text block<.+>

to output to any javadoc-oracle/java/lang/Appendable especially (see 9.1.12 Openfile).

To output with a newline on end written in one line you can write

<+>An output line<.+n>

The generated text contains the same characters like written in the source, except line feeds and indentation. The linefeed can be controlled by a parameter, the indentation can be controlled in the following forms.

     <+>
       This is an line left aligned
         This line starts 2 spaces after ,,<+,,-column, therefore it has 2 spaces as indentation.
       <:@indent*2>This line starts at the column ,,indent*2,,
 :::  This line starts with 2 spaces, because 2 spaces after ,,:::,,
 :::::::::::::This line is left aligned because it starts after ,,:::::,, which starts before the ,,<+,,-line
 <.+>

See 13.3 Lines and indentation in the script.

One can write to the stdout using <+out>...<.+> and to the stderr using <+err>...<.+>. The environment of the JZtxtcmd invocation can show this texts in a console, redirect to files or redirect for example to a message system in Java using srcJava_vishiaBase/org/vishia/msgDispatch/MsgRedirectConsole:

<+out>stdout output like java.lang.System.out.println(...)<.+n>
<+err>stderr output like java.lang.System.err.println(...)<.+n>

6.8 Comments in the script

Topic:.JZtxtcmd.script.rem.

Syntax see $chapter.

The script is parsing with comment specifications which are regarded from the parser. That is:

##line comment to end of line
(? block comment
  over some more lines ?)

Additional the // and the /* ... */ can be used for comments like in Java or C. That comments are formally parsed, they are visible in the parsers result xml file with option -debug:file, but they are ignored for execution.

Note that a

//comment  <+>text...

does not ignore a start of a text output on the same line. This capability is proper for writing text output in a right column whereby statements are written left. To ignore lines which contain text output use:

##comment <+>inclusively ignore the text output<.+>

Inside text expressions the // does not act as comment. Instead it is a part of the generated text.

<+>text  ##comment to end of line
  function(arg);  //A C file may be generated with comments!
  ..<.+>

In Text expressions it is possible to comment some parts without disturbing the structure, for tests:

<:> <&-datapath.is.comment>
    <:---> comment till <--->
    <:-if> it is commment till <.-if>
    <:-for> it is commment till <.-for>
    <!--- It is not comment, but it is comment in an XML file --->
<.>

See syntax 16.14 TextExpression


7 Statements

Topic:.JZtxtcmd.statements.

Any independent line in a statement block is a statement. Some statements are designated by a keyword. Statements without a keyword are assignments and / or expressions which can invoke to Java methods.

The statements can be divide to

Statements are terminated by a colon ; character. The line structure (spaces, line feed) have not any influence.

The full syntax is described in 16.6 statements.


7.1 Definition of variables

Topic:.JZtxtcmd.statements.data.

Variables have to be definined before using. The definition can be come together with an initial or final assignment, which invokes an expression maybe with side effects. There are some but rare types.

A variable except Openfile can be defined and initialized or only defined. Openfile is initialized in any case, it opens the designated file for text write operations. The textDatapath is the file name.

See 9 Data and variables and syntax: 16.7 Variables


7.2 start, cmd: Invocation of operation system commands

Topic:.JZtxtcmd.statements.cmd.

If the JZtxtcmdExecuter is used as a script executer, it may be substantial to invoke operation system commands. Their result can be used for further evaluation.

To invoke a simple executable one should write

start notepad.exe &file;

to execute for example the notepad program in windows. &file is a 16.9 Text value: textDatapath, textValue for the first argument.

If you write

cmd notepad.exe &file;

then the JZtxtcmd waits till notepad is finished. That is the difference between the both JZtxtcmd statements start and cmd

Note that the invocation of a batch script in windows, a shell script in linux or a so named 'internal' command in windows can't be invoked direct. It needs the invocation of cmd.exe in windows or a shell for example konsole in Linux. To invoke a batch file in windows and wait for its finishing one should write

cmd cmd.exe /C thebatch.bat "maybe param" &nextParam ;

The cmd.exe, Window's command interpreter, is invoked with the calling of the batch as command argument. The invoked executable, cmd.exe in this example is executed in an own process of the operation system, but without any console window. The standard in, out and err are provided and gathered by the execution enviroment of the JZtxtcmd respectively from the Java's process execution facility.

If the execution of the batch should be shown in a console window ('DOS-box'), one should invoke:

cmd cmd.exe /C start cmd.exe /C thebatch.bat

It seems to be obfuscated but it is straight forward:

Only the first cmd.exe may be intuitively unexpected. But this cmd.exe is the programm which is called from the JZtxtcmd/Java process invocation, instead for example notepad.exe or windword.exe etc. It does not creates a console window by itself just as cmd.exe written in a console window does not create a second window.


7.2.1 Arguments for the command

Topic:.JZtxtcmd.statements.cmd.args.

There are four possibilities to give arguments. For the full syntax see 16.20 Command line invocation.

Firtly and simple the arguments can be given as a constant text. The " are necessary if spaces, a ; or a ( are contained in the text:

cmd notepad.exe "myfile.txt";
cmd notepad.exe myfile.txt;

An argument can be contained in a variable. It is given as access path to either a variable, Java data etc. which contains the value for the argument:

cmd notepad.exe &file;

The argument can be built with a text expression, see syntax: 16.9 Text value: textDatapath, textValue:

cmd notepad.exe <:>path/<&file><.>;

Last but not least arguments can be prepared in a List of Strings or any other Objects. the <:args:LIST> expands the list in maybe more as one argument:

List myArgs;
myArgs += "myfile.txt";
cmd notepad.exe <:args:myArgs>;

7.2.2 Check of command arguments

Topic:.JZtxtcmd.statements.cmd.argsCheck.

The command arguments can be complexely. For example to execute a command like

result += cmd !argsCheck! cmd.exe /C netsh interface ip set address <:>name="<&nameNetAdapter>"<.> static <:><&ipOwn><.> 255.255.255.0 192.168.1.1 1;

the arguments are build in the line with some variables. Any of the variables may be set with a faulty content. The command have a syntax check, sends a error text and sets an error level if any of its arguments are faulty. But like usual the error text of the command is not so pithy like necessary. To view what exactly is gotten by the command executer the !argsCheck! label can be used. Then the arguments which are sent to the command line are stored as String[]-array in the local variable argsCheck. This variable can be written out for checks. For example:

<+out><:for:arg:argsCheck><:n>--><&arg><--<.for><.+n>

presents the command arguments in one line per argument

-->arg1<--
-->arg2 may contain spaces <--

7.2.3 Additional environment variables

Topic:.JZtxtcmd.statements.cmd.env.

The command line invocation gets all variables from the calling environment of the JZtxtcmd script, especially that are the operation system variables. Additionally all local variables which are defined with set starts with $ are transfered without $ in its name as environment variable for the cmd execution.

If some environment variables will be defined in one subroutine level, all of them are added to the jztcsub.cmdExecuter instance. The cmdExecuter in another subroutine level does not know this environment variables:

sub mySub(){
  set myEnv = "text";  //added as $myEnv in variables
  cmd execute.exe;     //adds $myEnv as myEnv
  set Env2="text2";    //adds Env2 as %myEnv in variables and to the cmdExecuter.
}                      //end of subroutine removes the instance of cmdExecuter.

7.2.4 pipeline handling

Topic:.JZtxtcmd.statements.cmd.pipe.

The standard output of a cmd invocation can be gathered with an append assignment:



textBuffer += cmd myCommand;

whereby the textBuffer of this example can be a Stringjar, a Openfile, a Pipe or any other Appendable in the Java data. It is possible to have more as one Appendable which gather the standard output. Especially out can be used to forwarding the stdout of the process to the stdout of the JZtxtcmd execution:

textBuffer += out += cmd myCommand;

In this case the stdout is forwarding to the JZtxtcmd console output and gathered in the textBuffer too. The output is handled simultaneous while the command line execution process runs. If a execution needs some time, for example a search and report process from many files, the user can visit the output of the command line execution straight. This is a capability of the java virtual machine command line process handling with its application interface class javadoc-oracle/java/lang/Process and the class srcJava_vishiaBase/org/vishia/cmd/CmdExecuter

The other possiblity for gathering the stdout of the process and the only one possibility for a separated stderr and stdin is:

cmd myCommand <:stdout:textBuffer> <:stdout:out> <:stderr:out> <:stdin:myPipe>;

Both variants can be combined. stdout and stderr can be written in any number of destinations. The stdin can be given only one time.


7.2.5 Exit code of cmds, errorlevel

Topic:.JZtxtcmd.statements.cmd.errorlevel.

A cmd invocation has an exit code. It is a principle both in UNIX-like operation systems and in MS-Windows. Usual a higher value of an exit code means a more fatal error. 1 may be a warning, 0 is successfully. The exit code is designated as errorlevel usual in MS-Windows batch files.

After a cmd invocation one can output the exitcode for example as hexadecimal value writing

cmd myCmd ...
<+out>exit error level = <&jztcsub.cmdErrorlevel:"%8X"><.+n>

There are two startegies to handle the exit code:

if errorlevel 1 { ...statements...}

That statements are executed additionally if the last cmd sets the requested or a higher errorlevel. For example a warning can be logged.

throw on errorlevel 2;

If that statement is executed, an exception is thrown if the exit code (errorlevel) of the last cmd invocation is equal or higher to the requested value. It means, the following statements are skipped till a onerror {...} or onerror cmd {...} statement is found or the block is left with that exception.

Both strategies can be combined:

cmd myExecutable.exe arguments
throw on errorlevel 5
if errorlevel 1 { ...}
...
...further statements
...
onerror cmd {
  ... alternatively statements on fail
}
...continue processing

If the command generates an exit code equal or greater 5, the further statments are skipped. They should not be executed, because the permissions are not given. If the errorlevel is 1..4, the further statements are executed. The onerror cmd block is executed only if the exit code is 5 or higher. There may be executed any alternatively things. Last not least the processing continues after the onerror-block.

See examples_JZtxtcmd:TestAll/readme.txt: sub testErrorlevel()


7.2.6 Execution time for operation system commands

Topic:.JZtxtcmd.statements.cmd.calctime.

The invocation of a operation system command call creates a new process in the operation system. That needs a few milliseconds. A value of about 50 ms was measured with an Notebook with MS-Windows XP, Intel dual core about 1.2 GHz.

That time is not large if a complex command line process is started. But if some command lines are executed one after another, each of them with a small task, then this 50 ms are multiplied by the number of cmd invocations. For example a compilation or any other translation was started.

If a Windows-batch-file or a UNIX shell script runs, the cmd.exe or shell script interpreter optimizes the invocation of commands. There is not an extra process for each command. Therefore it may be recommended for a block of commands to generate such an script and executed the whole script. Of course the advantage of an operation-system-independent syntax for JZtxtcmd is not able to use if either a MS-Windows batch file should be executed or on the other hand an UNIX/LINUX shell script. But usual such JZtxtcmd user scripts are proposed for a special operation system.

For example to invoke some commands as batch in windows one can write:

Openfile bat = "myBatch.bat";  ##opens in current directory
<+bat>
  echo off
  dir >out.txt
  call otherbatch.bat
<.+close>
cmd cmd.exe /C myBatch.bat;

The batch is contained as text lines in a JZtxtcmd script. That text lines are written to a file. That file is executed with cmd.exe, the MS-Windows batch file executer.

The produced text in out.txt can be read in the JZtxtcmd script then and it can be evaluated:

Stringjar sdir = FileSystem.readFile("out.txt");  ##reads the file.
if(sdir.seek("myBatch").line().found()){
  String line = sdir.getCurrentPart();
  <+out><&line><.+n>
}

See examples_JZtxtcmd:TestAll/readme.txt: sub testBatch()


7.3 currdir, cd statement

Topic:.JZtxtcmd.statements.currdir.

Inside a JZtxtcmd script a current directory can be set. It is used especially for 7.2 start, cmd: Invocation of operation system commands and for file operations with relative paths:

cmd execute anything;                 ## uses the currdir for command process
Openfile myfile = relative/path.ext   ## uses the currdir to build the file path
datapath.method(File:"relative/path") ## creates an absolute File object with currdir

Practice of absolute and relative paths:

It is not recommended to define an absolute path if the script should be used on several computers may be with different locations in the file system.

On the other hand the usage of absolute paths for files is at runtime proper. For example if a file should be opened but it fails, an error message which names the absolute path of the file is more helpfull. If the message contains the relative path only, the question remains on which path starts the relative one.

The following rule should be valid:


7.3.1 Determine the currdir on start on JZtxtcmd

Topic:.JZtxtcmd.statements.currdir.start.

A path for the current directory can be given:


7.3.2 cd versus currdir = path

Topic:.JZtxtcmd.statements.currdir.cd.

The statement cd or CD is known from both Unix shell scripts and MS-Windows batch files. The JZtxtcmd supports it too:

cd newDir

changes the content of the currdir of any subroutine level. Relative paths can be used, especially ... This changes are done in the local copy of the subroutine, not for the script variable currdir. If the newDir is faulty, non existing or any faulty path, an IllegalArgumentException is thrown. The user can catch such an exception with

cd requestedPath/maybe/faulty
... do something with it
onerror{ ...errorHandling }

See 12 onerror - Exceptionhandling

Instead cd the form

currdir = "newDir";

can be used. The difference between both is less.

cd mydir;

currdir = "mydir";

Especially on start of a JZtxtcmd script or in a sub routine the following statement can be used:

currdir = scriptdir;
currdir = <:><&scriptdir>/../relative<.>;

Often it is usefull if the script is contained in a working area in an sub directory, and the working area should be used as current directory without any other effort.

Especially some environement variable of the operation system can be used to set a special, usual absolute currdir:

currdir = $CD;  ##set it to the operation system's current dir
currdir = $PWD; ##adequate for Unix
currdir = $HOME;
currdir = <:><&$HOME>/myDir<.>; ##inside the HOME directory

Note that the environment variables are case sensitive in the JZtxtcmd script like in UNIX/Linux in opposite to the non case-sensitive ones in MS-Windows.


7.3.3 Access to the currdir as variable

Topic:.JZtxtcmd.statements.currdir.varaccess.

The currdir is a variable of JZtxtcmd. But the assignment currdir = ... is a special statement. If the value of the currdir is need as text value for example to output it for check one can write:

<+out><&jztc.scriptLevel.currdir><.+n>
<+out><&jztc.scriptLevel.currdir()><.+n>
<+out><&jtcmdsub.currdir><.+n>
<+out><&jztcsub.currdir()><.+n>
<+out><&currdir><.+n>

The method currdir() on sub level or for the whole JZtxtcmd script returns a string which uses / as separator for directories in the path, like it is recommended for internal use.

The field currdir in the instance jztcsub or jztc.scriptLevel is a reference to a java.io.File. Therefore it's conversion to a String returns the path in the operation system's kind. It is a property of the Java Virtual Machine. Therefore the backslash \ is written as path separator.


7.3.4 The currdir of JZtxtcmd does not affect the operation system's current directory

Topic:.JZtxtcmd.statements.currdir.noOs.

If you invoke any Java method, and that Java method tries to open a file for example with

Writer openit = new FileWriter("relative/path");

then the Java Virtual Machine delegates the resolving of the relative path to an absolute one to the operation system. Of course the operation system does not know a currdir variable of the JZtxtcmd level. Therefore it may be failed.

If you use a File object instead:

Writer openit = new FileWriter(File:"relative/path");

then the File will be build with an absolute path which uses the JZtxtcmd-internal currdir instead.

If any Java module can be influenced with a special setting of the current directory you can do so. For example and especially the class srcJava_vishiaBase/org/vishia/mainCmd/MainCmd knows an command line argument "--currdir:value" which can be set from Java internally too. You can write

java path.to.Main.main(<:>--currdir:<&currdir><.>, "further arguments...");

If you're attempt to invoke a Java program which uses MainCmd from the JZtxtcmd script.


7.4 File commands

Topic:.JZtxtcmd.statements.copy.

There are some commands to offer operation systems capability:

mkdir path/to/dir;

Syntax see 16.6 statements. It makes all necessary directories starting from the current directory or with the given absolute path. If the directory exists already, it is ok, no error. The path can be given as immediate text without spaces, or in "" or as <:>textexpression<.>. If the path ends with a ' (Apostroph, Hexa 0x27) then it means, the path ends with a file name. The file part is removed then, only the directory is created:

mkdir <:><&path_to_file_variable>'<.>;

creates the directories to the file, not the file itself (since 2018-01).

Copying a file. The copy command knows 3 options:

The arguments for copy are textvalues Use "path/with special;chars", you can build a path with a <:>textexpression with <&values><.>.

The copy command does only copy files. For copying directory trees use

copydir ...TODO

The move command is a rename if the

move source/File dstdir

The source/File can be a directory which is moved into the dstdir. Both arguments are paths as textValue. Therefore you can write for example:

copy <:>myPath/<&fileNameInVariable>.ext<.> <:><&dstPath>/<&fileNameInVariable>.ext<.>

using variables. The copy operation copied directory trees if it is given.

Check of file properties

To check file properties the capability of the class javadoc-oracle/java.io.File can be used. A file object can be build with:

Obj myFile = File:name.ext;

whereby name.ext is a textValue. It builds the File with the given path inside the currdir of the JZtxtcmd environment.

It is possible or proper to build the File object only temporary, in conclusion with the check operation:

if(File:"path/to/file.ext".exists()) { ... }

In this case the name of the file is written in "" because the following .exists() method should be separated from the name. Of course it is a syntax error if you write if(File:path/to/file.ext.exists()) ... because .exists is recogized as part of the file name (extension) and the following () are unexpected.

Like usual for a textValue the file can be build with:

File:&variableContainsPath
File:&dataAccess.to.javadata
File:<:><&basepath>/to/<&name>.ext<.>

7.5 call: Invocation of sub routines

Topic:.JZtxtcmd.statements.call.

Sub routines are parts of a JZtxtcmd script, see 6.5 Subroutines and subtext.

Syntax see 16.18 callSubroutine, callSubtext.

calls a subroutine



call mySubroutine(argname=argvalue);

Writing rules, name of the sub routine:

The Name of the sub routine can be either a constant string value or a value from any location. In the last case the routine is determined by the user's data.

call &theName();

Actual arguments for the subroutine:

The order of the formal arguments and the order of the actual values does not need the same one. The arguments are named both in formal and actual lists (other than in C, Java). It is checked whether corrent names for actual arguments are used and whether all necessary actual arguments are given. Formal arguments can have default values for missing actual arguments.

Be aware that the calculation of actual values may have side effects, depending on their calculation routines. The default value will be calculated

Because JZtxtcmd is a interpreted execution, it may be possible that the calling environment is used to calculate the actual values. But from static view the calling environment is unknown from the subroutine's head line. Therefore the calling environment is displaced for that operation.

Example:

sub mySubroutine(String arg1="example", Obj arg2 = scriptVar){
  <+out><&arg1>, <&arg2><.+n>
}
...
{ //any calling enviroment:
  Obj scriptVar = xyz;
  call mySubroutine(arg1="myOtherExample");
}

It is called without actual argument arg2. Therefore the value for arg2 is calculated on calling time. But the local scriptVar is not used, instead the script variable with that same name is used.

Type of arguments:

Usual an argument of a sub routine is either a constant or an expression, see 16.10 Object value: objExpr. It may be a simple access to a variable.

An object expression allows some type conversions:

If a java.io.File object is expected but only the path is given, use

call subroutine(fileArg = File: "path/to/file");

If the filepath is relative then the 7.3 currdir, cd statement is used. It is the same like arguments for invocation of Java methods, see 9.9 Access to Java internal data.

If a Filepath variable should be build only for the subroutine's argument then the definition can be write directly in the actual argument list:

call subroutine(pathArg = Filepath: "path:local/file.ext");

It builds a srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdFilepath object on demand as actual argument. The subroutine gets the reference to it. Hint: The filepath does not need to write in "" if it does not contain spaces and special characters.

Adequate the access to a fileset with a filepath can be written with:

call subroutine(pathArg = Fileset: path:&filesetVariable);

That construct builds a srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdAccessFileset

Hint: On missing variables etc. a runtime error occurs. Because JZtxtcmd is interpretative, it is not possible to check all variables on compile respectively start time. Use 12 onerror - Exceptionhandling to handle such situations.

Return values:

To transport results from the subroutine to outside there are 2 ways:

Both ways can be combined. For the first way the call-statement is an assignment:

sub testResultRet(String someArgs){
 //creates a String variable inside the return Map:
 String return.text = <:>testResult-return from <&someArgs><.>;
 String return.anotherOne = "other return value";
}

Map result;
result = call testResultRet(someArgs = "someArgs");

The return value in this example assigned to result is a Map which contains all returned variables from the sub routines. It is similar a returned instance of a comprehensive class type in Java.

To replenish any argument variable one can use the following pattern:

sub testResultSub(Map arg){
 String arg.ret = "testResult-replenish";
}

The arg is a Map of variables, maybe created by

Map map;

or maybe the local variables of the calling level:

call testResultSub(arg=jztcsub.localVariables);

This method is not functionally, not object oriented, but it may be convenient for practice. It is typical for interpretatively execution: The local variables can be replenished by some more stuff.


7.6 Invocation of Java methods

Topic:.JZtxtcmd.statements..

You can invoke static java methods with arguments:

java org.vishia.util.FileList.list("anyDirectory/path", "*", ".filelist.list");

This example invokes the static method list of the class org.vishia.util.FileList with the given textual arguments. The arguments can be build as text expression with <:>expression <&value><.>, with numeric expressions are with JZtxtcmd variable which are instances of Java data, see 9 Data and variables.

You can create java instances and invoke their non-static methods. Example:

Obj checkDeps = new org.vishia.checkDeps_C.CheckDependencyFile(console, 1);
....
test = checkDeps.readDependencies(<:><&objDir>/ccs_dsp_obj<&$PARAM>.deps.txt<.>);

An instance of org.vishia.checkDeps_C.CheckDependencyFile will be created. After them the method readDependencies(...) is called.

See


7.7 Zmake

Topic:.JZtxtcmd.statements.zmake.

A Zmake statement is written in form:

zmake output := subroutine(input&fileset, input, parameter=value);

See Syntax: 16.19 Zmake. The subroutine is the translator between some inputs and the output. The output is a file or a directory and extension, where some files should be stored.

For example some files can be zipped. The output is the location of the zip file. The inputs are the files to zip. Another example is: C/C++ compilation (outputs: object files) and linking (output: The executable, maybe some more files in the output directory).

The subroutine contains the statements how to make. It is possible to invoke that commands, which executes the make process. It is possible too to produce a text output which contains the make controlling. The text output file can be a classic make file, an ANT make file, any batch or shell script or any other. The subroutine or some variables can contain some parameter to control the make. For details see Zmake.

The Zmake works with file entities and file sets. See 9.1.13 Filepath, Fileset

The subroutine is a normal JZtxtcmd sub routine. The output and input are assembled in an instance of srcJava_vishiaBase/org/vishia/cmd/ZmakeTarget which is given as first parameter:

sub subroutine( Obj target :org.vishia.cmd.ZmakeTarget, .....) {
  ...make target statements
}

Example make for one file only whereby the file path is given as absolute path in a environment variable:

zmake <:><&$2>.crefl<.> := genReflection(&$1);

The output file will be build with the input file plus the special extension. The input argument is only the given file path.

Example using a fileset:

Fileset srcSet =
( fileA.c
, local/path/fileB.c
, otherPath/*.c       ##all files of that directory
);
zmake "output/path/*.obj" := ccCompile("access/path": &srcSet, argument="arg_value");
zmake "output/path/*.obj" := ccCompile(access/path:&srcSet, argument="arg_value");

The zmake routine can decide which parts from the output is used for any file. For example the output files can be build with the directory of output and the extension, and the names or local pathes without extension from the input files. The & is the separator between a access path and the name of the set. The access path can be empty, an text expression or a dataAccess.

The : on end of access path marks, that the access path acts as base path for the files of the set. If the accessPath contains a : than the localPath starts there if the paths in the Fileset don't contain an localPath part. Especially .:&fileset means, the accessPath starts from the current directory and the paths of the Fileset are the local ones. Note: . is the current directory. Another example: ../../access/path:&fileset. It is a good style if the Fileset does name the local paths only. Too see variants with the localPath in Fileset and usage of parts of the filePath see the example in the zbnf.zip download

The zmake routine takes arguments in the same way like any other subroutine, see 7.5 call: Invocation of sub routines. The no named argument is a target input. It consists of two parts: The accessPath and the access to the Fileset. The access to Fileset is written right after a &. The accessPath can be omitted or given as "string", as & <dataAccess> or as chars till & without quotes. If the accessPath is given as & <dataAccess>, the distinction between a singulary access path as data Access and the & <dataAccess?zmakeFilesetVariable> is done with test of the accessed instance. It is checked whether it is a Fileset or not.

The given accessPath is converted to a String if it is accessed via & <dataAccess>. The String-given accessPath is converted to a srcJava_vishiaBase/org/vishia/util/FilePath. In that constructor the String is divided especially into the local path and the base path, separated by the character ':'.

ZBNF/examples_JZtxtcmd/TestAll/testFileset.JZtxt.bat

7.8 Assignments, Expressions and Text expressions

Topic:.JZtxtcmd.statements.expr.

An Expression maybe a simple access to data, but it is an execution of methods/routines often. The execution may be seen as side effect of the assignment, but it may be the originally approach and the assignment may be the secondary one. It is like in normal programming languages.

Assignments see 9.1 Types of variables and their assignment, its syntax: 16.21 Assignment to variables

Expressions see Chapter: 10 Expressions, its syntax: 16.10 Object value: objExpr

Text expressions see 13 Text output and text generation, its syntax: 16.9 Text value: textDatapath, textValue


8 Program flow control

Topic:.JZtxtcmd.if.

Syntax see 16.16 Control statements.


8.1 if()...elsif()...else...

Topic:.JZtxtcmd.if.if.

One can write

if(condition){
  statements;
}
elseif(otherCondition){
  statements;
}
else {
  statements;
}

All program flow control statements can be nested, of course. The { } are necessary, other than in C, Java.

The elsif is the same like else if which is possible in Java, C etc. also. It is a chain of if. elsif and else are optional.

The condition is a 10.5 Boolean expression, Conditions. If the condition is a datapath only, it is false if the path is faulty.


8.2 while()...

Topic:.JZtxtcmd.if.while.

One can write

while(condition) {
  statements;
}

to execute statemens so long as the condition is true.

do {
 statements;
} while(condition);

checks after the loop body.


8.3 for(container)...

Topic:.JZtxtcmd.if.for.

The JZtxtcmd does support the iteration over a container and execute statements with the current element. The old-style for loop known from other programming languages is not supported. If such one is necessary, it is able to execute it with while(...) instead. The old style for loop is imagined for indexed access to arrays usually. The for-container iteration is also known in other modern programming languages. One can write

for(element: datapath.container){
  statements ...;
}

The statements were executed for each element in the container. The element on each loop referred by the variable, can (should) be used inside the statements.

Condition in for:

Additionally there is a possibility to leave the for-loop. One should write:

for(element:container && condition){
  ....
}

If the condition is false the for-loop is left. For example an element can be searched in the container. Write:

Obj found;
for(element:container && not found){
  if(element.attribute == expected){
    found = element;
  }
}

Iteration variable can be used after a broken loop:

Since 2016-02: The iteration variable (element of the container) is created with this for loop. It is existing in the following statements after the for furthermore (rather than in Java, there it is a local variable of the for loop only). But if the for-loop is executed till its end, the iteration variable is null. Only if the for-loop was broken either by a condition or by a break statement, the iteration variable remains the last used container value. This can be used especially for searching an element in a container. The iteration variable is set before the condition is checked. Therefore it is possible to use the iteration variable in the condition too. To search an element is is shorter to write:

for(element:container && element.attribute != expected);
//use element in further statements
//it contains that value where the condition was false,
//in this case: ,,element.attribute == expected,,.
if(element) {
  ... //The element where the for loop was broken.
}

check if the container has a next element <:hasNext>:

Especially for text generation there is a possibility to quest whether a next element exists after the current one. Often things should be separated by a colon etc, but the colon should not be written after the last element. Write:

for(element: container) {
  <+textOutput><&element.value><:hasNext>, <.hasNext><.+>
}

then the elements are separated with , but after the last element there is no ,.

The same operation in a text:

<+textOutput><:for:element:container><&element.value><:hasNext>, <.hasNext><.for><.+>

Implementation in Java, container types are Iterable, Map or an array:

The container is any javadoc-oracle/java/lang/Iterable, a javadoc-oracle/java/util/Map or any array in Java. A Map is iterated by its entrySet(), the elements are the value of the entries.


8.4 break, return, exit

Topic:.JZtxtcmd.if.break.

Don't use return except in an onerror block:

A subroutine ends on its last statement. The only exception of this rule should be: An exception has occurred inside the subroutine. A conditional return inside a subroutine is not recommended, it is a bad style. The reason for that is: A return inside a lot of statements can lose sight. The algorithm inside a sub routine should be strongly structured. Note the following example:

With return inside (for example in Java);

void mySub(){
  ObjType foundObj;
  anyContainer.anyOpenAction();
  while(anyContainer.hasNext()){
    ObjType obj = container.next();
    if(obj.hasExpectedProperties){
      anyContainer.anyCloseAction();
      do something...
      return;
    }
  }
  anyContainer.anyCloseAction();
  <+out>not found.<.+n>;
}

Something is searched in a while loop. If it is found, the evaluation is done in a if-branch inside the while, with return inside.

Without return, code of JZtxtcmd:

Of course, the algorithm without return inside needs the second if-condition. It may be more expensive for calculation time. But that is minimal. In fast algorithm with slow processors (C programming for embedded) a return inside may be proper, because calculation time. But for complex algorithm in fast execution environments the return inside is not necessary, and a less proper style for programming.

Don't use break in loops:

A conditional break in a loop is not recommended. It is a bad style. The reason for that is: A break inside the loop's statements can lose sight. The condition to whether continue a loop should be able to seen only in the loop's head statement. Note the following example:

 Obj found;
 Obj myIterator = myList.iterator();
 while(!found && myIterator.hasNext()){
   Obj element = myIterator.next();
   <+out><&element><.+n>
   if(element.equals("test2")){
     found = element;
   }
 }

One of the condition to continue the loop is !found, the other one is myIterator.hasNext() - some more elements exists. That both conditions are able to see in the while(...)-line. Thats all. If the algorithm has a break:

 Obj found;
 Obj myIterator = myList.iterator();
 while(myIterator.hasNext()){
   Obj element = myIterator.next();
   <+out><&element><.+n>
   if(element.equals("test2")){
     found = element;
     break;
   }
 }

- the break is not seen if the while(...) is checked.

The possibility for break in loops and return in subroutines in JZtxtcmd is a concession for widely used styles only. But the break inside an ..onerror block is necessary to abort further execution after the onerror-block.


9 Data and variables

Topic:.JZtxtcmd.data.

A JZtxtcmd script can have script variables and local variables in sub routines. (future extension: class variables). Another possibility is getting and storing values from/to any Java instances.


9.1 Types of variables and their assignment

Topic:.JZtxtcmd.data.type.

A JZtxtcmd variable is a reference to the data. There are a few types:


9.1.1 Num

Topic:.JZtxtcmd.data.type.Num.

A numerical variable is presented by a integer or float (double) value. It is calculated using 10.6 Numeric Expression and presented by an Object of type srcJava_vishiaBase/org/vishia/util/CalculatorExpr.Value.

Num value = 5.0;  ##initialize a double value
Num val1 = 0x124;  ##initialize a int value from hex form.
Num val2 = stringValue;

A stringValue will be converted to a numeric equivalent. Depending on the string value it will be stored as long, integer, float or double. (since 2018-09)


9.1.2 Bool

Topic:.JZtxtcmd.data.type..

It is a boolean value or a condition, set to true or false. It is presented by an Object of type javadoc-oracle/java/lang/Boolean. Note that on definition of a Bool variable one can write

Bool myBool = a > 5;

whereby on assignment one should write:

myBool = bool(a > 5);

The reason for that difference is: The translator of the script (parser) does not recognize the type of a variable on assignment. To accept a boolean expression the bool(...) is necessary. It may be a good style because the reader of the script sees that it is a boolean assignment.

Note that the test of existence of a variable path can be written with a simple boolean assignment:

Bool myPathexists = path/to/variable;  //false if path is faulty.
myPathExists = bool(path/to/variable);
myPathExists = path/to/variable;

In this case both variants to write are accepted, with or without bool(...) because syntactical it is not necessary, The execution evaluates an boolean expression anytime with the feature of false on a non existing path instead of an exception.


9.1.3 String

Topic:.JZtxtcmd.data.type.String.

A String: refers a constant text.

The text can be built with any text expression. A String variable can change its content. But the string gotten from a String variable before changing will be never changed. It is the same like a String in Java.

String myString = "text";
String mySecond = myString; //refers text
myString = "other text";    //mySecond remain unchanged!

For text expressions see the syntax in 16.9 Text value: textDatapath, textValue


9.1.4 Stringjar - adding Strings, search in Strings

Topic:.JZtxtcmd.data.type.Stringjar.

A Stringjar references a srcJava_vishiaBase/org/vishia/util/StringPartAppend. It contains a javadoc-oracle/java/lang/StringBuilder which is used as Appendable. This class has all features of srcJava_vishiaBase/org/vishia/util/StringPartScan and srcJava_vishiaBase/org/vishia/util/StringPart. With that it is possible to Append or store any text and analyze it after them or while appending. Additional a remove method is included to remove parts of texts which are not need furthermore.

One can append using

Stringjar myBuffer;                //a new empty buffer
Stringjar myBuffer = "start text"; //a new buffer with intial text
myBuffer += " appended text";         //append

The += operation symbol for the assignment is the append symbol. A = assigns a new start text.

One can search any text in the Stringjar. The access to a Stringjar reads the current visible part. Additionally one can use the javadoc-oracle/java/lang/StringBuilder-methods with the stringBuilder()-method. For example:

myBuffer.stringBuilder().insert(myPosition, "a inserted text").

The instruction

myBuffer = "new Text"

does not create a new Stringjar Object (not like in Java) but initialize the given object with this new value. If a reference

Obj myBuffer2 = myBuffer;

was build before, the value of myBuffer2 is changed too because it is the same reference. But if is defined

Stringjar myBuffer2 = myBuffer;

then a new Instance of a Stringjar is created with initial value of the content of myBuffer.

Note that the javadoc-oracle/java/lang/StringBuilder is not threadsafe. A StringBuffer is threadsafe but slower. Since the Java version 5 the StringBuffer can be replaced by using the java-StringBuilder with exact the same capabilities, but without synchronized-Mechanism. It is more fast. The major of applications don't need the thread-safe property because the StringBuffer will be filled and changed usual in one thread. If it is necessary to handle a StringBuilder in more as one threads, in Java synchronized mechanism can be used. A JZtxtcmd script should not encouraged to handle with data in threads complexly. Fill in one thread, evaluate after them in another thread. Therefore the usage of StringBuilder is proper.


9.1.5 Obj - any Object

Topic:.JZtxtcmd.data.type.Obj.

It is possible to create a Java instance or get any instance from a Java context:

Obj myObj = new org.myPackage.MyClass(args);
myObj = otherInstance.method_whichReturnsAnObject(args);
myObj = java org.myPackage.MyClass.myStaticMethod(args);

With this java instance any action can be done:

myObj.method();

Or the object can be added to a container to use it in a for loop.

myList.add(myObj);

The reference to the Java instance should be removed if the instance is not used any more. The garbage collector of the Java Runtime Environment will removed it:

myObj = null;

9.1.6 Pipe

Topic:.JZtxtcmd.data.type.Pipe.

One can append to the pipe with


Pipe myPipe += "appended text";

or invoke any method of this class. The pipe can read out usual in another thread with the getLine or get method.


9.1.7 List - a List of values

Topic:.JZtxtcmd.data.type.List.

It is able to use as container in a for-statement. A

List myList;
myList += anyObjectExpression

creates an empty list and adds an Object.

myList += anotherList;

If the added object is a java/util/List-container too, its elements are added.

myList.clear();

clears the list. One can use all methods of the List interface.

Building of container with List:

A List (an instance which implements the javadoc-oracle/java/util/List interface) is a container, able to use in a JZtxtcmd-for loop, see 8.3 for(container)....

The List can be built and used in the following way:

The last one possibility is proper to set some data, then evaluate something with this settings.

A list can be defined with constant texts:

List myList = [ "ab", "cd", "xyz" ];

The [...] are the brackets for the container. The items of the container are separated with comma.

Another form of such a container is a Container which contains variables:

List list2 =
[ String var1 = "ab";
  String var2 = "cd";
];

An advantage in opposite to the simple Strings is: The Strings have names. It is possible to evaluate:

 for(var: list2) {
   <+><&var.name>, <.+>
 }
 <+><.+n>
 for(var: list2) {
   <+><&var.value>, <.+>
 }

This outputs the names in the first line and the values in the second line.

A List can be build by a Subtext variable:

List listSubtext =
[ Subtext item1 = <:>Use the content of <&otherVariable><.>;
  Subtext item2 = "constant text";
];

For evaluating that container it can be written:

 String otherVariable = "content";
 for(var: listSubtext) {
   <+><&var.name>, <.+>
 }
 <+><.+n>
 for(var: listSubtext) {
   <+><&var>, <.+>
 }

In this case the <&var> contains a Subtext, therefore the content is evaluated now in the given context. It means the variable with name otherVariable is found in the Subtext and its content is used in the for loop.

Another form of a List container can be built like:

 List variationParameter =
 [ { name="hi",  Rfault="10.0", Lfault = "0.1", descr="High impedance fault"  }
 , { name="mid", Rfault="0.2", Lfault = "0.1", descr="Middle impedance fault" }
 , { name="low", Rfault="0.1", Lfault = "0.1", descr="Low impedance fault"    }
 ];

This list contains a Map of String variables. Now the combination is interesting. A loop of all variations is build, the loop uses the listSubtext:

List cellcontent =
[ Subtext cell1 = <:>Rfault = <&parameter.Rfault><.>;
[ Subtext cell2 = <:>Lfault = <&parameter.Lfault><.>;
  String  cell3 = "constant text";
];



 ##Builds a line with the names:
 ##
 for(var: listSubtext) {
   <+><&var.name>, <.+>
 }
 <+><.+n>
 ##Builds some lines with values:
 ##
 for(parameter: variationParameter) {
   for(cell: cellContent) {
     <+outs><&cell>, <.+>
   }
   <+outs><.+n>
 }

This builds a file with 4 lines for the names and the 3 variations with a content which is defined on the Subtext cell1 etc.


9.1.8 Map - a Set of variables

Topic:.JZtxtcmd.data.type.Map.

A Map is an instance which implements the javadoc-oracle/java/util/Map interface.

It is able to use as container in a for-statement.

A map is able to use especially to store variables:

Map myContainer;
String myContainer.anyVariable = "text";  //defines a String variable inside that Map

The variable is stored in the map and can be gotten by myContainer.anyVariable. This can be used to provide the variable container for sub routines too:

sub mysubroutine(Map data) {
  String data.myNewVariable = "value";
}
.....
call mysubroutine(data=myContainer);
<+out><&myContainer.myNewVariable><.+n>;

A Map is build if a dataStruct is created writing (see also Chapter: 10.4 Object expression):

Map dataStruct = { String text = "value"; List anyOther = something; };

or if such an construct is used in an argument list:

myData.myJavaMethod({ String cmd1 = "cmd"; String data = anydata; }, furtherArg);

In this case the method gets an argument of type Map which contains that two elements.

One can use all methods of the java.lang.Map interface especially

myMap.clear();
myMap.put("name", value);

The value can be accessed though it is not a Variable with

Obj value = myMap.name
Obj value = myMap.get("name");

9.1.9 Subtextvar, Subroutinevar - statements to execute

Topic:.JZtxtcmd.data.type.Subtextvar.

A Subtext is a variable which contains a srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdScript.Subroutine to build a text. It is a subroutine stored in a variable, similar like a function pointer in C-programming.

Subtextvar myStatements = <.>constant text and <&variable><.>;
Subtextvar myParametrizedStatements(String textArg) = <:>uses only <&textArg><.>;

A static subtext as script part is slightly different:

subtext mySubtext(String textArg) = <:>uses only <&textArg><.>;

Syntactically only the keyword subtext against Subtextvar is different. But a Subtextvar is a variable which can be a part of a List or Map, can be used as argument or stored in another Obj variable. mySubtext is not a variable but the name of a static subtext. The name can be stored as String: String theSubtext = "mySubtext";; this String can be used as argument to invoke different subtexts writing <:subtext:&theSubtext:args>. Dealing with that subtext names it is possible too to dynamic the invocation of subtexts - but using a Subtextvar may be more simple in some cases.

The statements of a Subtextvar are executed either if the value of the variable is used in an access to &myStatements, or with a <:subtext:...> in a text expression:

String myValue = <&myStatements>;
<+>textExpression invokes <:subtext:&myParametrizedStatements:textArg="my textArg">
but it can invoke <:subtext:&myStatements> without arguments too...<.+>

It is for a simple application without arguments in the current execution environment, and for a exactly application like any other subroutine respectively subtext with its own execution environment and arguments. The argumentless variant is adequate

Subtextvar myStatemens(use-local) = <.>...<:>

see &chapter, arguments and local variables. For this variant the execution environment is the current context. For example:

String variable = "Example";
<:>Any text uses <&myStatements>. <.>

The execution of the text expression finds the variable myStatements, detects that it contains statements, and exucutes it with the given context where the variable is known. Therewith the following text is produced:

Any text uses constant text and Example.

See 9.1.7 List - a List of values to see how some Subtext in a List container are used.

A Subtext variable can be used as actual and formal argument for a subroutine, maybe stored, used for a callback-mechanism. It can be used in a call statement too.

If some Subtext are contained in a map and get from there, you should store it in an Obj variable temporary because the map.get(key)-statement can only return an Obj. See 9.1.8 Map - a Set of variables. For example:

Map accesses = {
 Subtextvar int(String name) = <:>super.getInt32(k_<&name>)<.>;
 Subtextvar char(String name) = <:>super.getChar(k_<&name>)<.>;
 Subtextvar int16(String name) = <:>super.getInt16(k_<&name>)<.>;
 Subtextvar float(String name) = <:>super.getFloat(k_<&name>)<.>;
 Subtextvar double(String name) = <:>super.getDouble(k_<&name>)<.>;
};

This is from Cheader2JavaByteDataAccess.jztc. The map was build to find a type from C-programming, int16 etc. To find the proper Subtextvar with a given C-type, it is programmed:

Obj accessRtn = accesses.get(attrib.type.name);

The Obj contains the gotten access routine after the access. To execute it:

<+javaSrc>
  return <:subtext:&accessRtn:name=&attrib.name><.+>

The Obj which is typeof org.vishia.JZtxtcmdScript.Subroutine is taken as subtext argument and executed therewith with the given further arguments.


9.1.10 Class - ?instanceof check, class loader, static method invocation

Topic:.JZtxtcmd.data.type.Class.

A Class variable is created with

Class myClass = path.to.MyClass;
Class myInnerClass = path.to.MyClass$InnerClass;

Whereby path.to.MyClass is a java package path. The named javadoc-oracle/java/lang/Class object will be stored in the myClass variable.

A Class can be defined in a specific jar-file or any file location which needs a specific javadoc-oracle/java/lang/ClassLoader-instance. Such can be stored in a Classpath-variable or it can be accessed via any data.path. Using that one can write:

Classpath classLoader = "D:/The/specific/jarfile.jar";
Class myClass = : classLoader : path.to.MyClass;

A Class variable can be used to access static fields and call of methods or to create an instance of the class:

myClass.aStaticMethod(args);          ##calls it.
<:>A text <&myClass.staticMethodText(args)> ...<.>
Obj aObj = java new &myClass:(args);  ## creates an Object

Using a Class variable is a short form to invoke:

java path.to.MyClass.aStaticMethod(args);  ## without Class variable

A benefit using a Class variable in opposite to the last example is: If the path is wrong, an exception is thrown on definition of the Class variable already.

To check whether any Object is instanceof the expected type, write

if(myObj ?instanceof myClass) { ....

The check returns true if the object is derived from the myClass or implements the given myClass-interface of course. See 10.5 Boolean expression, Conditions


9.1.11 Classpath

Topic:.JZtxtcmd.data.type.Classpath.

A Classpath-variable holds a ClassLoader-instance. The javadoc-oracle/java/lang/ClassLoader in a Java environment is responsible to load classes from any jar-file or other location and translating it into internal machince code. If the JZtxtcmd script application needs other classes than given in the classpath of the java invocation, the Classpath should be used:

Command line to invoke JZtxtcmd. Only the Zbnf.jar is given usual:

java -cp path/to/Zbnf.jar myScript.jztc

Inside the script, an additonal jar file should be used:

Classpath loader = path/to/additonal.jar;
java :loader: package.path.Userclass.main();

The example shows the invocation of the main-routine of any class, which is located in the additonal.jar.

A javadoc-oracle/java/lang/ClassLoader can know more as one jar files (and other sources of class code). It is possible to build a:

Fileset jarfiles =
( path/jar1.jar
, path2/jar2.jar
);
Classpath loader = path/to&jarfiles, D:/any/other/file.jar;

This example shows a Fileset, describing some jar files which are located in the same pool. The path/to is the common path of both. Additinal D:/any/other/file.jar is addressed. All three jar files are given with this ClassLoader instance.

One can give absolute paths to the files or relative ones. Relative paths are regarded to the current currdir directory. Usual it is set relative to the scriptdir where the main script is located:

currdir = scriptdir;
Classpath loader = relative/to/currdir/myjar.jar;

The other possibility is, relativ to the maybe included script:

Classpath loader = <:><:scriptdir>/path/myjar.jar<.>;

A Classpath variable can be used especially to create a Class-Variable.


9.1.12 Openfile

Topic:.JZtxtcmd.data.type.Openfile.

It opens a file for writing on creation. It is a javadoc-oracle/java/io/Writer and an Appendable.

Openfile myFile = "filename";
myFile += "any text";
myFile.flush();
myFile.close();

The filename can be built as text expression, of course. It have to be supplied on the definition statement.

String name = ...from any procedure;
Openfile myFile = <:><&name>.txt<.>;

It is recommended to close the file. Elsewhere the file remain open till the process, which executes the JZtxtcmd interpreter is finished on the operation system. If it is a long-running process, the file will remain open.

To provide an Openfile to another subroutine, an Objshould be used. The Openfile keyword can only be used for create and opening a Writer instance. It is an Obj:

call mySub( myFile = myFile);
...
sub mySub(Obj myFile) {
  <+myFile>output anything<.+n>

The <+append> accepts formally any Obj but expects that it is an Appendable.


9.1.13 Filepath, Fileset

Topic:.JZtxtcmd.data.type.fileset.

See examples_Fileset.

Syntax see 16.8 Fileset, Filepath.

A Filepath is a String-given path which describes a file or maybe some files with wildcards. The parts of a Filepath are divide to drive, directory path. local path, name, extension and some designations for wildcards usage. From a Filepath several Strings can be build.

See srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdFilepath: Instance which is used in JZtxtcmd for Filepath

See srcJava_vishiaBase/org/vishia/util/FilePath: Core instance which implements the Filepath with its access methods.

localfile():

As a special feature a : can be used as separation between the path and a local part of the path:

Filepath myPath = "D:/the/path:local/path/file.ext";

A Filepath can be written relative or absolute. A relative path can be associated to different base directory locations in its usage in the script. There are methods to build the file String using an access path or a common-path:

myPath.file(Appendable, commonpath, accesspath)

adds the filepath to the appendable regarding a commonpath and a accesspath. For example:

Filepath commonpath = mydocs;
Filepath accesspath = D:/data;
Filepath thefile = docA/fileX.doc;
Stringjar buffer;
thefile.fileW(buffer,commonpath, accesspath);

fills the buffer with D:\data\mydocs\docA\fileX.doc. The commonpath and the accesspath can be parameters of a subroutine and can be set for example in an included script. The file which should be handled is docA/fileX.doc. The other Filepath variables determines where this file will be located. The commonpath is an additional feature for common base paths. Usual only the accesspath is a point of interest:

Wildcards in a Filepath:

One can write a single * one time in any name of a path, maybe in a directory part too. Then all matching directories respectively files are used.

One can write a /**/ as directory in the path. That means all sub directories in any tree depth are matching:

mydir/**/*.obj

addresses all object files in any sub directory level from mydir.

my*dirs/test*/*

addresses all files in directories which starts with my end ends with dirs, then in all directories which starts with test and there all files.

The method

myFilepath.expandFiles(listToAdd, commonPath, accessPath, currdir)

builds Filepath instances for all found files and adds it to the given list.

Variable in a Filepath:

A Filepath can start with any JZtxtcmd variable. In the Filepath the variable is designated with an &. Then the Filepath starts with &. On evaluation the path the content of the variable is used. Usual the variable is a filepath too, which contains the start directory of files. This feature increases the flexibility while using FilePaths:

Filepath whichDocu = docA;
Fileset docuFiles = ( &whichDocu/fileX.doc, &whichDocu/fileY.doc);

This two statements can be written in different files, one may be included.

Usage of &$ gets an environment variable:

Filepath tmpfile = &$TMP/tmpfile.txt;

Build Strings from file entities:

The following table presents all methods to build Strings from a file entity:

Path designation:

Part designation:

windows or slash designation:

With that the following combinations exists as methods:

absolute

base_local

like given

only local

abs-backslash

like given

local

absbasepath()

basepath()

absbasepathW()

basepathW()

absdir()

base_localdir()

dir()

localdir()

absdirW()

dirW()

localdirW()

absname()

pathname()

localname()

absnameW()

pathnameW()

localnameW()

absfile()

base_localfile()

file()

localfile()

absfileW()

fileW()

localfileW()

name()

namext()

ext()

Examples using several configurations of Filepath and Fileset are contained in the Zbnf-Download examples_JZtxtcmd/HandleSomeFiles.

Fileset:

A Fileset contains one or more Filepath, it names files:

Fileset myset = ( file1.ext, path/file2.ext, "base path:local/**/file 3.*");

The ** means any directory tree depth. Wildcards can be used in directory names too. One can use slash or backslash as directory separator. The slash is recommended.

See srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdFileset.

One can build a list of Filepath with the method

List files = myset.listFiles();

Then all files from the set are presented in that list. If you invoke:

List files = myset.listFilesExpanded();

then all files with wildcards are expanded to the real existing files of the moment of execution. This method accesses the file system.

Since 2017-09: A Fileset can include another Fileset:

FileSet set2 = ( &myset, file2.ext, .....);

On listFiles() or listFilesExpanded() this sub Fileset is recognized, unpacked and included.

Using of Fileset in zmake:

zmake supports file sets because most of operation of zmake deals with files. One can write:

zmake myOutput/file.ext := makeroutine(path/sub & fileset);

whereby fileset is a name of a Fileset. path/sub is the access path to the Fileset.

Usual the access path should be a base path and the files of the Fileset describe a local path. Then one should write:

zmake myOutput/file.ext := makeroutine(path/sub: & fileset);

The colon as last character of the Filepath of the access path defines path/sub as base path.

The access path can be a variable, because a Filepath can be build with a variable:

zmake myOutput/file.ext := makeroutine(&filepath:&fileset);

In this case the filepath.file() builds the access path as base path.

Relation between base path and local path:

Especially if a Fileset is used with an access path, then the following rules are valid:

View the following examples:

Fileset fileset = (localpath/myFile, otherpath/file2.ext);

zmake output1 := routine1(base:local&fileset);
zmake output2 := routine2(path&fileset);

base:local respectively path is the access Filepath for the Fileset.

routine2 uses path as base path, routine1 use local/ from the access variable as part of the local path.

If a Filepath contains a scriptVariable, the scriptVariable will be handled in an adequate way:

Filepath path1 = base:local;
Filepath path2 = path2;
Filepath path1a = &path1/file.ext;
Filepath path2a = &path2/file.ext;
Filepath path1b = &path1:file.ext;
Filepath path2b = &path2:file.ext;

The resulting is

path1a = base:local/file.ext;
path2a = path2/file.ext;
path1b = base/local:file.ext;
path2b = path2:file.ext;

See examples_Fileset.


9.1.14 Set

Topic:.JZtxtcmd.data.type.set.

It sets environment variables for the next 7.2 start, cmd: Invocation of operation system commands.

set name = value

The environment variable is stored in the variable context with $ as prefix for its identifier. One cannot change the value of an environment variable, but the variable is possible to set newly:

Set env = "value";
cmd anyCmd;
Set env = <:>other value<.>;
cmd otherCmd;

9.2 The data path

Topic:.JZtxtcmd.data.path.

A variable of the script or subroutine level may contain a simple value or text. On the other hand

In the first case a JZtxtcmd variable can contain a reference to any Java instance. The attributes, references and methods of that instance can be accessed.

In the second case the Map refers other data by its name. It builds a tree of data.

In JZtxtcmd it is possible to build a datapath to address data. The syntax is described in 16.11 DataPath, Data access.

jztc.startmilli

is the path from the predefined variable jztc which refers the instance of JZtxtcmdExecuter to the data field srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.JZtxtcmd#startmilli.

In a Datapath methods can be invoked. For example the current directory as String with Slash (unified) can be gotten with

jztcsub.currdir()

A method can be called with actual arguments. The next example creates a user specific object and invokes a method from it. That is inclusion of Java classes pure:

Obj myObj = new mypackage.MyClass();
myObj.myMethod(5, "a string", jztcsub.currdir());

The fields and methods from any instance are found and accessed via the reflection mechanism of Java. The translator of the JZtxtcmd-script has not any knowledge of the objects and there elements. It means the translator cannot detect errors, other then a Java compiler. It is a property of script languages in opposite to static languages. Errors in access are detect on runtime via an exception, which can be catched with an onerror statement in the JZtxtcmd script:

anyObj.reference.method(parameter);
anyOther.datapath = value;
onerror {
  <+out>Access error in script: <&error><.+n>
}

A script should be checked by running all branches of software. Therewith all data paths should be checked on runtime. If a branch is not tested the a probably usefully message should be outputted.

Access to private fields and methods:

The flag

jztc.bAccessPrivate = 1;

can be set in the script. Then the datapath can access private and protected elements of a class members just as well public ones. Note that the private and protected encapsulation is forehand a property of the compilation and source dependencies. A debugger can access private members to show there content of course. Therefore it may nice to access them in a JZtxtcmd script too. But a software, including the JZtxtcmd script software should not presume the existence of the private members. Private and protected elements are not public, therefore they can be changed and removed in the software life time cycle without consultation of all assumedly users.

Syntax and implementation:

The access via datapath is implemented in the class srcJava_vishiaBase/org/vishia/util/DataAccess.

For the syntax of a datapath in a JZtxtcmd script see 16.11 DataPath, Data access

Predefined script and subroutine variable are described in 9.5 Predefined script variables


9.3 Variable definition context, datapool

Topic:.JZtxtcmd.data.defcontext.

A JZtxtcmd script knows scriptvariable, see 6.1 Script variables. They are defined at script level and contained in the script datapool. The other possibility is the class level (future extension) or the level of the routine with the local datapool.

Local variables in subroutines:

Variable which are defined inside sub routines are local valid, usual known from all static programming languages. But Variable which are defined in inner statement blocks are defined for the subroutine level, other than in static programming languages. This feature saves calculation time for nested blocks because the variable should not be copied for any inner block. Often inner blocks does not define variables, then this feature does not matter. But respect:

sub anySubroutine(String arg)
{ if(condition) {
    String s2 = arg;
  } else {
    String s2 = "other";
  }
  <+out>result= <&s2><.+>
}

It is possible to define a variable conditionally, and evaluate outside of the conditions. If the variable is not defined on evaluating time, an exception is thrown or false is returned:

sub anySubroutine()
{ if(condition) {
    String s2 = arg;
  }
  if(s2) {
    //only if s2 is existing
    <+out>result= <&s2><.+>
  }
}

For checking the existence of a datapath see10.5 Boolean expression, Conditions.

On comparison with static languages it is:

void aC_function(char const* arg)
{ char const* s2;  //defined but not set.
  if(condition){
    s2 = arg;
  } else {
    s2 = "other";
  }
  ...
}

The C/C++ or Java language needs the declaration of the variable outside the nested statement block but the assignment can be done inside. There may be the adequate effect: an undefined variable. But the Java compiler detects this situation on compiletime (other than C), the JZtxtcmd script execution detects it on run time only.

Note that the last value of an element of a

for(element: container){
  //...
}
<+out>last element:<&element><-+>

is existing outside of the for loop because that behaviour. Other than in static languages. In case of doubt you should not use that property. Use the policies of static language for a well program structure. But you can use that behaviour if it is gainful for your solution.

Tree of variable definition, build structures:

It is possible to define a tree of variables. A variable acts at tree root, some variables are defined below that root, that variables can act as tree root too. A treelike structure of variable offers a struct definition of data. It is possible to use the root variable of a tree or any of its boughs as argument of a subroutine. Then the subroutine knows all data of that bough. Note that it is another concept of structuring data than in C with a struct definition.

The writing rule for definition a variable inside a tree is:

Obj myContainer.insideContainer.newObjvariable;

That defines the myContainer if not existing yet, inside the deeper level insideContainer and then the Object Variable with name newObjVariable.

It is possibile to deal with myContainer for example to supply it to a sub routine call. The sub routine gets the content of this container and can define inside more variables:

sub mySub(Obj container){
  String container.myStringInSub = "anyText";
}
...
call mySub(container = myContainer);

This possibility builds data structures in form of variables in a pool. The container is a Map<String, DataAccess.Variable> with the given name of the variable.

It is possible too to create a variable in this kind in a existing user level Java instance:

Obj myJavaObj = anyOtherAccess.getJavaObject(); //gets the reference in the given context
String myJavaObj.container.newString = "xxx";   //creates a String Variable in the users instance.

With them in the Java programming level that data can be used:

myJavaObj.doAnything();   //invokes a method of the Java instance.

A simple variable without dot or the start variable will be created in the datapool of the context, either in the script, or at class level or as local variable of the routine. Because a subroutine has its local datapool, the script variables are never destroyed. A defined variable in a sub routine with the same name like a script variable covers the script variable. This is a well used effect if necessarry. The created variable is a instance of type srcJava_vishiaBase/org/vishia/util/DataAccess.Variable. This instance contains the name, the type, the const designation and an Object reference to the value. The datapool is a Map<String, DataAccess.Variable> with the name as key.

If a variable is existing already, it will be created newly. Normally a variable should not be declared twice. But it is not checked. In further versions of JZtxtcmd a second definition may be cause an exeception. Don't do so.

The next level after a dot is either a 9.9 Access to Java internal data or the level before is a datapool. A new variable will be created always inside its left side datapool. The following rules are valid:

Examples:

For the syntax of variable definition see 16.7 Variables.


9.4 Datapath depending on Variables

Topic:.JZtxtcmd.data.dataElementVar.

Sometimes it may be necessary to access data depending on other conditions. For example access data in a tree which is build from any data base. Instead write

if   (ctrlVar == "A"){ data = path.to.A.data; }
elsif(ctrlVar == "B"){ data = path.to.B.data; }

one can write:

data = path.to.&(ctrlVar).data;

The content of ctrlVar replaces that part inside the Datapath. Of course only admissible values can be processed. Elsewhere an exception is thrown which can catched with 12 onerror - Exceptionhandling.

An example for that is contained in examples_JZtxtcmd/TestAll/testAll.jz.bat in the sub testVariableDatapath().


9.5 Predefined script variables

Topic:.JZtxtcmd.data.prevar.

Some variables are defined on start of JZtxtcmd-execution and for any sub level. They are constant, it means not able to change in the users script. Some variable are constant for the whole execution, some variable are set for special situations. They are:

The following static classes are provided as 9.1.10 Class - ?instanceof check, class loader, static method invocation script variables for simple access to static methods:

Some variables are defined in any subroutine level. That are local variables, which are independent only valid for the subroutine level:


9.5.1 jztc

Topic:.JZtxtcmd.data.prevar.jztc.

It references srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.JZtxtcmd. Able to use for:


9.5.2 jztcsub

Topic:.JZtxtcmd.data.prevar.jztcsub.

It references srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.ExecuteLevel. Able to use for:


9.6 Definition and change of script variables

Topic:.JZtxtcmd.data.var.

Script variables have a global character. They should be only a few variable, able to look over them. Some script variable are pre-defined and not able to change. Some other script variable can be changed but that is restricted. Normally the subroutines get a local copy of the script variables, so a change of it does only change the value of the local copy. In seldom cases a change of a script variable should be required. That can be done by using the script variable jztc. It is the JZtxtcmdExecuter itself, see 9.5 Predefined script variables. One should write

jztc.scriptVariables().TEST = "new script value";

to copy the local value of - for example TEST to the script variable. That should only be done if the variable for the whole script need to be changed really. It should not used because it is more simple to deal with that value between two sub invocations.

//Negative pattern:
call mySub1(...);  //changes the TEST globally.
call mySub2(...);  //Uses the changed value of the global variable.

That is an simple old programming style. It disadvantage: A subroutine can not assert that the value of a script variable is set with the known value of the script, any other program part may have change it for its stuff.

If it is necessary to have a changed value of a script variable, you can change it locally:

TEST = "new value";  //changes the local copy

If subroutines of a deeper level should use this changed current directory, it is possible to give it as a parameter:

sub mySub(TEST=TEST,...){...}

That subroutine defines a calling argument TEST, it is initialized per default with the current value of TEST of the script, not of the caller.

If that subroutine should override the script variable of TEST one should write:

call changeCD(TEST=TEST);

9.7 Access to environment variables

Topic:.JZtxtcmd.data.env.

Environment variables of the systems environment which has called the JZtxtcmd process are available with

&$name

Especially the standard operation system variable are stuff to use, such as &$HOME, &$OS Which variable are existing depends on the operation system and the calling environment.


9.8 Access to JZtxtcmd local or script variables

Topic:.JZtxtcmd.data.env.

The first level of a variable is a local variable of the current JZtxtcmd subroutine or a scriptvariable of the current jztc Script. Note the existence of 9.5 Predefined script variables.

A JZtxtcmd variable can be stored in a tree structure. A node is a 9.1.8 Map - a Set of variables, the last element is the specified JZtxtcmd variable. To access such a treed variable write

localVar.subvar.subsubvar

Note that such a structure can be defined with

Map localVar;
Map localVar.subvar;
String localVar.subvar.subsubvar;

It is possible too to transport a reference to a node to any subroutine:

call mySub(localVar.subvar);
sub mySub(Map map){
  <+out><&map.subsubvar><.+n>
}

In a context where a normal text is parsed as text literal a * have to be written before the variable. For example:

call mySub();  //mySub is the direct name
call *mySub(); //mySub is a variable which contains the name.
cmd execute.exe argument;   //"argument" is the direct argument.
cmd execute.exe *argument;  //argument contains the argument string.

The same rule is valid for environment variables: &$envvar in that adequate context.

Variable can start with $ in its identifier. That are conventionell JZtxtcmd variable. But they are used as environment variable for 7.2 start, cmd: Invocation of operation system commands.


9.9 Access to Java internal data

Topic:.JZtxtcmd.data.jdata.

The first tag to access to Java internal data is a JZtxtcmd variable. It can contain any Reference to a Java object. For example a new Object can be created:

Obj myBuffer = new java.lang.StringBuilder("initial text");

If a JZtxtcmd script is embedded in a Java environment some JZtxtcmd script variables can be predefined with references to Java objects. For example refer Zmake. A Zmake generation script is a JZtxtcmd script. It knows via zmake all necessary stuff from the zmake input file.

To access to java elements one can write

myBuffer.insert(8, "any other ");

in this example insert(...) is a method from the referenced class javadoc-oracle/java/lang/StringBuilder.

The path starting from the JZtxtcmd variable is written in normal Java language style. It is executed using the Reflection mechanism of the Java language.

The actual arguments of methods are 10 Expressions, see also the syntax in Chapter: 16.10 Object value: objExpr. If a method expects a java.io.File as argument, one can write

to get a file object with the textual given path. Note that return values from 9.1.13 Filepath, Fileset is a CharSequence. to convert it to an expected File instance write

java pkg.path.javaMethod(..., File: &myFilepath.absfile(), ...);

References to other instances can be given with datapaths too:

Obj myStringPart = new org.vishia.util.StringPart(myBuffer);
java pkg.path.javaMethod(..., myStringPart, ...);

The constructor of StringPart expects a Reference to an java.lang,CharSequence which is given with the myBuffer. The mechanism of overloaded (argument dependent) methods works properly.

Access to protected and private elements:

The access is restricted normally, only public members can be accessed. But it can be unlocked. The cmd line Argument

-accessPrivate

of srcJava_Zbnf/org/vishia/jztxtcmd/JZtxtcmd

respectively calling arguments accessPrivate

of srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter#execute(org.vishia.cmd.JZtxtcmdScript, boolean, boolean, java.lang.Appendable)

can be set on invocation of JZtxtcmd. Then the access to private members are unlocked. Private members may be necessary to access for example for debugging.

The access to Java data can be a long term, started on any given variable in the JZtxtcmd context:

 myVariable.field.method().fieldB

In this example the method() may return an instance which's fieldB is accessed.

If an instance is a java.util.Map the next element is taken is key for the map to select the member:

myVariable.myMap.key

It is the same to write

myVariable.myMap.get(key)

A special feature is, to hold the name inside a variable:

myVariable.myMap.&(variableContainsKey)

The length of an array or the size of a java.util.Container or java.util.Map can be requested by

myVariable.myMap.[]

The [] should be associated with the length of the whole container.

To Access array elements you can use the known

myData[index]

but yet only with one index as constant value. (2016-01-17). It is proper to read out data from a pre-prepared array.


9.10 Access to static Java data and Invocation of static Java methods

Topic:.JZtxtcmd.data.jstatic.

The keyword java or a simple % on start of a datapath declares the path as a package.class path to a Java class or method.

Obj myObj = java org.myPackage.MyClass.getData(args);
java org.myPackage.MyClass.doAnything();
%org.myPackage.MyClass.doAnything();

Alternatively a Class variable can be used to invoke a static method:

Class MyClass = java org.myPackage.MyClass;
...
MyClass.doAnything();

The package path should be complete and the classes should be able to find by the running JVM. It means self-written Java classes should be the part of the class path of the invocation of JZtxtcmd. Alternatively the capabilities of the java.lang.ClassLoader can be used.

Some classes are able to address by the name without the package path. It is more easy to write. That are classes which provides often used static methods. The following identifier are pre-defined as Class-Variable:


9.11 Creation of new instances of Java classes

Topic:.JZtxtcmd.data.jnew.

The keyword new or java new on start of a datapath declares the path as a package.class path to a Java class for creation a new instance.

Obj myObj = java new org.myPackage.MyClass(args);

The package path should be complete and the classes should be able to find by the running JVM. It means self-written Java classes should be the part of the class path of the invocation of JZtxtcmd. Alternatively the capabilities of the java.lang.ClassLoader can be used.


9.12 Invocation of Java methods, arguments

Topic:.JZtxtcmd.data.method.

A method invocation is part of a Chapter: 9.2 The data path.

Static java methods can be invoked with 9.10 Access to static Java data and Invocation of static Java methods. The following examples shows the invocation of the static method atan2 (arcus tangens) with 2 numeric values:

Num value = java java.lang.Math.atan2(1.5, 2.2);

An interesting case is the invocation of a

public static final void main(String[] args){ ... }

which is the main routine of all Java classes which can be ivoked by a command line. In a JZtxtcmd script you can write:

java myPackage.Path.Class.main();
java myPackage.Path.OtherClass.main("argument", <:>argument <&variabe><.>, "third argument");

If a method expects exactly one argument of type String[] and all given arguments are CharSequence, then the proper String[] will be build with all given CharSequences. If no argument is given, that routine gets a String[0].

Non-static Java methods can be invoked either on a reference to a 9.11 Creation of new instances of Java classes or on a Java instance referred with a 9.5 Predefined script variables. The following example creates an instance and invokes a method from them with numeric values:

 Obj obj = new org.vishia.zcmd.JZtxtcmdUserExample();
 obj.methodTest(5,8);

The arguments are an ObjExpr, see 10.4 Object expression and syntax: 16.10 Object value: objExpr. The expression will be translated to the internal presentation in JZtxtcmd and it will be calculated on Runtime before the method is searched.

Methods in Java are argument-sensitive (adequate in C++ also). It means, methods with the same name but with different argument numbers or types are different methods. Therefore the argument should be checked. Additionally the arguments should be converted. It is done as capability of srcJava_vishiaBase/org/vishia/util/DataAccess.

A numeric value will be calculated and the result will be converted if possible. For example

 Obj obj = new org.vishia.zcmd.JZtxtcmdUserExample();
 obj.methodTest(5*Math.PI, 8+5);

In this case the first argument uses the JZtxtcmd variable Math which is the class javadoc-oracle/java/lang/Math to get the value of pi. The double density value of 5*pi is converted to the requested float. The second argument is 13.

An integer value can be converted to a char. A String with exactly 1 character can be converted to a char argument:

 obj.methodTest('a');
 obj.methodTest('b'-1);
 obj.methodTest(65+32);
 obj.methodTest(0x61);
 obj.methodTest("a");

All this examples invokes the method methodTest(char cc) in that class with the character 'a'.

Any CharSequence can be converted to a String:

 ## invokes methodTest(String)
 obj.methodTest(<:>content of <&obj><.>);

The expression is calculated in a StringBuilder-Buffer. It is converted to a String because the methodTest(String) exists.

A boolean argument can be given with an integer value:

void myMethod(int a, boolean b) ...//Java
obj.myMethod(23, 1);  //JzTxtCmd, give ,,true,, for ,,b,,.
Num value = 34;
Num condition = 1;
obj.myMethod(value, condition);  //JzTxtCmd, from variable.

A Bool condition = 1 does not work unfortunately till version 2018-08.

Bool condition = a > b;  //can be used from version 2018-09

The possible conversions are programmed in srcJava_vishiaBase/org/vishia/util/DataAccess in private initConversion().

If a method requests a javadoc-oracle/java/io/File it can be written:

obj.methodTest(File: "myFile");
obj.methodTest(File: path/theFile.ext);

The File: causes to convert the following text expression to a file path and name with the currdir how it is set in the JZtxtcmd context.

Note that comlex numeric calculations are much slower than in a Java execution environment because the JVM translates operations from its bytecode in machine code before execution. Therefore a Java Bytecode execution is aproximately equal fast like programming in a direct compiled language such as C or C++. But the JZtxtcmd execution is really an interpreter and therefore slower. Complex numeric calculations should be programmed in Java. But the numeric calculations are not slower as in other script languages.


10 Expressions

Topic:.JZtxtcmd.expr.

An expression can be used to combine something to assign its result to a variable or for a actual argument only. The basic idea of Functional Programming is, expressions to calculate something ('functions') should not have side effects.

An expression can have side effects, it changes other data. The so named 'side effect of an expression' can be the goal to invoke an expression. Calling a procedure.

It is the same like in all other programming languages.

The result of an expression can associated to the categories:

To concatenate strings see 13 Text output and text generation.

A numeric or boolean value is stored in the wrapped form as Object.


10.1 Operands of the expression, constants, Java DataAccess

Topic:.JZtxtcmd.expr.DataAcess.

Operands are either

See, 9.8 Access to JZtxtcmd local or script variables or 9.9 Access to Java internal data.


10.2 textValue or textDatapath

Topic:.JZtxtcmd.expr.textDatapath.

See its syntax in 16.9 Text value: textDatapath, textValue.

textValue

If a text is expected in the syntactical context the constant text can be written as usual. For example in 7.2 start, cmd: Invocation of operation system commands a command can be written simple as:

cmd notepad.exe myfile;

It is like a command line in a batch file or shell script. The spaces are the separator between arguments. Any argument is a textValue. Note that a textValue written as simple text cannot start with an ampersand & and ends on a whitespace or one of the character ;,)(.

If a constant text should not be used rather the content of a variable one can write:

cmd &myCommand &myArg;

If the textValue starts with an ampersand, a 16.11 DataPath, Data access follows. In the simple kind it is the name of a variable which's content is used.

Alternatively a textvalue can be written with quotation mark like known:

cmd notepad.exe "my file with spaces in the name.txt"

The forth form is use an 10.3 Text expression for a textValue. It offers the possibility to assemble the text with variable content in any desired form. One can write for example:

cmd notepad.exe <:><&topic>.<&extension><.>;

In this case the file name for the notepad is built with the content of a variable topic and a special extension stored in the variable extension.

textDatapath

If a text is expected but usually not an immediately text a textDatapath is used syntactically. To get a constant text one should be used quotation marks. It initializes with a constant text. Writing of quotation marks are usual in that kinds:

String myVariable = "any text";

A datapath can be written immediately. A simple String is recognized as identifier. For example, the new defined String myVariable is filled with the content of otherVariable:

String myVariable = otherVariable;

For compatibility you can write also, the & is optional. Then the textDatapath and the textValue are written with the same syntax:

String myVariable = &otherVariable;

Note that a datapath can be a variable path. In the following example the datapath is contained in the variable a_datapath, see 9.4 Datapath depending on Variables:

String myVariable = &(a_datapath);

The same in a textValue but compatible in a textDatapath can be written as:

String myVariable = &&(a_datapath);

A textDatapath can be build with an Chapter: 10.3 Text expression too, it is the same like in textValue:

<:>a textDatapath with <&value><.>

10.3 Text expression

Topic:.JZtxtcmd.expr.textExpr.

See also Chapter: 13 Text output and text generation

Syntax see Chapter: 16.14 TextExpression

A textExpression is written between

<:>the text expression<.>

if it is used as an argument String or for assignment to a String or Stringjar or Obj-Variable.

Text expressions are used for 13 Text output and text generation respectively write into files and output texts to console. The the expression is written between

<+channel>the text expression<.+n+flush>

A text expression can contain:

A text expression can be spreaded over some lines, whereby indentation is regarded, see 13.3 Lines and indentation in the script

Simple example: build a path relative to the script directory:

<:><:scriptdir>/my/file.ext<.>

For example a String argument should be given for a subroutine or Java method invocation. The argument list may contain:

myObj.method(<:>The String with <&variable> has called <&otherObj.method(<:>with <&variable><.>)><.>);

In this example two text expressions are nested.


10.4 Object expression

Topic:.JZtxtcmd.expr.objExpr.

Syntax see Chapter: 16.10 Object value: objExpr.

Any free instance is an java.lang.Object and it can be stored as an Obj:

Obj data = myDatapool.method(args);

The args are an Object expression too. The gotten instance has its specified type of course. Therefore any method of this type can be used:

data.specialMethod(args);

Because the JZtxtcmd is an dynamic language, not only the few methods of java.lang.Object can be invoked.

An Object expression can be build as Map of some named Objects:

Obj myDatastruct = { String val1 = "anything"; Obj data = theData; };

That is usefull if the Object with more as one data should be stored and transfered in an container.


10.5 Boolean expression, Conditions

Topic:.JZtxtcmd.expr.bool.

Syntax see Chapter: 16.12 Condition expression.

To get boolean values with boolean operators especially for method arguments one have to be used the JZtxtcmd

bool( boolExpr )

method. To check conditions in 8 Program flow control one should write

if( boolExpr ) { ... }

A boolExpr can contain && and || and the ! like known for Java, C. Instead ! not can be written. It may be better visible in a JZtxtcmd script. The bool(...) syntax is not necessary if only boolean is expected, especially in 8 Program flow control.

The operands for boolean logic are either compare results or simple values.

Not found variable:

A boolExpr which contains only a 16.11 DataPath, Data access is false if the data path is faulty. A NoSuchFieldException or a NoSuchMethodException are catched and forces the false value. In this kind the user can write

Obj exist = bool( data.path);

then exists is set to false or true depending of the corretness of the path.

if(data.path){...}

is not executed if the path is faulty or the variable is null or 0, whereby

if(not data.path ==null){...}

causes an exception if the data.path is faulty, because the path is used to compare.

Comparison:

Two numeric expression results can be compared using

==  !=  >   >=  <   <=

like it is known in Java, C. Alternatively it can be used

?eq ?ne ?gt ?ge ?lt ?le

especially in text generation parts because > has an abbreviating meaning <&textpart> etc, see 13 Text output and text generation.

Note that comparison are parts of a boolean expression. bool(a > b) should be written to build a boolean value of the comparison.

Comparison of Strings:

If you write

myVariable == "reqested text"

and the variable is a CharSequence, the content is be checked on equality. != can be checked too. The operation

myVariable >= "starttext"
myVariable ?ge "starttext"

returns true, if the variable startsWith the comparison text. The >= means it may be longer or equal. It is not a comparison of alphabetic order. The >= it usefull in some operations. Another proper special operator is

myVariable > "containstext"
myVariable ?gr "containstext"

It returns true if the variable contains the text.

That comparison are done if both operands left and right of the compare operator are a CharSequence such as a javadoc-oracle/java/lang/String, a javadoc-oracle/java/lang/StringBuilder or a Stringjar: srcJava_vishiaBase/org/vishia/util/StringPartAppend.

Check of a reference whether it is null:

In difference to Java language it is possible to write simple

if(myObject) { ...

If the myObject is null that expression is false. myObject can be any reference in any data.

instanceof - Check of a reference whether it is an expected type:

Similar to Java language an Object can be checked whether it is an instance of an expected type. Write

Class myExpectedType = org.myPackage.MyType;   ##used for instanceof check

Obj anyObj = ...
Class
...
if(anyObj ?instanceof myExpectedType) { ...

The ?instanceof operator needs on left side any Object and on right side a Class object. It is true if the class is type of the given type, maybe in an super class too.

Automatic conversion to boolean:

Inside a bool(...) respectively in a boolean expression of a control statement an automatic boolean conversion is done:


10.6 Numeric Expression

Topic:.JZtxtcmd.expr.num.

Syntax see Chapter: 16.13 Numeric Expression

A numeric expression can be build with the ordinary numeric operators + - * / and ( ) with numeric values. Functions can be called with the javadoc-oracle/java/lang/Math methods.




Class Math = java.lang.Math;  ##defines Math in a variable

Num y = Math.sin(0.1);               //calculates
Num y2 = %java.lang.Math.sin(0.1);   //long form for static methods
<+out>y = <&y:%1.5f> <.+n>           //outputs it with given format.

Usual numeric expressions may be used only for building of arguments for some methods. Complex numeric calculations should be programmed in Java routines. arrays are supported yet only with access to 1 index as constant (2016-01).


11 Multithreading

Topic:.JZtxtcmd.thread.

Multithreading is an important capability, which is missing in some other script languages. For example an executable can be started via 7.2 start, cmd: Invocation of operation system commands which needs some time to execute. Simultan another executable can be started. It needs its own thread because the thread should wait of finish the cmd line process when its result is needed. Java methods can be started too in the other thread. Then it works in the same process space with possibility of data exchange.

A thread is able to define in two ways:

{ ... any statement block;
  thread {
    ... statements;
  }
  ...more statements,
}

The thread starts if the execution in the parent statements arrives the thread statement. The thread is executed concurrently to the parent statements with the Java's VM thread capability. It is similar as a _Fork_(system_call)_(Wikipedia) in UNIX systems, but with a second thread in the same process of operation system. In opposite fork creates an new process on operation system level.

If the last statement of the thread is finished, the thread will be removed.

If the parent statement block reaches its end, the thread is not influenced. The thread block is independently. But the thread block uses the same local variable as the parent statement block. It means, that variables are not removed so long as the thread runs.

{ parent block;
  Thread myThread = {
    ...threadblock;
  }
  ...
}

The second form uses a dedicated thread variable. But it is the same principle and an adequate syntax. The thread variable is type of srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdThread. The state of the thread can be gotten by reading the variable srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdThread#state. Last not least the method srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdThread#join(int) can be called in any other thread (usual the main thread) to await the finishing of that thread. This is a join operation.

The statements of a thread can produce text with <+>text<.+> which is merged in the output text consistently. The text generation is not interrupted between <+> and its closing <.+> by another thread, it is synchronized.


11.1 Commands and messages to and from a thread

Topic:.JZtxtcmd.thread.msg.

The class JZtxtcmdThread contains 2 queues one for commands, one for messages. A thread can await a command writte with:

 Obj cmd1 = myThread.awaitcmd(100000);  ##NOTE: cmd is a keyword, use variable name 'cmd1'

For that time the thread is dormant. The command is type of docuSrcJava_vishiaBase/org/vishia/cmd/JZtxtcmdThread.MsgItem. Any other thread can send a command to the JZtxtcmdThread instance with

myThread.sendcmd("command", anydata);

The Thread can send a message with

myThread.sendmsg("identifier", data);

which is awaiting by another thread:

myThread.awaitmsg(10000);

The argument is the timeout time. Because JZtxtcmd is not used for interactive operations but for batch processing the waiting time need only for execution time of some other operations. The timeout is proper if any thing hangs.


11.2 Join two threads, Fork and join the task

Topic:.JZtxtcmd.thread.join.

One thread can wait till the other thread is finished with its work:

if(myThread.join(10000)) { .... }

The join method returns with false if the timeout expires. This capability is important if a common task is splitted and should be continued if both parts are finished. Join with more than two threads is possible with some join invocations one after another.

Because multi-core processing is usual the fork and join can save time. The Java Virtual Machine respectively the operation system will divide several threads to extra cores if there are enough CPU time for that. Then the execution works really simultaneously.


12 onerror - Exceptionhandling

Topic:.JZtxtcmd.onerror.

Syntax see 16.17 Exception handling.

The Wikipedia:_Exception_handling is a core concept of a modern programming style. Older programming strategies works with an error variable for example the errorlevel of MS-Windows commands and batches or the errno variable in C language (Wikipedia:_Errno.h). In that older style an error have to be checked. If the error was not recognized, the algorithm is continued with erroneous data.

The basic idea of the modern exception handling is: The causer of an error may not correct the problem - it can be propagate the situation only.

If an error occurs then the normal operation order is aborted without additional programming effort. The program flow is continued on an proper catch block. That block can be located in the own procedure or in any superior calling level. In the catch block either the whole program may be aborted with a proper output, it is the simple variant, or erroneous or missing data are replaced and the session can be go on.

On the other hand errors such as missing variables should not cause an aborting of the algorithm, instead it should only reported and the algorithm should be continued. Especially on text generation the generated text can contain such error reports instead of the expected text parts. The generated text can be checked wether it contains such error reports. They should be fixed in the JZtxtcmd script language or in the called Java routines, - and then generate ones more! This strategy is substantially the same like the throw-catch. The catch routine generates the error report into the output text.

There are two types of exception thinking:

Not at any time a programmer should think: There is never a reason for a mistake, it doesn't be need to handle. Think: The unknown reason cannot be known! It is adequate Murphy's Law. Therefore a) is present anytime.


12.1 errortoOutput

Topic:.JZtxtcmd.onerror.errortoOutput.

With the statement

errortoOutput;

all errors of execution are written in the current output text in the form

<??? error-report ???>

That flag is valid for the sub routine and all called levels till the statement

errortoOutput off;

but not for superior (calling) levels. It has not a script-global effect. If it is given:

errortoOutput;  //set on script level

it is valid for the script. In a sub routine

errorToOutput off;
statements ...;
on error{
  exception handling statements;
}

can be set though the scriptlevel sets errorToOutput.


12.2 onerror statement block

Topic:.JZtxtcmd.onerror.onerror.

The statement

onerror {
  statementblock
}

can be inserted after some statements inclusively calling of sub routines, which may throw an exception. On exception the JZtxtcmd execution is continued on the next found onerror statement with the proper type. This block is executed.

If an onerror block is found in the normal statements order, it is skipped.

The onerror block is the catch block in comparison to Java, C++ and other adequate programming languages. A try is not necessary in JZtxtcmd. All of the program code is tried.

That mechanism works both for internal thrown Exceptions in Java codes and the throw statement in JZtxtcmd.

There are a few types of onerror:

onerror notfound { ... }

It is executed especially if a variable is used in a JZtxtcmd script which is not existing. JZtxtcmd is a dynamic languages, which does not check the existence of variables on compile time. Furthermore that type is used if a field or method is not found in any Java classes using reflection. Commonly one can say if a datapath is faulty. See 9 Data and variables, especially 9.8 Access to JZtxtcmd local or script variables and 9.9 Access to Java internal data. That onerror block may be usefull if a script is written newly. The associated exception types are javadoc-oracle/java/lang/NoSuchFieldException and javadoc-oracle/java/lang/NoSuchMethodException

onerror file { ... }

Files are a known causer of errors. A file can be deleted thought its existence is expected. It can be write protected, locked, corrupted, or the media is not present. All that errors are subclasses of javadoc-oracle/java/io/IOException whereby the javadoc-oracle/java/io/FileNotFoundException is a known candidat of this group.

onerror exit { ... }

This exception is thrown by an exit statement of a JZtxtcmd script. Any subroutine can invoke exit. But whether the whole program is exited or not can be catched with this onerror handling. Normally exit should be done. But if a sub routine is called and the caller has a replacement strategy, the exit can be prohibited. The error type which is thrown is srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.ExitException.

onerror cmd { ... }

This onerror handling is especially for the throw on errorlevel statement after cmd line invocations, see 7.2 start, cmd: Invocation of operation system commands.

onerror internal { ... }

This onerror block is used for all other Exceptions especially any of the javadoc-oracle/java/lang/RuntimeException.

onerror { ... }

If an error type is not given, all Exceptions where catched here.

In the statements of an onerror-Block should offer alternatively handlings and set data with proper values. To control the program after such an block, all further necessary data should be set with proper information.

For example a file cannot be read. Some Information are not present. But all others of the following algorithm should be done nevertheless. Write

data = anyReadAlgorithmFromFile();
onerror file {
  data = "default-value";
}

The following algorithm does not need to know about the file read problem, it looks only to data.


12.3 Exception handling for cmd line invocation

Topic:.JZtxtcmd.onerror.throwCmd.

See Topic:.JZtxtcmd.statements.cmd.errorlevel.@$chapter

The cmd line invocation ends with an errorlevel which is stored in the variable jztcsub.cmdErrorlevel. An exception is not thrown. That is the old style of error handling. But with the statement

throw on errorlevel 99

an exception is thrown if the errorlevel is greater or equal the given number (99 in example). It means the next statements are skipped till the next onerror block or the subroutine if left if there is not an onerror block and the next expressions in the superior routine are skipped etc.


12.4 conditional throw statement

Topic:.JZtxtcmd.onerror.throw.

In a JZtxtcmd an exception can be thrown usual conditionally:

if(condition){ throw "any text"; }

It throw an org.vishia.cmd.JZtxtcmdExecuter$JZtxtcmdThrow exception. The execution is continued on the next onerror block.


12.5 Show exception information

Topic:.JZtxtcmd.onerror.info.

The following data access paths can be used:

error
excStacktraceinfo()
jztcsub.threadData.exception

The text of an exception is stored in the error variable. That variable can be used especially to log the exception.

<+log>Exception <&error><.+>

The Exception object itself (derived type of javadoc-oracle/java/lang/Throwable is stored in the jztcsub.threadData.exception field. See 9.5.2 jztcsub.

A Stacktrace can be reported by using

String stacktrace = jztcsub.excStacktraceinfo();

This method returns in one line the information about the exception (Type, message) and the stacktrace for up to 20 levels in a one-line-presentation. The one-line is an advantage if this information should be merged in an outputted text: It does not disturb the line structure.

An example for sucn an line with wrapped lines for better readybility, it is one line:

JZtxtcmd.execute - exception at; @D:\vishia\ZBNF\sf\ZBNF\examples_JZtxtcmd\T
estAll\testAll.jz.cmd:142,28; e <*);; java.lang.NoSuchFieldException:
DataAccess.getData - not found in  datapool; unknown; datapool contain
s; :$TEST, FileSystem, StringFunctions, System, console, conv, err, er
ror, error, file, jztc, jztcsub, nextNr, nextnr, null, out, scriptOb
j, scriptStringEmpty, scriptStringSet, scriptStringSet2, scriptdir, sc
riptfile, test, text, ; org.vishia.util.DataAccess.access(DataAccess.j
ava:670); org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.dataAccess(JZtxtcmdEx
ecuter.java:1964); org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.executeDa
tatext(JZtxtcmdExecuter.java:1590); org.vishia.cmd.JZtxtcmdExecuter$ExecuteL
evel.execute(JZtxtcmdExecuter.java:752); org.vishia.cmd.JZtxtcmdExecuter$Exe
cuteLevel.execute(JZtxtcmdExecuter.java:662); org.vishia.cmd.JZtxtcmdExecute
r$ExecuteLevel.textAppendToVarOrOut(JZtxtcmdExecuter.java:1169); org.vish
ia.cmd.JZtxtcmdExecuter$ExecuteLevel.execute(JZtxtcmdExecuter.java:714); org
.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.execute(JZtxtcmdExecuter.java:662)
; org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.execSubroutine(JZtxtcmdExecut
er.java:1321); org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.execCall(JZcm
dExecuter.java:1211); org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.execut
e(JZtxtcmdExecuter.java:753); org.vishia.cmd.JZtxtcmdExecuter$ExecuteLevel.e
xecute(JZtxtcmdExecuter.java:662); org.vishia.cmd.JZtxtcmdExecuter.execute(J
ZcmdExecuter.java:431); org.vishia.zcmd.JZtxtcmd.execute(JZtxtcmd.java:398);
org.vishia.zcmd.JZtxtcmd.execute(JZtxtcmd.java:354); org.vishia.zcmd.JZtxtcmd.s
main(JZtxtcmd.java:190); org.vishia.zcmd.JZtxtcmd.main(JZtxtcmd.java:142);

One stacktrace level is presented with (last line of the example):

 org.vishia.zcmd.JZtxtcmd.main(JZtxtcmd.java:142);

In an Eclipse console window that format is shown with links to the source code, like usual with an eclipse-generated stack trace. The method and the file and line is shown.


12.6 Omitted stacktrace for JZtxtcmd call levels

Topic:.JZtxtcmd.onerror..

The exception information contains the original exception type and text from its Java internal context inclusively the stacktrace in the Java context. Additionally the file and line-number and a short presentation of the JZtxtcmd statement is shown, where the exception was caused. If the onerror {...}-block is found in a superior subroutine level, the calling order to the subroutine is not shown (no stacktrace at JZtxtcmd level). Usual the calling order is less complex as in Java method nesting. See the example:

sub routine(){
  line = causes.exception;
}
sub callingRoutine(){
  call routine();
  other statements;
  onerror{ <+out>error: <&error> <.+n>
}

The error variable contains the line where the exception was caused. Though the onerror-catch block is in the other subroutine it is evident that the call routine() was executed lastly before onerror. If that routine contains:

sub callingRoutine(){
  call routine();  ## first
  other statements;
  call routine();  ## second
  onerror{ <+out>error: <&error> <.+n>
}

it is not clear whether the first or the second call is done lastly. But usual this fact may not important. Therefore the effort of a stack trace on JZtxtcmd execution is omitted. The Java stacktrace shows indeed the fact of calling a subroutine, but it also does not contain the fact which line causes the call. A stacktrace in Java does not contain data unfortunately.

If a debugger is used, for example with an Eclipse environment, a break can be set in the catch block of the method srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.ExecuteLevel#execute(...) to view details.


13 Text output and text generation

Topic:.JZtxtcmd.text.

The capability of text generation is used either to build arguments or textual values for Strings or to produce output text.


13.1 Text output

Topic:.JZtxtcmd.text.out.

For building a text expression the text should be surrounded with

<:>That is the text with <&variable>-content or <&obj.operation()><.>

If the text is written in more as one line, either a line break can be suppressed using

<:>Text in one line <: >
  but written in the script in more lines<.>

The all white spaces after <: > are skipped. Or: The text can be marked with

   .....some script statements maybe indented
    <:>
====    The indented text, but with 4 spaces only
====  } //end of block for example in a generated source
    <.>

The == till the position of <:> in the line above are skipped. That helps to designate text part in a script.

Inside a text expression subtexts, if and for-container can be used, special characters can be used:

  <:>Text <:if:condition>with conditional parts><.if> continue though line break in script:
==<:for:item:containerVariable>repeated <&item.text> <.for> <: >
  <:call:subtext:argument,argument>
==<:n><.>

The subtext is the name of the sub subtext routine, see Chapter: 6.5 Subroutines and subtext, or the name of the subtext routine can be gotten from a String variable writing <call:&subtextvariable:...>. That enables more complex controlled sub texts.

A text expression used especially for assignment and argument string is written like

String var = <:>this text is assigned to the var<.>
call subroutine(<:>text used as argument<.>);

A text expression is outputted to the JZtxtcmd output file if it is not a part of an assignment or argument:

<:>this text is written to the text generation output<.>
<+>it is the same output<.>

The JZtxtcmd output file can be determined by -o=file option on invocation or with setting the script variable

text = "path/to/file.txt";

If a subtext is called inside the

sub mySubtext(args)
  <:>This text is the output of the sub text -
    the core funtionality of the subroutine
  <.>
  <+>But this text is written to the text generation output immediately<.>
  <+out>Of course the standard output can be used<.<

A text can be send to the

<+out>Text to standard out, it uses System.out from Java<.>
<+err>Text to standard err, it uses System.err from Java<.>

It depends on the settings in the Java environment whether this text is written to console output or it is redirected anywhere other, using System.redirectOut(PrintStream).

To write text into a file one can write:

Openfile myfile = "path/to/file.txt";
<+myfile>Write text<.+n>
...
<+myfile>more text<.+n>
myfile.close();  //the file should be closed!
<+myfile>The last line<.+n.+close> //alternative close

To flush or close the text output, one can write:

<+>a line seen in the output file<.+flush>
<+>another line with newline on end<.+n+flush>
<+>The last line<.+n+close>

After <.+close> or <.+n+close> the next <+myfile>text...<.> causes an NullPointerException because the output is closed. Therefore <.+close> or <.+n+close> should be written on the last text output statement.

Note: Don't forget close. In a short running script a close is done by the operation system because the process is finished and terminated. But a longer running application locks the file if it is not closed.

The text between <+...>TEXT<.+>.. is a 10.3 Text expression which can contain values from any data (datapath), conditionals. for-loops etc.


13.2 Set and change the JZtxtcmd text output file

Topic:.JZtxtcmd.text.text.

The text output file may be given with the command line argument -t:path/to/textOutput.ext or for Java-internal invocation as argument of invocation of docuSrcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter#execute(org.vishia.cmd.JZtxtcmdScript, boolean, boolean, java.lang.Appendable, java.lang.String) and docuSrcJava_vishiaBase/org/vishia/cmd/JZtxtcmdExecuter#execSub(org.vishia.cmd.JZtxtcmdScript.Subroutine, java.util.Map, boolean, java.lang.Appendable, java.io.File). In this cases the output is determined outside of the JZtxtcmd script.

The text output file can be set or changed within the JZtxtcmd script with the statement

<+:create>path/to/textOutputFile.ext<.+>
<+:append>path/to/textOutputFile.ext<.+>

Both statements closes a current existing text output and opens the new one. If that action fails, an Exception is thrown which can catched by a Chapter: 12 onerror - Exceptionhandling. The text expression till <.+> is used as file path. The <+:append> opens for append, the <+:create> clears an existing file. Both creates a new one if not existing.

The path can be build as text expression:

<+:create><&argdir>/out.txt<.+>;

for example if a directory is given as argument.

The output can be determined for the whole script via setting the script variable (fixed in 2018-09):

text = "path/to/textOutputFile.ext";

Another approach is: assign an existing appendable. It can be especially a TextBox in a GUI:

text = window.getWidget("outTexts");

See Chapter: 14 Interaction.


13.3 Lines and indentation in the script

Topic:.JZtxtcmd.text.indent.

To produce a newline after the output line one can write

<+>My line<.+n>

The Text in a JZtxtcmd script for text output is written as plain text after a text output statement. It can be written over some lines.

Because the script usually works with indentation for the statements, the text in the script should be indented too. If the indentation of the text in the script is the same as the statement which introduces the text output, it is not indented in the output:

sub myRoutine(...)
{ for(variable: container) {
    <+><: >
    Create this text in the output without indentation
    with several lines, maybe with <&variable.value>
    <.+>
    if(condition) { <+>A text line
                    next Line of this text
                    <.+>
  } ...

There are some more possibilities especially to mark and separate ranges of text with ranges of statements. The rule for that is: One of the character =, : or + can be used as marker left of the indentation column of the plain text. You can write in the same example:

sub myRoutine(...)
{ for(variable: container) {
    <+><: >
====Create this text in the output without indentation
====with several lines, maybe with <&variable.value>
====<.+>
    if(condition) { =========<+>A text line
                    =========next Line of this text
                    =========<.+>
    }  ...

The === or ::: with at least 3 character length is possible overall in the script, it is ignored by the parser. It should be used only before the <:> to mark that area as text output.

It may be better obvious that there are text lines. Instead ====== there can be used :::: or ++++++ too, but not in combination in one line.

     <+><:s>
     ==testText()==
   1. line without indentation. It starts before indentation column in the script.
     2. line without indentation. It starts exactly on indentation column.
       3. line has 2 spaces indentation. It starts after the indentation column.
 ::::4. line without indentation with :::: in script.
 ::::::::5. line without indentation with more :::::: in script.
 ++  6. line with 2 spaces indentation because it starts after indentation chars.
 ::::::::  7. line with 2 spaces indentation. It starts after the indentation chars though there are longer as indentation point in the script.
 ++++: 8. line starts with a colon as first char after ++++ indentation.
   =====9. line without indentation
 ==+10. line starts with a '+' because first char after another indentation char though before indentation point.
     <.+>

The text can be written with an indentation in the script. It is generated without indentation if the text starts after the column where the <+ ends. The indentation till this start column should be done with spaces or with colon ::: in the script. In this example all lines except the fifth are written in output without indentation. A line which starts left of the script indentation column is written correctly. Because the fifth indented line starts one character after the script indentation column, it is written with one space in the output.

The <:s> skips over all white spaces inclusively that text marker before indentation. It is processed while preparing the source for an jztxtcmd script (translating phase), not at runtime. A <: > skips over all white spaces while parsing the source. Therefore it does not skip the text marker before indentation. A <: > can be used instead <:s> in special cases.

A ::: may clearly mark a text line. That marker can be written starting before the indentation line. Then the line starts exactly after the :::::. The number of colons is no matter how:

     <+>
  :::::::::line without indentation
  ::::::::: line with one space left
  :: line with one space left.
       ::::line starts with the ::::<.+>

One should not use tabulators for indentation. The JZtxtcmd executer does not know a tabulator width of the used editor. Only if all text lines should be left aligned in output the user can use tabs in the script. The JZtxtcmdExecuter counts only spaces and tabs from the start of a JZtxtcmd source text to skip over the source indentation characters independent of spaces or tabulators.

Pattern for well readable JZtxtcmd script code and generated text:

To separate statements and text the following pattern can be used. Separation of text and statements is nice to have especially if C-code or similar should be produced. The JZtxtcmd source is better able to read, no confusion because the syntax is similar. Write:

if(JZtxtcmdexpression) {              <+>
                       ::::::::::::  if(C_expression) { //similar syntax like JZtxtcmd
                       ::::::::::::    doSomethind()
                       ::::::::::::  }<.+>
 }

Often an variable indentation is necessary in the generated text. See the example:

sub generateWhile(int recurs, ...)
{                                              <+>
                                ::::::::<:@2*recurs>while(C_condition) {<.+>
  call generateInnerCode(recurs = recurs+1);
                                       ::::::::<+>
                                ::::::::<:@2*recurs>} //while <.+>
}

See 13.7 Column tabulator. The column tabulator produces the necessary indentation with the recurs variable. If there are nested while(...) etc it is written in the correct indentation form. The while(C_condition)-line in the example starts on the column 2 * recurs so far as the } //while because the line starts immediately after the colons :::::: but set its output column to the calulated value.

On the other hand if a generated text contains less and simple JZtxtcmd statements one can write it inside the text like:

sub switchStates(Obj stateComposite, Num recurs)
{
  <+>
:::<:@2*recurs>  switch(<&stm.zsrcFile.variables.StateInstance>.state<&stateComposite.stateId>) {
:::<:@2*recurs>    case 0: entry_<&stateComposite.stateDefault><&stateMethodSuffix>(thiz); break;<.+>
                    call switchCaseState(stateComposite = stateComposite, recurs = recurs+1);
  <+>
:::<:@2*recurs>  } //switch <&stateComposite.stateId> <.+>
}

In this example the case-Statements are generated from a JZtxtcmd-subroutine. It is well able to read to write the subroutine call inside the text. The formal syntactical separation between both is done with the

text<.+>
JZtxtcmd statements <+>
text

The well able to read separation is done with the :::::.

To write a text without newline on start one can write:

JZtxtcmdExpression()                  <+>output text <.+>
                         ::::::::::<+>further text<.+>

Note that

                      :::::::::::::<+>output text<.+n>

produces an output text with a line feed on end.

Line feed on start or end of an output:

Writing

<+output:n>Line starts with newline<+>
<+output> appends on this line<+>
<+output>and ends with newline <.+n>

produces a newline on start or on end of the text with a lightweigth code in the script.

<+:n>One line in the -t:text-output<.+>
<+> appends on this line<.+>
<+> and ends the line <.+n>

Prevent line feed and spaces with more as one script lines:

It is possible to write a text in the script in several lines, which should be outputted in one line. For example this is able to use to produce batch or shell script files with long lines because long command line arguments are necessary. Write

<+>cmd <: >
  arg1 <: >
  arg2 <: >  ##comments are possible
<.+>
if(condition){ <+>arg3<.+> }
<+>
<.+>

This produces in the output:

cmd arg1 arg2 arg3

With conditional arg3 and a newline on end. The syntax <: > (one space after : ) skips over all following white spaces, especially over the line feed in this example.


13.4 Special characters and text parts in the text

Topic:.JZtxtcmd.text.transcript.

All characters in the line are transformed to the output without changing. One can use tabulator characters in the text to produce tabulators in the output text.

The newline character(s) in the produces text is given with the argument -nl=[n|rn|r] of the invocation of JZtxtcmd. It is not the newline character(s) of the JZtxtcmd script. For example the script can be written with only a \n-Character (0x0a) and the produced text can be written with \r\n like standard in Windows.

One can output some characters writing:

Example:

<+>Text<:lf>next line<.+>
<+><:t>after tab <:<:special>> <:r>after 0x0d

produces

Text
next line  after tab <:special>
after 0x0d

13.5 Datapath depending on Variables

Topic:.JZtxtcmd.text.dataElementVar.

Sometimes it may be necessary to access data depending on other data. The name in a datapath is given in any other variable, not as constant name. It is an indirection. If the ctrlVar contains a part of the name in another datapath you may write:

if   (ctrlVar == "A"){ data = path.to.A.data; }
elsif(ctrlVar == "B"){ data = path.to.B.data; }

Because the content in the ctrlVar is exact the name in the datapath, it is more simple to write:

data = path.to.&(ctrlVar).data;

or inside a text expression:

<:>... <&path.to.&(ctrlVar).data> ...<.>

The content of ctrlVar replaces that part inside the Datapath. Of course only admissible values can be processed. Elsewhere an exception is thrown which can catched with 12 onerror - Exceptionhandling.

A maybe typical construct is

<:>... <&&(path)> ...<.>

if the path contains the whole data path.

An example for that is contained in examples_JZtxtcmd/TestAll/testAll.jz.bat in the sub testVariableDatapath().


13.6 Expression in the expression

Topic:.JZtxtcmd.text..

It is possible to hold an


13.7 Column tabulator

Topic:.JZtxtcmd.text.col.

One can set the next column position in a line writing

<:@100>

Then the position in the line is set exactly in this example to 100. If the line is shorter, spaces are appended before. If the line is longer then the content at this position will be overwrite. Use

<:@100 : 2>

to prevent over-writing of content. If a : is written, the column position is set after the current end, with at least the given number of spaces, 2 in this example. Both forms may be proper:

The example produces a list where the information is over-written, the column is correct:

<+out><&information><:@20>  <&furtherOne><.+n>

information           further one
next line with a inf  furtherOneContent
third line is shorte  thefurtherOne

The information in the left column will be clipped because of the <:@20>. The spaces after <:@20> ensure a proper readability.

<+out>#define <&name><:@20:1>  <&value><.+n>

#define myName        value
#define aLongLongExplicitelyName value
#define otherName     otherValue

The information will never be clipped. This is an example of a generated C file. The value may be better able to read in a column orientation, but the correct syntax is prior.

Instead a constant value an expression can be used to calulated the column. Usually that is a given numeric value in a variable:

<+><:@ indent : 2> text<.+>

This text has an indentation which is given in the variable indent.

<+><:@2*recursion> +--<&treecontent><.+>

It shows a tree with indentation depending on tree depth given in a variable recursion.


13.8 Place holder and values <&dataText>

Topic:.JZtxtcmd.text.data.

The text can contain variable values of course. One should use

<&any.datapath>

to get data from any location. The any.datapath is the same like in assignments to String variables, see the whole chapter 9 Data and variables, the syntax of datapath in 16.9 Text value: textDatapath, textValue and syntax: 16.11 DataPath, Data access. All non-textual Objects are converted to its text presentation using the toString() method of javadoc-oracle/java/lang/Object#toString(). Numeric values are converting using its Standard conversion of the Wrapper types javadoc-oracle/java/lang/Float etc.


13.9 Replacement text on error

Topic:.JZtxtcmd.text..

Since 2016-02:

If a datapath is faulty, an replacement text can be used instead to see the mistake in the output text. Then an 12 onerror - Exceptionhandling] is not necessary. Write

<&my.datapath:?replacement-text>

to output replacement-text if an error is occurred. Usual one can write:

<&my.datapath:? ?error? > <&datapath?" <--->error<---> ">

to see ?error? or <--->error<---> in the output text. Such a label can be searched. The error text can be written in ""..." if it contains a : or >.


13.10 Numeric formatting

Topic:.JZtxtcmd.text..

Numeric types can be converted with a special format. Write

<&datapath:formatString>

with a valid format string of the Java's formatter class javadoc-oracle/java/util/Formatter. Example:

Obj numeric = myData.intvalue;  //accesses to any int variable.
<+>Value = <&numeric> = 0x<&numeric:%08x><.+>

The JZtxtcmd variable numeric stores a numeric value, with its Wrapper class javadoc-oracle/java/lang/Integer. Then a text is produces containing the value in decimal (standard) and with the given format String as hexadecimal value.

In this example the replacement on text error is used too with String "?error?". This should be written before the format string. See 16.14 TextExpression


13.11 Program control in text expressions

Topic:.JZtxtcmd.text.if.

In a text expression some control statements can be used, see the syntax in 16.9 Text value: textDatapath, textValue.

One can write conditional text using

Syntactical the conditions are conditionInText, see 16.12 Condition expression. A condition can be a simple quest whether a variable exists or a data path is valid:

<:if:datapath>

If the datapath is invalid (the destination does not exist), then it is false.

If one write

<:if:datapath !=null>

then an exception is thrown if the datapath is invalid. Because, it is tested explicitely. If a datapath returns a String value, one can use all javadoc-oracle/java/lang/String test capabilties such as

<:if:datapath.to.any.string.contains("check it")>

The

<:if:datapath.to.any.string == "my text">

checks with String.equals("my text"). != is !string.equals().

<:if:datapath.to.any.string ?ge "my text">

means is equal or longer which is String.startsWith("my text") in Java-language.

All other compare operators executes a comparison in alphabetic order.

Numeric values can be calculated and compared, for example

<:if:datapath.to.any.numValue ?ge 345.56>

Note that the operator > and >= cannot be used because syntactical conflicts. Use ?gt and ?ge instead. < and <= can be used because it is not a syntactical conflict. But because better read ability one should use ?lt and ?le.

One can use a

and a container-iteration.

An assignment is possibile writing

That assignments may be important in a <:while...>.


13.12 Insert text form a subroutine: <:subtext:...>

Topic:.JZtxtcmd.text.subtext.

Syntax see 16.18 callSubroutine, callSubtext. and Chapter: 16.5 subroutine.

You can define a subtext or sub routine to produce text inside a given text. A subtext can be defined in two forms:

subtext mySubtext(String arguments) <:>this is the text with <&arguments><.>
sub mySubtext(String arguments) { <:>this is the text with <&arguments><.> }

Both forms of definition seems to be similar. The difference is: A subtext can only define one text expression, whereby a subroutine can be used to do some other text output additionally. Use a subtext for short texts.

Such a subtext can be called, the text will be inserted inside any text expression:

<:>...<:call: name: data = anyData, arg2=value> ...<.>
<:>...<:subtext: name: data = anyData, arg2=value> ...<.>
<:>...<:subtext: "name" :data = anyData, arg2=value> ...<.>

Usage of <call:... or <:subtext... is adequate. The name of the subroutine is a textValue, see 16.9 Text value: textDatapath, textValue. Therefore it can be gotten from a variable too writing an & before the variable name:

<:>...<:call:&nameFromDatapath :data = ...> ...<.>

That is a possibility to invoke several sub texts controlled by data content.

A subtext can be held inside a variable too, see 9.1.9 Subtextvar, Subroutinevar - statements to execute.


13.13 Setting variables in the text expression

Topic:.JZtxtcmd.text..

<:=variablePathString>any text <&content><.=>

<:=variablePathOther = 234>
<:=variableAppend += 234>

The first form fills a String variable with a String expression.

The second form defines any expression to set the variable after the =

The third form appends to the variable equivalent to the += 9.1 Types of variables and their assignment

That assignments do not produce text in the current output.


13.14 Writing to the main output file

Topic:.JZtxtcmd.text.file.

The JZtxtcmd knows one main output text file. It is possible that this output file is the approach of the script invocation, the user will get a generated output file from some inputs. Another approach may be, the main output file is the log output of the script running process.

The main output file is given by parameter of the script invocation. This output file is deleted if it is existing and reopened newly. If the output file is locked from another process (opened), the script invocation is aborted with an error. The output file is remaining opened but flushed frequently, so the output can be monitored by the user while reading this file in another process. It is necessary if the main output is used as log.

Nevertheless the script process can have a second log file which is written from some Java methods which uses the log capability of the message dispatcher. That log can't be controlled by the user, it is a really log of Java processing. That log is given with the --report:FILE parameter.

Writing in the main output file is done by writing

<+>text<.+>

wherby text is a 16.14 TextExpression.

To flush the output one should use a flush operator inside the text:

<+>text<:flush><.+>

or more simple flush with the and tag:

<+>text<.+flush>

or flush in conclusion with a newline:

<+>text<.+n+flush>

like any other text output with <+channel>....<.+n+flush>.


14 Interaction

Topic:.JZtxtcmd.gui.

One of the JZtxtcmd script approach is using as batch script only. But on the other hand a graphical user interface can be initialized and used by using proper Java classes. The org.vishia.gral is proper to use for that. Especially building a GUI can be described via a script, which can be a part of the JZtxtcmd script, as text in a String. Subroutines of JZtxtcmd can be used inside a Graphical User Interface as action code. for fields, buttons etc.

String guicfg =
  <:>
  @primaryWindow, 3-2++,0+5: Text("Mini-GUI");
  @5-2,0+10: Text("script controlled via <&scriptfile>");
  @10-4,0+45: InputTextline(%t:"Tracefile (d&drop)", name=inputfile, dropFiles="dropFile");
  @14-3,33+12: Button(TestButton, "read & check", action=readCheck);
  @18-4,0+45: InputTextline(%t:"Out dir (d&drop)", name=outDir, dropFiles="dropFile");
  @22-4,0+4: InputTextline(%t:"Nr trace 1..4", name=nrTrace);
  @22-3,33+12: Button(TestButton, "convert", action=convertCsv);
  @24+20,0+45: OutputBox(name=outTexts);
  <.>;
Obj gralActions = java new org.vishia.gral.ifc.GralActionJztc(jztc, out);
gralActions.add(jztc.sub("readCheck"));
gralActions.add(jztc.sub("convertCsv"));
gralActions.add(jztc.sub("dropFile"));
Obj window=java org.vishia.gral.cfg.GralCfgWindow.createWindow("MLtraceGui", "Trace GUI ML", "C", guicfg, null, console);
text = window.getWidget("outTexts");
main(){
  while(!window.isGraphicDisposed()) {
    jztc.sleep(1000);
  }
}

sub readCheck(){
  String sfile = window.getTextFrom("inputfile");
  <+out>read and prepare <&sfile><.+n>
  Filepath file = &sfile;
  ....

This example creates a Window with content given as script in guicfg. The sub routines as action should be registered in the shown form. The Subroutines are executed as callback from the buttons etc. in an extra thread created in the class srcJava_vishiaGui/org/vishia/gral/ifc/GralActionJztc which creates a thread in srcJava_Zbnf/org/vishia/cmd/JZtxtcmdThreadQueue. For this reason the actions are not executed in the graphical thread, but one after another. If you press several buttons fastly one after another, the sub routines will be executed in a few milliseconds usually, but the graphic does not hang in any case, also if the execution needs some more time for example for converting routines.


15 Debugging possibilities

Topic:.JZtxtcmd.debug.

A JZtxtcmd script should be simple and short. Usual a well running script is modified and tested. Any small-step modification should be tested. Errors can be seen in comparison of the last well running version to the changes. It is the recent strategy of scripting.

If special java routines should be used, the associated javadoc should be read well. Then test...


15.1 Handling syntax errors

Topic:.JZtxtcmd.debug.syntax.

While invocation JZtxtcmd the given script is translated complete firstly. If any syntactical error is found, an error message like

JZtxtcmd - Error parsing genscript;
Parse ERROR at input:2202(0x89a) >>>>call TestResult.replenish(arg=map);|    <+out>testResult() - replenish; <&map.re
expected: ----------------------------------------------
 "." in topLevelSyntax.subClass.subroutine.statementBlock.statement.DefVariable.DefMapVar.variable.
 ";" in topLevelSyntax.subClass.subroutine.statementBlock.statement.
founded before: ----------------------------------------------
 [184..187]<...?datapath>  syntax=? input=0..0(78, 51) read: "result.anotherOne" xmlNode=<datapath>...</>
 [185]<...?startVariable> identifier:result syntax=$ input=0..0(0, 0) xmlNode=result

One can report the syntax with invocation

java -cp $CLASSPATH org.vishia.zcmd.JZtxtcmd --help

or check the syntax in this documentation. The syntax error shows that position in the text where the parser has failed. Often the mistake is on position before that. The expected: names the nesting of syntax component and the characters which where expected there.

In that example a ; is missing only on the last statement. The parser cannot know that you have forgotten a semicolon. The parser thinks the last statement should be continued. The second expected: proposal names the error in fact, the missing semicolon on statement end. But the parser expects that the last written text may be a variable path which is incomplete. Which of that expected: things are correct, one can desired on viewing the text before.

Additional the parser reports what is accepted before. In this case it is a datapath. View the syntax of datapath. After a startvariable some more path elements separated with a dot may be expected.

The output of the syntax error is the standard behavior of a ZBNF-parser.


15.2 Check the content of the script

Topic:.JZtxtcmd.debug.xmlSrc.

Sometimes there may be differences in interpretation of the source code of a JZscript. The JZscript will be parsed with a ZBNF parser. That parse result can be shown in XML format to check only the parser. Write on the first line:

!checkXml = "path/to/checkfile.xml";

Then the parser's result will be written in that file in XML format.

You can use

!checkXml= <:><:scriptdir>/test.xml<.>;

instead to write it in the directory of the script.

Note that included scripts are not regarded.

On the other hand you can write:

!checkJZtxtcmd = "path/to/checJzcmd.txt";

That writes a text file which contains the 'toString()'-result of all statements in the script, included scripts regarding. This second form representates that data, which are converted from the parser's result (able to show with XML) into the internal presentation.


15.3 onerror facility

Topic:.JZtxtcmd.debug.onerror.

A static language tests as soon as possible mistakes on compile time. But a dynamic language accepts some constructs which's mistakes are obvious on run time only. For example a static language tests types of arguments of a subroutine. The JZtxtcmd dynamic language does not distinguish types, like other dynamic languages. An Obj type can contain any Object. Whether it is matching to a called Java subroutine, it can be checked on runtime only.

If any dissonant constellation are ascertain on run time, an exception is thrown by the Java execution process. One can use an onerror construct in the JZtxtcmd script:

doAnything in the script;
do next;
onerror {
  <+out>Error on xyz; <&error><.+n>
}

If an exception is thrown, the next following onerror block is executed. The error variable should contain a significant text about the mistake. It is outputted on console in this example. The console may be redirect in a message system. With that stuff the error may be able to interprete by the user.

If the error is not catched in that level, it may be catched in the calling level. Last not least the JZtxtcmd class aborts and reports.

The error variable contains the Java-Exception class name, the exception message text, the file and source line and column and a short notification of the JZtxtcmd statement where the error occurs. For example in a subroutine a faulty variable is used. The error is catched in the level above.

The following text is outputted:


15.4 Check data on runtime

Topic:.JZtxtcmd.debug.JZtxtcmdTester.

The JZtxtcmd knows a variable test which refers an instance of srcJava_vishiaBase/org/vishia/cmd/JZtxtcmdTester. This class has some capabilities for output data for test.

The following statement writes a line which contains the information about the type and the toString()-value of data:

out += test.infoln("my info", data);  //appends a line with info
<+out>it is the same: my info<&test.info(data)>, maybe some more in the line <.+n>

The following statement writes the internal data of an instance which is able to address with a datapath:

 test.dataTree(data, out, 1);
 <+>  <&test.dataTree(path/to/data, out, 1)> <.+>

The third argument 1 is the deepness of data, used if references are used in the instance. It can be set to any number of deepness. Then referenced data and the references their etc. are shown too.

The out is the standard output. You can use any Appendable object, especially to get the information in a file:

Openfile outfile = "path/to/myFile.txt";
test.dataTree(data, outfile, 3);
outfile.close();  //don't forget to close!

It is possible to write that information with a html format:

Filepath htmldata = "path/to/myFile.html";
test.dataHtml(data, htmldata);

This is the most complex but recommended form to output the data which can be used in a script. Usual the root data in a special script may be outputted. The html file contains the data of the given instance and all referenced instances. The references instances are written independent, not in form of a tree. The references are presented in html as hyperlinks inside that html document. With the known usability of following links and switch back of a browser the referenced data can be evalated. That can help to write a JZtxtcmd script:


15.5 Debugging in an Integrated Development Environment, for example Eclipse

Topic:.JZtxtcmd.debug.eclipse.

The JZtxtcmd can be executed in an Eclipse or another integrated development environment. You don't need to understand the whole source code of the translator javadocPriv-Zbnf/org/vishia/zcmd/JZtxtcmd and interpreter javadocPriv-vishiaBase/org/vishia/cmd/JZtxtcmdExecuter. It is sufficient to view to some details, set a breakpoint, view data etc.

Especially if Java routines of the user are invoked inside the user's JZtxtcmd script, the user can set a breakpoint and debug its own routines. On return of this routines it returns to the JZtxtcmdExecuter loop, see the stacktrace of debugging.

break on access to any data:

If any variable or a method is not is not found, you can set the following instruction line before that access:

java org.vishia.util.DataAccess.debugIdent("myData");
myData.myMethod(args);

The first instruction sets a (non-threadsafe) debug comparison String in the class DataAccess. If that indentifier is used then it forces the execution of srcJava_vishiaBase/org/vishia/util/DataAccess#debug() where a breakpoint can be set. There you can visit given variables, methods etc. with the debugger variable context maybe especially in the given localVariables.

You can set a break for a found method but with argument problems by setting:

java org.vishia.util.DataAccess.debugMethod("myMethod");
myData.myMethod(args);

The next instructions in DataAccess checks the actual arguments, which may be faulty.

break in the execution loop of JZtxtcmd:

If any of the execution of the JZtxtcmd script seems to be obscure, you can insert a debug statement bevor the obscure statement:

...jztxtcmd statements
debug "my text";
debug <:>any <&variable>-expression<.>;
debug;
obscure statements;
...
<+out> any text <:debug:"my text"> <&obscureData><.+>
<+out> any text <:debug> <&obscureData><.+>

On a debug statement the method javadocPriv-vishiaBase/org/vishia/cmd/JZtxtcmdExecuter.ExecuteLevel#debug(org.vishia.cmd.JZtxtcmdScript.JZtxtcmditem)

   int debug(JZtxtcmdScript.JZtxtcmditem statement) //throws Exception
   { try{ CharSequence text = evalString(statement);
     } catch(Exception exc){  //unexpected
     }
     Assert.stop();
     return 1;
   }

is executed. You can set a breakpoint to the stop() line. The text should be set with your "my text" of the debug-statement. If this statement returns, it continues in the interpreter loop of the JZtxtcmd script. The next statement will be the 'obscure' one. You can study whats happen.


16 Syntax of a JZtxtcmd script

Topic:.JZtxtcmd.syntax.

This chapter describes the exact formal syntax which is used to parse the script. The syntax is shown both in ZBNF and in a more readable explaination format. The internal used ZBNF-Syntax-Script is contained in the Java-class javadoc-Zbnf/org/vishia/zcmd/JZcmdSyntax. You can invoke JZtxtcmd from command line to output the syntax with the help text:

 java -cp path/to/zbnf.jar org.vishia.zcmd.JZtxtcmd --help:helpoutput.txt

Details of the syntax may be changed in further development. Therefore see and compare that help output.


16.1 The head of a script

Topic:.JZtxtcmd.syntax.script.

The syntax starts with some common settings and the definition of the top-level component, the frame of a script.

$comment=(?...?).
$endlineComment=\#\#.  ##The ## is the start chars for an endline-comment or commented line in the generator script.
$keywords= new | cmd | cmd_check | start
  | debug | java
  | stdout | stdin | stderr
  | subtext | sub | main | call | cd | CD | REM | Rem | rem
  | Pipe | StringBuffer | Stringjar | String | List | Openfile | Fileset | Obj | Set | set | include | zbatch
  | break | XXXreturn | exit | onerror | instanceof | for | while | do | if | elsif | else | throw .

The syntax of the whole script is given with:

JZtxtcmd::=
[<*|==JZtxtcmd==?>==JZtxtcmd== ]
[<*|==JZcmd==?>==JZcmd== ]
[{ ! checkjzTc = <textValue?checkJZcmdFile> ;
 | ! checkJZcmd = <textValue?checkJZcmdFile> ;
 | ! checkXml = <textValue?checkXmlFile> ;
}]
[{ [REM|Rem|rem] <*\n\r?> ##Remark like in batch files
 | include <include> ;
 | currdir = <textDatapath?cd> ;
}]
.....

It contains:


16.2 The content of a script

Topic:.JZtxtcmd.syntax..

The syntax of the JZtxtcmd::=.... continues with

.....
{ [//] ==endJZcmd==<*\e?>
| [REM|Rem|rem] <*\n\r?> ##Remark like in batch files
| //JZtxtcmd       ##ignore //JZtxtcmd, it may be a comment for another language
| //JZcmd      ##ignore //JZcmd, it may be a comment for another language
| //<*\n\r?> ##line comment in C style
| /*<*|*/?>*/ ##block commment in C style
| <DefVariable?> ;
| <statement?>
| subtext  <subtext?subroutine>
| sub <subroutine>
| class <subClass>
| main ( ) \{ <statementBlock?mainRoutine> \}
} \e.

16.2.1 End marker

Topic:.JZtxtcmd.syntax...

It is possible to set an end marker in the text. It is is detect, all content till the end of the file will be skipped. <*\e?> means, skip all till the end of file, without semantic meaning.

{ [//] ==endJZcmd==<*\e?>

16.2.2 comments

Topic:.JZtxtcmd.syntax..comment.

Comments can be given with starting from ## to the line end or between (? comment ?). That comments are ignored in the parsing process.

Additional the // and the /* ... */ can be used for comments like in Java or C. That comments are formally parsed, they are visible in the parsers result xml file with option -debug:file, but they are ignored for execution.

| [REM|Rem|rem] <*\n\r?> ##Remark like in batch files
| //JZtxtcmd      ##ignore //JZtxtcmd, it may be a comment for another language
| //<*\n\r?>   ##line comment in C style
| /*<*|*/?>*/  ##block commment in C style

16.2.3 ScriptVariable and Script-Statements

Topic:.JZtxtcmd.syntax..var.

The <DefVariables?> enables the declaration of variables on script level. The variables can be declared between routines and classes. But they are visible and created all on start of execution.

| <DefVariable?> ;
| <statement?>

See 6.1 Script variables


16.2.4 The main syntax of the rest of the script

Topic:.JZtxtcmd.syntax..main.

The script consist of definition of sub, subroutines and classes and the main routine. All of it can be contained more as one time in any order.

| subtext  <subtext?subroutine>
| sub <subroutine>
| class <subClass>
| main ( ) \{ <statementBlock?mainRoutine> \}
} \e.

16.3 The include statement

Topic:.JZtxtcmd.syntax.include.

The path can be given starting with an optional environment variable, optional continued with a path.

include::= [$<$?envVar>[/|\\]][ <""?path> | <*;\ ?path>].

16.4 Classes

Topic:.JZtxtcmd.syntax.class.

Syntax:


subClass::= <$?name> \{
{ subtext  <subtext?subroutine>
| sub <subroutine>
| class <subClass>
} \}.

A subclass starts with class <subClass> either on script level or inside a class. It can contain sub routines with statements or sub routines to build text.

A class is yet only a division of the script. The subRoutine have static character.


16.5 subroutine

Topic:.JZtxtcmd.syntax.sub.

Syntax:

subroutine::= <$?name> ( [ use-locals<?useLocals> | { add-locals<?addLocals> | <DefVariable?formalArgument> ? , }|] ) \{ [<statementBlock>] \}.
subtext::= <$?name> ( [ use-locals<?useLocals> | { add-locals<?addLocals> | <DefVariable?formalArgument> ? , }|] ) \<:\><textExpr>\<\.\>.

The difference between a subroutine and a subtext is: A subtext can be invoked inside a 16.14 TextExpression, it contains a <textExpr> itself. The procedures for calling are the same.


16.6 statements

Topic:.JZtxtcmd.syntax.stm.

Syntax:

statementBlock::= { <statement?> }.
statement::=
  \{ [<statementBlock>] \}
| REM <*\n\r?> ##Remark like in batch files
| ::{:}                ##Skip over :::
| =={=}                ##Skip over :::
| //JZtxtcmd       ##ignore //JZtxtcmd, it may be a comment for another language
| //JZcmd      ##ignore //JZcmd, it may be a comment for another language
| //<*|\n|\r|\<+?>     ##line commment in C style but only till <+
| /*<*|*/?>*/          ##block commment in C style
| text = <textValue?createTextOut> ;    ##set text output
| currdir = <textDatapath?cd> ;   ##set current directory
| [cd|CD] [<textValue?cd> | <*\ ;?cd> ; ]  ##change current directory
| mkdir <textValue?mkdir> ;                 ##create any directory if not exists
| <DefVariable?> ;
| for <forCtrl>
| if <ifCtrl>
| while <whileCtrl>
| do <dowhileCtrl>
| start <cmdLine?cmdStart>
| zmake <zmake>
| move <srcdst?move> ;
| copy <srcdst?copy> ;
| [rm|del] <oneArg?del> ;
| break <?breakBlock> ;
| return <?return> ;
| exit <#?exitScript> ;
| throw on errorlevel <#?throwonerror>
| throw <textDatapath?throw>
| onerror <onerror>
| errortoOutput off <?errorToOutput=0>
| errortoOutput <?errorToOutput=1>
| if errorlevel <iferrorlevel>
| debug [<textValue?debug>| <?debug>] ;
| debugOp <textValue?debugOp> ;
| <callSubroutine?call>
| <threadBlock>
| \<+:create\><textExpr?createTextOut>\<\.+\>
| \<+:append\><textExpr?appendTextOut>\<\.+\>
| \<+ <textOut>
| \<:\><textExpr?.indent=-3>\<\.\> [;]
| <cmdLineWait?cmdWait>
| <assignExpr>
| ;
.
srcdst::= [{ -n<?newTimestamp>| -w<?overwr> | -r<overwro>}] [ src=] <textValue?src> [ dst=] <textValue?dst> .
oneArg::= <textValue?src> .

16.7 Variables

Topic:.JZtxtcmd.syntax.var.

See

The syntax component <DefVariable?> is used both in the script outside of routines for script variables, 16.1 The head of a script in classes and in the body of routines, see $chapter. The first one builds script variables, the second and third one builds variables valid in its class or routine context non stored outside of the class or subroutine execution time.

See 16.11 DataPath, Data access how access variables.

DefNumVar::= [const <?const>] <definePath?defVariable>  [ = <numExpr>].
DefBoolVar::= [const <?const>] <definePath?defVariable>  [ = <boolExpr>].
DefList::= [const <?const>] <definePath?defVariable>

[ = [ {<?element> { <dataStruct?dataSet> } ? , } ] ##some { dataSet, ...}

= [ <dataStruct?> ] ##some String or variable (const) definitions in the container.

= <objExpr?> [!;]

= [ { <objExpr?objElement> ? , } ]

].

DefSpecVar::= [const <?const>] <definePath?defVariable>  [ = <objExpr?>].
DefObjVar::= [const <?const>] <definePath?defVariable> [ : <$\.?type>]  [ = <objExpr?>].
DefClassVar::= [const] <definePath?defVariable>  =
  [: <dataAccess?loader> : ]  ## a datapath to a ClassLoader instance, a Classpath variable.
  <textValue?>.               ## The package path maybe contained in any expression
DefClasspath::= [const] <definePath?defVariable>  = [ : <$?parentClasspath> : ] { <filesetAccess> ? , }.
DefStringVar::= [const <?const>] <definePath?defVariable> [ = <textDatapath?>].
DefMapVar::= [const <?const>] <definePath?defVariable> [ = \{ <dataStruct> \}  ].
Openfile::= [const <?const>] <definePath?defVariable> = <textDatapath?> .

The variable is defined like a datapath, though it is not an access path but an path which defines a variable.

definePath::= <$-?startVariable>[ [?\. \>] \.{ <defineSubelement?datapathElement> ? [?\. \>] \.}].
defineSubelement::= <$-?ident> [( [{ <objExpr?argument> ? ,}])<?whatisit=(>].

A definePath for a variable starts with an identifier. An identifier is written like in Java, C or the most other programming languages. The character - is admissible too inside the identifier. An identifier can be written for example my-variable. It does not contain any $. The so named start variable is member of the datapool of a JZtxtcmd execution environment. A new defined variable will be added to this pool, but only valid for the execution level, in the current subroutine.

A variable can be continued with defineSubelement which can be either a variable identifier or a method call. But the last member of that should be a simple variable ident. It is not shown in syntax, only checked on run time.

In this kind it is possible to create a tree of variables. If a subroutine needs some variables, one does not need to offer all variables as parameter singly by singly. One can build a proper local datapool and offer this pool as variable to the subroutine. See 16.18 callSubroutine, callSubtext. Another possibility is adding a variable in a Map-container inside any user-Java-class.

A variable in an container is always an instance of javadoc-vishiaBase/org/vishia/util/DataAccess.Variable. A defineSubelement can describe a field or method inside any (user-) Java class, see javadoc-vishiaBase/org/vishia/util/DataAccess.access(...).

The value after the = is the initial value of the variable. It is necessary, if the variable is const, elsewhere it is optional. See next chapter. On Openfile it is necessary, it's the file name.


16.8 Fileset, Filepath

Topic:.JZtxtcmd.syntax.filepath.

See 9.1.13 Filepath, Fileset

DefFileset::= <definePath?defVariable> [ =  (
[ commonpath = [<""?commonPath>|<*;,)(\ \r\n?commonPath>] , ]
{ [{ //JZtxtcmd | //<*\n\r?>}] [<""?filePath>|<*;,)(\ \r\n?filePath>] [{ //JZtxtcmd | //<*\n\r?>}] ? , }
) ] .

A Fileset is a variable with the same definition context possibilities like any other variable. It is constant initialized by a list of <Filepath> and maybe a commonpath which is used as base path for all files.

DefFilepath::= <definePath?defVariable> [ = <textValue?> ].

A Filepath is a variable with the same definition context possibilities like any other variable. It is constant initialized by a <Filepath>. A Filepath is written either in "" or as character string till a whitespace or till a ;. The prepFilePath-syntax is applicated to that parse result:

prepFilePath::=<$NoWhiteSpaces><! *?>
[ &$<$?@envVariable> [\\|/|]      ##path can start with a environment variable's content
| &<$?@scriptVariable> [\\|/|]    ##path can start with a scriptvariable's content
| [<!.?@drive>:]                  ## only 1 char with followed : is the drive letter
  [ [/|\\]<?@absPath>]            ## starting with / maybe after d: is absolute path
|]
[ <*:?@pathbase>[?:=]:]           ## all until : is pathbase, but not till a :=
[ <toLastChar:/\\?@path>[\\|/|]] ## all until last \ or / is path
[ <toLastChar:.?@name>              ## all until exclusive dot is the name
  <*\e?@ext>                       ## from dot to end is the extension
| <*\e?@name>                      ## No dot is found, all is the name.
] .

The String definition of a Filepath is divided in the parts like shown. Note that a Filepath can contain either the identifier of an environment variable or of a JZtxtcmd-Scriptvariable as start of the path. The content of the variable is evaluated on access to the Filepath. See javadoc-vishiaBase/org/vishia/util/FilePath.

The Filepath is tokenized in its part from the Constructor javadoc-vishiaBase/org/vishia/util/FilePath#FilePath(java.lang.String) in the same way like shown here with an Java core algorithm.


16.9 Text value: textDatapath, textValue

Topic:.JZtxtcmd.syntax.textDatapath.

A text expression presents a String:

textDatapath::=  <""?text> | \<:\><textExpr>\<\.\> | [& [?(] ] <dataAccess> .
textValue::=  <""?text> | \<:\><textExpr>\<\.\> | & <dataAccess> | <*;,)(\ \r\n\>?text> .

textValueTextExpr::=  <""?text> | \<:\><textExpr>\<\.\> | & <dataAccess> | <*:;,)(\ \r\n\>?text> .

There are two forms. The textDatapath is used in a normal programming environment. The textValue is used in that syntactical contexts where a simple text value is expectable. Without quotion marks, a text value is supplied: cmd myCmd.exe

Such an constant text ends respectively cannot contain the characters *;( and spaces because that are following syntactical characters. A textValue allows to write more simple in the script.

For textExpr see 16.14 TextExpression

The datapath can access either to a location which contains text, or to a location which does not contain text. If a text is expected in the running context, a non-text will be converted to text calling the toString() operation of the gotten instance.


16.10 Object value: objExpr

Topic:.JZtxtcmd.syntax.objExpr.

An objExpr which presents any Object to assign to a variable or used for a calling argument is defined as

objExpr::=
| Filepath : <textValue?Filepath> ## A textValue which builds a Filepath in the currdir
| Fileset: <filesetAccess>
| \{ <dataStruct> \}              ## It is a Map of Variables.
| <""?text>                       ## It is a constant text.
| \<:\><textExpr>\<\.\>           ## It is a text assembled in runtime.
| <numExpr>.                      ## special detection of a simple dataAccess.
dataStruct::= { <DefVariable?> ; } | { <DefStringVar?textVariable> ? , }.

It is either a text, an concatenation of texts, an access to data or a complex boolean or numeric expression. If the numExpr only contains a DataPath it is stored as simple dataAccess.

The dataStruct is a special form which can be used to build a Map of Objects to store as one Object.

If the type File: is given a textual expression is converted to a java.io.File-instance on runtime.

If one of the types Filepath or Fileset are given a texual expression or the special syntax of an filesetAccess is converted to the types javadoc-vishiaBase/org/vishia/cmd/JZcmdFilepath respectively javadoc-vishiaBase/org/vishia/cmd/JZcmdAccessFileset.


16.11 DataPath, Data access

Topic:.JZtxtcmd.syntax.DataAccess.

See

For variable see 16.7 Variables. The same syntax is used to describe an access to a variable and describe the path to create a variable. The difference in runtime is: The last element of an access can be a method invocation. The elements should be existing.

Inside a data path a new Java instance can be created, see 9.11 Creation of new instances of Java classes or a static method can be accessed either with the keyword java or a simple % on start of the path to the Java class. See 9.10 Access to static Java data and Invocation of static Java methods. Both expressions need a package-path to the Java class and the constructor- or the method-name.

A Class-variable can be used instead a direct given package path. Note that a few Classes are given by 9.5 Predefined script variables. The Class-variable can be located anywhere in the JZtxtcmd script or in any Java data context. Therefore it is written as & <dataAccess?classVar> : itself.

The package path can be located in another jar file which is defined with a Classpath-Variable.

Therefore an access to static elements of a Java class can be written with the syntax:

## Access to a Java class constructor or static method or field
staticJavaAccess::=
  [ & <dataAccess?Class_Var> : [<$\.$?javapath>]       ## access via Class variable .element
  | [: <dataAccess?Classpath_Var> : ] <$\.$?javapath>  ## [Classpath] package.path.Class.element
  ] [( [ { <objExpr?argument> ? , } ])].               ## arguments

A dataPath is used to address any field or method in a Java class or any member of a Map in a path.

dataPath::=
[ File : <textValue?File>     ##creates a file object with given path
| <startDatapath>
] [ [?\. \>] \.{ <datapathElement> ? [?\. \>] \.}].
## A datapath cannot start with an JZtxtcmd keyword!
startDatapath::= <?whatisit=@>
[ & ( <dataPath> )  ##takes the result of <dataPath> as name of an element or method.
| <$-?ident>
][
  ( [{ <objExpr?argument> ? ,}]) <?whatisit=(>   ##a method
| \[ <#?index> \] <?whatisit=\[>   ##an indexed array access
|].
datapathElement::=
[ & ( <dataPath> ) ##takes the result of <dataPath> as name of an element or method.
| ##Field or method identifier, use regex for the second datapath element, it can be a JZtxtcmd keyword too!
  [<?ident> [@] [\[\]   ##[] instead name for length operation.
  | <![\\w-]+?>]        ##name as regex or [] for length of array or size() of container
  ]
][
  ( [{ <objExpr?argument> ? ,}]) <?whatisit=(>   ##a method
| \[ <#?index> \] <?whatisit=\[>   ##an indexed array access
|].

An indentifier of a datapath element can start with @ especially to access to a XML tree, to the attributes.


16.12 Condition expression

Topic:.JZtxtcmd.syntax.condition.

A condition is a boolean expression:

condition::=<andExpr?> [{\|\| <?boolCheckOrOperation> <andExpr?boolOrOperation>}].
andExpr::= <boolExpr?> [{ && <?boolCheckAndOperation> <boolExpr?boolAndOperation>}].
boolExpr::= [<?boolNot> ! | not| NOT|]
[ ( <condition?parenthesisCondition> )
| <numExpr?> [<cmpOperation>]
].
cmpOperation::=[ \?[<?cmpOperator>gt|ge|lt|le|eq|ne|instanceof] |  [<?cmpOperator> != | == | \>= | \> | \<= | \< ]] <numExpr?>.
instanceof::=<objExpr> instanceof <staticJavaAccess>.

Because the cascade of or operations with andExpr which can contain and operations, that contains an boolExpr with comparison, the rule of higher priority of

is met. The boolExpr can contain the unary not able to write with ! like in C, Java or with the keyword not which may be better able to read. (...)-parenthesis conditions are possible too.

The compareOperation defines additional to the known compare operators from Java, C and the most other programming languages the operators written with:

This writing possibility should be used especially in text expressions, where the > may have another meaning (closing of a tag).

For text expressions the adequat syntax components are given. The only one difference is the absence of the > etc. comparison operators.

conditionInText::=<andExprInText?> [{\|\| <?boolCheckOrOperation> <andExprInText?boolOrOperation>}].
andExprInText::= <boolExprInText?> [{ && <?boolCheckAndOperation> <boolExprInText?boolAndOperation>}].
boolExprInText::= [<?boolNot> ! | not|]
[ ( <conditionInText?parenthesisCondition> )
| <numExpr?> [<cmpOperationInText?cmpOperation>]
].
cmpOperationInText::=[ \?[<?cmpOperator>gt|ge|lt|le|eq|ne] |  [<?cmpOperator> != | == ]] <numExpr?>.

16.13 Numeric Expression

Topic:.JZtxtcmd.syntax.numExpr.

See 10.6 Numeric Expression

numExpr::=  bool ( <boolExpr?> )
            | <multExpr?> [{ + <multExpr?addOperation> | - <multExpr?subOperation>}].
multExpr::= <value?> [{ * <value?multOperation> | / <value?divOperation> }].
value::= 0x<#x?intValue> | <#?intValue>[?\.] | <#f?doubleValue> |    ##unary - associated to value.
[{[<?unaryOperator> ! | ~ | - | + ]}]        ##additional unary operators.
[ 0x<#x?intValue> | <#?intValue>  ##ones of kind of value:
| '<!.?charValue>' | <""?textValue>
| ( <numExpr?parenthesisExpr> )
| [& [?(] ] <dataAccess>   ## & is optional, don't confuse with &(variable)
].

Because the cascade of + - operations with multExpr which can contain * / operations, that contains an value, the rule of higher priority of

is met. The value can contain the unary ! ~ - + operators and (...)-parenthesis like in C, Java.

A non const value comes from a datapath, see 16.11 DataPath, Data access and $chapter, 9.9 Access to Java internal data. If that results are used for numeric expressions, they should be of an numeric type or they should be a String which is able to translate in a numeric type. That translation rules are processed in the javadoc-vishiaBase/org/vishia/util/CalculatorExp. In a JZtxtcmd variable a numeric wrapper type such as javadoc-oracle/java/lang/Float can be stored.

All numeric methods of the Java standard class javadoc-oracle/java/lang/Math can be used.


16.14 TextExpression

Topic:.JZtxtcmd.syntax.textExpr.

See 13 Text output and text generation

textExpr::=<$NoWhiteSpaces>
{ [?\<\.]                             ##abort on <.
[ \<&-<*\>?>\>                          ##<&- it is comment>
| \<:---\><*|---\>?>\<---\> ##<:---> comment <---> not confused with XML <--- will be produced as output --->
| \<:-<*\>?>\><textExpr?>\<\.-<*\>?>\> ##<:-comment> comment <.- >
| \#\#<*\r\n?>   ##comment to eol in a text Expression
| \<:\{  <statementBlock?>  <!\\s*>  \}\>  ##one or more statements inside a text expression, do not produce an output text.
| \<:for:<forInText?forCtrl>
| \<:if: <ifInText?ifCtrl>
| \<:hasNext\> <textExpr?hasNext> \<\.hasNext\>
| \<:subtext : <callSubtext?call>
| \<:call : <callSubtext?call>
| \<:scriptdir<?scriptdir>\>
| \<:debug[:<textDatapath?debug>| <?debug>]\>
| \<&<dataText>
| \<: [<?transliteration>n|r|t|b|[\<|#|\"]<*\>?>] \>
| \<:[<#?utf16code>|x<#x?utf16code>]\>
| \<:lf\><?newline>
| \<:\ \><!\\s*?> [ \#\#<*\r\n?> <!\\s*?> ]
| \<:s\><?skipWhiteSpaces>
| \<:@<setColumn>\>
| \<:<DefVariable?>\>
| \<:\><textExpr?>\<\.\>
| <*|\<:|\<&|\#\#|\<\.?plainText>
]
}.

Text expressions are used either to output text in 16.6 statements <+textout> or for textual arguments and values. Generally all white spaces in the text are used. The tag <$NoWhiteSpace> in the syntax means, that whitespaces in the syntax have not the meaning to skip over the whitespaces in the parsed text. Therefore all white spaces of the parsed text are read. The text can contain the named control elements and the possibility of values with format dataText:

dataText::=<dataAccess>[ \:\?[<""?errorText>|<*\>:?errorText>]][ \: [<""?formatText>|<*\>?formatText>]] \>.

A <:n> produces a new line with the requested coding like given as calling argument of JZtxtcmd (0x0d, 0x0a, only 0x0a, only 0x0d).

The transcription of some special characters is possible:

The <: > overrides all whitespaces. It is the possibility to wrap text where the generated text should not wrapped.

The ## comment is recognized especially, because the comment functionality of the parser is switched off too in the <$NoWhiteSpace>-mode. Note that the syntax should contain \#\# instead a simple ## because elsewhere it is a comment in the syntax.

Note that a

//comment  <+>text...

does not ignore a start of a text output on the same line. This capability is proper for writing text output in a right column whereby statements are written left. To ignore lines which contain text output use:

##comment <+>inclusively ignore the text output<.+>

16.15 Assign an output text

Topic:.JZtxtcmd.syntax.textOut.

See 13 Text output and text generation.

textOut::= [<dataPath?assign>] [:n<?newline>] \>
  [<textExpr>]
  [ \<\.+\>                     ## end text variants:
  | \<\.n+\><?newline>
  | \<\.+n\><?newline>
  | \<\.+n+flush\><?newline><?flush>
  | \<\.+flush\><?flush>
  | \<\.+n+close\><?close>
  | \<\.+close\><?close>
  ].
setColumn::=<numExpr> [ : <numExpr?minSpaces>] | : <numExpr?minSpaces>.

Note: in

statement::=
| \<+ <textOut>

The textOut appends the text between <+variable>...TEXT...<.+> to the variable. The variable should be an Appendable type. See 16.7 Variables. It is either an Openfile, a Stringjar, a Pipe or any other Obj which is of type javadoc-Oracle/java/lang/Appendable. That is checked on Runtime.

The Indentation of the plainText is realized with storing the column position where the syntax component <textOut> starts. It is after the <+ because the white space is parsed inside the syntax component.


16.16 Control statements

Topic:.JZtxtcmd.syntax.ctrl.

Program flow control is used both in statements of the script and it is possible inside a text expression.

That control statements iterates over any container, which is gotten from any Java data context. For example and especially it is a result of a parsing process. The datapath should describe a path to either a javadoc-oracle/java/util/Iterable, a javadoc-oracle/java/util/Map or to any array type. The Map will be iterated over its ValueSet whereby the forVariable gets the values. The key of the Map element is not used. Usual the key information may be found in the value too. The forVariable gets the reference to one element of the container for any repetition.

Additionally a for can be terminated if the optional condition is false. Therewith it is possible to iterate over an container but abort that iteration if anything was found there.

ifCtrl::= <ifBlock> [{ elsif <ifBlock>  }][ else \{ [<statementBlock?elseBlock>] \} ].
ifBlock::= ( <condition> ) \{ <statementBlock> \} .
ifInText::= <ifBlockInText?ifBlock> [{ \<:elsif : <ifBlockInText?ifBlock>  }][ \<:else\> <textExpr?elseBlock> ] \<\.if\>.
ifBlockInText::= <conditionInText?condition> \> <textExpr>.

To support a chain of if blocks any number of elsif can be used. It is the same like else if(condition){...} in Java or C/C++.

whileCtrl::= ( <condition> ) \{ [<statementBlock>] \} .
dowhileCtrl::=  \{ [<statementBlock>] \} while ( <condition> ) ; .

Both while forms are known in other programming languages.

The JZtxtcmd does not support a switch-case. Adequate the if..elsif may be used. Secondary a simple for(int var...) with an numeric index is not supported. Use while(...) instead, it does the same.


16.17 Exception handling

Topic:.JZtxtcmd.syntax.onerror.

See 12 onerror - Exceptionhandling

onerror::= [ <#?errorLevel>
           | [<?errortype> notfound | cmd | file | internal | exit ]
           |]
           \{ [<statementBlock>] \}.

16.18 callSubroutine, callSubtext

Topic:.JZtxtcmd.syntax.call.

See

callSubroutine::= [{ <dataPath?assign> [ = | += <?append>] }] call <textValue?callName> ( [{ <namedArgument?actualArgument> ? , }] ) ; .
callSubtext::=<textValue?callName> [ : { <namedArgument?actualArgument> ? , }] \>.
namedArgument::= <$?name> = <objExpr?>.

A namedArgument is any expression. If a namedArgument is designated as Filepath or Fileset it has the special syntax of this elements able to use to build such values on the fly on a subroutine call with the Filepath-Syntax for the actual value.


16.19 Zmake

Topic:.JZtxtcmd.syntax.zmake.

See 7.7 Zmake.

zmake::= [ : <$-?name> :[?=] ]  ##optional : name : of the zmake target, not ends with :=
         <textValue?zmakeOutput> := <textValue?callName>
         ( { <namedArgument?actualArgument> | <filesetAccess> ? ,} ).
## An accessPath is a Filepath, see prepFilepath::=, but analyzed on Java level.
filesetAccess::= [ <""?accessPath> | \<:\><textExpr>\<\.\>
                 | & <dataAccess>
                 | <*\ \r\n,)&?accessPath> ##will be converted to Filepath maybe with ':'
                 |] [ & <dataAccess?zmakeFilesetVariable>] .

The accessPath can be given as & <dataAccess>. The distinction between a singulary access path as data Access and the & <dataAccess?zmakeFilesetVariable> is done with test of the accessed instance. It is checked whether it is a Fileset or not.

The accessPath is converted to a String if it is accessed via & <dataAccess>. The String-given accessPath is converted to a srcJava_vishiaBase/org/vishia/util/FilePath. In that constructor the String is divided especially into the local path and the base path, separated by the character ':'.


16.20 Command line invocation

Topic:.JZtxtcmd.syntax.cmd.

See 7.2 start, cmd: Invocation of operation system commands

cmdLineWait::=[{ <dataPath?assign> += }] cmd\  <cmdLine?>.
cmdLine::= [\!argsCheck!<?argsCheck>] <textValue?> [{[?;[\ |\n|\r]] [ \<\:arg\><textExpr?actualArgument>\<\.arg\> | \<\:args:<dataAccess?argList>\> |<textValue?actualArgument>] }]
  [ \<:stdout:[ pipe<?pipe>| [$]<$?stdoutVariable>] \>] ;.
iferrorlevel::= <#?errorLevel> \{ [<statementBlock>] \}.

A cmdLineWait assigns its stdout to the variable(s), see 16.20 Command line invocation


16.21 Assignment to variables

Topic:.JZtxtcmd.syntax.assign.

Syntax:

assignExpr::= [{ <dataPath?assign> [ = | += <?append>] }] <objExpr?> ;.

The assignExpr is an either an expression without any assign, a procedure call in Pascal-programming language slang. Or it is a function call (Pascal) with or without side effects respectively a simple access to variables (get) or const which value or result may be assigned to any variables. For the objExpr see the syntax of 16.10 Object value: objExpr. An assignment can be done for more as one variable, or the objExpr can be executed without assignment.

The assignment can be an append, especially to a Appendable, Stringjar or Pipe variable. Then the += should be written. A Stringjar can be set newly by using a "=". An Appendable or Pipe can't be assigned, only append. If a = is used, an IllegalArgumentException is thrown in runtime. See 16.7 Variables and their types.

In opposite to the definition of variables the variable have to be existing. A variable is never created on demand. It is a important property of program safety: In some other dynamic languages a variable is created whenever it is used without explicit declaration. If the programmer writes a false identifier, this error is not detected whether on compile- nor on run-time. The actually meant variable will be unchanged, and a new not used variable will be created. The failure is non-obvious.

The rules for variable in 16.7 Variables are not valid for assignments, because there are not newly created variables. Instead the following rules are valid to recognize the type of a variable:


16.22 Thread block

Topic:.JZtxtcmd.syntax..

See 11 Multithreading

threadBlock::= Thread <dataPath?defThreadVar> = [thread] \{ <statementBlock> \}
             | thread \{ <statementBlock> \}.

A thread can be defined eiher with a thread variable or without it. If a thread variable is not given, it will be created internally but not referenced by the users JZtxtcmd data.