<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://devwiki.neosys.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AlexNenko</id>
	<title>NEOSYS Dev Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://devwiki.neosys.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AlexNenko"/>
	<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php/Special:Contributions/AlexNenko"/>
	<updated>2026-04-28T15:49:48Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Assert_examples&amp;diff=1038</id>
		<title>Assert examples</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Assert_examples&amp;diff=1038"/>
		<updated>2010-11-26T15:13:04Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: Created page with &amp;#039; // main1.cpp - demonstrates standard usage of asserts  #include &amp;lt;iostream&amp;gt;  #include &amp;lt;cassert&amp;gt;  int main() {     int x = 3;     cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;  &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;  …&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; // main1.cpp - demonstrates standard usage of asserts&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;   assert( x == 4);&amp;lt;/font&amp;gt;             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// aborts here with message &amp;quot;Assertion failed: x == 4, file main1.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // main2.cpp - demonstrates how to avoid aborting a program&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;#include &amp;lt;cassert_warn&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
    assert( x == 4);             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Assertion failed: x == 4, file main.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;                    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// ... and immediately returns successfully&amp;lt;/font&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // main3.cpp - demonstrates how to avoid aborting a program&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;#include &amp;lt;cassert_pause&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
    assert( x == 4);             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Assertion failed: x == 4, file main.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;                    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Press any key to continue ...&amp;quot; and waits for keypress&amp;lt;/font&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // main4.cpp - demonstrates how to modify asserts on per statement basis&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;#include &amp;lt;cassert_exodus&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;   assert( x == 4);&amp;lt;/font&amp;gt;             &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// aborts here with message &amp;quot;Assertion failed: x == 4, file main1.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // main5.cpp - demonstrates how to modify asserts on per statement basis&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;#include &amp;lt;cassert_exodus&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;   assert_warn( x == 4);&amp;lt;/font&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Assertion failed: x == 4, file main.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;                    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// ... and immediately returns successfully&amp;lt;/font&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 // main6.cpp - demonstrates how to modify asserts on per statement basis&lt;br /&gt;
 #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;#include &amp;lt;cassert_exodus&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
 int main() {&lt;br /&gt;
    int x = 3;&lt;br /&gt;
    cout &amp;lt;&amp;lt; &amp;quot;Hello, world !\n&amp;quot;;&lt;br /&gt;
 &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;   assert_pause( x == 4);&amp;lt;/font&amp;gt;        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Assertion failed: x == 4, file main.cpp, line 7&amp;lt;/font&amp;gt;&lt;br /&gt;
    return x;                     &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// print &amp;quot;Press any key to continue ...&amp;quot; and waits for keypress&amp;lt;/font&amp;gt;&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1037</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1037"/>
		<updated>2010-11-26T14:53:23Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
If &amp;lt;code&amp;gt;some_expression_that_should_be_normally_true&amp;lt;/code&amp;gt; happens to be false, the program aborts with message printed to console.&lt;br /&gt;
&lt;br /&gt;
Exodus has 3 additional include files which modify or extend the functionality of standard cassert file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_warn&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, but not to abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_pause&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, and then pause the program until user presses a key; macro does not abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_exodus&amp;lt;/code&amp;gt; - defines assert() macro in the standard way, but adds 2 more macros:&lt;br /&gt;
&amp;lt;code&amp;gt;assert_warn( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, no abort();&lt;br /&gt;
&amp;lt;code&amp;gt;assert_pause( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, pause until keypress, no abort().&lt;br /&gt;
&lt;br /&gt;
For simple examples - click on [[assert_examples]].&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1036</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1036"/>
		<updated>2010-11-26T14:52:06Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
If &amp;lt;code&amp;gt;some_expression_that_should_be_normally_true&amp;lt;/code&amp;gt; happens to be false, the program aborts with message printed to console.&lt;br /&gt;
&lt;br /&gt;
Exodus has 3 additional include files which modify or extend the functionality of standard cassert file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_warn&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, but not to abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_pause&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, and then pause the program until user presses a key; macro does not abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_exodus&amp;lt;/code&amp;gt; - defines assert() macro in the standard way, but adds 2 more macros:&lt;br /&gt;
&amp;lt;code&amp;gt;assert_warn( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, no abort();&lt;br /&gt;
&amp;lt;code&amp;gt;assert_pause( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, pause until keypress, no abort().&lt;br /&gt;
&lt;br /&gt;
For simple examples - click on [assert_examples].&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1035</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1035"/>
		<updated>2010-11-26T14:50:35Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
If &amp;lt;code&amp;gt;some_expression_that_should_be_normally_true&amp;lt;/code&amp;gt; happens to be false, the program aborts with message printed to console.&lt;br /&gt;
&lt;br /&gt;
Exodus has 3 additional include files which modify or extend the functionality of standard cassert file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_warn&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, but not to abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_pause&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, and then pause the program until user presses a key; macro does not abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_exodus&amp;lt;/code&amp;gt; - defines assert() macro in the standard way, but adds 2 more macros:&lt;br /&gt;
&amp;lt;code&amp;gt;assert_warn( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, no abort();&lt;br /&gt;
&amp;lt;code&amp;gt;assert_pause( some_expression_that_should_be_normally_true)&amp;lt;/code&amp;gt; - message, pause until keypress, no abort().&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1034</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1034"/>
		<updated>2010-11-26T14:48:54Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
 &amp;lt;/source&amp;gt;&lt;br /&gt;
If &amp;lt;code&amp;gt;some_expression_that_should_be_normally_true&amp;lt;/code&amp;gt; happens to be false, the program aborts with message to console.&lt;br /&gt;
&lt;br /&gt;
Exodus has 3 additional include files which modify or extend the functionality of standard cassert file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_warn&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, but not to abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_pause&amp;lt;/code&amp;gt; - redefines all assert()s to display diagnostic message when triggered, and then pause the program until user presses a key; macro does not abort() the program;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cassert_exodus&amp;lt;/code&amp;gt; - defines assert() macro in the standard way, but adds 2 more macros:&lt;br /&gt;
assert_warn( some_expression_that_should_be_normally_true); - message, no abort();&lt;br /&gt;
assert_pause( some_expression_that_should_be_normally_true); - message, pause until keypress, no abort().&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1033</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1033"/>
		<updated>2010-11-26T14:40:21Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
&lt;br /&gt;
If some_expression_that_should_be_normally_true happens to be false, the program aborts with message to console.&lt;br /&gt;
&lt;br /&gt;
Exodus has 3 additional include files which modify or extend the functionality of standard cassert file.&lt;br /&gt;
&lt;br /&gt;
cassert_warn - redefines all assert()s to display diagnostic message when triggered, but not to abort() the program;&lt;br /&gt;
&lt;br /&gt;
cassert_pause - redefines all assert()s to display diagnostic message when triggered, and then pause the program until user presses a key; macro does not abort() the program;&lt;br /&gt;
&lt;br /&gt;
cassert_exodus - defines assert() macro in the standard way, but adds 2 more macros:&lt;br /&gt;
assert_warn( some_expression_that_should_be_normally_true); - message, no abort();&lt;br /&gt;
assert_pause( some_expression_that_should_be_normally_true); - message, pause until keypress, no abort().&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1032</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1032"/>
		<updated>2010-11-26T14:32:36Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
&lt;br /&gt;
 // near beginning of .cpp file:&lt;br /&gt;
 #include &amp;lt;cassert&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 // somewhere in the code:&lt;br /&gt;
 assert( some_expression_that_should_be_normally_true);&lt;br /&gt;
&lt;br /&gt;
If some_expression_that_should_be_normally_true happens to be false, the program aborts with message to console.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1031</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1031"/>
		<updated>2010-11-26T14:31:04Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* using asserts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;br /&gt;
&lt;br /&gt;
Asserts may be used to trap some errors in Exodus code.&lt;br /&gt;
Typical scheme to use asserts:&lt;br /&gt;
&lt;br /&gt;
// near beginning of .cpp file:&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;cassert&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// somewhere in the code:&lt;br /&gt;
assert( some_expression_that_should_be_normally_true);&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1030</id>
		<title>Manual</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Manual&amp;diff=1030"/>
		<updated>2010-11-26T14:28:20Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* if (aa ^ bb &amp;gt; cc) //won&amp;#039;t compile! */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=== Hello World ===&lt;br /&gt;
&lt;br /&gt;
After installing Exodus, you can develop Exodus programs from any operating system command line.&lt;br /&gt;
&lt;br /&gt;
This introduction concentrates on simple development from the command line because it is common to all platforms.&lt;br /&gt;
&lt;br /&gt;
==== Edit ====&lt;br /&gt;
&lt;br /&gt;
Use Exodus&#039;s all-in-one editor+compiler+cataloger &#039;edic&#039;&lt;br /&gt;
&lt;br /&gt;
 edic hello1&lt;br /&gt;
&lt;br /&gt;
edic will give you a skeleton Exodus program which you can develop as you wish.&lt;br /&gt;
&lt;br /&gt;
There must be one and only one &amp;quot;function main()&amp;quot; statement and this is run when the program is started.&lt;br /&gt;
&lt;br /&gt;
By convention, main() must return an integer value. If desired, this can be used to indicate &amp;quot;success&amp;quot; with zero or &amp;quot;failure&amp;quot; with some error number.&lt;br /&gt;
&lt;br /&gt;
The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Save and compile ====&lt;br /&gt;
&lt;br /&gt;
Make any changes you fancy to the skeleton and save it.&lt;br /&gt;
&lt;br /&gt;
NB Even if you just want to try out the skeleton program exactly as it is without any changes, you must still explicitly save it - otherwise, if you just exit without saving,  edic will assume you didn&#039;t want a hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.&lt;br /&gt;
&lt;br /&gt;
Upon saving hello1, edic will compile and catalog it automatically.&lt;br /&gt;
&lt;br /&gt;
You can also compile programs directly using &#039;compile&#039;. &#039;compile&#039; has a V option (Verbose) to show exactly how &#039;edic&#039; calls the compiler on your platform in case you wish to customise your own compilation process.&lt;br /&gt;
&lt;br /&gt;
 compile hello1 {V}&lt;br /&gt;
&lt;br /&gt;
==== Run ====&lt;br /&gt;
&lt;br /&gt;
To run/open/execute your new hello1 program just type its name.&lt;br /&gt;
&lt;br /&gt;
 hello1&lt;br /&gt;
&lt;br /&gt;
and the output is ...&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
&lt;br /&gt;
=== Deployment of Compiled Programs ===&lt;br /&gt;
&lt;br /&gt;
All programs you develop with Exodus&#039;s edic or compile commands are stored in the same directory as their source code. They are also copied to a folder in your home directory. This folder is called &amp;quot;Exodus&amp;quot; on Windows and bin or lib on other operating systems.&lt;br /&gt;
&lt;br /&gt;
On Windows, the user who installs Exodus can run any program they develop in Exodus by typing its name at any command prompt. It does not matter what the current working directory is because the Exodus installer permanently adds the Exodus home program directory to the PATH of the user who installs it.&lt;br /&gt;
&lt;br /&gt;
Users other than the user who installed Exodus on Windows, and all users on Linux, Mac or other operating systems, must type &amp;quot;exodus&amp;quot; at a command prompt (or open an Exodus console from an application menu) before they can run any program they develop in Exodus. Once they have done that, it does not matter what the current working directory is because the &amp;quot;exodus&amp;quot; program temporarily adds the Exodus home program directory to the users PATH.&lt;br /&gt;
&lt;br /&gt;
On all operating systems, if there is a similarly named program earlier on in your path (e.g. operating system commands) then you will not be able to run your program because in all cases Exodus adds its path (to your home program directory) to the end of your existing path - not the beginning.&lt;br /&gt;
&lt;br /&gt;
To make any developed Exodus programs available to other users you must arrange for them to be copied to some directory on their path.&lt;br /&gt;
&lt;br /&gt;
=== Local subroutines ===&lt;br /&gt;
&lt;br /&gt;
To simulate classic multivalue basic&#039;s &amp;quot;gosub/return&amp;quot; in Exodus, you can add additional subroutines and functions between the programinit() and programexit() lines.&lt;br /&gt;
&lt;br /&gt;
You can add them either above or below the &amp;quot;main&amp;quot; function. There is no rule that functions must appear before or above the code that calls them.&lt;br /&gt;
&lt;br /&gt;
Subroutines and functions cannot be nested otherwise compilation will fail. In other words, no function or subroutine can be contain within the body of another.&lt;br /&gt;
&lt;br /&gt;
==== Simple Example ====&lt;br /&gt;
&lt;br /&gt;
Here is hello1 modified to call a subroutine that says something.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;gosub&amp;quot; is just there for classical clarity. It could be omitted. It could also be replaced by &amp;quot;call&amp;quot; which is also a throwaway word. While gosub and call are interchangeable, if you are going to use them at all, it is probably a good idea to use &amp;quot;gosub funcx()&amp;quot; to indicate internal subroutines and &amp;quot;call funcx()&amp;quot; to indicate external subroutines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;hello1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        gosub subr1();&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
subroutine subr1() {&lt;br /&gt;
        printl(&amp;quot;subr1 says &#039;Hello&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 hello1 says &#039;Hello World!&#039;&lt;br /&gt;
 subr1 says &#039;Hello&#039;&lt;br /&gt;
&lt;br /&gt;
=== Subroutine and Function Parameters (Arguments) ===&lt;br /&gt;
&lt;br /&gt;
Parameter names must be prefixed by &amp;quot;in&amp;quot;, &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; to indicate if they are inbound, outbound or both.&lt;br /&gt;
&lt;br /&gt;
Inbound parameters (prefixed with &amp;quot;in&amp;quot;) cannot be amended within the function and the compiler will enforce this. This provides a guarantee to the programmer calling the subroutine or functions that their inbound parameters will not be modified by calling the function. Inbound parameters may be provided by the calling program either as a variable or as raw data like &amp;quot;xyz&amp;quot; or 123 etc.&lt;br /&gt;
&lt;br /&gt;
In/Outbound parameters (&amp;quot;io&amp;quot;) must be provided by the calling program in the form of a variable and not raw data. The function can both read and write into these parameters.&lt;br /&gt;
&lt;br /&gt;
Outbound parameters (&amp;quot;out&amp;quot;) indicate to the programmer using the function how it works. However, outbound parameters do not actually prevent them being used to provide data to the subroutine or function and are therefore no different from in/outbound parameters. There is no simple way to enforce &amp;quot;write only&amp;quot; parameters using the underlying C++ language.&lt;br /&gt;
&lt;br /&gt;
For special cases, or where performance is critical, the usual C++ parameters are also allowed for example &amp;quot;int arg1&amp;quot; or &amp;quot;const char* arg2&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
=== External functions and subroutines ===&lt;br /&gt;
&lt;br /&gt;
Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:&lt;br /&gt;
&lt;br /&gt;
#the word &amp;quot;program&amp;quot; becomes &amp;quot;library&amp;quot; so we have &amp;quot;library.h&amp;quot;, &amp;quot;libraryinit()&amp;quot; and &amp;quot;libraryexit()&amp;quot;.&lt;br /&gt;
#function main can have any parameters you like, for example: &amp;quot;function main(in arg1, in arg2, out arg3)&lt;br /&gt;
&lt;br /&gt;
NB The name of the function internally MUST be main and not the name of the function so we still have &amp;quot;function main(...)&amp;quot; but this time it can have parameter names eg &amp;quot;subroutine main(in instr1, out outstr2)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
External functions and subroutines are implemented as dll or so files and are only loaded into memory the first time that they are used. A missing function or subroutine so or dll file will not cause any failure unless and until it is first used.&lt;br /&gt;
&lt;br /&gt;
==== Example func1 ====&lt;br /&gt;
&lt;br /&gt;
 edic func1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/library.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
libraryinit()&lt;br /&gt;
&lt;br /&gt;
function main(in arg1, out arg2) {&lt;br /&gt;
        printl(&amp;quot;func1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
        arg2=&amp;quot;arg1 was &amp;quot;^arg1;&lt;br /&gt;
        return 999;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
libraryexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example prog1 using func1 ====&lt;br /&gt;
&lt;br /&gt;
Compiling func1 created a func1.h file that is required to &amp;quot;glue&amp;quot; func1 into any program that wants to use func1.&lt;br /&gt;
&lt;br /&gt;
To use func1 in any program or external subroutine or function, you need to insert an #include &amp;quot;func1.h&amp;quot; somewhere between &amp;quot;programinit()&amp;quot; and &amp;quot;programexit()&amp;quot; - and not within the body of any function or subroutine.&lt;br /&gt;
&lt;br /&gt;
 edic prog1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/program.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
programinit()&lt;br /&gt;
&lt;br /&gt;
//you must &amp;quot;declare&amp;quot; that we want to use func1&lt;br /&gt;
#include &amp;quot;func1.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
function main() {&lt;br /&gt;
        printl(&amp;quot;prog1 says &#039;Hello World!&#039;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        //we print what func1 returns, and also what func1 returns in arg2&lt;br /&gt;
        var arg2;&lt;br /&gt;
        printl(   func1(&amp;quot;myarg1&amp;quot;,arg2)   );&lt;br /&gt;
        printl(arg2);&lt;br /&gt;
&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
programexit()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
run prog1&lt;br /&gt;
&lt;br /&gt;
 prog1&lt;br /&gt;
&lt;br /&gt;
output:&lt;br /&gt;
&lt;br /&gt;
 prog1 says &#039;Hello World!&#039;&lt;br /&gt;
 func1 says &#039;Hello World!&#039;&lt;br /&gt;
 999&lt;br /&gt;
 arg1 was myarg1&lt;br /&gt;
&lt;br /&gt;
=== Functions versus Subroutines ===&lt;br /&gt;
&lt;br /&gt;
Functions can be used anywhere an expression would be used whereas subroutines can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
The same principle applies to both internal and external subroutines/functions.&lt;br /&gt;
&lt;br /&gt;
Both subroutines and functions can return information in any of their &amp;quot;out&amp;quot; or &amp;quot;io&amp;quot; arguments.&lt;br /&gt;
&lt;br /&gt;
The word &amp;quot;call&amp;quot; or &amp;quot;gosub&amp;quot; before the use of a function or subroutine is optional and can be omitted.&lt;br /&gt;
&lt;br /&gt;
==== Functions ====&lt;br /&gt;
&lt;br /&gt;
Functions return a value so you can use them anywhere an expression is required, for example on the right hand side of an assignment.&lt;br /&gt;
&lt;br /&gt;
 var yy=funcx(xx);&lt;br /&gt;
&lt;br /&gt;
Even though a function returns a value, the value it returns can be ignored so the following are all equivalent.&lt;br /&gt;
&lt;br /&gt;
 call funcx(xx);&lt;br /&gt;
 gosub funcx(xx);&lt;br /&gt;
 funcx(xx);&lt;br /&gt;
&lt;br /&gt;
==== Subroutines ====&lt;br /&gt;
&lt;br /&gt;
Subroutines do not return a value so they can only be used as statements.&lt;br /&gt;
&lt;br /&gt;
 call subrx(xx);   &lt;br /&gt;
 gosub subrx(xx);  &lt;br /&gt;
 subrx(xx);        &lt;br /&gt;
 var yy=subrx(xx); //will not compile&lt;br /&gt;
&lt;br /&gt;
=== Differences between Exodus&#039;s Internal Subroutines and Functions and those of classic multivalue basic ===&lt;br /&gt;
&lt;br /&gt;
Exodus&#039;s internal subroutines and functions are very different from and arguably much better than classic multivalue internal subroutines. They are very similar to external subroutines and functions except they also have access to the global variables of the main program.&lt;br /&gt;
&lt;br /&gt;
Exodus Internal Subroutines and Functions:&lt;br /&gt;
&lt;br /&gt;
#can be called with parameters e.g. gosub funcx(xx,yy,zz)&lt;br /&gt;
#only have access to the main programs global variables - this eliminates a major category of multivalue bugs&lt;br /&gt;
#functions (not subroutines) can return a result e.g. abc=funcx(xx,yy,zz)&lt;br /&gt;
&lt;br /&gt;
Exodus internal subroutines and functions only have one entry point. In classic multivalue basic you can jump into the middle of any internal subroutine. To simulate this type of coding in Exodus you must create a hierarchy of subroutines or functions that call each other.&lt;br /&gt;
&lt;br /&gt;
The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.&lt;br /&gt;
&lt;br /&gt;
==== Moving external subroutines and functions to internal ====&lt;br /&gt;
&lt;br /&gt;
Exodus allows many classic multivalue basic external subroutines and functions to be reimplemented as internal subroutines and functions. This means that you can now, where appropriate, keep all source code related to one and only one program in a single file. This is a major improvement in source code management.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic, if you wanted to implement some function to be used in expressions you were forced to implement it as an external function requiring a separate source code file.&lt;br /&gt;
&lt;br /&gt;
In classic multivalue basic if you wanted to call a subroutine with parameters, or you wanted to be sure that a subroutine would not accidentally overwrite main program variables, you were forced to implement it as an external subroutine or function.&lt;br /&gt;
&lt;br /&gt;
In Exodus the above situations no longer force you to have separate compilation and source files. However you can still make subroutines and functions external exactly as before where that is the best strategy, for example:&lt;br /&gt;
&lt;br /&gt;
#to provide some common feature to more than one program&lt;br /&gt;
#to avoid having to recompile the whole of a large program when you just change part of it&lt;br /&gt;
#where there is some benefit in not loading all the parts of a program into memory immediately on start-up.&lt;br /&gt;
&lt;br /&gt;
NB Exodus internal subroutines and functions have access to the global variables of the main program so you might want them to make them external to make sure that there is no risk that they touch any global variable.&lt;br /&gt;
&lt;br /&gt;
=== Dimensioned Arrays ===&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!statement!!effect&lt;br /&gt;
|-&lt;br /&gt;
|dim arraya(10);      ||create a one dimensional array with 10 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arrayb(20,30);   ||create two dimensional array with 20x30 elements&lt;br /&gt;
|-&lt;br /&gt;
|dim arraryc=arrayb;  ||create a new array from an existing array;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb=&amp;quot;&amp;quot;;     ||initialise all elements to &amp;quot;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|arrayb(15,3)=&amp;quot;abc&amp;quot;;  ||set element 15,3 to &amp;quot;abc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var xx=arrayb(15,3); ||get element 15,3&lt;br /&gt;
|-&lt;br /&gt;
|arrayd=arrayc;       ||copy the elements of one array to another. If the arrays are of different sizes then only overlapping columns and rows are copied and all others are set to &amp;quot;&amp;quot;. If the target array has not been dimensioned then the array is duplicated.&lt;br /&gt;
|-&lt;br /&gt;
|arrayb.redim(15,20); ||destroy all data and redimension the array to 15x20&lt;br /&gt;
|-&lt;br /&gt;
|var nfields=matparse(record1,arrayb); ||create a dimensioned array &amp;quot;arrayb&amp;quot; from a dynamic array/string &amp;quot;record1&amp;quot; and return the number of elements.&lt;br /&gt;
|-&lt;br /&gt;
|var record1=matunparse(arrayb); ||create a dynamic array/string &amp;quot;record1&amp;quot; from a dimensioned array &amp;quot;arrayb&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dynamic Arrays and &amp;lt; &amp;gt; Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not offer the elegant multivalue-style dynamic array extraction and replacement using xx&amp;lt;10&amp;gt; xx&amp;lt;10,2&amp;gt; etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Exodus Alternative&amp;lt;br&amp;gt;&amp;quot;Explicit&amp;quot; Syntax!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10&amp;gt;||aa=bb(10); ||aa=bb.extract(10); || Extract the 10th field of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2&amp;gt;||aa=bb(10,2); || aa=bb.extract(10,2); || Extract the 10th field, 2nd multivalue of bb into aa&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB&amp;lt;10,2,3&amp;gt;||aa=bb(10,2,3); || aa=bb.extract(10,2,3); || Extract the 10th field, 2nd multivalue, 3rd subvalue of bb into aa&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== xx(10,2) versus xx.extract(10,2) ====&lt;br /&gt;
&lt;br /&gt;
Using round brackets &amp;quot;()&amp;quot; to indicate dynamic array extraction is potentially confusing since round brackets are also used for accessing dimensioned arrays.&lt;br /&gt;
&lt;br /&gt;
It is sometimes useful to use the alternative explicit syntax e.g. &amp;quot;aa.extract(10)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#when using dynamic and dimensioned arrays together&lt;br /&gt;
#when the meaning of round brackets &amp;quot;recordx()&amp;quot; is considered not obvious from the context or variable names.&lt;br /&gt;
#to be more visually or technically compatible with &amp;quot;curly bracket&amp;quot; family of languages&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
Unfortunately no way has been found to provide both replacement and extraction of dynamic arrays by round brackets using standard C++ language. It is one or the other. Therefore Exodus has chosen to utilise round brackets for the more common operation which is extraction i.e. &amp;quot;aa=bb(10);&amp;quot; and require explicit &amp;quot;replacer&amp;quot; syntax for replacement.&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10&amp;gt;=BB||replacer(aa,10,bb);  || Replace the 10th field of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2&amp;gt;=BB||replacer(aa,10,2,bb);  || Replace the 10th field, 2nd multivalue of aa with bb&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,3&amp;gt;=BB||replacer(aa,10,2,3,bb);  || Replace the 10th field, 2nd multivalue, 3rd subvalue of aa with bb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(10)=bb; //compiles but doesnt do anything!&lt;br /&gt;
&lt;br /&gt;
==== Appending ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,-1&amp;gt;=BB||replacer(aa,-1,bb);  || Append bb as a new multivalue of the 10th field of aa.&lt;br /&gt;
|-&lt;br /&gt;
|AA&amp;lt;10,2,-1&amp;gt;=BB||replacer(aa,-1,bb);  ||  Append bb as a new subvalue of the 10th field, 2nd multivalue of aa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
NB The following apparently logical syntax will compile but do nothing.&lt;br /&gt;
&lt;br /&gt;
 aa(-1)=bb;&lt;br /&gt;
&lt;br /&gt;
=== Strings and [ ] Brackets ===&lt;br /&gt;
&lt;br /&gt;
Exodus does not provide elegant multivalue-style substring extraction and replacement using xx[10,2] xx[-3,3] etc. The same result is achieved, if slightly less elegantly, with a different syntax which is compatible with mainstream languages. &lt;br /&gt;
&lt;br /&gt;
Exodus provides a slightly better syntax for single character extraction.&lt;br /&gt;
&lt;br /&gt;
Exodus provides a proper method to extract or replace all characters from a certain character to the end of the string without needing a hack like 999999.&lt;br /&gt;
&lt;br /&gt;
Negative parameters have their usual meaning.&lt;br /&gt;
&lt;br /&gt;
==== Extracting ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,2]||aa=bb.substr(10,2); || Extract 2 characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,999999]||aa=bb.substr(10); || Extract all the characters of bb starting from the 10th character (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-3,3]||aa=bb.substr(-3); || Extract the last three characters of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[10,1]||aa=bb[10]; || Extract the 10th character of bb (into aa)&lt;br /&gt;
|-&lt;br /&gt;
|AA=BB[-1,1]||aa=bb[-1]; || Extract the last character of bb (into aa)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Replacing ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Mv Basic!!Exodus!!Effect&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,1]=BB||splicer(aa,10,1,bb); || Replace the 10th character of aa (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,2]=BB]||splicer(aa,10,2,bb); || Replace 2 characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|-&lt;br /&gt;
|AA[10,999999]=BB||splicer(aa,10,bb); || Replace all characters of aa starting from the 10th character (with bb)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Operator Precedence ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!priority!!operators!!effect!!associativity&lt;br /&gt;
|-&lt;br /&gt;
|1||X++&amp;amp;nbsp;&amp;amp;nbsp;X--&amp;amp;nbsp;&amp;amp;nbsp;()&amp;amp;nbsp;&amp;amp;nbsp;.&amp;amp;nbsp;&amp;amp;nbsp;|| evaluate then increment/decrement || right&lt;br /&gt;
|-&lt;br /&gt;
|2|| ++X&amp;amp;nbsp;&amp;amp;nbsp;--X&amp;amp;nbsp;&amp;amp;nbsp;+&amp;amp;nbsp;&amp;amp;nbsp;-&amp;amp;nbsp;&amp;amp;nbsp;not|| increment/decrement then evaluate.&amp;lt;br&amp;gt;positive, negative, logical negation || left&lt;br /&gt;
|-&lt;br /&gt;
|3||*&amp;amp;nbsp;&amp;amp;nbsp;/&amp;amp;nbsp;&amp;amp;nbsp;% || multiply, divide, remainder || right&lt;br /&gt;
|-&lt;br /&gt;
|4|| +&amp;amp;nbsp;&amp;amp;nbsp;- || add, subtract || right&lt;br /&gt;
|-&lt;br /&gt;
|5|| lt&amp;amp;nbsp;&amp;amp;nbsp;le&amp;amp;nbsp;&amp;amp;nbsp;ge&amp;amp;nbsp;&amp;amp;nbsp;gt || compare less than, less than or equal, greater than or equal, greater than ||right&lt;br /&gt;
|-&lt;br /&gt;
|6||eq&amp;amp;nbsp;&amp;amp;nbsp;ne || compare equal, not equal ||right&lt;br /&gt;
|-&lt;br /&gt;
|7||^ || concatenate  ||right&lt;br /&gt;
|-&lt;br /&gt;
|8||and || logical union || right&lt;br /&gt;
|-&lt;br /&gt;
|9||or || logical alternative || right&lt;br /&gt;
|-&lt;br /&gt;
|10||=&amp;amp;nbsp;&amp;amp;nbsp;+=&amp;amp;nbsp;&amp;amp;nbsp;-=&amp;amp;nbsp;&amp;amp;nbsp;*=&amp;amp;nbsp;&amp;amp;nbsp;/=&amp;amp;nbsp;&amp;amp;nbsp;%=&amp;amp;nbsp;&amp;amp;nbsp;^= || assign, various self update||left&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Logical and comparative operators ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!word||example!!symbolic&amp;lt;br&amp;gt;alternative&lt;br /&gt;
|-&lt;br /&gt;
|and||if (aa and bb)||&amp;amp;&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|or||if (aa or bb)||&amp;amp;#x7c;&amp;amp;#x7c;&lt;br /&gt;
|-&lt;br /&gt;
|not||if (not aa)||!&lt;br /&gt;
|-&lt;br /&gt;
|eq||if (aa eq bb)||==&lt;br /&gt;
|-&lt;br /&gt;
|ne||if (aa ne bb)||!=&lt;br /&gt;
|-&lt;br /&gt;
|gt||if (aa gt bb)||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|lt||if (aa lt bb)||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|le||if (aa le bb)||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|ge||if (aa ge bb)||&amp;gt;=&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== and/or short circuiting ====&lt;br /&gt;
&lt;br /&gt;
If the left hand side of an &amp;quot;or&amp;quot; operator is true then the right hand side is not even evaluated. Similarly, if the left hand side of an &amp;quot;and&amp;quot; operator is false then the right hand side is not even evaluated.&lt;br /&gt;
&lt;br /&gt;
This provides a major programming convenience/performance advantage over classic multivalue basic.&lt;br /&gt;
&lt;br /&gt;
 if (aa eq 1 and bb eq 1) // if aa is not 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
 if (aa eq 1 or bb eq 1)  // if aa is 1 then bb is not checked and could even be unassigned.&lt;br /&gt;
&lt;br /&gt;
=== ICONV/OCONV PATTERNS ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Decimal (MD/MC) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD2||12.34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20||1234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20,||1,234.00&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD2||12.35&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20||1234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234.5678||MD20,||1,234.57&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC2||12,34&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20||1234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MC20,||1.234,00&lt;br /&gt;
|-&lt;br /&gt;
|1234||MD20-||1234.00 &lt;br /&gt;
|-&lt;br /&gt;
|-1234||MD20-||1234.00-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Date (D) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|12345||D||18 OCT 2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/||10/18/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D-||10-18-2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||D2||18 OCT 01&lt;br /&gt;
|-&lt;br /&gt;
|12345||D/E||18/10/2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS||2001 OCT 18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DS/||2001/10/18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DM||10&lt;br /&gt;
|-&lt;br /&gt;
|12345||DMA||OCTOBER&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY||2001&lt;br /&gt;
|-&lt;br /&gt;
|12345||DY2||01&lt;br /&gt;
|-&lt;br /&gt;
|12345||DD||18&lt;br /&gt;
|-&lt;br /&gt;
|12345||DW||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DWA||THURSDAY&lt;br /&gt;
|-&lt;br /&gt;
|12345||DQ||4&lt;br /&gt;
|-&lt;br /&gt;
|12345||DJ||291&lt;br /&gt;
|-&lt;br /&gt;
|12345||DL||31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Time (MT) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|234800||MT||17:13&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTH||05:13PM&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTS||17:13:20&lt;br /&gt;
|-&lt;br /&gt;
|234800||MTHS||05:13:20PM&lt;br /&gt;
|-&lt;br /&gt;
|0||MT||00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTH||12:00AM&lt;br /&gt;
|-&lt;br /&gt;
|0||MTS||00:00:00&lt;br /&gt;
|-&lt;br /&gt;
|0||MTHS||12:00:00AM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hex (HEX/MX) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX||(same as HEX8 or HEX4 depending on platform)&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX8||0000006100000062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX4||00610062&lt;br /&gt;
|-&lt;br /&gt;
|ab||HEX2||6162&lt;br /&gt;
|-&lt;br /&gt;
|15||MX||F&lt;br /&gt;
|-&lt;br /&gt;
|254||MX||FE&lt;br /&gt;
|-&lt;br /&gt;
|255||MX||FF&lt;br /&gt;
|-&lt;br /&gt;
|256||MX||100&lt;br /&gt;
|-&lt;br /&gt;
|27354234||MX||1A1647A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Text (L/R/T) ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!input!!conversion!!output&lt;br /&gt;
|-&lt;br /&gt;
|abcd||L#3||abc&lt;br /&gt;
|-&lt;br /&gt;
|ab||L#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||R#3||bcd&lt;br /&gt;
|-&lt;br /&gt;
|ab||R#3|| &amp;amp;#9251;ab&lt;br /&gt;
|-&lt;br /&gt;
|ab||T#3||ab&amp;amp;#9251; &lt;br /&gt;
|-&lt;br /&gt;
|abcd||T#3||abc&amp;amp;trade;d&amp;amp;#9251;&amp;amp;#9251;  &lt;br /&gt;
|-&lt;br /&gt;
|42||L(0)#5||42000&lt;br /&gt;
|-&lt;br /&gt;
|42||R(0)#5||00042&lt;br /&gt;
|-&lt;br /&gt;
|42||T(0)#5||42000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dictionaries ===&lt;br /&gt;
&lt;br /&gt;
Exodus dictionaries enable classic multivalue database data definition. Dictionaries are just normal Exodus multivalue files that contain one record for each data column definition. You can use Exodus&#039;s edir program to manually edit dictionaries.&lt;br /&gt;
&lt;br /&gt;
Dictionary file names must start with the word &amp;quot;dict_&amp;quot;. For example, if you have a &amp;quot;books&amp;quot; file, then you will probably have a &amp;quot;dict_books&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
You can list the contents of a dictionary by typing &amp;quot;list dict_filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Format ====&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|0 || DICTID || Field/Column Code&lt;br /&gt;
|-&lt;br /&gt;
|1 || DICTTYPE || &amp;quot;F&amp;quot; or &amp;quot;S&amp;quot; : &amp;quot;F&amp;quot; means use Field No (i.e. raw data) and &amp;quot;S&amp;quot; means use Source Code (i.e. a function).&lt;br /&gt;
|-&lt;br /&gt;
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for &amp;quot;Fields&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|3 || TITLE ||Title on reports&lt;br /&gt;
|-&lt;br /&gt;
|4 ||SM || S or M or Mnn : &amp;quot;Single Value&amp;quot; or &amp;quot;Multivalue&amp;quot; or &amp;quot;Multivalue Group nn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|5 ||KEYPARTNO || Multipart keys are separated by * characters.&lt;br /&gt;
|-&lt;br /&gt;
|6 ||&lt;br /&gt;
|-&lt;br /&gt;
|7 || CONVERSION ||Conversion (MD/MT/D etc.)&lt;br /&gt;
|-&lt;br /&gt;
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable &amp;quot;ANS&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|9 || JUST || &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot; or &amp;quot;T&amp;quot; requesting left, right or text justification&lt;br /&gt;
|-&lt;br /&gt;
|10||WIDTH||Column Width on fixed width reports&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Exodus Dictionary Subroutines ====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;S&amp;quot; type file dictionary entries define table columns that are derived by calling a subroutine.&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines can be executed in two cases.&lt;br /&gt;
&lt;br /&gt;
# During a SSELECT command e.g. SELECT USERS WITH AGE_IN_YEARS &amp;gt; 10&lt;br /&gt;
# In any Exodus program using the Exodus&#039;s &amp;quot;calculate&amp;quot; function. e.g. calculate(&amp;quot;AGE_IN_YEARS&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===== Dictionary Subroutine Library Format =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines are a simplified type of Exodus external subroutine.&lt;br /&gt;
&lt;br /&gt;
A dictionary subroutine is in the format &amp;quot;dict(xyz){...}&amp;quot; where xyz is the dictionary field key *without* quotes and ... is one or more lines of ordinary Exodus source code.&lt;br /&gt;
&lt;br /&gt;
The source code may contain calculate() statements that obtain the results of other dictionary fields.&lt;br /&gt;
&lt;br /&gt;
The source code must result in the variable ANS being set with the required result. &lt;br /&gt;
&lt;br /&gt;
Return statement(s) may be placed anywhere in the code but are not required.&lt;br /&gt;
&lt;br /&gt;
They are slightly different from ordinary external subroutines and do not have programinit()/programexit() clauses. In OO terms, this means that they are simple global functions and not classes, therefore:&lt;br /&gt;
&lt;br /&gt;
#No global variables&lt;br /&gt;
#Any local subroutines or functions must be defined before (above) the dictionary subroutine.&lt;br /&gt;
&lt;br /&gt;
All the subroutines related to one dictionary file go in one &amp;quot;external subroutine library&amp;quot; which can either be written manually or generated automatically from the source code in field 8 of S type dictionaries using the &amp;quot;compile dict_USERS&amp;quot; command.&lt;br /&gt;
&lt;br /&gt;
The library name must be the same as the dictionary file name unless a &amp;quot;USING dictfilename&amp;quot; clause is included in the SSELECT or LIST command.&lt;br /&gt;
&lt;br /&gt;
 edic dict_USERS&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exodus/dict.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_DAYS) {&lt;br /&gt;
        ANS=date()-RECORD(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
dict(AGE_IN_YEARS) {&lt;br /&gt;
        ANS=calculate(&amp;quot;AGE_IN_DAYS&amp;quot;)/365.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Dictionary subroutine variables =====&lt;br /&gt;
&lt;br /&gt;
Dictionary subroutines have access to the following variables.&lt;br /&gt;
&lt;br /&gt;
When using &amp;quot;calculate(dictid)&amp;quot; the programmer is responsible for setting all these variables (with the exception of ANS) *before* the calculate() expression.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
!Variable!!Purpose&lt;br /&gt;
|-&lt;br /&gt;
|ID || The database record key.&lt;br /&gt;
|-&lt;br /&gt;
|RECORD || The database record&lt;br /&gt;
|-&lt;br /&gt;
|DICT|| The dictionary file name.&lt;br /&gt;
|-&lt;br /&gt;
|MV  || The required multivalue number or 0 for all.&lt;br /&gt;
|-&lt;br /&gt;
|ANS || Dictionary subroutines return their result in ANS.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Sort/Select Command ====&lt;br /&gt;
&lt;br /&gt;
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().&lt;br /&gt;
&lt;br /&gt;
Classic multivalue select/readnext functions only provide the keys of the selected records. Exodus provides the classic select/readnext and also selectrecords/readnextrecord which provides complete records instead of just keys.&lt;br /&gt;
&lt;br /&gt;
The format of the select/sselect command is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;PRE&amp;gt;&lt;br /&gt;
 SELECT|SSELECT&lt;br /&gt;
&lt;br /&gt;
 {max_number_of_records}&lt;br /&gt;
&lt;br /&gt;
 {using filename}&lt;br /&gt;
&lt;br /&gt;
 filename&lt;br /&gt;
&lt;br /&gt;
 {datakeyvalue} ...&lt;br /&gt;
&lt;br /&gt;
 {BY|BY-DSND fieldname} ...&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
&lt;br /&gt;
  WITH&lt;br /&gt;
&lt;br /&gt;
  {NO|ALL|ANY}&lt;br /&gt;
&lt;br /&gt;
  dict_field_id&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|&amp;lt;&amp;gt;|&amp;gt;|&amp;lt;|&amp;gt;=|&amp;lt;= value(s)&lt;br /&gt;
   |&lt;br /&gt;
   BETWEEN value AND value&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  {AND|OR}&lt;br /&gt;
&lt;br /&gt;
 } ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Traditional Multivalue Functions and Statements (non-OO) ===&lt;br /&gt;
&lt;br /&gt;
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.&lt;br /&gt;
&lt;br /&gt;
* Traditional functions are rendered as Exodus functions.&lt;br /&gt;
* Traditional statements are rendered as Exodus subroutines.&lt;br /&gt;
&lt;br /&gt;
 PRINT OCONV(DATE(),&#039;D&#039;)&lt;br /&gt;
&lt;br /&gt;
in Exodus becomes:&lt;br /&gt;
&lt;br /&gt;
 printl(oconv(date(),&amp;quot;D&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
==== String Commands ====&lt;br /&gt;
&lt;br /&gt;
The use of most of Exodus&#039;s functions will be fairly obvious to traditional multivalue programmers.&lt;br /&gt;
&lt;br /&gt;
Ηοwever it is not so obvious that all the functions ending in &amp;quot;-er&amp;quot; correspond to the old string commands.&lt;br /&gt;
&lt;br /&gt;
For example, the classic multivalue &amp;quot;modify in-place&amp;quot; character conversion command:&lt;br /&gt;
&lt;br /&gt;
 CONVERT &#039;ab&#039; TO &#039;cd&#039; IN ZZ&lt;br /&gt;
&lt;br /&gt;
is now represented in Exodus by:&lt;br /&gt;
&lt;br /&gt;
 converter(zz,&amp;quot;ab&amp;quot;,&amp;quot;cd&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.&lt;br /&gt;
&lt;br /&gt;
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old &amp;quot;self assign&amp;quot; idiom.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 ZZ=TRIM(ZZ)&lt;br /&gt;
&lt;br /&gt;
should appear in Exodus as:&lt;br /&gt;
&lt;br /&gt;
 trimmer(zz);&lt;br /&gt;
&lt;br /&gt;
and not:&lt;br /&gt;
&lt;br /&gt;
 zz=trim(zz);&lt;br /&gt;
&lt;br /&gt;
==== Function Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!TYPE	!!FUNCTION TYPE||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||&lt;br /&gt;
|-&lt;br /&gt;
|if	||traditional conditional statements that started with &amp;quot;if&amp;quot; or ended with &amp;quot;then/else&amp;quot; (or could have)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||traditional commands with no outputs||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2	||traditional commands that now have outputs and can be used in expressions||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Parameters/Argument Types ====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|unspecified||Same as &amp;quot;in&amp;quot;. Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions &amp;quot;in&amp;quot; cannot be omitted from the source code.||&lt;br /&gt;
|-&lt;br /&gt;
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or &amp;quot;X&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Optional Parameters&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
!Key	!!Default||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;&amp;quot;	||&amp;quot;&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot; &amp;quot;	||&amp;quot; &amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=&amp;quot;.&amp;quot;	||&amp;quot;.&amp;quot;||&lt;br /&gt;
|-&lt;br /&gt;
|=1	||1 ||&lt;br /&gt;
|-&lt;br /&gt;
|=0	||0||&lt;br /&gt;
|-&lt;br /&gt;
|=true	||true||&lt;br /&gt;
|-&lt;br /&gt;
|=false	||false||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Complete List of Functions ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Environment =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osgetenv(envname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osgetenv(envname, out value)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||ossetenv(envname, newvalue)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Time/Date/Sleep =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||date()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||time()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||timedate()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||ossleep(milliseconds)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||ostime()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System File =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||osopen(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osclose(filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osbread(filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbread(out data, filehandle, startoffset, length)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osbwrite(data, filehandle, startoffset)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osread(out data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osread(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oswrite(data, osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osdelete(osfilename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrename(oldosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||oscopy(fromosdir_or_filename, newosdir_or_filename)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||osflush()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== System Directory =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oslist(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;, mode=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistf(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oslistd(path=&amp;quot;.&amp;quot;, wildcard=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osdir(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osmkdir(newdirname)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||osrmdir(dirname, evenifnotempty=false)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||oscwd(newdirname)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Program Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||suspend(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||osshell(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||osshellread(command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellread(out commandoutput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||osshellwrite(commandinput, command)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||stop(text=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||abort(text)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||perform(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||execute(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||chain(command)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||logoff()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||debug()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Variable Control =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if    ||assigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||unassigned(anyvar)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||exchange(var1,var2)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2    ||transfer(fromvar,tovar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Output =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd	||print(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printl(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||printt(instring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Cursor =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||at(column0orcode)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||at(column0, row0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getcursor()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setcursor(cursorstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||getprompt()||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||setprompt(promptchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Console Input =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input()||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||input(prompt, out inputstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||inputn(n)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Math =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||rnd(number)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||initrnd(seednumber)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||mod(dividend, divisor)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||abs(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||pwr(base, exponent)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||exp(power)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sqrt(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||sin(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||cos(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||tan(degrees)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||atan(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||loge(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||integer(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||floor(number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||round(number, ndecimals=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Creation =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=  ||chr(integer)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||str(instring, number)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||space(number)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== String Info/Search =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||count(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||dcount(instring, substr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index(instring, substr, occurrenceno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||index2(instring, substr, startcharno=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||len(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||length(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||match(instring, matchstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||seq(inchar)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||convert(instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||crop(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lcase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||ucase(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||lower(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||raise(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquote(instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||substr(instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||swap(instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trim(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimb(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||trimf(instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== String Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||converter(io instring, oldchars, newchars)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||cropper(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lcaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||ucaser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||lowerer(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||raiser(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||quoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||unquoter(io instring)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||substrer(io instring, fromcharno, nchars)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||swapper(io instring, oldstr, newstr, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmer(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerb(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2  ||trimmerf(io instring, trimchars=&amp;quot; &amp;quot;)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== iconv/oconv =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||oconv(instring, conversion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||iconv(instring, conversion)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||connect(connectionstring=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||disconnect()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||createdb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||deletedb(dbname, out errmsg)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createfile(filename, options=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deletefile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||clearfile(filename)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listfiles()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||createindex(filename, fieldname, usingdictfilename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleteindex(filename, fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||listindexes(filename=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||begintrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||rollbacktrans()||&lt;br /&gt;
|-&lt;br /&gt;
|if    ||committrans()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Database Files and Records =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||open(filename, out filehandle)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||read(out record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readv(out record, filehandle, key, fieldnumber)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||write(record, filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||writev(record, filehandle, key, fieldn)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||deleterecord(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||updaterecord(record, filehandle, key)||the record key must already exist&lt;br /&gt;
|-&lt;br /&gt;
|if	||insertrecord(record, filehandle, key)||the record key must not already exist&lt;br /&gt;
|-&lt;br /&gt;
|if    ||lock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlock(filehandle, key)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd    ||unlockall()||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Record Selection =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|if	||select(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd	||clearselect()||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.&lt;br /&gt;
|-&lt;br /&gt;
|if	||selectrecord(sortselectclause=&amp;quot;&amp;quot;)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=	||calculate(fieldname)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||xlate(filename, key, fieldno, mode)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Functions =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|var=    ||replace(instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||replace(instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||extract(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||erase(instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locate(instring, target, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||&lt;br /&gt;
|-&lt;br /&gt;
|if	||locateusing(instring, target, usingchar)||&lt;br /&gt;
|-&lt;br /&gt;
|var=  ||remove(fromstr, io startx, out delimiterno)||&lt;br /&gt;
|-&lt;br /&gt;
|var=	||sum(instring, sepchar=VM_)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Dynamic Array Commands =====&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot; cellpadding=&amp;quot;10&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2   ||replacer(io instring, fieldno, valueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||replacer(io instring, fieldno, valueno, subvalueno, replacement)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||inserter(io instring, fieldno, valueno, subvalueno, insertion)||&lt;br /&gt;
|-&lt;br /&gt;
|cmd2 	||eraser(io instring, fieldno, valueno=0, subvalueno=0)||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Troubleshooting ===&lt;br /&gt;
&lt;br /&gt;
==== printl(lcaser(&amp;quot;ABC&amp;quot;)); //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
Simply use lcase instead of lcaser.&lt;br /&gt;
&lt;br /&gt;
 printl(lcase(&amp;quot;ABC&amp;quot;));  //result is abc&lt;br /&gt;
&lt;br /&gt;
lcaser is designed to modify a variable so lcaser&#039;s parameter must be a variable and not raw data like &amp;quot;ABC&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== aa(10)=bb; //compiles but doesnt do anything! ====&lt;br /&gt;
&lt;br /&gt;
To replace field 10 of dynamic array aa do one of the following.&lt;br /&gt;
&lt;br /&gt;
 replacer(aa,10,bb);&lt;br /&gt;
 aa.replacer(10,bb);&lt;br /&gt;
&lt;br /&gt;
Exodus doesnt support &amp;quot;aa(10)=&amp;quot; style syntax to replace dynamic array fields.&lt;br /&gt;
&lt;br /&gt;
==== if (aa ^ bb &amp;gt; cc) //won&#039;t compile! ====&lt;br /&gt;
&lt;br /&gt;
If the intent is to work like classic multivalue basic code then put brackets to clarify that to the compiler.&lt;br /&gt;
&lt;br /&gt;
 if ( (aa ^ bb) &amp;gt; cc)&lt;br /&gt;
&lt;br /&gt;
If instead the intent is aa ^ (bb &amp;gt; cc) then you must pre-calculate the result of bb &amp;gt; cc ...&lt;br /&gt;
&lt;br /&gt;
 var dd=bb &amp;gt; cc;&lt;br /&gt;
 if (aa ^ dd)&lt;br /&gt;
&lt;br /&gt;
... or just wrap it in var()&lt;br /&gt;
&lt;br /&gt;
 if (aa ^ var(bb&amp;gt;cc) )&lt;br /&gt;
&lt;br /&gt;
Exodus will not treat the direct result of a logical operation as a character &amp;quot;1&amp;quot; or &amp;quot;0&amp;quot; for the purposes of string concatenation. This is the only deliberate difference from multivalue Basic in Exodus. For why this is so, read about Exodus&#039;s concatenation operator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== using asserts ====&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Postgres&amp;diff=949</id>
		<title>Installing Postgres</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Postgres&amp;diff=949"/>
		<updated>2010-11-11T15:06:50Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Postgres 8.3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Downloading and Installing PostgresSQL:==&lt;br /&gt;
&lt;br /&gt;
=== Postgres 8.3 ===&lt;br /&gt;
&lt;br /&gt;
http://www.postgresql.org/ftp/binary/&lt;br /&gt;
http://www.enterprisedb.com/products/pgdownload.do&lt;br /&gt;
&lt;br /&gt;
X: drive below should be the same as the drive you build exodus otherwise the include files will not be found.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|QUESTION&lt;br /&gt;
|RESPONSE&lt;br /&gt;
|COMMENT&lt;br /&gt;
|-&lt;br /&gt;
|Installation Directory&lt;br /&gt;
|X:\Program Files\PostgreSQL\8.3&lt;br /&gt;
|NB Keep the directory structure even if you change the drive otherwise will have to modify build project folder settings.&lt;br /&gt;
|-&lt;br /&gt;
|Data Directory&lt;br /&gt;
|X:\Program Files\PostgreSQL\8.3\data&lt;br /&gt;
|Put this whereever you like&lt;br /&gt;
|-&lt;br /&gt;
|password for superuser &amp;quot;postgres&amp;quot;&amp;lt;br&amp;gt;AND windows service&lt;br /&gt;
|yourpasshere&lt;br /&gt;
|Invent your own and TAKE A RECORD BECAUSE YOU WILL BE NEEDING IT LATER. If reinstalling enter the existing postgress user pass or delete the user and let it be recreated&lt;br /&gt;
|-&lt;br /&gt;
|Port number the server should listen on&lt;br /&gt;
|5432&lt;br /&gt;
|Exodus uses the default by default&lt;br /&gt;
|-&lt;br /&gt;
|Locale:&lt;br /&gt;
|Default&lt;br /&gt;
|-&lt;br /&gt;
|Charset:&lt;br /&gt;
|UTF8 for server and client&lt;br /&gt;
|-&lt;br /&gt;
|Run StackBuilder:&lt;br /&gt;
|uncheck&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Postgres 8.1 ===&lt;br /&gt;
&lt;br /&gt;
[[Postgres 8.1]]&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Boost&amp;diff=896</id>
		<title>Installing Boost</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Boost&amp;diff=896"/>
		<updated>2010-11-09T09:45:42Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Boost C++ Libraries 1.38.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Boost C++ Libraries 1.38.0==&lt;br /&gt;
&lt;br /&gt;
Exodus builds with boost 1.35 onwards in Linux but that is untested in Windows.&lt;br /&gt;
&lt;br /&gt;
Note: if you have Visual Studio 2010 installed, you should download and install Boost 1.43 or later version. Previous versions (like 1.38) are not compatible with VS2010.&lt;br /&gt;
&lt;br /&gt;
Below shows installation for Visual Studio 2008. Choose slightly different options for Visual Studio 2005.&lt;br /&gt;
&lt;br /&gt;
# Click on http://www.boostpro.com/download/boost_1_38_setup.exe or click on http://www.boostpro.com/download then find and click Boost 1.38.0 Installer.&lt;br /&gt;
# Click Run and again.&lt;br /&gt;
# Agree to the licenses.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Compilers: Visual C++ 9.0 (Visual studio 2008).&lt;br /&gt;
# Variants: (1) Multithread (2) Multithread Debug&lt;br /&gt;
[[Image:boost3.png]]&lt;br /&gt;
&lt;br /&gt;
#Click Next&lt;br /&gt;
# Now untick every box except:&lt;br /&gt;
#* Boost Header files (you dont need to do this every time you add more libraries)&amp;lt;br&amp;gt;&lt;br /&gt;
#* Boost Start menu shortcut&amp;lt;br&amp;gt;&lt;br /&gt;
#* Tools&amp;lt;br&amp;gt;&lt;br /&gt;
#* Boost DateTime&amp;lt;br&amp;gt; &lt;br /&gt;
#* Boost FileSystem&amp;lt;br&amp;gt;&lt;br /&gt;
#* Boost Regex&amp;lt;br&amp;gt;&lt;br /&gt;
#* Boost System&amp;lt;br&amp;gt;&lt;br /&gt;
#* Boost Thread&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Actually the above options seem to load libs for all compilers and you can cut down the download volume as follows if you wish.&lt;br /&gt;
&lt;br /&gt;
[[Image:boost4.png]]&lt;br /&gt;
&lt;br /&gt;
Make sure you install to the same drive as you are going to build exodus on otherwise you will have to modify the visual studio include folders in the visual studio solution and this will mess up other developers setups if you submit a modified VS solution.&lt;br /&gt;
&lt;br /&gt;
[[Image:boost5.png]]&lt;br /&gt;
&lt;br /&gt;
Click Next, Install&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=872</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=872"/>
		<updated>2010-11-08T15:28:10Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Update Paths in VS2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
== Update Paths in VS2010 ==&lt;br /&gt;
&#039;&#039;TODO:as Platform SDK is not used, clean following from unnessesary paths&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
#* Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation): &#039;&#039;&#039;Tools -&amp;gt; Settings -&amp;gt; Expert Settings&#039;&#039;&#039;&lt;br /&gt;
#* Load any project or solution&lt;br /&gt;
#* Open &amp;quot;Properties Manager&amp;quot; dialog: &#039;&#039;&#039;View -&amp;gt; Property Manager&#039;&#039;&#039;&lt;br /&gt;
#* Expand all branches, you should see &#039;&#039;&#039;Microsoft.Cpp.Win32.user&#039;&#039;&#039; leaves&lt;br /&gt;
#* Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &#039;&#039;&#039;Microsoft.Cpp.Win32.user Property Page Dialog&#039;&#039;&#039; is opened&lt;br /&gt;
#* Do the following:&lt;br /&gt;
#** Click the value of Executable Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#** Click the value of Library Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_38_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_38_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Your window should look like this:&amp;lt;br&amp;gt;[[Image:MVS2010ExpressDirs.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=871</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=871"/>
		<updated>2010-11-08T15:23:23Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Updated Paths in VS2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
== Update Paths in VS2010 ==&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
#* Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation): &#039;&#039;&#039;Tools -&amp;gt; Settings -&amp;gt; Expert Settings&#039;&#039;&#039;&lt;br /&gt;
#* Load any project or solution&lt;br /&gt;
#* Open &amp;quot;Properties Manager&amp;quot; dialog: &#039;&#039;&#039;View -&amp;gt; Property Manager&#039;&#039;&#039;&lt;br /&gt;
#* Expand all branches, you should see &#039;&#039;&#039;Microsoft.Cpp.Win32.user&#039;&#039;&#039; leaves&lt;br /&gt;
#* Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &#039;&#039;&#039;Microsoft.Cpp.Win32.user Property Page Dialog&#039;&#039;&#039; is opened&lt;br /&gt;
#* Do the following:&lt;br /&gt;
#** Click the value of Executable Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#** Click the value of Library Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_38_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#** Click the value of Include Directories, then small Down button to the right, &amp;lt;Edit...&amp;gt;, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_38_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Your window should look like this:&amp;lt;br&amp;gt;[[Image:MVS2010ExpressDirs.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=870</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=870"/>
		<updated>2010-11-08T15:16:13Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
== Update Paths in VS2010 ==&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
#* Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation: &#039;&#039;&#039;Tools -&amp;gt; Settings -&amp;gt; Expert Settings&#039;&#039;&#039;&lt;br /&gt;
#* Load any project or solution&lt;br /&gt;
#* Open &amp;quot;Properties Manager&amp;quot; dialog: &#039;&#039;&#039;View -&amp;gt; Property Manager&#039;&#039;&#039;&lt;br /&gt;
#* Expand all branches, you should see &#039;&#039;&#039;Microsoft.Cpp.Win32.user&#039;&#039;&#039; leaves&lt;br /&gt;
#* Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &#039;&#039;&#039;Microsoft.Cpp.Win32.user Property Page Dialog&#039;&#039;&#039; is opened&lt;br /&gt;
#* Your window should look like this:&amp;lt;br&amp;gt;[[Image:MVS2010ExpressDirs.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
#* Do the following:&lt;br /&gt;
#** Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#** Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#** Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#** Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#** Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=869</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=869"/>
		<updated>2010-11-08T15:09:03Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Update Paths in VS2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS2010 ===&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
# Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation: Tools -&amp;gt; Settings -&amp;gt; Expert Settings&lt;br /&gt;
# Load any project or solution&lt;br /&gt;
# Open &amp;quot;Properties Manager&amp;quot; dialog: View -&amp;gt; Property Manager&lt;br /&gt;
# Expand all branches, you should see &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaves&lt;br /&gt;
# Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &amp;quot;Microsoft.Cpp.Win32.user Property Page Dialog&amp;quot; is opened&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:MVS2010ExpressDirs.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=868</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=868"/>
		<updated>2010-11-08T15:07:43Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Update Paths in VS2010 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS2010 ===&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
#* Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation:&lt;br /&gt;
	Tools -&amp;gt; Settings -&amp;gt; Expert Settings&lt;br /&gt;
#* Load any project or solution&lt;br /&gt;
#* Open &amp;quot;Properties Manager&amp;quot; dialog:&lt;br /&gt;
	View -&amp;gt; Property Manager&lt;br /&gt;
#* Expand all branches, you should see &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaves&lt;br /&gt;
#* Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &amp;quot;Microsoft.Cpp.Win32.user Property Page Dialog&amp;quot; is opened&lt;br /&gt;
# &lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:MVS2010ExpressDirs.png]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=File:MVS2010ExpressDirs.png&amp;diff=867</id>
		<title>File:MVS2010ExpressDirs.png</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=File:MVS2010ExpressDirs.png&amp;diff=867"/>
		<updated>2010-11-08T15:01:25Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: How to configure paths in VS2010Express&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;How to configure paths in VS2010Express&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=866</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=866"/>
		<updated>2010-11-08T14:58:37Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Update the corewin_express.vsprops file. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
NB Platform SDK is required only for MSVC EXPRESS 2005 ... not Express 2008 or Express 2010&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS prior to VS2010 ===&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
===Update Paths in VS2010 ===&lt;br /&gt;
&lt;br /&gt;
VC++ Directories are no longer supported in VS2010 through Tools-&amp;gt;Options page. Instead, VS2010 introduces the user settings file (Microsoft.cpp.&amp;lt;Platform&amp;gt;.users.props) to control global settings including Global search path. These files are located at $(USERPROFILE)\appdata\local\microsoft\msbuild\v4.0 directory. Upon migration to VS2010, the custom settings of VC++ Directories from VS2005 or VS2008 are migrated to these user files. These global settings files are imported into all the converted and newly created projects.&lt;br /&gt;
&lt;br /&gt;
#* Switch VS2010 IDE to &amp;quot;Expert&amp;quot; setting (default is &amp;quot;Basic&amp;quot; after the installation:&lt;br /&gt;
	Tools -&amp;gt; Settings -&amp;gt; Expert Settings&lt;br /&gt;
#* Load any project or solution&lt;br /&gt;
#* Open &amp;quot;Properties Manager&amp;quot; dialog:&lt;br /&gt;
	View -&amp;gt; Property Manager&lt;br /&gt;
#* Expand all branches, you should see &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaves&lt;br /&gt;
#* Double Click &amp;quot;Microsoft.Cpp.Win32.user&amp;quot; leaf, and &amp;quot;Microsoft.Cpp.Win32.user Property Page Dialog&amp;quot; is opened&lt;br /&gt;
# &lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
All the paths updated will be saved in &amp;quot;C:\Documents and Settings\&amp;lt;user&amp;gt;\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=864</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=864"/>
		<updated>2010-11-08T13:15:39Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Downloading &amp;amp; Installing Platform SDK: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=863</id>
		<title>Installing Visual Studio Express C++</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Visual_Studio_Express_C%2B%2B&amp;diff=863"/>
		<updated>2010-11-08T13:08:49Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: /* Downloading &amp;amp; Installing Platform SDK: */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Downloading &amp;amp; Installing Visual Studio C++ Express Edition:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/express/download/&lt;br /&gt;
# Scroll down the web page till you see 6 different downloads e.g. Visual Basic, SQL Server and Visual C++.&lt;br /&gt;
# Select your language for Visual C++ Express Edition, as soon as you select your language a &amp;quot;File download&amp;quot; window will pop up, click Run.&lt;br /&gt;
# There should be a bit of loading, once finished click Run and again.&lt;br /&gt;
# There should be a minute or two of loading, click Next in the Visual Studio C++ set-up.&lt;br /&gt;
# Accept the terms and click Yes.&lt;br /&gt;
# Tick the Graphical IDE if it hasn&#039;t been ticked already and click Next.&lt;br /&gt;
# Browse for a location in where you would like Visual Studio C++ (although, it would be best to keep the default location in case something need to find the Visual Studio C++ folder and cannot find it in its default location) then click Next.&lt;br /&gt;
# If you have any minor jobs to do, I suggest you do so now as it will take a while, but keep checking on how the installation is coming.&lt;br /&gt;
# Then reboot your computer.&lt;br /&gt;
# Once your pc is ready look for Visual Studio C++ on icon your desktop, if its not there go to start, all programs in the start menu and look for Visual Studio C++ Edition as shown in the example: &amp;lt;br&amp;gt;[[Image:whereVSC++.jpg]]&lt;br /&gt;
# The window below will pop up, telling you that you need to register your copy of Visual Studio C++ Express Edition.&lt;br /&gt;
[[Image:registerVSC++.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Downloading &amp;amp; Installing Platform SDK:===&lt;br /&gt;
&lt;br /&gt;
# Go to http://www.microsoft.com/downloads/details.aspx?familyid=0baf2b35-c656-4969-ace8-e4c0c0716adb&amp;amp;displaylang=en. The page is titled: &amp;quot;Microsoft ® Windows Server® 2003 R2 Platform SDK Web Install&amp;quot;&lt;br /&gt;
# Click on the &amp;lt;b&amp;gt;Continue&amp;lt;/b&amp;gt; button.&lt;br /&gt;
# Depending on your internet browser, you might have to install a plug-in. IF not, scroll down the web page and click on the &amp;lt;B&amp;gt;Continue&amp;lt;/B&amp;gt; button.&lt;br /&gt;
# Click on the link called &amp;quot;Download Files Below&amp;quot; or you can just find the subheading &amp;lt;b&amp;gt;Files in this Download&amp;lt;/b&amp;gt;&lt;br /&gt;
# There will be list of different types of files, depending on your processor to download. &amp;lt;br&amp;gt;&lt;br /&gt;
#* If you have a 64 bit Intel processor download &amp;lt;b&amp;gt;PSDK-ia64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have a 64 bit AMD processor download &amp;lt;b&amp;gt;PSDK-amd64.exe&amp;lt;/b&amp;gt;&lt;br /&gt;
#* If you have another processor type, and it&#039;s listed on the web site but not here choose that Download.&lt;br /&gt;
#* If you have another processor type which is not included in the list on the web page download &amp;lt;b&amp;gt;PSDK-x86.exe&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
#* &lt;br /&gt;
&amp;lt;br&amp;gt;Extra: If your on a virtual computer, then check the version on windows you are using.&lt;br /&gt;
# Save the file into your download folder.&lt;br /&gt;
# Then click Run, Then click Run again.&lt;br /&gt;
# At the next window, with two button, click Cancel.&lt;br /&gt;
# Click Next.&lt;br /&gt;
# Agree to the terms, and click Next.&lt;br /&gt;
# Do a custom installation, and click Next.&lt;br /&gt;
&lt;br /&gt;
# You come to a stage in the set-up where it asks &amp;quot;In which driver do you want to save you files to?&amp;quot;. Pick the drive you prefer. To change from drive to drive you change the beginning of the location. So if you want to save SDK in the C drive, leave it as it is and if you want to save SDK to the D drive, change C to D. Or click browse. Then click Next.&lt;br /&gt;
# Click Next again, and wait for the loading.&lt;br /&gt;
# Then continue the download, till the end.&lt;br /&gt;
&lt;br /&gt;
===Update the corewin_express.vsprops file.===&lt;br /&gt;
&amp;lt;br&amp;gt;One more step is needed to make the Win32 template work in Visual C++ Express. You need to edit the corewin_express.vsprops file - *NOT* the CoreWin.vsprops file (found in C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults) - and&amp;lt;br&amp;gt;&lt;br /&gt;
Change the string that reads:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib&amp;quot;&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;to&lt;br /&gt;
&amp;lt;br&amp;gt;AdditionalDependencies=&amp;lt;b&amp;gt;&amp;quot;kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib&amp;quot;&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Go to Tools, Options, open Project and Solutions and go to VC++ Directoies&lt;br /&gt;
# Your window should look like this:&amp;lt;br&amp;gt;[[Image:VSC++EEoptions.JPG]]&lt;br /&gt;
# Do the following:&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin&amp;lt;/b&amp;gt;  &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include&amp;lt;/b&amp;gt; &lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy an paste the following path, and then press Enter: &amp;lt;b&amp;gt;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&amp;lt;/b&amp;gt;&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Include Files, now click the button that looks like a yellow folder and in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
#* Click the drop down menu for Show directories for: and click Library Files, now click the button that looks like a yellow folder in the field were the cursor is blinking copy and paste the path to the &amp;lt;b&amp;gt;boost_1_34_0\lib&amp;lt;/b&amp;gt; folder you created earlier when installing the Boost libraries.&lt;br /&gt;
&lt;br /&gt;
===Generate and build a Win32 application to test your paths.===&lt;br /&gt;
&amp;lt;br&amp;gt;In Visual C++ Express, the Win32 Windows Application type is disabled in the Win32 Application Wizard. To enable that type, you need to edit the file AppSettings.htm file located in the folder %ProgramFiles%\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1033\&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;In a text editor comment out lines 441 - 444 by putting a // in front of them as shown here:&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// WIN_APP_LABEL.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP.disabled = true;&lt;br /&gt;
&amp;lt;br&amp;gt;// DLL_APP_LABEL.disabled = true;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt; Save and close the file and open Visual C++ Express. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From the File menu, click New Project. In the New Project dialog box, expand the Visual C++ node in the Product Types tree and then click Win32. Click on the Win32 Console Application template and then give your project a name and click OK. In the Win32 Application Wizard dialog box, make sure that Windows application is selected as the Application type and the ATL is not selected. Click the Finish button to generate the project.&amp;lt;br&amp;gt;&lt;br /&gt;
Compile by pressing F5.&amp;lt;br&amp;gt;&lt;br /&gt;
Win32 application should build and run.&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
	<entry>
		<id>https://devwiki.neosys.com/index.php?title=Installing_Postgres&amp;diff=862</id>
		<title>Installing Postgres</title>
		<link rel="alternate" type="text/html" href="https://devwiki.neosys.com/index.php?title=Installing_Postgres&amp;diff=862"/>
		<updated>2010-11-08T10:59:24Z</updated>

		<summary type="html">&lt;p&gt;AlexNenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Downloading and Installing PostgresSQL:==&lt;br /&gt;
&lt;br /&gt;
=== Postgres 8.3 ===&lt;br /&gt;
&lt;br /&gt;
http://www.postgresql.org/ftp/binary/&lt;br /&gt;
http://www.enterprisedb.com/products/pgdownload.do&lt;br /&gt;
&lt;br /&gt;
X: drive below should be the same as the drive you build exodus otherwise the include files will not be found.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|QUESTION&lt;br /&gt;
|RESPONSE&lt;br /&gt;
|COMMENT&lt;br /&gt;
|-&lt;br /&gt;
|Installation Directory&lt;br /&gt;
|X:\Program Files\PostgreSQL\8.3&lt;br /&gt;
|NB Keep the directory structure even if you change the drive otherwise will have to modify build project folder settings.&lt;br /&gt;
|-&lt;br /&gt;
|Data Directory&lt;br /&gt;
|X:\Program Files\PostgreSQL\8.3\data&lt;br /&gt;
|Put this whereever you like&lt;br /&gt;
|-&lt;br /&gt;
|password for superuser &amp;quot;postgres&amp;quot;&amp;lt;br&amp;gt;AND windows service&lt;br /&gt;
|yourpasshere&lt;br /&gt;
|Invent your own. If reinstalling enter the existing postgress user pass or delete the user and let it be recreated&lt;br /&gt;
|-&lt;br /&gt;
|Port number the server should listen on&lt;br /&gt;
|5432&lt;br /&gt;
|Exodus uses the default by default&lt;br /&gt;
|-&lt;br /&gt;
|Locale:&lt;br /&gt;
|Default&lt;br /&gt;
|-&lt;br /&gt;
|Charset:&lt;br /&gt;
|UTF8 for server and client&lt;br /&gt;
|-&lt;br /&gt;
|Run StackBuilder:&lt;br /&gt;
|uncheck&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Postgres 8.1 ===&lt;br /&gt;
&lt;br /&gt;
[[Postgres 8.1]]&lt;/div&gt;</summary>
		<author><name>AlexNenko</name></author>
	</entry>
</feed>