Manual: Difference between revisions

From NEOSYS Dev Wiki
Jump to navigationJump to search
 
(233 intermediate revisions by 3 users not shown)
Line 1: Line 1:
=== Hello World ===
=== Programmer's Guides ===


After installing Exodus, you can develop Exodus programs from any operating system command line.
Only for C++ at the moment. For all others, see some examples:
http://code.google.com/p/exodusdb/source/browse/#svn%2Ftrunk%2Fswig%2Fshare


Any programs you develop are stored in the same directory as their source code. They are also copied to an folder in your home directory - Exodus on Windows and bin or lib on other operating systems. These folders are added to the end of your path by the Exodus installer. This means that, as long as you are logged in as the developing user, and there is no similarly named program early on in your path (e.g. operating system commands) you can use any developed program from any command line. To make any programs available to other users you must arrange for the programs to be copied to some directory on their path.
==== [[Python]] ====
==== [[Perl]] ====
==== [[PHP]] ====
==== [[Java]] ====
==== [[C#]] ====
==== [[C++]] ====


==== Edit ====
=== ICONV/OCONV PATTERNS ===


Use Exodus's all-in-one editor+compiler+cataloger 'edic'


edic hello1
==== Decimal (MD/MC) ====


edic will give you a skeleton Exodus program which you can develop as you wish.
{|border="1" cellpadding="10" cellspacing="0"
!input!!conversion (string)!!output
|-
|1234||MD2||12.34
|-
|1234||MD20||1234.00
|-
|1234||MD20,||1,234.00
|-
|1234.5678||MD2||12.35
|-
|1234.5678||MD20||1234.57
|-
|1234.5678||MD20,||1,234.57
|-
|1234||MC2||12,34
|-
|1234||MC20||1234,00
|-
|1234||MC20,||1.234,00
|-
|1234||MD20-||1234.00
|-
|-1234||MD20-||1234.00-
|}


There must be one and only one "function main()" statement and this is run when the program is started.
==== Date (D) ====


By convention, main() must return an integer value. If desired, this can be used to indicate "success" with zero or "failure" with some error number.
{|border="1" cellpadding="10" cellspacing="0"
!input!!conversion (string)!!output
|-
|12345||D||18 OCT 2001
|-
|12345||D/||10/18/2001
|-
|12345||D-||10-18-2001
|-
|12345||D2||18 OCT 01
|-
|12345||D/E||18/10/2001
|-
|12345||DS||2001 OCT 18
|-
|12345||DS/||2001/10/18
|-
|12345||DM||10
|-
|12345||DMA||OCTOBER
|-
|12345||DY||2001
|-
|12345||DY2||01
|-
|12345||DD||18
|-
|12345||DW||4
|-
|12345||DWA||THURSDAY
|-
|12345||DQ||4
|-
|12345||DJ||291
|-
|12345||DL||31
|}


The programinit() and programexit() lines are required and provide all the standard multivalue system variables using a simple C++ class macro.
==== Time (MT) ====


<pre>
{|border="1" cellpadding="10" cellspacing="0"
#include <exodus/program.h>
!input!!conversion (string)!!output
|-
|234800||MT||17:13
|-
|234800||MTH||05:13PM
|-
|234800||MTS||17:13:20
|-
|234800||MTHS||05:13:20PM
|-
|0||MT||00:00
|-
|0||MTH||12:00AM
|-
|0||MTS||00:00:00
|-
|0||MTHS||12:00:00AM
|}


programinit()
==== Hex (HEX/MX) ====


function main() {
{|border="1" cellpadding="10" cellspacing="0"
        printl("hello1 says 'Hello World!'");
!input!!conversion (string)!!output
        return 0;
|-
}
|ab||HEX||(same as HEX8 or HEX4 depending on platform)
|-
|ab||HEX8||0000006100000062
|-
|ab||HEX4||00610062
|-
|ab||HEX2||6162
|-
|15||MX||F
|-
|254||MX||FE
|-
|255||MX||FF
|-
|256||MX||100
|-
|27354234||MX||1A1647A
|}


programexit()
==== Text (L/R/T) ====
 
{|border="1" cellpadding="10" cellspacing="0"
!input!!conversion!! (string)output
|-
|abcd||L#3||abc
|-
|ab||L#3||ab&#9251;
|-
|abcd||R#3||bcd
|-
|ab||R#3|| &#9251;ab
|-
|ab||T#3||ab&#9251;
|-
|abcd||T#3||abc&trade;d&#9251;&#9251; 
|-
|42||L(0)#5||42000
|-
|42||R(0)#5||00042
|-
|42||T(0)#5||42000
|}
 
=== Dictionaries ===
 
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's edir program to manually edit dictionaries.
 
Dictionary file names must start with the word "dict_". For example, if you have a "books" file, then you will probably have a "dict_books" file.
 
You can list the contents of a dictionary by typing "list dict_filename".
 
==== Exodus Dictionary Format ====
 
{|
|-
|0 || DICTID || Field/Column Code
|-
|1 || DICTTYPE || "F" or "S" : "F" means use Field No (i.e. raw data) and "S" means use Source Code (i.e. a function).
|-
|2 || FIELDNO || Field number (0=key, 1=field 1 etc for "Fields"
|-
|3 || TITLE ||Title on reports
|-
|4 ||SM || S or M or Mnn : "Single Value" or "Multivalue" or "Multivalue Group nn"
|-
|5 ||KEYPARTNO || Multipart keys are separated by * characters.
|-
|6 ||
|-
|7 || CONVERSION ||Conversion (MD/MT/D etc.)
|-
|8 || SOURCE || Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable "ANS".
|-
|9 || JUST || "L" or "R" or "T" requesting left, right or text justification
|-
|10||WIDTH||Column Width on fixed width reports
|}
 
==== Sort/Select Command ====
 
Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().
 
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.
 
The format of the select/sselect command is as follows:
 
<PRE>
SELECT|SSELECT
 
{max_number_of_records}
 
{using filename}
 
filename
 
{datakeyvalue} ...
 
{BY|BY-DSND fieldname} ...
{
 
  WITH
 
  {NO|ALL|ANY}
 
  dict_field_id
 
  {
  CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|<>|>|<|>=|<= value(s)
  |
  BETWEEN value AND value
  }
 
  {AND|OR}
 
} ...
</pre>
</pre>


==== Save and compile ====
=== Traditional Multivalue Functions and Statements (non-OO) ===
 
Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.
 
* Traditional functions are rendered as Exodus functions.
* Traditional statements are rendered as Exodus subroutines.
 
PRINT OCONV(DATE(),'D')
 
in Exodus becomes:
 
printl(oconv(date(),"D"));
 
==== String Commands ====
 
The use of most of Exodus's functions will be fairly obvious to traditional multivalue programmers.
 
Ηοwever it is not so obvious that all the functions ending in "-er" correspond to the old string commands.
 
For example, the classic multivalue "modify in-place" character conversion command:
 
CONVERT 'ab' TO 'cd' IN ZZ
 
is now represented in Exodus by:
 
converter(zz,"ab","cd");
 
Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.


Make any changes you want in to the skeleton and save it.
To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old "self assign" idiom.


NB If you just want to try out the skeleton program as is then you must still explicitly save it otherwise if you just exit without saving,  edic will assume you have changed your mind and that no longer want the hello1 program, and will cancel. For the default editor (nano), explicit save is usually Ctrl+O.
For example:


On saving hello1, edic will compile and catalog it.
ZZ=TRIM(ZZ)


==== Run ====
should appear in Exodus as:


To run/open/execute your new hello1 program just type its name.
trimmer(zz);


hello1
and not:


and the output is ...
zz=trim(zz);


hello1 says 'Hello World!'
==== Function Types ====


=== Local subroutines ===
{|border="1" cellpadding="10" cellspacing="0"
!TYPE !!FUNCTION TYPE||
|-
|var= ||traditional functions that return values and can be used in expressions and be on the right hand side of assignments||
|-
|if ||traditional conditional statements that started with "if" or ended with "then/else" (or could have)||
|-
|cmd ||traditional commands with no outputs||
|-
|cmd2 ||traditional commands that now have outputs and can be used in expressions||
|}


To simulate classic multivalue basic's "gosub/return" in Exodus, you add additional subroutine and functions above or below your "main" function.
==== Parameters/Argument Types ====


In Exodus's you dont need to local subroutines are functionally almost identical to external subroutines and functions so you can move your external subroutines and functions into the main program source code if you wish.
{|border="1" cellpadding="10" cellspacing="0"
|in|| Parameters that provide data to the function. Can be variables or raw data like 1 or "X"||
|-
|unspecified||Same as "in". Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions "in" cannot be omitted from the source code.||
|-
|io|| Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or "X"||
|-
|out|| Parameters that return data. Must be variables. Cannot be raw data like 1 or "X"||
|-
|}


Local subroutines and functions (including the "main" function) can be any order. There is no rule that functions must appear before or above the code that calls them.
Optional Parameters


Exodus's local subroutines and functions are rather different and arguably much better than classic multivalue local subroutines since they have their own set of variables.
{|border="1" cellpadding="10" cellspacing="0"
!Key !!Default||
|-
|="" ||""||
|-
|=" " ||" "||
|-
|="." ||"."||
|-
|=1 ||1 ||
|-
|=0 ||0||
|-
|=true ||true||
|-
|=false ||false||
|}


#can be called with parameters e.g. gosub funcx(xx,yy,zz)
==== Complete List of Functions ====
#except for program global variables all variables are private (preventing many bugs)
#can return a result e.g. abc=funcx(xx,yy,zz)


Essentially they are identical to *external* functions and subroutines except that 1) they are written in the main program and 2) they have access to the programs global variables.


They do not have any access to the variables of the calling program unless they are passed as parameters or are defined as global variables.
===== Environment =====


They only have one entry point whereas in classic multivalue basic you can jump into the middle of any local subroutine. To simulate this type of coding in in Exodus you must create nested subroutines or functions.
{|border="1" cellpadding="10" cellspacing="0"
|-
|var= ||osgetenv(envname)||
|-
|if ||osgetenv(envname, out value)||
|-
|if ||ossetenv(envname, newvalue)||
|}


The old RETURN TO XYZ syntax is not supported at all and such code must be redesigned to eliminate it.
===== Time/Date/Sleep =====


==== Simple Example ====
{|border="1" cellpadding="10" cellspacing="0"
|var= ||date()||
|-
|var= ||time()||
|-
|var= ||timedate()||
|-
|cmd ||ossleep(milliseconds)||
|-
|var= ||ostime()||
|}


Here is hello1 modified to call a subroutine that says something.
===== System File =====


The word "gosub" is just there for classical clarity. It could be omitted. It could also be replaced by "call" 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 "gosub funcx()" to indicate internal subroutines and "call funcx()" to indicate external subroutines.
{|border="1" cellpadding="10" cellspacing="0"
|if ||osopen(filename, out filehandle, in locale="")||
|-
|cmd ||osclose(filehandle)||
|-
|var= ||osbread(filehandle, startoffset, length)||
|-
|cmd ||osbread(out data, filehandle, startoffset, length)||
|-
|cmd ||osbwrite(data, filehandle, startoffset)||
|-
|if ||osread(out data, osfilename, in locale="")||
|-
|var= ||osread(osfilename, in locale="")||
|-
|if ||oswrite(data, osfilename, in locale="")||
|-
|if ||osdelete(osfilename)||
|-
|if ||osrename(oldosdir_or_filename, newosdir_or_filename)||
|-
|if ||oscopy(fromosdir_or_filename, newosdir_or_filename)||
|-
|cmd ||osflush()||
|}


All functions and subroutines must be after programinit() and before programexit().
===== System Directory =====


<pre>
{|border="1" cellpadding="10" cellspacing="0"
#include <exodus/program.h>
|var= ||oslist(path=".", wildcard="", mode=0)||
|-
|var= ||oslistf(path=".", wildcard="")||
|-
|var= ||oslistd(path=".", wildcard="")||
|-
|var= ||osfile(filename)||
|-
|var= ||osdir(filename)||
|-
|if ||osmkdir(newdirname)||
|-
|if ||osrmdir(dirname, evenifnotempty=false)||
|-
|var= ||oscwd()||
|-
|var= ||oscwd(newdirname)||
|}


programinit()
===== Program Control =====


function main() {
{|border="1" cellpadding="10" cellspacing="0"
        printl("hello1 says 'Hello World!'");
|var= ||suspend(command)||
|-
|var= ||osshell(command)||
|-
|var=    ||osshellread(command)||
|-
|cmd    ||osshellread(out commandoutput, command)||
|-
|cmd    ||osshellwrite(commandinput, command)||
|-
|cmd ||stop(text="")||
|-
|cmd ||abort(text)||
|-
|var= ||perform(command)||
|-
|var= ||execute(command)||
|-
|var= ||chain(command)||
|-
|var= ||logoff()||
|-
|cmd ||debug()||
|}


        gosub subr1();


        return 0;
===== Variable Control =====
}


subroutine subr1() {
{|border="1" cellpadding="10" cellspacing="0"
        printl("subr1 says 'Hello'");
|if    ||assigned(anyvar)||
}
|-
|if    ||unassigned(anyvar)||
|-
|cmd2    ||exchange(var1,var2)||
|-
|cmd2    ||transfer(fromvar,tovar)||
|}


programexit()
===== Console Output =====
</pre>
 
{|border="1" cellpadding="10" cellspacing="0"
|cmd ||print(instring)||
|-
|cmd ||printl(instring="")||
|-
|cmd ||printt(instring="")||
|}
 
===== Cursor =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||at(column0orcode)||
|-
|var= ||at(column0, row0)||
|-
|var= ||getcursor()||
|-
|cmd ||setcursor(cursorstr)||
|-
|var= ||getprompt()||
|-
|cmd ||setprompt(promptchar)||
|}
 
===== Console Input =====
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|var= ||input()||
|-
|var= ||input(out inputstr)||
|-
|var= ||input(prompt, out inputstr)||
|-
|var= ||inputn(n)||
|}
 
===== Math =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var=    ||rnd(number)||
|-
|cmd    ||initrnd(seednumber)||
|-
|var=    ||mod(dividend, divisor)||
|-
|var=    ||abs(number)||
|-
|var=    ||pwr(base, exponent)||
|-
|var=    ||exp(power)||
|-
|var=    ||sqrt(number)||
|-
|var=    ||sin(degrees)||
|-
|var=    ||cos(degrees)||
|-
|var=    ||tan(degrees)||
|-
|var=    ||atan(number)||
|-
|var=    ||loge(number)||
|-
|var=    ||integer(number)||
|-
|var=    ||floor(number)||
|-
|var=    ||round(number, ndecimals=0)||
|}
 
===== String Creation =====
 
{|border="1" cellpadding="10" cellspacing="0"
|var=  ||chr(integer)||
|-
|var=    ||str(instring, number)||
|-
|var=    ||space(number)||
|}
 
 
===== String Info/Search =====
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|var=  ||count(instring, substr)||
|-
|var=  ||dcount(instring, substr)||
|-
|var=  ||index(instring, substr, occurrenceno=1)||
|-
|var=  ||index2(instring, substr, startcharno=1)||
|-
|var=  ||len(instring)||
|-
|var=  ||length(instring)||
|-
|if    ||match(instring, matchstr, options="")||
|-
|var=  ||seq(inchar)||
|}
 
===== String Functions =====
 
Return new and doesnt change original.
 
{|border="1" cellpadding="10" cellspacing="0"
|var= ||convert(instring, oldchars, newchars)||
|-
|var=  ||crop(instring)||
|-
|var=  ||field(instring, sepchar, fieldno, nfields=1)||
|-
|var=  ||field2(instring, sepchar, fieldno, nfields=1)||
|-
|var=  ||fieldstore(instring, sepchar, fieldno, nfields, replacementstr)||
|-
|var= ||lcase(instring)||
|-
|var=    ||ucase(instring)||
|-
|var= ||lower(instring)||
|-
|var=  ||raise(instring)||
|-
|cmd2  ||quote(instring)||
|-
|cmd2  ||squote(instring)||
|-
|cmd2  ||unquote(instring)||
|-
|var=  ||splice(instring, fromcharno, nchars, insertionstr)||
|-
|var= ||substr(instring, fromcharno)||
|-
|var= ||substr(instring, fromcharno, nchars)||
|-
|var= ||swap(instring, oldstr, newstr, options="")||
|-
|var=  ||trim(instring, trimchars=" ")||
|-
|var=  ||trimb(instring, trimchars=" ")||
|-
|var=  ||trimf(instring, trimchars=" ")||
|}
 
===== String Commands =====
 
Modify original in place
 
{|border="1" cellpadding="10" cellspacing="0"
|-
|cmd2  ||converter(io instring, oldchars, newchars)||
|-
|var=  ||cropper(io instring)||
|-
|cmd2  ||fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)||
|-
|cmd2  ||lcaser(io instring)||
|-
|var=  ||ucaser(io instring)||
|-
|cmd2  ||lowerer(io instring)||
|-
|cmd2  ||raiser(io instring)||
|-
|cmd2  ||quoter(io instring)||
|-
|cmd2  ||squoter(io instring)||
|-
|cmd2  ||unquoter(io instring)||
|-
|cmd2  ||splicer(io instring, fromcharno, nchars, insertion)||
|-
|var=  ||substrer(io instring, fromcharno)||
|-
|var=  ||substrer(io instring, fromcharno, nchars)||
|-
|cmd2  ||swapper(io instring, oldstr, newstr, options="")||
|-
|cmd2  ||trimmer(io instring, trimchars=" ")||
|-
|cmd2  ||trimmerb(io instring, trimchars=" ")||
|-
|cmd2  ||trimmerf(io instring, trimchars=" ")||
|}
 
===== iconv/oconv =====


output:
{|border="1" cellpadding="10" cellspacing="0"
|var= ||oconv(instring, conversionstring)||
|-
|var= ||iconv(instring, conversionstring)||
|}


hello1 says 'Hello World!'
===== Database =====
subr1 says 'Hello'


=== External functions and subroutines ===
{|border="1" cellpadding="10" cellspacing="0"
|if ||connect(connectionstring="")||
|-
|if ||disconnect()||
|-
|if    ||createdb(dbname, out errmsg)||
|-
|if    ||deletedb(dbname, out errmsg)||
|-
|if ||createfile(filename, options="")||
|-
|if ||deletefile(filename)||
|-
|if ||clearfile(filename)||
|-
|var= ||listfiles()||
|-
|if ||createindex(filename, fieldname, usingdictfilename="")||
|-
|if ||deleteindex(filename, fieldname)||
|-
|var= ||listindexes(filename="")||
|-
|if    ||begintrans()||
|-
|if    ||rollbacktrans()||
|-
|if    ||committrans()||
|}


Editing and compiling external subroutines and functions in Exodus is identical to normal programs except:
===== Database Files and Records =====


#"program" become "library" so we have "library.h", "libraryinit()" and "libraryexit()".
{|border="1" cellpadding="10" cellspacing="0"
#function main can have any parameters you like eg "function main(in arg1, in arg2, out arg3)
|if ||open(filename, out filehandle)||
|-
|if ||read(out record, filehandle, key)||
|-
|if ||matread(out dimrecord, filehandle, key)||
|-
|if ||readv(out record, filehandle, key, fieldnumber)||
|-
|if ||write(record, filehandle, key)||
|-
|if ||matwrite(in dimrecord, filehandle, key)||
|-
|if ||writev(record, filehandle, key, fieldn)||
|-
|if ||deleterecord(filehandle, key)||
|-
|if ||updaterecord(record, filehandle, key)||the record key must already exist
|-
|if ||insertrecord(record, filehandle, key)||the record key must not already exist
|-
|if    ||lock(filehandle, key)||
|-
|cmd    ||unlock(filehandle, key)||
|-
|cmd    ||unlockall()||
|}


edic func1
===== Record Selection =====


<pre>
{|border="1" cellpadding="10" cellspacing="0"
#include <exodus/library.h>
|if ||select(sortselectclause="")||
|-
|cmd ||clearselect()||
|-
|if ||readnext(out key)||
|-
|if ||readnext(out key, out valueno)||valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.
|-
|if ||selectrecord(sortselectclause="")||
|-
|if ||readnextrecord(out record, out id)||must be preceded by a selectrecord() not select()
|}


libraryinit()
===== Dictionary =====


function main(in arg1, in arg2, out arg3) {
{|border="1" cellpadding="10" cellspacing="0"
        printl("func1 says 'Hello World!'");
|var= ||calculate(fieldname)||
        return 0;
|-
}
|var= ||xlate(filename, key, fieldno, mode)||
|}


libraryexit()
</pre>


edic prog1
===== Dynamic Array Functions =====


<pre>
Return modified, dont change original
#include <exodus/program.h>


programinit()
{|border="1" cellpadding="10" cellspacing="0"
|var=    ||replace(instring, fieldno, replacement)||
|-
|var= ||replace(instring, fieldno, valueno, replacement)||
|-
|var=    ||replace(instring, fieldno, valueno, subvalueno, replacement)||
|-
|var= ||extract(instring, fieldno, valueno=0, subvalueno=0)||
|-
|var= ||erase(instring, fieldno, valueno=0, subvalueno=0)||
|-
|var=  ||insert(instring, fieldno, insertion)||
|-
|var=  ||insert(instring, fieldno, valueno, insertion)||
|-
|var=  ||insert(instring, fieldno, valueno, subvalueno, insertion)||
|-
|if ||locate(instring, target, out setting, fieldn=0, valuen=0)||
|-
|if ||locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)||
|-
|if ||locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)||
|-
|if ||locateusing(instring, target, usingchar)||
|-
|var=  ||remove(fromstr, io startx, out delimiterno)||
|-
|var= ||sum(instring, sepchar=VM_)||
|}


#include "func1.h"
===== Dynamic Array Commands =====


function main() {
Modify original in place
        printl("prog1 says 'Hello World!'");
        return 0;
}


programexit()
{|border="1" cellpadding="10" cellspacing="0"
</pre>
|cmd2 ||replacer(io instring, fieldno, replacement)||
|-
|cmd2  ||replacer(io instring, fieldno, valueno, replacement)||
|-
|cmd2 ||replacer(io instring, fieldno, valueno, subvalueno, replacement)||
|-
|cmd2 ||inserter(io instring, fieldno, insertion)||
|-
|cmd2 ||inserter(io instring, fieldno, valueno, insertion)||
|-
|cmd2 ||inserter(io instring, fieldno, valueno, subvalueno, insertion)||
|-
|cmd2 ||eraser(io instring, fieldno, valueno=0, subvalueno=0)||
|}

Latest revision as of 16:12, 4 November 2014

Programmer's Guides

Only for C++ at the moment. For all others, see some examples: http://code.google.com/p/exodusdb/source/browse/#svn%2Ftrunk%2Fswig%2Fshare

Python

Perl

PHP

Java

C#

C++

ICONV/OCONV PATTERNS

Decimal (MD/MC)

input conversion (string) output
1234 MD2 12.34
1234 MD20 1234.00
1234 MD20, 1,234.00
1234.5678 MD2 12.35
1234.5678 MD20 1234.57
1234.5678 MD20, 1,234.57
1234 MC2 12,34
1234 MC20 1234,00
1234 MC20, 1.234,00
1234 MD20- 1234.00

Date (D)

input conversion (string) output
12345 D 18 OCT 2001
12345 D/ 10/18/2001
12345 D- 10-18-2001
12345 D2 18 OCT 01
12345 D/E 18/10/2001
12345 DS 2001 OCT 18
12345 DS/ 2001/10/18
12345 DM 10
12345 DMA OCTOBER
12345 DY 2001
12345 DY2 01
12345 DD 18
12345 DW 4
12345 DWA THURSDAY
12345 DQ 4
12345 DJ 291
12345 DL 31

Time (MT)

input conversion (string) output
234800 MT 17:13
234800 MTH 05:13PM
234800 MTS 17:13:20
234800 MTHS 05:13:20PM
0 MT 00:00
0 MTH 12:00AM
0 MTS 00:00:00
0 MTHS 12:00:00AM

Hex (HEX/MX)

input conversion (string) output
ab HEX (same as HEX8 or HEX4 depending on platform)
ab HEX8 0000006100000062
ab HEX4 00610062
ab HEX2 6162
15 MX F
254 MX FE
255 MX FF
256 MX 100
27354234 MX 1A1647A

Text (L/R/T)

input conversion (string)output
abcd L#3 abc
ab L#3 ab␣
abcd R#3 bcd
ab R#3 ␣ab
ab T#3 ab␣
abcd T#3 abc™d␣␣
42 L(0)#5 42000
42 R(0)#5 00042
42 T(0)#5 42000

Dictionaries

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's edir program to manually edit dictionaries.

Dictionary file names must start with the word "dict_". For example, if you have a "books" file, then you will probably have a "dict_books" file.

You can list the contents of a dictionary by typing "list dict_filename".

Exodus Dictionary Format

0 DICTID Field/Column Code
1 DICTTYPE "F" or "S" : "F" means use Field No (i.e. raw data) and "S" means use Source Code (i.e. a function).
2 FIELDNO Field number (0=key, 1=field 1 etc for "Fields"
3 TITLE Title on reports
4 SM S or M or Mnn : "Single Value" or "Multivalue" or "Multivalue Group nn"
5 KEYPARTNO Multipart keys are separated by * characters.
6
7 CONVERSION Conversion (MD/MT/D etc.)
8 SOURCE Source Code of a subroutine to calculate the field. Multivalues are lines and the result must be placed in a variable "ANS".
9 JUST "L" or "R" or "T" requesting left, right or text justification
10 WIDTH Column Width on fixed width reports

Sort/Select Command

Exodus provides the classic multivalue sort/select command within any Exodus program followed by readnext().

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.

The format of the select/sselect command is as follows:

 SELECT|SSELECT

 {max_number_of_records}

 {using filename}

 filename

 {datakeyvalue} ...

 {BY|BY-DSND fieldname} ...
 
 {

  WITH

  {NO|ALL|ANY}

  dict_field_id

  {
   CONTAINING|STARTING|ENDING|LIKE|EQ|NE|NOT|GT|LT|GE|LE=|<>|>|<|>=|<= value(s)
   |
   BETWEEN value AND value
  }

  {AND|OR}

 } ...

Traditional Multivalue Functions and Statements (non-OO)

Exodus clones traditional multivalue function and statement behaviour and retains their syntax as far as possible.

  • Traditional functions are rendered as Exodus functions.
  • Traditional statements are rendered as Exodus subroutines.
PRINT OCONV(DATE(),'D')

in Exodus becomes:

printl(oconv(date(),"D"));

String Commands

The use of most of Exodus's functions will be fairly obvious to traditional multivalue programmers.

Ηοwever it is not so obvious that all the functions ending in "-er" correspond to the old string commands.

For example, the classic multivalue "modify in-place" character conversion command:

CONVERT 'ab' TO 'cd' IN ZZ

is now represented in Exodus by:

converter(zz,"ab","cd");

Exodus provides a complete set of string modification commands even where there was no specific command in classic mv basic.

To guarantee fast performance (regardless of compiler optimisation) you should always use the command instead of the old "self assign" idiom.

For example:

ZZ=TRIM(ZZ)

should appear in Exodus as:

trimmer(zz);

and not:

zz=trim(zz);

Function Types

TYPE FUNCTION TYPE
var= traditional functions that return values and can be used in expressions and be on the right hand side of assignments
if traditional conditional statements that started with "if" or ended with "then/else" (or could have)
cmd traditional commands with no outputs
cmd2 traditional commands that now have outputs and can be used in expressions

Parameters/Argument Types

in Parameters that provide data to the function. Can be variables or raw data like 1 or "X"
unspecified Same as "in". Omission of the most common type de-clutters the documentation. NB When defining your own subroutines and functions "in" cannot be omitted from the source code.
io Parameters that may provide and/or return data. Must be variables. Cannot be raw data like 1 or "X"
out Parameters that return data. Must be variables. Cannot be raw data like 1 or "X"

Optional Parameters

Key Default
="" ""
=" " " "
="." "."
=1 1
=0 0
=true true
=false false

Complete List of Functions

Environment
var= osgetenv(envname)
if osgetenv(envname, out value)
if ossetenv(envname, newvalue)
Time/Date/Sleep
var= date()
var= time()
var= timedate()
cmd ossleep(milliseconds)
var= ostime()
System File
if osopen(filename, out filehandle, in locale="")
cmd osclose(filehandle)
var= osbread(filehandle, startoffset, length)
cmd osbread(out data, filehandle, startoffset, length)
cmd osbwrite(data, filehandle, startoffset)
if osread(out data, osfilename, in locale="")
var= osread(osfilename, in locale="")
if oswrite(data, osfilename, in locale="")
if osdelete(osfilename)
if osrename(oldosdir_or_filename, newosdir_or_filename)
if oscopy(fromosdir_or_filename, newosdir_or_filename)
cmd osflush()
System Directory
var= oslist(path=".", wildcard="", mode=0)
var= oslistf(path=".", wildcard="")
var= oslistd(path=".", wildcard="")
var= osfile(filename)
var= osdir(filename)
if osmkdir(newdirname)
if osrmdir(dirname, evenifnotempty=false)
var= oscwd()
var= oscwd(newdirname)
Program Control
var= suspend(command)
var= osshell(command)
var= osshellread(command)
cmd osshellread(out commandoutput, command)
cmd osshellwrite(commandinput, command)
cmd stop(text="")
cmd abort(text)
var= perform(command)
var= execute(command)
var= chain(command)
var= logoff()
cmd debug()


Variable Control
if assigned(anyvar)
if unassigned(anyvar)
cmd2 exchange(var1,var2)
cmd2 transfer(fromvar,tovar)
Console Output
cmd print(instring)
cmd printl(instring="")
cmd printt(instring="")
Cursor
var= at(column0orcode)
var= at(column0, row0)
var= getcursor()
cmd setcursor(cursorstr)
var= getprompt()
cmd setprompt(promptchar)
Console Input
var= input()
var= input(out inputstr)
var= input(prompt, out inputstr)
var= inputn(n)
Math
var= rnd(number)
cmd initrnd(seednumber)
var= mod(dividend, divisor)
var= abs(number)
var= pwr(base, exponent)
var= exp(power)
var= sqrt(number)
var= sin(degrees)
var= cos(degrees)
var= tan(degrees)
var= atan(number)
var= loge(number)
var= integer(number)
var= floor(number)
var= round(number, ndecimals=0)
String Creation
var= chr(integer)
var= str(instring, number)
var= space(number)


String Info/Search
var= count(instring, substr)
var= dcount(instring, substr)
var= index(instring, substr, occurrenceno=1)
var= index2(instring, substr, startcharno=1)
var= len(instring)
var= length(instring)
if match(instring, matchstr, options="")
var= seq(inchar)
String Functions

Return new and doesnt change original.

var= convert(instring, oldchars, newchars)
var= crop(instring)
var= field(instring, sepchar, fieldno, nfields=1)
var= field2(instring, sepchar, fieldno, nfields=1)
var= fieldstore(instring, sepchar, fieldno, nfields, replacementstr)
var= lcase(instring)
var= ucase(instring)
var= lower(instring)
var= raise(instring)
cmd2 quote(instring)
cmd2 squote(instring)
cmd2 unquote(instring)
var= splice(instring, fromcharno, nchars, insertionstr)
var= substr(instring, fromcharno)
var= substr(instring, fromcharno, nchars)
var= swap(instring, oldstr, newstr, options="")
var= trim(instring, trimchars=" ")
var= trimb(instring, trimchars=" ")
var= trimf(instring, trimchars=" ")
String Commands

Modify original in place

cmd2 converter(io instring, oldchars, newchars)
var= cropper(io instring)
cmd2 fieldstorer(io instring, sepchar, fieldno, nfields, replacementstr)
cmd2 lcaser(io instring)
var= ucaser(io instring)
cmd2 lowerer(io instring)
cmd2 raiser(io instring)
cmd2 quoter(io instring)
cmd2 squoter(io instring)
cmd2 unquoter(io instring)
cmd2 splicer(io instring, fromcharno, nchars, insertion)
var= substrer(io instring, fromcharno)
var= substrer(io instring, fromcharno, nchars)
cmd2 swapper(io instring, oldstr, newstr, options="")
cmd2 trimmer(io instring, trimchars=" ")
cmd2 trimmerb(io instring, trimchars=" ")
cmd2 trimmerf(io instring, trimchars=" ")
iconv/oconv
var= oconv(instring, conversionstring)
var= iconv(instring, conversionstring)
Database
if connect(connectionstring="")
if disconnect()
if createdb(dbname, out errmsg)
if deletedb(dbname, out errmsg)
if createfile(filename, options="")
if deletefile(filename)
if clearfile(filename)
var= listfiles()
if createindex(filename, fieldname, usingdictfilename="")
if deleteindex(filename, fieldname)
var= listindexes(filename="")
if begintrans()
if rollbacktrans()
if committrans()
Database Files and Records
if open(filename, out filehandle)
if read(out record, filehandle, key)
if matread(out dimrecord, filehandle, key)
if readv(out record, filehandle, key, fieldnumber)
if write(record, filehandle, key)
if matwrite(in dimrecord, filehandle, key)
if writev(record, filehandle, key, fieldn)
if deleterecord(filehandle, key)
if updaterecord(record, filehandle, key) the record key must already exist
if insertrecord(record, filehandle, key) the record key must not already exist
if lock(filehandle, key)
cmd unlock(filehandle, key)
cmd unlockall()
Record Selection
if select(sortselectclause="")
cmd clearselect()
if readnext(out key)
if readnext(out key, out valueno) valueno returns multivalue numbers if your sortselectclause sorted BY-EXP on a multivalued field. Not implemented yet.
if selectrecord(sortselectclause="")
if readnextrecord(out record, out id) must be preceded by a selectrecord() not select()
Dictionary
var= calculate(fieldname)
var= xlate(filename, key, fieldno, mode)


Dynamic Array Functions

Return modified, dont change original

var= replace(instring, fieldno, replacement)
var= replace(instring, fieldno, valueno, replacement)
var= replace(instring, fieldno, valueno, subvalueno, replacement)
var= extract(instring, fieldno, valueno=0, subvalueno=0)
var= erase(instring, fieldno, valueno=0, subvalueno=0)
var= insert(instring, fieldno, insertion)
var= insert(instring, fieldno, valueno, insertion)
var= insert(instring, fieldno, valueno, subvalueno, insertion)
if locate(instring, target, out setting, fieldn=0, valuen=0)
if locateby(instring, target, ordercode, out setting, fieldn=0, valuen=0)
if locateusing(instring, target, usingchar, out setting, fieldn=0, valuen=0, subvaluen=0)
if locateusing(instring, target, usingchar)
var= remove(fromstr, io startx, out delimiterno)
var= sum(instring, sepchar=VM_)
Dynamic Array Commands

Modify original in place

cmd2 replacer(io instring, fieldno, replacement)
cmd2 replacer(io instring, fieldno, valueno, replacement)
cmd2 replacer(io instring, fieldno, valueno, subvalueno, replacement)
cmd2 inserter(io instring, fieldno, insertion)
cmd2 inserter(io instring, fieldno, valueno, insertion)
cmd2 inserter(io instring, fieldno, valueno, subvalueno, insertion)
cmd2 eraser(io instring, fieldno, valueno=0, subvalueno=0)