1 Substantiation


JZcmd is a script language with its interpreter. A JZcmd 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 JZcmd script will be interpreted using Java. Only a standard Java Virtual Machine (upto version 6) 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.

In a JZcmd 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 JZcmd script--->|           |  use Java data
                        |           +==>+
                       JZcmd ===========+===>cmd line
                        ^               +===>generate text output
                        |               +<== read files
                       Users JZcmd      +===>write files, especially text generation
                       script           +===>invoke Java routines,
                                             prepare data.

As a special capability you can have access to Java data. In this kind you can work with complex container (arrays, lists, trees). A Java class can prepare data in a special and complex kind, and the JZcmd organizes the calling of that class methods with given parameters. You can prepare Java data inside a JZcmd script accessing some user specific Java classes and calling their methods. You can invoke JZcmd from a Java application too.

JZcmd has well capabilities to generate text output from any given Java data. The output text may be a XML format, a programming language's sources code, csv-Format for MS-Excel table calculation, a make script (see Zmake) or any other. The structure of the text is described with the JZcmd script. The data determine the value of place holders, conditionals and repetition sequences. The approach is similar like Wikipedia:_XSLT. But XSLT deals with XML input data only.

JZcmd is used inside

It is possible to write a .bat batch execution script for windows or a shell script for linux, which contains only the start of java JZcmd in a single line, then contains the JZcmd script text. Such a file is named usual with the extension


If a JZcmd script is used for text generation then it is invoked from a special Java program, or especially from one of the ZBNF tool suite Zbnf2Text, Zmake, ZState. Then the script contains the rules how to generate the text. Such a generation script file is designated usual with


2 Copyright, Copyleft


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/ZBNF/sf/docu/JZcmd.html.

3 Availability, test and examples


The capability is tested with the following script:


This test script can be invoked immediately with a command line. Copy it simply from the browsers output as text.

It has produced the following text on the last documented test, use it to compare:


To get the JZcmd script machine, you need only the zbnfjax.jar java class archive, which is contained in the


gotten from either the vishia downloadpage http://www.vishia.org/indexDownload.html

The content of zbnfjax.zip is contained in the ZBNF project: http://www.vishia.org/ZBNF/download/last/ZBNF.zip or from http://sf.net/projects/zbnf.

4 Capability and general Syntax of a JZcmd script


The syntax regards of 2 strategies:

The script has a


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


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 JZcmd script.

What offers JZcmd:

Command line invocation:

Program structure, control flow, variable:

Java usage:

Text generating capabilities:

Zmake approach:

The combination with Java programs offers the following strategy:

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

A JZcmd 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 JZcmd script


A JZcmd 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


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.JZcmd scriptfile

To shorten the invocation of JZcmd 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 JZcmd will be written only with

jzcmd scriptfile

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

help and JZcmd 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

jzcmd --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

jzcmd JZcmdScript -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 JZcmdScript.

User arguments can be given with the option


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

jzcmd 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.

5.2 Start batch file in a MS-Windows and UNIX


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

@echo off
REM This is the start batch for JZcmd 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 JZcmd is referenced here.

REM adapt the path to the zbnfjax folder of vishia-ZBNF tools.
REM It contains the jar archive for execution of JZcmd and some JZcmd scripts which may be included.
set ZBNFJAX_HOME=D:/vishia/ZBNF/sf/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

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 JZcmd scripts.
REM Comment it if not used.
set XML_TOOLS=D:\Programme\XML_Tools

REM This is the invocation of JZcmd, with up to 9 arguments.
java -cp %ZBNFJAX_HOME%/zbnf.jar   org.vishia.zcmd.JZcmd   %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:

jzcmd path\to\script.jzcmd

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

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

5.3 Invocation from a Java application


See javadoc-Zbnf/org/vishia/zcmd/JZcmd

A parsed script can be executed invoking execute(...) in javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter. 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 JZcmd script


A JZcmd script is a textual script. It is parsed and converted to an internal representation of data and statements while starting JZcmd. 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 JZcmd execution.

The syntax of a JZcmd script is defined in ZBNF syntax language internally in the JZcmd script translator engine. That syntax can be presented in the help output, see 16 Syntax of a JZcmd 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 JZcmdScript 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:


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

6.1 Script variables


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.5 Variables.

6.2 Included scripts


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 can contain some subroutines and a main(). The first found main() wins. Because the first script is parsed at first, its main routine wins. But the main routine can be defined in a included script too. One can use a script whith special sub routines but does not contain a main routine. With them, a special behavior can be variegated with a short special script.

The included scripts are not textual included like an #include statement in C++ or like the ZBNF-parsers $import in syntax scripts.

Syntay see 16.1.8 The include statement.

6.3 The main routine


The main routine is started if another routine is not specified.

6.4 Classes


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.2 Classes

To invoke a sub routine in a class one should write


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


Syntax see 16.3 subroutine.

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

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

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...

  Map result = call mySub();


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 things additionally. An text output written with <:>textexpression <.> inside a sub routine is written in the current text if the subroutine was called inside a text expression with <:subtext:"mySubtext":arguments>.

6.6 Statement blocks


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


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

Syntax see Chapter: 16.12 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.11 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 JZcmd invocation can show this texts in a console, redirect to files or redirect for example to a message system in Java using javadoc-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


Syntax see 16.1.5 comments.

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!

6.9 Script as part of another file


It is possible to write a JZcmd 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 jzcmd.bat thisFile.jz.bat
exit /B

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

Filepath input = path/to/myFile.csv;


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

Writing inside a java source file:

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

//JZcmd Obj a = java org.vishia.util.test.TestCalculatorExpr.testSimpleExpression();
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 //JZcmd. It is a comment in the Java source file. But if this file is used as JZcmd 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 JZcmd with the main class org.vishia.zcmd.JZcmd. 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 JZcmd script ends with the label //endJZcmd. The text after them is not used for JZcmd.

7 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.4 statements.

7.1 Definition of variables


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.5 Variables

7.2 start, cmd: Invocation of operation system commands


If the JZcmdExecuter 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.7 Text value: textDatapath, textValue for the first argument.

If you write

cmd notepad.exe &file;

then the JZcmd waits till notepad is finished. That is the difference between the both JZcmd 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 JZcmd 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 JZcmd/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


There are four possibilities to give arguments. For the full syntax see 16.18 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.7 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


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><.> 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:


presents the command arguments in one line per argument

-->arg2 may contain spaces <--

7.2.3 Additional environment variables


The command line invocation gets all variables from the calling environment of the JZcmd 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 jzcmdsub.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


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 JZcmd execution:

textBuffer += out += cmd myCommand;

In this case the stdout is forwarding to the JZcmd 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


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 = <&jzcmdsub.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_JZcmd:TestAll/readme.txt: sub testErrorlevel()

7.2.6 Execution time for operation system commands


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 JZcmd 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 JZcmd 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
  echo off
  dir >out.txt
  call otherbatch.bat
cmd cmd.exe /C myBatch.bat;

The batch is contained as text lines in a JZcmd 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 JZcmd script then and it can be evaluated:

Stringjar sdir = FileSystem.readFile("out.txt");  ##reads the file.
  String line = sdir.getCurrentPart();

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

7.3 currdir, cd statement


Inside a JZcmd 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 JZcmd


A path for the current directory can be given:

 currdir = "path/to/mycurrentdir"
 currdir = scriptdir;
 currdir = <:><&scriptdir>/../relative<.>

7.3.2 cd or currdir = path


The statement cd or CD is known from both Unix shell scripts and MS-Windows batch files. The JZcmd 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 JZcmd 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 JZcmd 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


The currdir is a variable of JZcmd. 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:


The method currdir() on sub level or for the whole JZcmd 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 jzcmdsub or jzcmd.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 JZcmd does not affect the operation system's current directory


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 JZcmd 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 the JZcmd-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 javadoc-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 JZcmd script.

7.4 File commands


There are some commands to offer operation systems capability:

mkdir path/to/dir

It makes the directory starting from the current directory or with the given absolute path. If the directory exists already, it is ok, no error.

Copying a file. The copy command knows 3 options:

copy -n-w-r path/to/source.ext dst/path/name.ext

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 JZcmd 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:


7.5 call: Invocation of sub routines


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

Syntax see 16.16 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 JZcmd 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.


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.8 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/JZcmdFilepath 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/JZcmdAccessFileset

Hint: On missing variables etc. a runtime error occurs. Because JZcmd 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=jzcmdsub.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 Zmake


A Zmake statement is written in form:

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

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 examples see Zmake.

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

7.7 Assignments, Expressions and Text expressions


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.19 Assignment to variables

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

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

8 Program flow control


Syntax see 16.14 Control statements.

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


One can write

else {

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()...


One can write

while(condition) {

to execute statemens so long as the condition is true.

do {
} while(condition);

checks after the loop body.

8.3 for(container)...


The JZcmd 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(variable: datapath.container){

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.

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

for(variable:container && condition){

The condition is checked before any iteration. If it 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;

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.

Condition if the container has a next element:

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 ,.

8.4 break, return, exit


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;
    ObjType obj = container.next();
      do something...
  <+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 JZcmd:

sub mySub(){
  Obj foundObj;
  while(foundObj ==null && anyContainer.hasNext()){
    Obj obj = container.next();
      foundObj = obj;
    do something...
  } else {
    <+out>not found.<.+n>;

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();
     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();
   Obj element = myIterator.next();
     found = element;

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

The possibility for break in loops and return in subroutines in JZcmd 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


A JZcmd 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


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

9.1.1 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 javadoc-vishiaBase/org/vishia/util/CalculatorExpr.Value.

9.1.2 Bool


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


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.7 Text value: textDatapath, textValue

9.1.4 Stringjar


A Stringjar references a javadoc-vishiaBase/org/vishia/util/StringPartAppend. It contains a javadoc-oracle/java/lang/StringBuilder which is used as Appendable. This class has all features of javadoc-vishiaBase/org/vishia/util/StringPartScan and javadoc-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 JZcmd 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 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.6 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.


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

9.1.7 Map


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";

The variable is stored in the map and can be gotten by myContainer.anyVariable.

A Map is build especially on an Chapter: 10.4 Object expression if a dataStruct is created writing:

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

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

myData.method({ String cmd1 = "cmd"; String data = anydata; }, nextArg);

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

One can use all methods of the Map interface especially


9.1.8 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:


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


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.9 Class


A Class variable is created with

Class MyClass = path.to.Class;

Whereby path.to.Class 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.Class;

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

<:>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.Class.itsStaticMethod(args);  ## without Class variable

A second benefit using a Class variable is: If the path is wrong, an exception is thrown on definition of the Class variable, before the access is executed.

9.1.10 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 JZcmd script application needs other classes than given in the classpath of the java invocation, the Classpath should be used:

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

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

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.11 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";

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 JZcmd interpreter is finished on the operation system. If it is a long-running process, the file will remain open.

9.1.12 Filepath, Fileset


See examples_Fileset.

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 javadoc-vishiaBase/org/vishia/cmd/JZcmdFilepath: Instance which is used in JZcmd for Filepath

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


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:


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


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 JZcmd 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:



like given

only local


like given





























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


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 javadoc-vishiaBase/org/vishia/cmd/JZcmdFileset.

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.

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.13 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


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

In the first case a JZcmd 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 JZcmd it is possible to build a datapath to address data. The syntax is described in 16.9 DataPath, Data access.


is the path from the predefined variable jzcmd which refers the instance of JZcmdExecuter to the data field javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter.JZcmd#startmilli.

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


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", jzcmdsub.currdir());

The fields and methods from any instance are found and accessed via the reflection mechanism of Java. The translator of the JZcmd-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 JZcmd script:

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

jzcmd.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 JZcmd script too. But a software, including the JZcmd 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 javadoc-vishiaBase/org/vishia/util/DataAccess.

For the syntax of a datapath in a JZcmd script see 16.9 DataPath, Data access

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

9.3 Variable definition context, datapool


A JZcmd 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.
    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 JZcmd 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 JZcmd 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:


For the syntax of variable definition see 16.5 Variables.

9.4 Datapath depending on Variables


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.A.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_JZcmd/TestAll/testAll.jz.bat in the sub testVariableDatapath().

9.5 Predefined script variables


Some variables are defined on start of JZcmd-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.9 Class 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 jzcmd


It references javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter.JZcmd. Able to use for:

9.5.2 jzcmdsub


It references javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter.ExecuteLevel. Able to use for:

9.6 Definition and change of script variables


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 jzcmd. It is the JZcmdExecuter itself, see 9.5 Predefined script variables. One should write

jzcmd.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


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


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 JZcmd local or script variables


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

A JZcmd variable can be stored in a tree structure. A node is a 9.1.7 Map, the last element is the specified JZcmd variable. To access such a treed variable write


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){

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 JZcmd 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


The first tag to access to Java internal data is a JZcmd 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 JZcmd script is embedded in a Java environment some JZcmd script variables can be predefined with references to Java objects. For example refer Zmake. A Zmake generation script is a JZcmd 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 JZcmd 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.8 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.12 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


of javadoc-Zbnf/org/vishia/zcmd/JZcmd

respectively calling arguments accessPrivate

of javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter#execute(org.vishia.cmd.JZcmdScript, boolean, boolean, java.lang.Appendable)

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

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


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();

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

Class MyClass = java org.myPackage.MyClass;

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 JZcmd. 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


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 JZcmd. Alternatively the capabilities of the java.lang.ClassLoader can be used.

9.12 Invocation of Java methods, arguments


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 JZcmd 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.JZcmdUserExample();

The arguments are an ObjExpr, see 10.4 Object expression and syntax: 16.8 Object value: objExpr. The expression will be translated to the internal presentation in JZcmd 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 javadoc-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.JZcmdUserExample();
 obj.methodTest(5*Math.PI, 8+5);

In this case the first argument uses the JZcmd 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:


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.

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 JZcmd 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 JZcmd 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


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


Operands are either

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

10.2 textValue or textDatapath


See its syntax in 16.7 Text value: textDatapath, 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.9 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.


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


Syntax see Chapter: 16.12 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:


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


Syntax see Chapter: 16.8 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:


Because the JZcmd 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


Syntax see Chapter: 16.10 Condition expression.

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

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 JZcmd 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.9 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.


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.


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: javadoc-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 = ...
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 like known in C language:

That is proper for a script. In opposite: the Java language forbids that simple automatic conversions because clarity of code.

10.6 Numeric Expression


Syntax see Chapter: 16.11 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. Therefore arrays are not supported yet.

11 Multithreading


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 = {

The second form uses a dedicated thread variable. But it is the same principle and an adequate syntax. The thread variable is type of javadoc-vishiaBase/org/vishia/cmd/JZcmdThread. The state of the thread can be gotten by reading the variable javadoc-vishiaBase/org/vishia/cmd/JZcmdThread#state. Last not least the method javadoc-vishiaBase/org/vishia/cmd/JZcmdThread#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


The class JZcmdThread 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/JZcmdThread.MsgItem. Any other thread can send a command to the JZcmdThread instance with

myThread.sendcmd("command", anydata);

The Thread can send a message with

myThread.sendmsg("identifier", data);

which is awaiting by another thread:


The argument is the timeout time. Because JZcmd 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


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


Syntax see 16.15 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 JZcmd 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


With the statement


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


The statement

onerror {

can be inserted after some statements inclusively calling of sub routines, which may throw an exception. On exception the JZcmd 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 JZcmd. All of the program code is tried.

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

There are a few types of onerror:

onerror notfound { ... }

It is executed especially if a variable is used in a JZcmd script which is not existing. JZcmd 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 JZcmd 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 JZcmd 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 javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter.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


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

The cmd line invocation ends with an errorlevel which is stored in the variable jzcmdsub.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


In a JZcmd an exception can be thrown usual conditionally:

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

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

12.5 Show exception information


The following data access paths can be used:


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 jzcmdsub.threadData.exception field. See 9.5.2 jzcmdsub.

A Stacktrace can be reported by using

String stacktrace = jzcmdsub.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:

JZcmd.execute - exception at; @D:\vishia\ZBNF\sf\ZBNF\examples_JZcmd\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, jzcmd, jzcmdsub, 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.JZcmdExecuter$ExecuteLevel.dataAccess(JZcmdEx
ecuter.java:1964); org.vishia.cmd.JZcmdExecuter$ExecuteLevel.executeDa
tatext(JZcmdExecuter.java:1590); org.vishia.cmd.JZcmdExecuter$ExecuteL
evel.execute(JZcmdExecuter.java:752); org.vishia.cmd.JZcmdExecuter$Exe
cuteLevel.execute(JZcmdExecuter.java:662); org.vishia.cmd.JZcmdExecute
r$ExecuteLevel.textAppendToVarOrOut(JZcmdExecuter.java:1169); org.vish
ia.cmd.JZcmdExecuter$ExecuteLevel.execute(JZcmdExecuter.java:714); org
; org.vishia.cmd.JZcmdExecuter$ExecuteLevel.execSubroutine(JZcmdExecut
er.java:1321); org.vishia.cmd.JZcmdExecuter$ExecuteLevel.execCall(JZcm
dExecuter.java:1211); org.vishia.cmd.JZcmdExecuter$ExecuteLevel.execut
e(JZcmdExecuter.java:753); org.vishia.cmd.JZcmdExecuter$ExecuteLevel.e
xecute(JZcmdExecuter.java:662); org.vishia.cmd.JZcmdExecuter.execute(J
ZcmdExecuter.java:431); org.vishia.zcmd.JZcmd.execute(JZcmd.java:398);
org.vishia.zcmd.JZcmd.execute(JZcmd.java:354); org.vishia.zcmd.JZcmd.s
main(JZcmd.java:190); org.vishia.zcmd.JZcmd.main(JZcmd.java:142);

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


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 JZcmd call levels


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 JZcmd 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 JZcmd 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 JZcmd 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 javadoc-vishiaBase/org/vishia/cmd/JZcmdExecuter.ExecuteLevel#execute(...) to view details.

13 Text output and text generation


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


For building a textual argument the text should be surrounded with

<:>That is the text<.>

To output to the JZcmd output file one should write

<+>Text to the text generation output<.>

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

<:>text as text expression for assignmant or as argument<.>

A text expression is outputted like <+>text<.> 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<.>
String var = <:>this text is assigned to the var<.>
call subroutine(<:>text used as argument<.>);

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 JZcmd text output file


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/JZcmdExecuter#execute(org.vishia.cmd.JZcmdScript, boolean, boolean, java.lang.Appendable, java.lang.String) and docuSrcJava_vishiaBase/org/vishia/cmd/JZcmdExecuter#execSub(org.vishia.cmd.JZcmdScript.Subroutine, java.util.Map, boolean, java.lang.Appendable, java.io.File). In this cases the output is determined outside of the JZcmd script.

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


text = path/to/textOutputFile.ext;  //now deprecated, use above

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:


for example if a directory is given as argument.

13.3 Lines and indentation in the script


To produce a newline after the output line one can write

<+>My line<.+n>

The Text is a plain text. It can be written over some lines. Usual it is indented if the surround algorithm is indented:

sub myRoutine(...)
{ for(variable: container) {
    <+><: >
    Create this text for it
    with several lines <&variable.value>
  } ...

The text is indented of course. But in the output file the text has not an indent, of course. That is because the text starts in the column where the <+> is notated which is the indentation column. Note that in this example the first line does not start with a newline because the <: >.

There are some more possibilities especially to mark and separate ranges of text with ranges of statements:

sub myRoutine(...)
{ for(variable: container) {
    <+><: >
====Create this text for it
====with several lines <&variable.value>
    if(condition) {   =========<+>A text line
                      =========next Line of this text
    }  ...

Therewith it is better obvious that there are text lines. Instead ====== there can be used :::: or ++++++ too, but not in combination in one line. Syntactically the ==== is written outside of the text before <+>A textline and inside the text in the next lines. Both is admissable. The first one is skipped by the parser of the JZcmd script. A === starting before the indentation column. See the next example which shows possibilities which may be proper or not:

     <+><: >
   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.

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 JZcmd 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 JZcmdExecuter counts only spaces and tabs from the start of a JZcmd source text to skip over the source indentation characters independent of spaces or tabulators.

Pattern for well readable JZcmd 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 JZcmd source is better able to read, no confusion because the syntax is similar. Write:

if(JZcmdexpression) {              <+>
                       ::::::::::::  if(C_expression) { //similar syntax like JZcmd
                       ::::::::::::    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.5 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 JZcmd 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 JZcmd-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

JZcmd statements <+>

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

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

JZcmdExpression()                  <+>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:


<+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


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 JZcmd. It is not the newline character(s) of the JZcmd 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:


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


next line  after tab <:special>
after 0x0d

13.5 Column tabulator


One can set the next column position in a line writing


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.6 Place holder and values


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


to get data from any location. The datapath is the same like in assignments to String variables, see the whole chapter 9 Data and variables, the syntax of datapath in 16.7 Text value: textDatapath, textValue and syntax: 16.9 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.7 Numeric formatting


Numeric types can be converted with a special format. Write


with a valie 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 JZcmd 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.

13.8 Program control in text expressions


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

One can write conditional text using

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


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")>


<: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.9 Insert text form a subroutine: <:subtext:...>


Syntax see 16.16 callSubroutine, callSubtext. Inside a text expression one can write

...<:subtext:name:arg = value, arg2=value> ...

Then the subroutine name is called and executed.

sub name(Obj arg, String arg2="default"){
  ...some statements

Its output

<:>text in subroutine<.>

is written to the currently text where the <:subtext...> is called.

With that feature a text expression can be more simple to read because some complex generation conditions of a part of a text can be externalized.

In a subroutine any other text output can be done too of course with


If the channel is the same, especially if


sub subroutine{ <+>text...<.+>...

was written, it has the same effect. The difference is a semantic one:

13.10 Writing to the main output file


The JZcmd 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


wherby text is a 16.12 TextExpression.

To flush the output one should use a flush operator inside the text:


or more simple flush with the and tag:


or flush in conclusion with a newline:


like any other text output with <+channel>....<.+n+flush>.

14 Interaction


A JZcmd script is intended as batch script firstly. For example its subroutines can be used inside a Graphical User Interface as action code. Though a minimal interaction is designated which may be important for simple user quests for a batch. Besides it is possible to open a graphical application within a JZcmd script.

15 Debugging possibilities


A JZcmd 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


While invocation JZcmd the given script is translated complete firstly. If any syntactical error is found, an error message like

JZcmd - 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.JZcmd --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


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:

!checkJZcmd = "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


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 JZcmd 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 JZcmd 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 JZcmd 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 JZcmd 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


The JZcmd knows a variable test which refers an instance of javadoc-vishiaBase/org/vishia/cmd/JZcmdTester. 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 JZcmd script:

15.5 Debugging in an Integrated Development Environment, for example Eclipse


The JZcmd 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/JZcmd and interpreter javadocPriv-vishiaBase/org/vishia/cmd/JZcmdExecuter. 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 JZcmd script, the user can set a breakpoint and debug its own routines. On return of this routines it returns to the JZcmdExecuter 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");

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 javadoc-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");

The next instructions in DataAccess checks the actual arguments, which may be faulty.

break in the execution loop of JZcmd:

If any of the execution of the JZcmd script seems to be obscure, you can insert a debug statement bevor the obscure statement:

...jzcmd statements
debug "my text";
debug <:>any <&variable>-expression<.>;
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/JZcmdExecuter.ExecuteLevel#debug(org.vishia.cmd.JZcmdScript.JZcmditem)

 void debug(JZcmdScript.JZcmditem statement) throws Exception{
   CharSequence text = evalString(statement);

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 JZcmd script. The next statement will be the 'obscure' one. You can study whats happen.

16 Syntax of a JZcmd script


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 JZcmd from command line to output the syntax with the help text:

 java -cp path/to/zbnf.jar org.vishia.zcmd.JZcmd --help:helpoutput.txt

Details of the syntax may be changed in further development. Therefore see and compare that help output.

16.1 The script


The syntax starts with some common settings and the definition of the top-level component, the frame of a script.

$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 .


16.1.1 JZcmd marker


A JZcmd script can contain some other text, especially a start sequence of a batch file or a shell script. One can write for example a windows batch file which invokes java ... JZcmd thisScript and exit then. After them the ==JZcmd== label is written. The parser skips over the whole text before the first ==JZcmd== is found.

[<*|==ZGen==?>==ZGen== ]
[<*|==JZcmd==?>==JZcmd== ]

The syntax means, all text will be skipped if the marker ==JZcmd== will be found. If that marker is not found, nothing is skipped. Note: Don't write that marker inside a JZcmd source.

16.1.2 Test outputs


On start of script it is possible to define output files for test:

[{ ! checkJZcmd = <textValue?checkJZcmdFile> ;
 | ! checkXml = <textValue?checkXmlFile> ;

16.1.3 include


The { include [<""?include> | <* ?include>] ; } enables the designation of included files. The file path can be given with or without quotion marks. A relative given file path starts from this file, which includes. The include statements should be given on start of the script.

[{ [REM|Rem|rem] <*\n\r?> ##Remark like in batch files
 | include <include> ;
 | currdir = <textDatapath?cd> ;

See 6.2 Included scripts.

16.1.4 End marker


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?>



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.

| //JZcmd      ##ignore //JZcmd, it may be a comment for another language
| //<*\n\r?>   ##line comment in C style
| /*<*|*/?>*/  ##block commment in C style
| [REM|Rem|rem] <*\n\r?> ##Remark like in batch files

16.1.6 ScriptVariable


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?> ;

See 6.1 Script variables

16.1.7 The main syntax of the rest of the script


The script consist of definition of subtext, 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.1.8 The include statement


The path can be given starting with an optional environment variable, optional continued with a path.

include::= [$<$?envVar>[/|\\]][ <""?path> | <*;\ ?path>].

16.2 Classes



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.3 subroutine



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.12 TextExpression, it contains a <textExpr> itself. The procedures for calling are the same.

16.4 statements



statementBlock::= { <statement?> }.

  \{ [<statementBlock>] \}
| REM <*\n\r?> ##Remark like in batch files
| ::{:}                ##Skip over :::
| //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
| currdir = <textDatapath?cd> ;   ##set current directory
| [cd|CD] [<textValue?cd> | <*\ ;?cd> ; ]  ##change current directory
| <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>] ;
| <callSubroutine?call>
| <threadBlock>
| \<+<textOut>
| \<:\><textExpr>\<\.\> [;]
| <cmdLineWait?cmdWait>
| <assignExpr>
| ;

srcdst::= [src=] <textValue?actualArgument> [dst=] <textValue?actualArgument> .
oneArg::= <textValue?actualArgument> .

16.5 Variables



  String\  <DefStringVar?textVariable>
| Stringjar\  <DefSpecVar?Stringjar>
| Num\  <DefNumVar>
| Bool\  <DefBoolVar>
| Pipe\  <DefSpecVar?Pipe>
| List\  <DefSpecVar?List>
| Map\  <DefMapVar>
| Obj\  <DefObjVar>
| Class\  <DefClassVar>
| Classpath\  <DefClasspath>
| Openfile\  <Openfile>
| Fileset\  <DefFileset>
| Filepath\ <DefFilepath>
| Set\  <DefStringVar?setEnvVar>
| set\  <DefStringVar?setEnvVar>
| SET\  <DefStringVar?setEnvVar>

The syntax component <DefVariable?> is used both in the script outside of routines for script variables, 16.1 The 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.9 DataPath, Data access how access variables.

DefNumVar::= [const <?const>] <definePath?defVariable>  [ = <numExpr>].

DefBoolVar::= [const <?const>] <definePath?defVariable>  [ = <boolExpr>].

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 JZcmd 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.16 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.6 Fileset, Filepath


See 9.1.12 Filepath, Fileset

DefFileset::= <definePath?defVariable> [ =  (
[ commonpath = [<""?commonPath>|<*;,)(\ \r\n?commonPath>] , ]
{ [{ //JZcmd | //<*\n\r?>}] [<""?filePath>|<*;,)(\ \r\n?filePath>] [{ //JZcmd | //<*\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>.

DefFilepath::= <definePath?defVariable> [ = <textValue?> ].

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 JZcmd-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.7 Text value: textDatapath, textValue


A text expression presents a String:

textDatapath::=  <""?text> | \<:\><textExpr>\<\.\> | [& [?(] ] <dataAccess> .

textValue::=  <""?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.12 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.8 Object value: objExpr


An objExpr which presents any Object to assign to a variable or used for a calling argument is defined as

  File : <textValue?File>         ## A textValue which builds a java.lang.File in the currdir
| 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?> ; }.

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.9 DataPath, Data access



[ $<$?envVariable>
| [<?startVariable> $<#?>| $<$?>]    ## $1 .. $999 are the arguments of JZcmd, $name for environment
| [java\ ] new\  <staticJavaAccess?newJavaClass>
| [%|java\ ] <staticJavaAccess?staticJavaMethod>
| <dataPath?>

For variable see 16.5 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 JZcmd 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
  [ & <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::= <startDatapath>[ [?\. \>] \.{ <datapathElement> ? [?\. \>] \.}].

## A datapath cannot start with an JZcmd keyword!
startDatapath::= [ & ( <dataPath> ) | <$-?ident> ] <?whatisit=@> [( [{ <objExpr?argument> ? ,}])<?whatisit=+>].
## Use regex for the second datapath element, it can be a JZcmd keyword too!
datapathElement::= [ & ( <dataPath> ) |[<?ident>[@]<![\\w-]+?>]] [( [{ <objExpr?argument> ? ,}])<?whatisit=(>].

An indentifier of a datapath element can start with @ especially to access to a XML tree, to the attributes.

16.10 Condition expression


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.11 Numeric Expression


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.9 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 JZcmd 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.12 TextExpression


See 13 Text output and text generation

{ [?\<\.\>]                             ##abort on <.>
[ \<&-<*\>?>\>                          ##<&- it is comment>
| \<:-<*\>?>\><textExpr?>\<\.-<*\>?>\> ##<:-comment> comment <.- >
| \#\#<*\r\n?>   ##comment to eol in a text Expression
| \<:for:<forInText?forCtrl>
| \<:if: <ifInText?ifCtrl>
| \<:hasNext\> <textExpr?hasNext> \<\.hasNext\>
| \<:subtext : <callSubtext?call>
| \<:scriptdir<?scriptdir>\>
| \<:debug[:<textDatapath?debug>| <?debug>]\>
| \<&<dataText>
| \<: [<?transliteration>n|r|t|[\<|#|\"]<*\>?>] \>
| \<:lf\><?newline>
| \<:\ \><!\\s*?> [ \#\#<*\r\n?> <!\\s*?> ]
| \<:@<setColumn>\>
| \<:\><textExpr?>\<\.\>
| <*|\<:|\<=|\<&|\#\#|\<\.?plainText>

Text expressions are used either to output text in 16.4 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.

dataText::=<dataAccess>[ \: [<""?formatText>|<*\>?formatText>]] \>.     ##<*expr: format>

The text can contain the named control elements and the possibility of values with format dataText.

A <:n> produces a new line with the requested coding like given as calling argument of JZcmd (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.13 Assign an output text


See 13 Text output and text generation.

textOut::= [<dataPath?assign>] \> <textExpr>[ \<\.+\>
  | \<\.n+\><?newline> | \<\.+n\><?newline>
  | \<\.+n+flush\><?newline><?flush> | \<\.+flush\><?flush>
  | \<\.+n+close\><?close> | \<\.+close\><?close>].

setColumn::=<numExpr> [ : <numExpr?minSpaces>] | : <numExpr?minSpaces>.

Note: in

| \<+ <textOut>

The textOut appends the text between <+variable>...TEXT...<.+> to the variable. The variable should be an Appendable type. See 16.5 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.14 Control statements


Program flow control is used both in statements of the script and it is possible inside a text expression.

forCtrl::= ( <$?forVariable> : <dataAccess?forContainer> [ && <condition> ])  \{ <statementBlock> \} .

forInText::= <$?forVariable> : <dataAccess?forContainer> [ && <condition> ] \> <textExpr> \<\.for[ : <$?@checkForVariable> ]\>.
##name is the name of the container element data reference

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 JZcmd 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.15 Exception handling


See 12 onerror - Exceptionhandling

onerror::= [ <#?errorLevel>
           | [<?errortype> notfound | cmd | file | internal | exit ]
           \{ [<statementBlock>] \}.

16.16 callSubroutine, callSubtext



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.17 Zmake


See 7.6 Zmake.

zmake::= [ : <$-?name> :[?=] ] <textValue?zmakeOutput> := <textValue?callName> ( { <namedArgument?actualArgument> | <filesetAccess> ? ,} ).

## An accessPath is a Filepath, see prepFilepath::=, but analyzed on Java level.
filesetAccess::= [
                   <""?accessPath> | \<:\><textExpr>\<\.\>
                 | [<?accessPathOrFilesetVariable> [&]<*\ \r\n,)&;?>]
                 ] [ & <$?zmakeFilesetVariable>] .

16.18 Command line invocation


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.18 Command line invocation

16.19 Assignment to variables



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.8 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.5 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.5 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.20 Thread block


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 JZcmd data.