NADIR Version 1.0 LANGUAGE REFERENCE Enexe Systems PO Box 771 Ashgrove 4060 Qld Australia Copyright c 1994 by Enexe Systems. All rights are reserved. Licence Agreement Carefully read the following terms and conditions. If you do not agree, return the documents and unopened software for a refund. The commercial version of Nadir must be treated like a book. That is, one copy of the commercial version may be used by one person on one computer at a time. If it is moved to another computer for use by another person, it must be removed from the original computer. It may not be copied, except for taking backup copies for archive and security reasons. A runtime version of Nadir is provided with the commercial version. A system developed using the commercial version may be installed at a user site with the runtime version of Nadir. No royalty fees are required to install the runtime version at a user site. A product provided with the runtime version must be substantially different to the Nadir product. A product that provides front-ends or enhancements to Nadir may not be installed at a user site without written permission from Enexe Systems. The contents of any version of the product may not be modified in any way. While every effort has been made, and will be made to provide a quality product, Enexe Systems will not be liable for any problems caused by the use of the product. CONTENTS Null Value .............26 INTRODUCTION.................1 Boolean Value ..........26 Overview...................1 Variables ................26 Syntax Definitions.........3 Local Variables ........26 Command Line Definitions...3 Symbol Tables ..........27 General Comments...........3 Symbol Names ...........27 Subscripting ...........27 CHAPTER 1 LEXICAL ELEMENTS Collating Sequence .....28 .............................4 next, prev operators ...29 Whitespace.................4 Subscripting Symbol Table Comments...................4 Names ..................29 Names......................4 Subscripting Function Names Keywords...................4 .......................29 Operators..................5 Databases ..............30 String Constants...........6 Operand Conversion Rules .31 String Literals..........6 Arithmetic Operators ...31 Escape Sequences.........6 Comparison Operators ...32 Code Strings.............7 Numbers....................7 CHAPTER 4 EXPRESSIONS ...34 Operators ................34 CHAPTER 2 PROCESSING......8 >< Operator ............35 config.sys and autoexec.bat Operator Precedence ......35 .........................8 Expression Syntax ........35 Command Line Syntax........8 Primary Expression .......37 Command Line Switches....9 Lvalue .................38 Single User Processing..12 Symbol .................38 Processing the Input File.13 Function Call ..........39 Initialization..........13 argc ...................40 Processing..............14 next ...................40 Macro Arguments.........15 prev ...................41 Redefining Keywords.....16 Logical negation ! .....41 Macro Definition........16 Unary minus - ..........41 Expression Evaluation...17 Parenthesis ............41 Conditional Keywords....18 Multiplicative Expression 42 Expansion Rules.........19 Additive Expression ......42 Processing the Input File Relational Expression ....43 in a Macro..............20 Equality Expression ......44 Logical And Expression ...44 CHAPTER 3 LANGUAGE OVERVIEW Logical Or Expression ....44 ............................22 Conditional Expression ...45 Functions.................22 Assignment Expression ....45 Function Name...........22 Expression ...............46 Arguments...............22 Return Value............23 CHAPTER 5 STATEMENTS ....47 argv, argc..............23 Compound Statement .......48 Assigning Arguments.....23 Label Statement ..........48 Passing by value and by Null Statement ...........49 reference...............23 Expression Statement .....49 Variable Types............24 Return Statement .........49 String..................25 If Statement .............50 Integer.................25 While Statement ..........50 Float...................25 Do Statement .............50 Date....................25 For Statement ............51 i Switch, Case and Default System ...................76 Statements................51 SystemRestart ............76 Break Statement...........52 SysType ..................77 Continue Statement........52 TaskNum ..................77 Goto Statement............52 TimeNow ..................77 TokenNext ................77 CHAPTER 6 SYSTEM INTRINSIC TokenScanCreate ..........78 FUNCTIONS...................53 TokenScanDestroy .........79 Bunch.....................53 TokenTerm ................79 DateDay...................53 TokenType ................80 DateDayName...............53 TokenValue ...............80 DateMonth.................54 Unbunch ..................80 DateMonthEnd..............54 DateMonthName.............54 APPENDIX A SYSTEM DateMonthStart............54 PARAMETERS .................82 DateToday.................55 DateYear..................55 APPENDIX B SYSTEM LIMITS84 Dump......................55 Explode...................56 APPENDIX C SYMBOL TABLE Exit......................56 UTILITY - STU ..............88 FieldType.................57 Command Line Syntax ......88 FileClose.................57 STU Commands .............90 FileColumn................57 bstat - Brief Statistics90 FileDump..................57 check - Check Integrity 90 FileIndentSet.............58 copy - Copy Symbol Table92 FileLineGet...............58 dump - Dump Symbol Table92 FileOpen..................58 fstat - Full Statistics 92 FilePrint.................59 pack - Pack Symbol Table93 FileRemove................60 rbuild - Rebuild Symbol FloatToInt................60 Table ..................94 Level.....................60 rtest - Random Test ....94 LineCurr..................61 LineGet...................61 APPENDIX D ERROR MESSAGES96 LineNum...................63 cnd - Condition Handler ..96 OutputColumn..............63 fm - File Manager ........96 OutputIndentSet...........63 hm - Handle Manager ......96 PreProcessSet.............63 key - Key File Functions .97 Print.....................64 lex - Lexical Analysis ...97 Process...................65 mem - Memory Manager .....98 Signal....................66 mi - Macro Interpreter ...98 Spawn.....................66 mif - Macro Intrinsic SpawnRestart..............66 Functions ................99 StrCat....................67 mm - Macro Manager ......100 StrFromAscii..............67 mp - Macro Parsing ......102 StrFromLit................67 n - The main program ....106 StrFromQuoted.............68 st - Symbol Table .......107 StrLen....................69 vm - Virtual Memory .....107 StrMatch..................70 StrPos....................70 INDEX .....................109 StrSubs...................71 StrToAscii................71 StrToLit..................71 StrToLower................72 StrToUpper................72 SymClose..................72 SymCreate.................72 SymLock...................73 SymOpen...................74 SymRemove.................75 ii INTRODUCTION Overview Nadir is a programming language. It is designed to be simple yet intelligent, to reuse as many of its algorithms as possible to produce a small yet powerful programming system. It combines powerful macro generation capabilities, with the ability to write procedural functions. With it you can generate code for any language, analyse and manipulate text files, write database style applications that run unchanged under DOS and Windows, or even use it as a calculator. The name Nadir, the opposite of the zenith, is used to signify a starting point, a small set of rules and functions upon which things can be built. Enexe Systems has developed a product that will appeal to students, professional programmers, and the home enthusiast who wants a no frills programming system with a minimum of fuss and mumbo jumbo that is easy to learn because it is based on the syntax of C. The base nucleus of Nadir comprises a number of modules that perform language parsing, language interpretation, error handling, and a set of inbuilt intrinsic functions for performing string, numeric and date maniplation, and the control of data files and the symbols in them. The nucleus is written in C, and has been ported to run under DOS and Windows. Other modules of intrinsic functions have been written to perform Screen Dialogues and Report Formatting. These functions have been written to perform under DOS in text mode and Windows. When an application is written using these functions, it will work under DOS and Windows without change. A Developer's Kit is planned to allow users to add modules of intrinsic functions written in C. Object modules of the nucleus will be provided, and customized versions of the Nadir programs can then be linked. Introduction 1 Nadir is designed to work with fields. Being an interpreted language, it is slow when compared with programs written in C. For writing applications, complex algorithms should be developed using C and made available by adding these algorithms to the language as intrinsic functions. The Nadir code should be the 90% of the code that runs for 10% of the time. 2 Nadir Reference Manual Syntax Definitions Syntax definitions consist of the entity being defined followed by a colon. Alternatives follow on separate lines. Optional elements are shown inside angle brackets Example macro-arg-list: ( macro-argument-list ) macro-argument-list: macro-argument macro-argument-list, macro-argument macro-argument: user-defined-word < macro-arg-list > token macro-argument terminator token A macro-arg-list is a left parenthesis, followed by an macro-argument-list, followed by a right parenthesis. A macro-argument-list is a macro-argument or a macro-argument-list followed by a comma and a macro-argument. A macro-argument is either a user-defined-word, followed by an optional macro-arg-list, or a token, or a macro-argument followed by a terminator and a token. Command Line Definitions When the syntax of commands are shown, brackets, [], are used to show optional items. Example stu command [switches] [file1 [file2]] The user must specify the command word, the switches, file1 and file2 are optional. General Comments All the examples show the date in the dd/mm/yyyy format. There is a system parameter that allows the output format of the date to be modified. Introduction 3 CHAPTER 1 LEXICAL ELEMENTS This chapter provides a formal definition of the Nadir lexical elements. When an input file is read, it is broken into components known as lexical elements or tokens. The syntax of the Nadir language, or the legal combination of tokens is dealt with in the following chapters. In Nadir, case is significant. i.e. The name MyMacro is considered to be a different name to mymacro. Whitespace Whitespace is used to separate tokens in the input file. The whitespace characters are space, tab, carriage return, newline, vertical tab and formfeed. Any amount of whitespace may be used to separate the tokens in the input file. Comments Comments may be used to write notes in the program source. The contents of the comment text are ignored. Comments may be defined in two ways. /* .... */ The character pair /* begins the comment. The comment ends with the next occurence of the character pair */. // ..... The character pair // begins the comment. The comment ends with the next newline character. Names A name starts with an alphabetic character or the underscore character, and may contain any number of alphanumeric or underscore characters. The name ends when a character that is not an alphanumeric or an underscore is encountered. Keywords Keywords are special forms of a name. 4 Nadir Reference Manual The following words have special meaning when processing the input file. Define Eval If Elseif Else Endif The following words are reserved words when defining macros. These words may not be used as variable names or components in variable names. if else return do while for switch goto break continue argv argc next prev Operators Operators are sequences of non alphabetic characters. The following table gives each operator and a short description of their use. Later chapters describe the operators in more detail. Operat Description and use or { Begin compound statement } End compound statement ( Argument list definition, set expression precedence ) [ Begin subscript ] End Subscript , Argument separator >< Argument separator ; Statement terminator + Addition - Subtraction, unary minus . Concatenation * Multiplication / Division % Modulus (remainder) ? Conditional operator : Conditional operator = Assignment operator += Assign sum -= Assign difference *= Assign product /= Assign quotient %= Assign modulus .= Assign concatenation == Logical equal to ! Logical not != Logical not equal to < Logcal less than <= Logical less than or equal to > Logical greater than Chapter 1 Lexical Elements 5 >= Logical greater than or equal to && Logical and || Logical or ^ Variable component seperator String Constants There are two types of string constants, string literals and code strings. String Literals String literals begin and end with matching single or double quotes. In Nadir, the use of single and double quotes is interchangeable. Stings may be continued onto the next line by using the backslash newline combination at the end of the first line. Example "abcd" 'abcd' "ab\ cd" all specify strings containing 4 characters, abcd. Escape Sequences Escape sequences are necessary to allow the definition of non printable characters in a string literal. They also allow the definition of double quotes in a string literal that begins and ends with double quotes. The valid escape sequences are shown in the following table. Sequen Char Remarks ce \a BEL Audible bell \b BS Backspace \f FF Formfeed \n LF Linefeed \r CR Carriage return \t HT Horizontal tab \v VT Vertical tab \\ \ Backslash \' ' Single quote \" " Double quote \xhh hh, a string of up to 2 hex digits \Xhh hh, up to 2 hex digits 6 Nadir Reference Manual \ooo ooo, up to 3 octal digits Notes If a character that follows a backslash is not in the list above, it is taken to mean the character itself. eg \z is lowercase z, \? is question mark. The hex string after \x or \X ends with the first non hexadecimal character. eg "\x7g" is two characters, a character with a value of 7, followed by lowercase g. If a digit between 0 and 7 follows the backslash, it is assumed to start an octal string. The octal string ends with the first non octal character, or an octal character that would make the character value more that octal 377. eg \777 is taken to mean 2 characters, one with an octal value of 77, followed by the character 7. Code Strings Code strings start and end with a matching accent ` character. Each character in the input file is placed in the code string. There are no escape sequences and it is not possible to have an accent in a code string. Example `abc def` "abc\ndef" are equivalent. Both specify strings of 7 characters, abc newline def. Numbers There are two types of numeric tokens, integer and floating point. Integers contain decimal digits. eg 1234 All integers are stored internally as 32 bit signed integers. Floating point numbers contain a decimal point. The integer before the decimal point and the fraction part after the decimal point must either be specified. eg .2, 22. and 22.22 are valid floating point numbers. A dot on its own is not seen as a floating point constant of zero. Floating point numbers are stored internally as double precision floating point numbers. Chapter 1 Lexical Elements 7 CHAPTER 2 PROCESSING The Nadir program is a filter. It takes input from an input file and writes output to an output file. This chapter describes the command line syntax and the method Nadir uses to process the input file to produce the output file. The runtime version of Nadir does not allow the processing of an input file. Applications may be executed using the runtime version using the -e or -p command line switches. There are two versions of the Nadir program. n.exe is the version that runs in text mode under DOS. nw.exe and nsys.dll are the files that run under Windows. config.sys and autoexec.bat The FILES statement in config.sys must allow for the number of files that are to be opened. This figure has to allow for all the files that are opened at one time by all active Windows tasks. If files are to be shared, the DOS SHARE program has to be loaded. This can be done in config.sys using the INSTALL statement, or by running the program directly in autoexec.bat. The /f and /l switches may be specified to manage the number of files that are to be shared. See the Nadir -s switch and the section Single User Processing later in this chapter. The following statement in config.sys will load the share program, allocate 3072 bytes for storing file sharing information and specifies that 64 files can be locked at one time. INSTALL C:\DOS\SHARE.EXE /F:3072 /L:64 Command Line Syntax DOS Command n [switches] [outfile] [infile] Windows Command nw [switches] [infile] 8 Nadir Reference Manual Under DOS the default input file is standard input and the default output file is standard output. They may be redefined by using the > and < redirection operators, or the -i and -o command line switches. Windows Windows does not provide standard input or Input/Output standard output or the < and > redirection operators when processing a command. To specify input, use the -i switch or specify an infile on the command line. If -i is not specified, the first time data is requested from the input file, end of file is returned. If -o is not specified, all output is collected in a temporary file and presented to the user using the browser. See Appendix A, System Parameters for details specifying a browser. Command Line Switches Switches may be specified by either a minus sign or a slash. Spaces may be optionally present between the switch name and the switch value. If a switch is specified more than once the last value will be used. If the -i switch is used and the infile argument is also specified, the last one specified will be used. Switch Description -a After processing, the macro specified by name is executed. -b Before processing is performed, the macro specified by name is executed. The macro is executed once. If an error is signalled and the -c switch is active, it will not be re-executed. The same comment applies to the -a switch. -c Cycle on errors If an error is signalled and the -c switch is active, Nadir will release all resources such as memory and file handles and restart the program. If the switch is not specified, the program terminates when an error is signalled. In this case, the return code of the Nadir program will be 20. Chapter 2 Processing 9 -e Execute Macro. The macro specified by name is executed. The input file is not processed. This is similar to -p, but is more efficient because the memory used by the macro compiler is not allocated Data may be read from the input file using system intrinsic functions. Any return value from the macro is discarded. -i Input filename. name specifies the input filename. Under DOS, if -i is not specified, input is read from standard input. Under Windows, if -i is not specified, any attempt to read from the input file will immediately return end of file. Under Windows, if -i is not specified, -e or -p must be specified for Nadir to perform a task. -l Use macro library. If specified, Nadir will open the default macro library, mlib.dat, on startup. Any reference to a user written macro, or symbol that is not found in the mdat symbol table, is searched for in the macro library. If the -L switch is used, -l is assumed. If -l, or -L is not used, Nadir will not open a library. - No Keywords. n[flags] This is used to pre-process Nadir code. It allows the user to ignore some or all keywords in the input file. Keywords are If, Else, Elseif, Endif, Eval and Define. flags is optional and is a string that may contain :- d - Ignore Define keyword e - Ignore Eval i - Ignore If, Elseif, Else and Endif If flags is not specified, dei is assumed. 10 Nadir Reference Manual -o Output filename. name specifies the output filename. Under DOS, if the -o switch is not specified, output is written to standard output. Under Windows, name is optional. If specified, output is directed to a file with that name. If -o is specified without name, output is written to a temporary file and is shown using the browser program after the Nadir program finishes processing. If -o is not specified under Windows, all output is discarded. - Process String p occurred in the input file. Processing is complete when data from the string is exhausted. Data may be read from the input file using system intrinsic functions. -r Reset input on errors. If the program cycles after an error, this switch will cause Nadir to start processing at the start of the input file. -s Single User Mode When specified, files are not opened shared, no locking is performed, and the special single user processing on incorrectly opened files is performed. -D Default Data Directory If a full pathname is not specified when a symbol table is opened, Nadir uses the dir value to specify the directory. If not specified, files will be opened in the default directory. -L Library data symbol table filename. name specifies the filename of a macro library symbol table. This file contains compiled definitions of macros. -M Macro data symbol table filename. name specifies the filename of the macro data symbol table. This data file contains the compiled definitions of macros. Chapter 2 Processing 11 -P Parameters symbol table filename. name specifies the filename of the symbol table containing system parameters. - Size of local value stack. Sl Local variables may be defined in macros. Their values are kept on the local value stack. size specifies the size in bytes of the local value stack. If not specified, size defaults to 4096 bytes. - Memory Block Size. Sm This applies to the Windows version only. Dynamic memory is obtained from the operating system in chunks of size bytes. Nadir then manages these chunks to provide dynamic memory allocation. If memory is required, and there is not enough free memory in the chunks that have been obtained, Nadir will request another block from the Operating System. If -Sm switch is not used, memory block size defaults to 40960 bytes. - Size of operand stack. So The operand stack is used to hold values when expressions are evaluated when executing compiled macro code. size specifies the size in bytes of the operand stack. If not specified, size defaults to 4096 bytes. -T Temporary File Directory dir specifies the directory where temporary files are created. All temporary files created by Nadir have a "$$$" extension. If not specified, temporary files are created in the default directory. -U Universal symbol table filename. name specifies the filename of the universal symbol table. Universal symbols are permanent and may be kept after invokations of Nadir. Single User Processing When the single user switch -s is specified, no file sharing is possible. The DOS SHARE program does not have to be loaded. If the -s switch is not specified, the SHARE program must be loaded before running Nadir. 12 Nadir Reference Manual When using single user mode, a check is made when each file is opened as to whether it was properly closed. If it was not properly closed, the open routine calls a user written function called SysFileRecover with one argument, the name of the file. This function can allow the user to check or restore the file. If this program uses the check option of the symbol table utility, stu, and the file has no errors, the utility will reset the improperly open flag in the file. If the SysFileRecover function does not exist, the program will be exited with a message "Symbol Table blah not properly closed". Processing the Input File Initialization When Nadir is started, default symbol tables are opened. Symbol tables are used to store the values of symbols. Symbols are variables and may be manipulated when macros are executed. Symbols are referenced in the macro language by using a prefix like univ, glob, parm, and mdat. The symbol tables that are always opened are described below. Intrinsic functions allow access to other symbol tables. univ The universal table is a permanent symbol table. Permanent symbol tables may be used to store data from one invokation of Nadir and refer to it by a later invokation. The universal table may also be shared. A shared table may be opened by simultaneous invokations of Nadir, either in different tasks under Windows, on different DOS boxes under Windows, or on different machines on a network. glob The global table is temporary. On each invokation, a table is created, and deleted when Nadir exits. Unlike univ, global data cannot be shared between sessions running simultaneously. Each invokation of Nadir will have a separate global symbol table. mdat The macro data file is a permanent table that may be shared. This file contains the compiled macro definitions. When macros are defined using the Define word, the code is analysed syntactically, converted to an internal form and stored in symbols in the mdat file. When a macro is evaluated, the internal form is interpreted to execute the statements in the macro. Chapter 2 Processing 13 mdat is not limited to storing compiled macro code and may also contain any symbols that the user chooses to store. parm The parameter file is a permanent file that may be shared. Its purpose is to contain system and user defined parameters. System parameters are used to alter the behaviour of Nadir, and are read from the parm file during initialization. See an appendix for details. mlib The macro library, mlib, is opened only if the -l or -L startup parameters are specified. Any reference to a macro definition or a symbol in mdat that is not found is attemped in mlib. Processing The input file is lexically analysed. If a token is not a name, the token is written to the output file. The whitespace before the token is also output. See Chapter 1 for information on Lexical Analysis. There are six words that are reserved and have special meaning when Nadir processes the input file. They are If, Elseif, Else, Endif, Eval and Define. The behaviour of these words in the input file is described below. If a name is not one of the reserved words, mdat and optionally mlib are checked to see if the word is a user-defined macro. If the name is not user defined, it is output to the output file, and the processing of the input file continues. If there are no user defined words and no reserved words in the input file, the output file will be the same as the input file. If the name is user defined, the value of the macro with that name is output. Nadir first searches the mdat file for the word. If the word is not found, and the -l ot -L command line switch has been used, Nadir will then search the macro library, mlib. If a macro is found it is executed and the value returned by the macro is output. Macros are defined by using the Define keyword. If an argument list exists after the name of the macro in the input file, the value returned by the macro replaces the macro name and the argument list in the input file. Argument lists are described in more detail in a later section. 14 Nadir Reference Manual Macros, when executed may perform the Print intrinsic function. The output of the Print function is put in the output file before the return value of the macro is output. Macro Arguments Arguments may be optionally passed to a macro when a user defined word in the input file is the name of a macro. The syntax of an argument list is :- macro-arg-list: ( macro-argument-list ) macro-argument-list: macro-argument macro-argument-list, macro-argument macro-argument: user-defined-word < macro-arg-list > token macro-argument terminator token If a user defined word is encountered, the return value of the macro replaces the text in the input file. Arguments to macros that are invoked during processing are always passed as strings, exactly as they appear in the input file. Arguments are separated by commas, and if more than one word appears before the next comma, the words and the intervening whitespace, the terminators, are concatenated into one string. Example String in input file Remarks MacroName(abcd) Macro called with a string of four characters, abcd. MacroName(abcd, efgh) Called with 2 arguments 4 character string abcd 4 character string efgh. MacroName(abcd efgh, Called with 2 arguments 1234 5678) 9 character string abcd efgh 9 character string 1234 5678 MacroName("abcd\nefgh") Called with 1 argument 12 character string, which includes the double quotes, and a backslash. Chapter 2 Processing 15 MacroName("abcd\ Called with 1 argument efgh") 12 character string, which includes the double quotes, a backslash and a newline. Redefining Keywords Keywords have special meaning when processing input. The keywords are Define, Eval, If, Elseif, Else and Endif. The values of the words may be changed by setting system parameters in the parm symbol table. i.e. symbol parm^system^word^Define may be used to redefine the word Define to for example DEFINE_A_MACRO. See Appendix A for more information on these System Parameters. Macro Definition Define The Define keyword is used to define or create a macro. If a macro exists, it is overwritten with the new definition. When macros are defined, the macro text is compiled into an internal form that is used when the macro is executed. This internal form is stored in symbols in the mdat symbol table. The syntax of the Define statement is :- Define macro-name <()> compound- statement macro-name: name macro-name ^ arg-name-list: name arg-name-list , name The macro name may contain carets. If a caret is not present, the macro is saved in the mdat symbol table. If a caret is present, the name component before the first caret specifies the symbol table where the macro is saved. The name of the macro in the symbol table is the macro- name with the first name component and the first caret removed. The optional arg-name-list allows the definition of argument names that are used in the body of the macro to refer to the arguments passed to the macro. The arg-list can be empty, or can have any number names, separated by commas. 16 Nadir Reference Manual The compound statement defines the processing that is performed when the macro is invoked. The syntax of a compound statement is defined in a later section. Briefly, it is a series of statements enclosed in matching braces {}. If a return statement is processed, the value returned by the macro is the value of the expression after the return keyword. If the compound statement does not have a return statement, the null value is returned. Example The following example shows the definition of a macro that takes 2 arguments, and some invokations of it. Define Adder(a1, a2) { return a1 + a2; } 3 + 2 is Adder(3,2) 3 + nothing is Adder(3) or Adder (3,) When this is processed, the following output is produced. 3 + 2 is 5 3 + nothing is 3 or 3 Expression Evaluation Eval Eval is used to evaluate expressions when processing input. The syntax of the Eval statement may be one of two forms. Eval ( expression ) Eval compound-statement The text of the Eval statement is replaced by its evaluation. When parenthesis are used, the expression is evaluated, and its value output. The closing right parenthesis is not required if the expression occurs at the end of the input. In the second case, the compound statement is evaluated as if it was a macro. The return statement is used to set a return value. If a return statement is not processed, the null value is returned. In either case, the text of the expression or the compound statement is compiled into the internal form using the macro language syntax rules, and then evaluated. Examples When the following text is processed Chapter 2 Processing 17 Today, Eval(DateToday()) is Eval { dayName = DateDayName(DateToday()); if (dayName == "Saturday" || dayName == "Sunday") return "on the weekend"; else return "a week day"; } The following text is output, (if you run it on 24/11/1993) Today, 24/11/1993 is a week day Conditional Keywords The words If, Elseif, Else and Endif may be used to conditionally process blocks of text in the input file. For each If, there may be any number of Elseif keywords and there must be a matching Else or Endif. For every Else, there must be a matching Endif. The keywords may be used as follows If ( expression-1 ) .... If expression-1 evaluates to true, the text represented by section-1 is processed. Otherwise, if expression-1 evaluates to false, section-1 is ignored (not processed). When an expression is evaluated, it is evaluated using the macro language rules of syntax and execution. In effect, the expression is compiled like a macro, and then executed. This, and the values of true and false expressions are defined in a later section. In the true case, after section-1 has been preprocessed, control passes to the matching Endif. When expression-1 is false, control passes to the next Elseif directive, where expression-2 is evaluated. If expression-2 evaluates to true, section-2 is processed and control passes to the matching Endif. Otherwise if expression-2 is false, control passes to the next Elseif, and so on, until either Else or Endif is encountered. The optional else-section is processed when no other section has been processed. The else-section ends with the matching Endif. 18 Nadir Reference Manual The If, Elseif, Else, Endif structure may be nested. Expansion Rules When expanding, comments are retained and written to the output file wherever possible. The comment after a user defined word is not output, as Nadir ignores comments when it looks for the next token to see if an argument list exists. This behaviour occurs because the program can then easily deal with comments of any length. For Define, If, Elseif, Else and Endif, the directive itself expands to nothing. Any whitespace before the keyword, back to, but not including the most recent newline, is ignored. Any whitespace and comments after the required syntax for the keyword, up to and including the first newline is dropped. The intention is to drop complete lines that contain these directives. When Eval and user defined words are expanded, the words and the necessary syntax that goes with them are replaced exactly by the value of the expansion. The whitespace before and after is output exactly as in the input file. Example The following input, when processed aaa Define Test1() { Print(".Test1."); } bbb Define Test2() { Print(".Test2."); } cccc Test1 dddd /* comment */ Test2 /* another comment */ ( ignored arg) eeee If (1) ffff Else gggg Endif hhhh If (1) /* comment about If directive */ /* comment about output text */ this is output text Else /* comment on Else directive */ no possibility here Endif /* comment of Endif directive */ blah Eval(33+44) blah Eval { tmp1 = "24/11/1993" - "20/09/1953"; return tmp1; } blah will produce the following output aaabbb cccc .Test1. dddd /* comment */ .Test2. eeee ffffhhhh /* comment about output text */ this is output text blah 77 blah 14675 blah Chapter 2 Processing 19 Processing the Input File in a Macro The input file may be processed from within a macro, either by processing tokens using the Token intrinsic functions, or using the LineCurr and LineGet functions to process by each line. When performing lexical analysis, there is a concept of the current token. The whitespace before the current token is known as the current terminator. When a macro is invoked without an argument list, the current token is the token after the macro name in the input file. If the user performs TokenNext or LineGet functions within the macro, Nadir will continue processing at the current token. If an argument list is present, the current token will be the closing right parenthesis of the argument list. After invoking the macro, Nadir performs automatically performs a TokenNext to move to the next token. It does this to retain as many comments in the output file as possible. This behaviour needs to be considered if TokenNext or LineGet functions are called in a macro that has an argument list. 20 Nadir Reference Manual Example The following file, when processed, Define TestToken() /* designed to test TokenValue, TokenNext and TokenType reads tokens from input file until a non integer is found, or the word TestTokenEnd. Returns the total of all the integers found. */ { while (TokenType() == "INT") { total += TokenValue(); TokenNext(); } if (TokenType() == "NAME" && TokenValue() == "TestTokenEnd") TokenNext(); return total; } TestToken 1 2 3 qwerty TestToken 1 2 3 4 TestTokenEnd 5 6 TestToken 1 2 3 4 5 EndOfFile will produce the following output. 6 qwerty 10 5 6 15 EndOfFile Chapter 2 Processing 21 CHAPTER 3 LANGUAGE OVERVIEW This chapter introduces the language. User written functions are defined using the Define keyword in the input file. The term macro is another name for a user written function. When the input file is processed, the macro source code is converted to an internal form, and stored in symbols in the mdat symbol table. Execution time is when an interpreter reads the internal form and uses this to perform the processing specified by the macro's statements. Functions There are two types of functions, user written and intrinsic. User written functions, or macros, are written using the Define keyword in the Nadir input file. Intrinsic functions are written in C and are part of the Nadir executable program. Intrinsic functions may be written and added to an executable program using the Developer's Kit. Function Name The function name may contain carets. When a function name does not contain a caret, Nadir searches for an intrinsic function and then for a user written function in mdat. If it is not found, and a macro library was specified on the command line, mlib is searched. If a caret is present, the name component before the first caret specifies the symbol table where the function is read from. The name of the function in the symbol table is the function name with the symbol table name and the first caret removed. Arguments Using Define, a list of arguments can be specified. The arguments in the function can then be referenced by name. The name given to an argument has to be a valid lexical name. A valid name starts with an alphabetic character or the underscore character, and may contain any number of alphanumeric or underscore characters. 22 Nadir Reference Manual If a function is called, and an argument is not passed, the argument value in the function will be the null value. Return Value A function always returns a result. The return statement can be used to specify the return value of a function. If a return statement if not executed, the null value will be returned. Example The following function returns the arithmetic sum of up to 8 arguments. Define AddArgs(a, b, c, d, e, f, g, h) { return a + b + c + d + e + f + g + h; } argv, argc Arguments passed to a function can be accessed using the argv and argc special variables. Example The following function returns the arithmetic sum of all the arguments. Define AddArgs() { for (i = 0; i < argc; i +=1) rv += argv[i]; return rv; } Assigning Arguments Inside the function, arguments may be assigned. Example Define Test(table) { if (!table) // if value of table not passed table = "univ"; // default to univ . . . } Passing by value and by reference By default, arguments are passed by value. In this case, if an argument is modified in a function, it is modified in the called function and not modified in the calling function. Chapter 3 Language Overview 23 Arguments may be passed by reference using the & operator in the calling function. Any local variable, argument or symbol may be passed by reference. In this case the value is modified in the calling function. Example The following input, when processed, Define Called(a, b) { Print(a, " ", b, " before change in called func\n"); a = 55; b *= 2; Print(a, " ", b, " after change in called func\n"); } Eval { a = 12; b = 24; Print("Values of a and b\n"); Print(a, " ", b, " before func call\n"); Called(a, &b); // a passed by value // b passed by reference Print(a, " ", b, " after func call\n"); } will produce the following output. Values of a and b 12 24 before func call 12 24 before change in called func 55 48 after change in called func 12 48 after func call Variable Types There are no declaration statements to define the type of variable in Nadir. The contents of the field determines the type of a variable. When an operation is to be performed, Nadir examines the contents of the operands, performs any necessary conversions, and then produces a result. The different types of variable that Nadir recognizes are string, integer, float and date. 24 Nadir Reference Manual Examples In the expression "1234" + "1234.5678", the operands are strings, the operator +, or arithmetic addition. Since the operands are strings, Nadir sees if they contain an integer, float or date. In this case the operands are recognized as an integer and a float. Nadir will convert the integer to a float, perform the addition, and produce a float result. Nadir will hold the result as a float, so that if further arithmetic is performed, no conversions may be necessary. If the result was printed using the Print intrinsic function, the float would be internally converted to a string prior to printing. Expression Result "" + 4 4 (nothing plus 4) "jhgjkhg" + 4 4 (same, nothing plus 4) "123" + 12 135 "12.2" + 15 27.2 "14/2/1983" + 5 "19/2/1983" "19/2/1983" - 5 "14/2/1983" String Strings contain sequences of characters. Integer Integers are stored internally as signed 32 bit integers. A valid integer has an optional negative sign and followed by one or more digits. Float Floats are stored internally as 8 byte double precision floating point values. This allows for 14 digits of accuracy. A valid float has an optional negative sign followed by one or more digits with one decimal point. Date Dates are stored internally as a 32 bit integer as a number of days from a starting date. The date format may be Australian, dd/mm/yyyy, or US, mm/dd/yyyy. A symbol in parm, parm^system^date^format specifies the date format on startup. If "u" (the character u), the date format is US, otherwise it is Australian. Chapter 3 Language Overview 25 Null Value The null value is a zero length string. It is used to signify nothing, and is the value returned when a variable or symbol has not been set. Setting a symbol to the null value using an assignment operator will delete it from the symbol table. Boolean Value Boolean values are produced by the logical operators. These include < <= > >= == != && and ||. Values need to be converted to boolean values when processing if statements, evaluating &&, || and ?: operators, and where intrinsic functions specify an argument to be a boolean. A boolean value is stored internally as an integer, zero is false, a non-zero integer is true. Zero length strings, or null values have a value of false. Strings that have one or more characters have a boolean value of true. Numeric values, integers, floats, and the internal representation of dates are false if they are zero, otherwise they are true. Variables In Nadir, values may be stored in function arguments, local variables or in symbol tables. When a function argument, local variable or symbol that does not exist or has not been defined, is referenced, the null value is returned. Local Variables Local variables are used in functions. They are only visible within the function that they are used. They may only be modified outside the function that they are defined in by passing the variable by reference to another function. Local variables are defined when they are first referenced. Local variables are always initialized to the null value. 26 Nadir Reference Manual The name given to a local variable has to be a valid lexical name. A valid name starts with an alphabetic character of the underscore character, and may contain any number of alphanumeric or underscore characters. Symbol Tables Symbol tables contain symbol names and symbol values. There are a number of system defined symbol tables, univ, glob, parm, mdat, mlib, data, temp. The user may define other symbol tables using the Sym family of intrinsic functions. Symbol tables may be permanent, shared, or temporary. Symbols are stored in a symbol table in alphabetic order by name. The next and prev operators may be used to scan through symbol tables. Symbol Names Symbol names are a series of lexical names with caret ^ separators. The first component specifies the name of the symbol table. univ^name^sex^m glob^total^group^Qld A symbol value is created or modified with an assignment statement. univ^name^sex^m = "Male"; univ^name^sex^f = "Female"; glob^total^group^Qld = 0; To delete a symbol, set it to the null string. univ^firstpass = ""; Subscripting Symbols may be subscripted by specifying a subscript expression in square brackets [ and ]. At runtime, the expression is evaluated and the name of the symbol is formed by concatenating the components. Chapter 3 Language Overview 27 Example The following input, when processed, Eval { univ^sex^m = "male"; univ^pers^bloggs^sex = "m"; univ^pers^bloggs^name = "Joe Bloggs"; code = "bloggs"; Print(univ^pers^[code]^name, " is ", univ^sex^[univ^pers^[code]^sex], "\n"); } will produce the following output. Joe Bloggs is male By using subscripts, it is possible to create a symbol name containing components that are not names, but integers, floats and date types. Example Source Code Remarks univ^10^code Invalid syntax, one of the components is not a name univ^[10]^code Valid syntax, resulting symbol name is univ^10^code Collating Sequence Symbol names are stored in symbol tables in the collating sequence order. This order is determined by comparing the symbol names. Each component of the name, the parts separated by carets, are compared in turn from left to right. The comparison of each component uses the rules for Comparison Operators, as defined in the Operand Conversion rules section. When a component is less than the other, the name that it belongs to is before the other in the collating sequence. Example Name 20^xyz is before 100^abc because the first components are both integers, and 20 is numerically less than 100. Name 100a^bc is before 20^xyz. The first components are different types, 100a being a string (100a is not a valid integer), and 20, an integer. When a string is compared to an integer, the integer is converted to a string, and a string comparison is performed. 28 Nadir Reference Manual next, prev operators The following code uses the next operator to print all symbols in the univ table. The next operator returns the next name after a symbol. The name is returned without the table name. The prev operator will return the symbol name before a symbol. If there is no next or previous value, the null value is returned. name = ""; while (name = next(univ^[name])) Print(name, " \t= ", univ^[name], "\n"); Subscripting Symbol Table Names The symbol table name may be subscripted. The following example shows a function that will list all symbols in the symbol table specified by the "table" argument. When the example is processed, the contents of the univ table will be output. Define List(table) { while (name = next([table]^[name])) Print(name, " \t= ", [table]^[name], "\n"); } List(univ) Subscripting Function Names Function names can be subscripted. The following example shows how the action from a menu selection may be used to branch to the required function. Eval { pre = "mdat^menu^main"; [pre]^u = "SysUtilities"; [pre]^r = "SysReporting"; [pre]^i = "InvoiceEntry"; [pre]^c = "ClientMtce"; [pre]^e = "SysEnquiry"; } Define HighLevelFunction() { . /* following code will call function based on contents of userChoice. System will error if userChoice does not contain "u", "r", "i", "c", or "e" */ [mdat^menu^main^[userChoice]](); . } Chapter 3 Language Overview 29 Databases Databases can be kept using the symbol tables. Building a database becomes a task of choosing an appropriate naming convention. Consider a database of person facts. For this example it is proposed that the code is a system generated number. The dots represent repeated leading parts of the symbol names. person^[code]^gnam = given name ..............snam = surname ..............dob = date of birth ..............sex = either "m" or "f" Sample data for this example could be :- person^[1]^dob = "15/8/1963"; ...........gnam = "Mary"; ...........sex = "f"; ...........snam = "Smith"; .......[2]^dob = "12/2/1954"; ...........gnam = "Frederick"; ...........sex = "m"; ...........snam = "Johnson"; .......[18]^dob = "1/12/1968"; ............gnam = "Bruce"; ............sex = "m"; ............snam = "Smith"; These symbols are examples of one to one relationships, where one person can only have one date of birth. To build keys, we build symbols names and set their values to "y" to indicate their existence. The following names and examples are for access by surname, sex and date of birth. These are one to many relationships, where any number of people could have the same surname. dob^person^[dob]^[code] = "y"; sex^person^[sex]^[code] = "y"; surname^person^[snam]^[code] = "y"; Sample values for the above names could be :- dob^person^["12/2/1954"]^[2] = "y"; // Johnson ...........["15/8/1963"]^[1] = "y"; // Smith, Mary ...........["1/12/1968"]^[18] = "y"; // Smith, Bruce sex^person^["f"]^[1] = "y"; // Smith, Mary ...........["m"]^[2] = "y"; // Johnson .................[18] = "y"; // Smith, Bruce surname^person^["Johnson"]^[2] = "y"; ...............["Smith"]^[1] = "y"; // Mary .........................[18] = "y"; // Bruce 30 Nadir Reference Manual The method chosen to store the symbol names and values uses a b-tree with leading key compression and allows for variable length values. By using leading key compression, the repeated parts at the beginning of the symbol name are not stored. This is represented by the dots in the examples above. This behaviour will determine the efficiency of the symbol naming convention chosen. The other consideration is that symbols next to each other in the collating sequence will tend to be stored in the same disk block. In the above example all the information for Mary Smith will most likely be in the same disk block. Operand Conversion Rules Arithmetic Operators The following table shows the results of an arithmetic operation between two operands. The arithmetic operators are + - / * and %. The divide function returns zero if the divisor is zero. The table shows the type of result and any conversion that is automatically performed when the expression a op b, eg a + b, is evaluated. String b Integer Date b Float b b String a Integer Integer Date * Float * * * Integer a Integer Integer Date Float ** * Date a Date * Date Integer Date *** Float a Float * Float ** Date *** Float * String is converted to zero ** Integer automatically converted to float. ***Float automatically converted to integer. For dates, the internal value, a 32 bit integer which represents a number of days from a starting date, is used in the arithmetic operation. Chapter 3 Language Overview 31 The intention with dates is to perform date arithmetic. If you subtract 2 dates, the result is an integer, the number of days between the dates. Adding an integer, a number of days, to a date produces a date. Comparison Operators When relational, equality and logical operators are performed, a boolean value always results. These operators are <, <=, >, >=, == and !=. The type of comparison performed varies depending on the operands. Numerically, 2 is less than 100, however "2" is greater than "100" if a string comparison is performed. A string comparison is performed by comparing the ascii values of each character in the strings, in turn from left to right. If one string is shorter than the other, and the leading characters are the same, the shorter string is less than the longer string. Integers and floats are compared using their numeric values. For dates, the internal value, a 32 bit integer which represents a number of days from a starting date, is used in the comparison operation. If a date is less than another date, it is an earlier date. The table shows the type of comparison performed and any conversion that is automatically performed when the expression a op b, eg a < b is evaluated. String b Integer Date b Float b b String a String String * String * String * Integer a String * Integer Integer Float ** Date a String * Integer Integer Float ** Float a String * Float ** Float ** Float * Non string value converted to string ** Integer or date is converted to a float. Example If a string is compared to a float, the float is converted to a string, and a string comparison is performed. 32 Nadir Reference Manual If a float is compared to an integer, the integer is converted to a float, and a float comparison is performed. Chapter 3 Language Overview 33 CHAPTER 4 EXPRESSIONS An expression is a sequence of operators and operands that performs a calculation. The precedence of the operators specify the order of evaluation. During evaluation, Nadir may automatically perform conversions. Operators The following operators are available in expressions. Operator [] Array subscript () Function call, Evaluate expression ! Logical negation (not) - Unary minus & Pass by reference next Next symbol in table prev Previous symbol in table * Multiply / Divide % Modulus (remainder) + Plus (addition) - Minus (subtraction) . Concatenation < Less than <= Less than or equal to > Greater than >= Greater than or equal to == Equal to != Not equal to && Logical AND || Logical OR ?: Conditional = Assign *= Assign product /= Assign quotent %= Assign modulus += Assign sum -= Assign difference .= Assign concatenation , Comma >< Alternative comma 34 Nadir Reference Manual >< Operator >< is an alternative to the comma. It is treated internally as a comma. The following shows an example of its use. The intention is to highlight, where the use of a comma may confuse. Define DosCharFieldDefine(title, name, row, value) { Print( ` `><`ch = parm^screen^char^`><`; SdPrompt(scr, `><`, 7, "`><`"); SdPrompt(scr, `><row><`,23, ":"); SdCombo(scr, "`><name><`ch", 1, `><row><`, 25, 6, 20, &`><name><`ch, "temp^ch^"); `); } Operator Precedence The following table shows the precedence of the operators, from the highest first to the lowest. () [] ! - & next prev * / % + - . < <= > >= == != && || ?: = *= /= %= += -= , >< Expression Syntax The formal syntax of an expression follows. Each of the elements will be described in detail in later sections. Chapter 4 Expressions 35 primary-expression: lvalue function-name ( <argument-list> ) subscript-list ( <argument-list> ) argc string-constant integer-constant float-constant date-constant next ( symbol ) prev ( symbol ) ! primary-expression - primary-expression ( expression ) symbol: symbol-table-name ^ <subscript-list> subscript-list lvalue: symbol argv [ expression ] argument-name local-variable-name function-name: name function-name ^ <name> subscript-list name <subscript-list> ^ <name> <subscript-list> [ expression ] argument: assignment-expression & lvalue argument-list: argument <argument-list> , <argument> multiplicative-expression: primary-expression primary-expression * multiplicative- expression primary-expression / multiplicative- expression primary-expression % multiplicative- expression additive-expression: multiplicative-expression multiplicative-expression + additive- expression multiplicative-expression - additive- expression multiplicative-expression . additive- expression 36 Nadir Reference Manual relational-expression: addition-expression addition-expression < relational-expression addition-expression <= relational-expression addition-expression > relational-expression addition-expression >= relational-expression equality-expression: relational-expression relational-expression == equality-expression relational-expression != equality-expression logical-and-expression: equality-expression equality-expression && logical-and- expression logical-or-expression: logical-and-expression logical-and-expression || logical-or- expression conditional-expression: logical-or-expression logical-or-expression ? expression : conditional-expression assignment-expression: conditional-expression lvalue = assignment-expression lvalue *= assignment-expression lvalue /= assignment-expression lvalue %= assignment-expression lvalue += assignment-expression lvalue -= assignment-expression lvalue .= assignment-expression expression: assignment-expression expression , assignment-expression Primary Expression primary-expression: lvalue function-name ( <argument-list> ) subscript-list ( <argument-list> ) argc string-constant integer-constant float-constant date-constant next ( symbol ) prev ( symbol ) ! primary-expression - primary-expression ( expression ) Chapter 4 Expressions 37 Lvalue An lvalue is the term given to an object that may be specified on the left hand side of an assignment expression. lvalue: symbol argv [ expression ] argument-name local-variable-name argv argv is a special type of variable that allows one of a macro's arguments to be referenced using an ordinal value. The expression after argv is converted an integer and defines which argument is to be used. If zero, the first argument is referenced, if one, the second argument is referenced, and so on. If the expression is greater than or equal to the number of arguments passed, the null value is returned. The other options for lvalue specify either an argument, a local variable or a symbol name. If the name does not contain a caret, or subscripts, the name will be an argument or a local variable. It is an argument if the name is in the arg-name- list specified with the Define keyword. Symbol A symbol is an item that is stored in a symbol table. It has the following syntax. symbol: symbol-table-name ^ <subscript-list> subscript-list For symbol names, the name may start with a symbol table name followed by a caret and a subscript list, or may be a subscript list where the symbol table name is subscripted. The symbol table name may be a system defined table, univ, glob, parm, mdat, mlib, data, temp, or a user defined name. See SymOpen or SymCreate intrinsic functions. subscript-list A subscript-list has the following syntax. subscript-list name <subscript-list> ^ <name> <subscript-list> [ expression ] 38 Nadir Reference Manual The intention is that a subscript-list can be any combination of caret, names and expressions in brackets []. Two names cannot appear next to each other, and a symbol cannot contain a single name. Subscripting allows the actual name of the symbol to be evaluated, by concatenating the components together. When a symbol name is evaluated, it must contain at least one caret, the component before the first caret specifying the name of the symbol table. Function Call A function call is specified when a name or subscript-list is followed by parenthesis enclosing an optional argument list. function-name ( <argument-list> ) subscript-list ( <argument-list> ) The function name specifies an intrinsic function built into the Nadir executable using the Developer's Kit, or a user defined function created by processing the Define keyword. The function name may contain carets. If a function name does not contain a caret, Nadir searches for an intrinsic function and then for a user written function in mdat. If it is not found, and a macro library was specified on the command line, mlib is searched. If a caret is present in the function name, the name component before the first caret specifies the symbol table where the function is read from. The name of the function in the symbol table is the function name with the symbol table name and the first caret removed. When the subscript list alternative is used, the subscript-list is evaluated at execution time to provide the name of the function to call. The name evaluated may be an intrinsic function or a user defined function. At execution time, if a function is not found, an error is signalled. A function call always evaluates to a value. If the called function executes a return statement, it is the value of the return expression, otherwise it is the null value. Chapter 4 Expressions 39 Argument List Arguments may be passed to a function. The argument list contains optional arguments separated by commas. argument: assignment-expression & lvalue argument-list: argument <argument-list> , <argument> An argument may be either an assignment expression, or an & followed by an lvalue. When the & is used, the lvalue is passed by reference. When a variable is passed by reference, the called function may modify the value or contents of the variable. Symbol names, local names, or argument names may be passed by reference. If the assignment expression form is used, the value is passed. If the argument is not specified, the null value is assumed. The following table shows some valid argument lists. Argument Remarks List () no arguments (a) 1 argument (,) 2 null arguments (b,) 2 arguments, last one null (a,b) 2 arguments (,b) 2 arguments, first one null argc argc is a special word that returns the number of arguments passed to the function that it occurs in. next The next operator is used to find the next symbol in a symbol table. next ( lvalue ) The lvalue must specifiy a symbol name. If it is a subscript list, the evaluated name must contain a caret with the first element of the name specifying a valid symbol table. 40 Nadir Reference Manual The return value is a string containing the next name after the lvalue. The return value of next does not include the symbol table name. If lvalue is the last symbol in the table, the null value is returned. See the example of next in Subscripting Symbol Table Names in the Language Overview chapter. prev The prev operator is used to find the previous symbol in a symbol table. prev ( lvalue ) The lvalue must specifiy a symbol name. If it is a subscript list, the evaluated name must contain a caret, with the first element of the name specifying a valid symbol table. The return value is a string containing the previous name before the lvalue. The return value of prev does not include the symbol table name. If lvalue is the first symbol in the table, the null value is returned. Logical negation ! The ! unary operator returns the logical negation of the operand, the following primary expression. ! primary-expression The result is a boolean value. The primary- expression is converted to a boolean, and then a logical negation is performed. i.e. True becomes false, false becomes true. Unary minus - The unary minus operator returns the negative of the operand. - primary-expression If the primary expression is not an integer, float or date, zero is returned. Parenthesis Parenthesis () may be used to override the precedence of an operator, or to change the order of evaluation. The following table shows some examples. Chapter 4 Expressions 41 Expression Evaluation Steps a + b * c b multiplied by c, then added to a (a + b) * c b added to a, then multiplied by c a + b + c b added to a, then c added. a + (b + c) c added to b, which is added to a Multiplicative Expression The three multiplicative operators are * / and %. multiplicative-expression: primary-expression primary-expression * multiplicative- expression primary-expression / multiplicative- expression primary-expression % multiplicative- expression The operands are converted using the arithmetic conversion rules for arithmetic operators. The * operator produces the product of the two operands. The / operator produces the quotent when the first operand is divided by the second operand. If the second operand is zero, the result will be zero. The % or modulus operator produces the remainder when the first operand is divided by the second operand. If the second operand is zero, the result will be zero. If the operands are floats, x % y is the remainder f, where x = ay + f for some integer a and 0 <= f < y. eg 5.0 % 2.0 is 1.0 Additive Expression The three additive operators are + , - and ., the fullstop. additive-expression: multiplicative-expression multiplicative-expression + additive- expression multiplicative-expression - additive- expression multiplicative-expression . additive- expression 42 Nadir Reference Manual For + and -, The operands are converted using the arithmetic conversion rules for arithmetic operators. The + operator produces the sum of the two operands. The - operator produces the difference, when the second operand is subtracted from the first. The . operator converts the operands to strings, if necessary, and concatenates them, forming a string result. Relational Expression The four relational operators are <, <=, >, >= relational-expression: additive-expression additive-expression < relational-expression additive-expression <= relational-expression additive-expression > relational-expression additive-expression >= relational-expression The operands are converted using the arithmetic conversion rules for comparison operators. The type of comparision performed depends on what types the operands are converted to. The result of a relational operator is a boolean value. The operators are described in the following table. a < b if a is less than b, true is returned, else false is returned. a <= b if a is less than or equal to b, true is returned, else false is returned. a > b if a is greater than b, true is returned, else false is returned. a >= b if a is greater than or equal to b, true is returned, else false is returned. Chapter 4 Expressions 43 Equality Expression The two equality operators are == and !=. These have a lower precedence than the relational operators. equality-expression: relational-expression relational-expression == equality-expression relational-expression != equality-expression The operands are converted using the arithmetic conversion rules for comparison operators. The type of comparision performed depends on what types the operands are converted to. The result of an equality operator is a boolean value. The operators are described in the following table. a == b if a is equal to b, true is returned, else false is returned. a != b if a is not equal to b, true is returned, else false is returned. Logical And Expression logical-and-expression: equality-expression equality-expression && logical-and- expression The logical and operator is &&. The result is a boolean value, true if both operands are true, otherwise the result is false. An operand is converted to a boolean value when the test for true is performed. If the first operand is false, the second operand will not be evaluated, and false will be the result. Logical Or Expression logical-or-expression: logical-and-expression logical-and-expression || logical-or- expression 44 Nadir Reference Manual The logical or operator is ||and has a lower precedence than logical and, &&. The result is a boolean value, true if either of the operands are true, otherwise the result is false. An operand is converted to a boolean value when the test for true is performed. If the first operand is true, the second operand will not be evaluated, and true will be the result. Conditional Expression conditional-expression: logical-or-expression logical-or-expression ? expression : conditional-expression In the expression a ? b : c, a is evaluated, and converted to a boolean value. If the value of a is true, expression b is evaluated, and is the result of the conditional expression. If a is false, expression c is evaluated, which becomes the result of the conditional expression. Assignment Expression assignment-expression: conditional-expression lvalue = assignment-expression lvalue *= assignment-expression lvalue /= assignment-expression lvalue %= assignment-expression lvalue += assignment-expression lvalue -= assignment-expression lvalue .= assignment-expression The assignment expressions are used to assign a value to the argument, variable or symbol specified by the lvalue operand. When the assignment operator = expression is evaluated, the assignment-expression is evaluated, and is stored in the variable specified by the lvalue. The result of the expression is the value of the lvalue after the assignment. The other assignment operators are *=, /=, %=, +=, -= and .=. Each of these are an arithmetic operator followed by an equals sign. a op= b has the same result as a = a op b. Chapter 4 Expressions 45 Expression expression: assignment-expression expression , assignment-expression The lowest precedence operator is the comma operator. An expression is a list of one or more assignment-expressions, separated by the comma operator. Each of the assignment-expressions are evaluated, starting from the left, and proceeding to the right. The result of the expression is the result of the last assignment-expression. 46 Nadir Reference Manual CHAPTER 5 STATEMENTS The Define keyword in the input file is used to define a user written function, sometimes referred to as a macro. The syntax of the Define keyword includes a compound statement. This compound statement specifies the processing to be performed by the function. The compound statement may contain a number of statements, performed in the order written. The syntax of the statements follow. Each of the statements are described in detail later in this chapter. statement: compound-statement label-statement null-statement expression-statement return-statement if-statement while-statement do-statement for-statement switch-statement case-statement default-statement break-statement continue-statement goto-statement compound-statement: { <statement-list> } statement-list: statement statement-list statement label-statement: label-name : <statement> null-statement: ; expression-statement: expression ; return-statement: return <expression> ; if-statement: if ( expression ) statement <else statement> Chapter 5 Statements 47 while-statement: while ( expression ) statement do-statement: do statement while ( expression ) ; for-statement: for ( <expression> ; <expression> ; <expression> ) statement switch-statement: switch ( expression ) statement case-statement: case expression : statement default-statement: default : statement break-statement: break ; continue-statement: continue ; goto-statement: goto label-name Compound Statement compound-statement: { <statement-list> } statement-list: statement statement-list statement A compound statement is an optional list of statements enclosed in matching braces {}. Syntactically, a compound statement is treated as a statement. For example, in the while statement, a statement is required. A compound statement is used in this case where the body of the while loop contains a number of statements. A compound statement is used to define the processing to be performed by a function in the Define keyword. Label Statement label-statement: label-name : <statement> 48 Nadir Reference Manual A statement may be labelled by using a label followed by a colon. A label-name is a valid lexical name. The same label name may not be used more than once in a function definition. The label-name may then be used as the target of the goto statement but only within the function that it is defined in. Null Statement null-statement: ; The null statement consists of a semi-colon. It does nothing and is used in situations where the syntax of a statement requires a statement, but no processing is necessary. Expression Statement expression-statement: expression ; An expression statement is an expression followed by a semicolon. The expression is evaluated, and control passed to the next statement. Return Statement return-statement: return <expression> ; The return statement is used to pass control from a function to the calling function. If the optional expression is present, it is evaluted, and the result becomes the return value for the function. If there is no expression, the null value is returned. If a function does not have a return statement, return is made after the last statement in the function is executed. The null value is returned. Chapter 5 Statements 49 If Statement if-statement: if ( expression ) statement1 <else statement2> The if statement allows conditional processing based on the result of an expression. The expression is evaluated, and the result is converted to a boolean value. If the value is true, statement1 is executed. If the value is false, and the optional else statement2 is present, statement2 is executed. While Statement while-statement: while ( expression ) statement The while statement is a pre tested loop statement. The expression is evaluated and converted to a boolean value. If the value is true, the statement is executed. If there are no statements that pass control out of the loop, the expression is evaluated again. The loop continues until the expression evaluates to false. When this occurs, contol is passed to the statement after the while statement. Do Statement do-statement: do statement while ( expression ) ; The do statement is a post-tested loop statement. The statement is executed. If there are no statements that pass control out of the loop, the expression is then evaluated and converted to a boolean value. If the value is true, control passed to the beginning of the statement, and the statement is then executed again. If the value is false, control is passed to the next statement. 50 Nadir Reference Manual For Statement for-statement: for ( <expression1> ; <expression2> ; <expression3> ) loop-statement The for statement is pre-tested loop statement. expression1 is the initializing expression. If it is present, it is executed. expression2 is the test expression. If present, it is evaluated and converted to a boolean value. If it is not present, a true value is assumed. If the value is true, the loop-statement is executed. expression3 is the increment expression. After the loop-statement is executed, the increment expression, if present, is evaluated. Control is then passed back to the step where the test expression is evaluated and tested. Switch, Case and Default Statements switch-statement: switch ( expression1 ) statement1 case-statement: case expression : statement2 default-statement: default : statement3 The switch statement allows branching to sections of code marked by case or default statements, based on the value of the switch expression. In statement1 there can optionally be one default statement, and any number of case statements. expression1 is evaluated. It is then tested for equality with each of the expressions in any case statements. These expressions are evaluated in the order they occur in statement1. When equality is found, statement2 in the case statement is executed. Execution then continues until the end of statement1. Any case expressions encountered are not evaluated, but any statement2 in following case statements or a statement3 will be executed. Chapter 5 Statements 51 To stop execution after a statement2 in a case statement, the break statement may be used to transfer control to after statement1. If no equality is found with case expressions, and there is a default statement, control passes to the statement3. If there is no default statement, control passes to the end of statement1. Break Statement break-statement: break ; A break can only be used within a while, do or for loop, or a switch statement. It terminates the nearest enclosing loop or switch statement. Continue Statement continue-statement: continue ; A continue statement can only be used within a while, do or for loop. In while and do loops, it transfers control to the test expression. In for loops, control is passed to the increment expression. With nested loops, the continue statement belongs to the nearest enclosing loop. Goto Statement goto-statement: goto label-name The goto statement transfers contol to the statement labeled with the label-name. The label must be defined in the same function as the goto statement. 52 Nadir Reference Manual CHAPTER 6 SYSTEM INTRINSIC FUNCTIONS This chapter details the basic set of intrinsic functions that is always present in Nadir. With the Developer's Kit, other modules of intrinsic functions may be added to the system. Bunch Function Bunch a number of fields into one field. Syntax Bunch(arg ...) Returns The bunch formed by the given arguments Remarks This allows a number of fields to be stored in one field. A bunch may be broken into its components by using the Unbunch function. Example l_ocal = Bunch(1, 2, 3, "abcd", 45.2); This will store a bunch of 5 elements in the local variable l_ocal. DateDay Function Get day component of date Syntax DateDay(date) Returns The day number in the month of the date argument. Example DateDay("3/5/1990") would return 3 if dd/mm/yyyy is the date format. DateDayName Function Get day name of a date Syntax DateDayName(date) Returns The day name of the date argument. Example DateDayName("18/1/1993") would return "Monday" Chapter 6 System Intrinsic Functions 53 DateMonth Function Get month component of date Syntax DateMonth(date) Returns The month number of the date argument. Example DateMonth("3/5/1990") would return 5 if dd/mm/yyyy is the date format. DateMonthEnd Function Get the month end date. Syntax DateMonthEnd(date) Returns Date of the last day of the month of the date argument. Example DateMonthEnd("3/5/1990") would return "31/5/1990". Note that the value returned is really a date, not a string. DateMonthName Function Get month name of a date Syntax DateMonthName(date) Returns The month name of the date argument. Example DateMonthName("18/1/1993") would return "January" DateMonthStart Function Get the month start date. Syntax DateMonthStart(date) Returns Date of the first day of the month of the date argument. Example DateMonthStart("3/5/1990") would return "1/5/1990". Note that the value returned is really a date, not a string. 54 Nadir Reference Manual DateToday Function Return today's date. Syntax DateToday() Returns Today's date. DateYear Function Get year component of date Syntax DateYear(date) Returns The year number of the date argument. Example DateYear("03/05/1990") would return 1990. Dump Function Dump values to the Nadir output file. Syntax Dump(arg...) Returns Null Value Remarks This routine is used to dump fields to the output file. The format of the output is such that the type of field can be determined. This function may be used for dump and load type operations with symbol tables. Dump attempts to limit the width of the standard output to 80 characters. If strings are longer, Dump will continue strings like continued strings in the Nadir language. Example Dump("ab\ncd") "ab\ncd" Dump("very long string") "very lo\ ng string" Dump(123) 123 Dump(123.45) 123.45 Dump("1/1/1992") "01/01/1992" Chapter 6 System Intrinsic Functions 55 Dump(Bunch(1,1.2,"abc")) Bunch(1, 1.2, "abc") In the second example, the continuation is really performed at the 80th character of a long string. The example is given to show how a long string is continued on the next line. Explode Function Break a string into components Syntax Explode(str, delimiter, &var1, &var2, &var3 ...) Returns The number of components in str that are separated by the delimiter character. This is the same as the number of delimeters + 1. Remarks If a delimiter is not specified, "^" is assumed. var1 will be set to the first component, var2 to the second and so on. If there are more variables than components, remaining variables are set to the null value. This function may be used to break a variable name into components. Example explode("fred^mary^joan", "^", &loc1, &loc2, &loc3) would set loc1 to "fred", loc2 to "mary", loc3 to "joan" and return 3. Exit Function Exit the Nadir program. Syntax Exit(msg, retCode) Returns Does not return. Remarks If the msg argument specified, it is displayed as an abnormal termination message. The Nadir program is exited. The exit occurs even if cycling is specified on the command line when starting Nadir. If retCode is specified, it will be the exit status of the Nadir program. If it is not specified a value of zero will be returned. 56 Nadir Reference Manual FieldType Function Get field type. Syntax FieldType(arg) Returns The field type of the argument. Will be one of the following "STRING" "INT" - integer field. "FLOAT" "DATE" "BUNCH" Remarks The type returned is the actual type of the field. For example, if arg is a string that contains "123", "STRING" will be returned. FileClose Function Close file opened with FileOpen Syntax FileClose(handle) Returns Null value. Remarks The file, specified by the handle argument is closed. The handle is the value returned from the FileOpen function. FileColumn Function Return current column in a file. Syntax FileColumn(handle) Returns The column number, 0 for first column. Remarks The column number is returned for the file opened with the handle specified by the handle argument. The current column is maintained for a file opened for output. It is reset to zero when a newline is printed to the file. Any other character printed to the file increments the column number by 1. FileDump Function Dump fields to a file. Chapter 6 System Intrinsic Functions 57 Syntax FileDump(handle, arg ...) Returns Null value Remarks Same as Dump function, except output is to the file specified by the handle argument. FileIndentSet Function Set the indent number for a file. Syntax FileIndentSet(handle, indent) Returns The original value of the indent number. Remarks The indent number is set for the file opened with the handle specified by the handle argument. The indent argument specifies the value that the indent column number is to be set to. When Nadir is outputting to a file, if the character to output is not a newline, and the current column number is zero, Nadir will output the indent number of spaces before the character is output. FileLineGet Function Get next line from file opened with FileOpen Syntax FileLineGet(handle, &var, lnlFlag) Returns Returns error status, 0 (zero) if line was read successfully, non zero for end of file. Remarks The line is read from the file opened with the handle specified by the handle argument into the variable, var. If lnlFlag, leave newline flag, is false, the newline character that separates lines is removed. This is the default action. If lnlFlag is true, any newline character at the end of the buffer is not removed. Note that the variable has to be passed by reference, if its value is to be set. FileOpen Function Open a text file for reading or writing. 58 Nadir Reference Manual Syntax FileOpen(fileName, mode) Returns The file handle to be used in subsequent FileRead, FileLineGet, FilePrint, FileDump and FileClose function calls. If the file cannot be opened, zero is returned. Remarks fileName specifies the name of the file to be opened. If no path information is present in fileName, the file is opened in the directory specified by the -D command line switch, or the current directory if -D was not used. The mode string may contain a word. The first character of the word can specify one the following types. Case is not significant. "R"ead Existing file is opened for reading. "W"rite File is created and opened for writing. "A"ppend Existing file is opened for append. Information is written to the end of the file. If the file does not exist, file will be created. Example Following example demonstrates the FileOpen, FileLineGet, FilePrint and FileClose functions. When it is processed, c:\autoexec.bat is printed to the Nadir output file, and is also printed to a file \tmp\junk. Define TestFile() { if (!(infile = FileOpen(`c:\autoexec.bat`, "read"))) Signal("Could not open input file"); if (!(outfile = FileOpen(`\tmp\junk`, "write"))) Signal("Could not open output file"); while (!FileLineGet(infile, &buff)) { Print(buff, "\n"); FilePrint(outfile, buff, "\n"); } FileClose(infile); FileClose(outfile); } TestFile FilePrint Function Print fields to a file. Syntax FilePrint(handle, arg ...) Chapter 6 System Intrinsic Functions 59 Returns Null value Remarks Same as Print function, except output is to the file specified by the handle argument. FileRemove Function Remove a file. Syntax FileRemove(fileName) Returns Returns error status, 0 (zero) if file was deleted successfully, non zero if it was not deleted. Remarks fileName specifies the name of the file to be deleted. FloatToInt Function Convert a float to an integer. Syntax FloatToInt(arg) Returns The integer value of arg. If arg is not a float, or cannot be converted to a float, zero is returned. Level Function Get procedure level. Syntax Level() Returns An integer, the level within the execution hierarchy. The outermost level is level 0. 60 Nadir Reference Manual Example Define Level00() { Print("Entering Level00, Level is ", Level(), "\n"); Level01(); Print("Leaving level00, Level is ", Level(), "\n"); } Define Level01() { Print(" In Level01, Level is ", Level(), "\n"); } Level00 when processed, will output Entering Level00, Level is 0 In Level01, Level is 1 Leaving level00, Level is 0 LineCurr Function Get contents of current line in input file Syntax LineCurr(&var, lnlFlag) Returns Returns null value. Remarks The current line being processed in the Nadir input file, is copied into the specified variable,var. If lnlFlag, leave newline flag, is false, the newline character that separates lines is removed. This is the default action. If lnlFlag is true, any newline character at the end of the buffer is not removed. Note that the variable has to be passed by reference, if its value is to be set. See example in LineGet to see how a macro can be used to process lines from the input file. LineGet Function Get next line from the input file. Syntax LineGet(&var, lnlFlag) Returns Returns error status, 0 (zero) if line was read successfully, non zero for end of file. Chapter 6 System Intrinsic Functions 61 Remarks The next line is read from the Nadir input file, and the resulting line is copied into the specified variable, var. If lnlFlag, leave newline flag, is false, the newline character that separates lines is removed. This is the default action. If lnlFlag is true, any newline character at the end of the buffer is not removed. Note that the variable has to be passed by reference, if its value is to be set. The line is initially read into the buffer used by lexical analysis when processing the Nadir input file. Using this macro, in conjunction with LineCurr, allows the user to process the input file by lines in a user written macro. Example When the following input is processed, Define Testit() /* Testit reads lines after it is invoked, and outputs them prefixed with 4 percent signs. This finishes with a line containing EndTestit */ { LineCurr(&buff); do { if (buff == "EndTestit") { LineGet(); TokenNext(); /* move lexical analysis off token after Testit word, and onto token after EndTestit line */ return; } Print("%%%%",buff,"\n"); } while (!LineGet(&buff)); } aaaaaaaaaa Testit bbbbbbbbbb cccccccccc EndTestit dddddddddd The following output is produced. aaaaaaaaaa %%%%bbbbbbbbbb %%%%cccccccccc dddddddddd 62 Nadir Reference Manual LineNum Function Get line number in the input file. Syntax LineNum() Returns Returns the line number of the current line being processed in the input file. The first line in the file is line number 1. OutputColumn Function Return current column in the output file. Syntax OutputColumn() Returns The column number, 0 for first column. Remarks The current column is maintained for the output file. It is reset to zero when a newline is printed to the output file. Any other character printed to the output file increments the column number by 1. OutputIndentSet Function Set the indent number for the output file. Syntax OutputIndentSet(indent) Returns The original value of the indent number. Remarks The indent argument specifies the value that the indent column number is to be set to. When Nadir is outputting to the output file, if the character to output is not a newline, and the current column number is zero, Nadir will output the indent number of spaces before the character is output. PreProcessSet Function Set pre-process flags. Symtax PreProcessSet(string) Returns Returns a string, the original value of the pre- process mode flags. Chapter 6 System Intrinsic Functions 63 Remarks The string argument specifies the required value for the pre-process flags. It may conain the following characters :- Char Meaning d Define keyword in input file is ignored e Eval is ignored i If, Elseif, Else and Endif are ignored. By ignoring all keywords, only user written macros are expanded. Using this feature, a user can pre process Nadir code. Pre-process flags may be initially set by using the -n command line switch. Example The following example defines a couple of useful macros that may be used to change the mode. Define PreProcessOn(flags) /* turns on pre processing */ { PreProcessSet(flags ? flags : "dei"); } Define PreProcessOff /* turns off pre processing */ { PreProcessSet(""); } Define MyMacro(a,b) /* pre processing off by default */ { return a + b; } PreProcessOn Define Testit { a = MyMacro(4, 3); } When the above is processed (without the -n switch), the following output is produced. Define Testit { a = 7; } Print Function Print to the Nadir output file. Syntax Print(arg ...) Returns Null Value 64 Nadir Reference Manual Remarks Print outputs all the given arguments to the Nadir output file. If arg is a bunch, the elements of the bunch are printed, separated by commas, and enclosed in parentheses, "(" and ")". Example Code Result Print(1, 2, "abc") 12abc Print("abc\ndef") abc def myBunch = Bunch(1,2,3,"abc"); (1, 2, 3, Print(myBunch) abc) Process Function Performs Nadir input to output processing on strings. Syntax Process(input, &output) Returns Returns a string. If no error, returns a null string. If an error occurs either in the syntax, or execution of the arguments, the text of the error is returned. Remarks The input is converted to a string, if necessary. This string is then processed as if it had occurred in Nadir's input file. The ouput of the processing is returned in the output argument. This variable has to be passed by reference. If an error occurs in the execution, any resource that was allocated may not be released. For simple expressions, no resources would probably be involved, however if functions are called, access counts will not be decremented, and any handles, memory etc will not be released as processing stops when the error occurs. The safest method is to call Signal with the error message to restart the system. Example myString = `Eval(DateToday() - "15/10/1955")`; Process(myString, &result); This example, when written in a function, compiles and runs the string in myString as if it had occurred in the input file. The age in days, of a person born on 15 October 1955 is written to the variable called result. Chapter 6 System Intrinsic Functions 65 Signal Function Display an error message, and restart depending on startup parameter. Syntax Signal(arg) Returns Does not return. Remarks The argument, arg, is converted to a string and is displayed as a condition message. If cycling was specified on the command line, the Nadir program is restarted. If cycling was not specified, the Nadir program is terminated. Spawn Function Execute another program. Syntax Spawn(string, silent) Returns An integer, the called program's exit status or - 1. -1 is returned if the program could not be run, either the argument list to the program was too long, the path or file could not be found, or there was not enough memory. Remarks If used under Windows, this function is the same as System. Under DOS, it has different behaviour to System. The string is parsed as if it was a command. The first word specifies the program to run. The other words are built into list of arguments, and the runtime library function spawnvp is called to execute the program. The purpose of this function is to allow programs to be called and their exit status to be examined. The silent argument is a boolean value. If true, it is assumed that the spawned program will not perform any output to the screen. The screen contents are not saved before spawning or restored after the program has finished. SpawnRestart Function Execute another program and then restart Nadir. Syntax SpawnRestart(string, silent) 66 Nadir Reference Manual Returns Resturn is never made, since system is restarted. Remarks This function is available under DOS only. It is the same as the Spawn function, except all data files are closed before the program is invoked. On return, Nadir is restarted, if the cycle on errors switch was specified on the command line. StrCat Function Concatenate strings. Syntax StrCat(arg ...) Returns The string formed by concatenating the arguments. Remarks Arguments are converted to strings. This function was used before the concatenation operator was developed. Example Print(StrCat("abc", 12, "def")); will print abc12def StrFromAscii Function Convert an ascii value to a character string. Syntax StrFromAscii(arg) Returns A character string which contains the byte with the ascii value of the integer argument. Remarks arg is converted to an integer. If arg is not a valid integer, the null value is returned. If arg is greater than 255, the least significant byte is placed in the result. Example StrFromAcsii(48) returns "0" StrFromLit Function Convert a literal to a string. Syntax StrFromLit(string) Returns The string formed by converting the string literal argument. Chapter 6 System Intrinsic Functions 67 Remarks This function performs the reverse of StrToLit. i.e. If the characters backslash lowercase n are in the argument, the returned string will contain 1 character, the newline character. A sequence of backslash newline is dropped. This is how long strings are continued. The valid sequences in the string literal are :- \a audible (bell) character. \b backspace. \f formfeed. \n newline. \r carriage return. \t tab. \v vertical tab. \\ backslash. \' single quote. \" double quotes. \x 2 digit hexadecimal constant follows \nnn 3 digit octal constant. Since the function does not error, there are slight differences to the lexical analysis performed on string literals in the Macro Language. If the string ends with a single backslash, a backslash is output. If there are not 2 valid hex characters after a \x, the value found so far is output to the result. eg "\xaz" would produce the same result as "\x0az", and "\xzz" would produce the same output as "\x00zz". Similarly, the conversion routine continues if there are not 3 valid octal characters for the octal constant. StrFromQuoted Function Convert from a quoted string to a string. Syntax StrFromQuoted(string) Returns The string formed by converting the quoted string argument. Remarks A quoted string begins and ends with a matching single quotes, double quotes or accents. If string is not one of these, the return value will be the same as string. 68 Nadir Reference Manual If string has matching single or double quotes, these are dropped, and the remaining characters are converted to a string using the same rules as StrFromLit. If string has matching accents, the accents are dropped. Remember that when processing input, arguments to macros are either strings or quoted strings. This function may be used to convert quoted string arguments passed to a macros. Examples Following results are the output from a Print(StrFromQuoted(Arguments)); For the first example it would be Print(StrFromQuoted("\"abc\"")); The double quotes have to be escaped to get the double quotes into the string. Arguments No of Printed No of contain chars Result chars "abc" 5 abc 3 "abc\ndef" 10 abc 7 def 'abc\x20def' 12 abc def 7 `abc 9 abc 7 def` def abc\ndef 8 abc\ndef 8 If the following input file is processed Define PrintIt(arg) { Print(StrFromQuoted(arg)); } PrintIt("abc\ndef") Quoted String PrintIt(abc\ndef) Not a quoted string The following output file would be produced abc def Quoted String abc\ndef Not a quoted string StrLen Function Obtain string length. Syntax StrLen(string) Returns The number of characters in the string argument. Chapter 6 System Intrinsic Functions 69 StrMatch Function Test if string matches a regular expression type pattern. Syntax StrMatch(pattern, string) Returns 1 if string matches the pattern, 0 if it doesn't. Remarks The second argument is the string that is matched against the pattern. Characters that have special meaning in the pattern are :- ? Match any character in this position. * Match zero or more characters. ! If first character in pattern, negates match expression. Has no significance if not the first character in pattern or not the first character after [ \ Quotes following character so it is taken literally | Logical or between two or more patterns to use to match the string. eg bob|mary would match either bob or mary [..] Defines a group of characters to match at the current position. The following characters have special meaning inside square brackets. ! If first character negates character set. - Used to specify a range. eg. a-z specifies the chars from 'a' to 'z' inclusive. eg [!-a-z] means not minus sign and not characters a to z. \ Quotes special characters. Examples Pattern String Result ab*cd abcd 1 ab*cd abxxxcdcd 1 ab?cd abcd 0 ab?cd abccd 1 !ab*cd abcd 0 [0-9][0-9]\|[a-z] 34|p 1 StrPos Function Find position of a string in another string. 70 Nadir Reference Manual Syntax StrPos(string, substring) Returns Returns the offset in string of the first occurrence of substring. Remarks Offset 0 means the first character. It the substring is not found in string, -1 is returned. StrSubs Function Extract a string from a string. Syntax StrSubs(string, offset, length) Returns Returns the substring which has length characters at offset characters in string. Remarks The offset of the first character is 0. If offset is too large, the null value is returned. If length is zero, or undefined, the rest of the string after offset is returned. StrToAscii Function Convert a character to an ascii value. Syntax StrToAscii(string) Returns The ascii value of the first byte of the string argument. Remarks StrToAscii returns zero if string has zero length Example StrToAcsii("0aB") returns 48. StrToLit Function Convert string to a literal Syntax StrToLit(string) Returns The string literal, formed by converting the string argument. Remarks A string literal is the string of characters that literally describe the contents of a string. If a string contains a newline character, the string literal will contain 2 characters, a backslash followed by a lowercase n. Chapter 6 System Intrinsic Functions 71 For a list of the sequences that may be output see StrFromLit. If a character is not one of the specified ones like newline, formfeed, vertical tab etc, a hex constant sequence will be output. Example Statement would print Print(StrToLit("Number\nis ", Number\nis 42.02 42.02)); Print("Number\nis ", 42.02); Number is 42.02 StrToLower Function Convert characters to lowercase. Syntax StrToLower(string) Returns The string converted to lowercase. Remarks Any uppercase character is converted to lowercase, any other characters are copied to the return value unchanged. StrToUpper Function Convert characters to uppercase. Syntax StrToUpper(string) Returns The string converted to uppercase Remarks Any lowercase character is converted to uppercase, any other characters are copied to the return value unchanged. SymClose Function Close a symbol table. Syntax SymClose(symtabName) Returns Null value. Remarks The symbol table, specified by symtabName is closed. Access is not possible until SymOpen is performed for the symbol table. SymCreate Function Create a symbol table file, and open for access. 72 Nadir Reference Manual Syntax SymCreate(symtabName, fileName, type, blkSize, buffCnt) Returns Returns an error status. 0 for success, 1 for file already exists. Remarks The function is used to create a symbol table file. After SymCreate, the symbol table is open for use. ie It is not necessary to perform a SymOpen. For an explanation of the arguments, see SymOpen. SymLock Function Lock symbol tables to control access. Syntax SymLock(symtabName, updateFlag ...) Returns Null Value. If return is made, lock requests were granted. Remarks Aruments are pairs of symtabName, eg "univ", and an updateFlag. If updateFlag is true, the user acquires an update lock, otherwise a read lock is acquired. Locks are required if a symbol table is not temporary and not exclusively opened. When an Update lock is acquired, no other user on the system will be able to update the symbol table until the lock is freed. Locks are freed when SymLock is called again, or if ScreenDialogues are used, an SdEdit function call is performed. SymLock unlocks any locks before performing the locks. The function locks the symbol tables in the order they are specified in the argument list. The order in the argument list should be kept consistent in an application to avoid deadlocks. Read locks, when updateFlag is not set, are used for reporting purposes. i.e. another user may get an update lock while you are using the file in this mode. If SymLock is not used, any access to a symbol table file that has not been locked, is locked in Update mode automatically. If the automatic method is used, the order of locking depends on the sequence in which the symbols are updated. When this happens, deadlocks may occur. Chapter 6 System Intrinsic Functions 73 If it is not possible to lock one of the symbol tables, any locks that have already been completed are unlocked, and control is passed to a user written function called SymLockQuery. This routine takes one argument, the filename and should return 0 to retry the lock(s). Any other response will cause a Signal to be performed. SymOpen Function Open a symbol table file for access. Syntax SymOpen(symtabName, fileName, type, blkSize, buffCnt) Returns Returns an error status. 0 for success, 1 for file not found. Remarks symtabName is the name of the symbol table that is being opened. Examples are "univ", "glob", "mdat", "parm", "data", "temp". These are fixed names that have specific meanings to Nadir. A number of user defined names may also be specified. The length is limited to 16 characters. When symbols are referenced, this name is the first component of the symbol name. eg "univ^var^name". fileName specifies the disk file name of the symbol table. If a directory name is not included in the name, the -D parameter specified on the command line is used. If -D was not specified, the current or working directory is chosen. If fileName is not specified, the system default name, or the last name used for the symbol table will be used. The system default is symtabName with the .DAT extension. The fileName argument is ignored for temporary files. A temporary filename is generated. The file is created in the directory specified by the -T command line parameter. If -T was not specified, a temporary file will be created in the current or working directory. If the symbol table is already open, SymOpen will perform a SymClose. The type string contains words separated by any number of non-alpha chars and specifies the type of symbol table that is to be opened. The first character of the word specifies the following types. Case is not significant. 74 Nadir Reference Manual "T"empora File is temporary and deleted when ry closed. If a file is temporary, exclusive use is assumed. SymOpen and SymCreate is the same for temporary files. "E"xclusi When opened has exclusive use. ve May not be shared with other users. If type is not specified, the default type is a permanent, shared file. blkSize defines the size of each block or node in the symbol table file. If not specified, the default size is 512 bytes. blkSize will affect performance and the maximum size of a symbol value. If blkSize is too large, too much memory will be used for buffers, and too much time will be spent searching the node. If blkSize is too small, the symbol table will have too many levels. The size of a symbol name plus its value needs to be less than half the blkSize minus a bit for overheads. blkSize can be changed for an existing symbol table by using the pack or copy function in the Symbol Table Utility, stu. buffCnt specifies the number of buffers that are used when managing the symbol table. If not specified, a default number of 4 is chosen. If a number less than 2 is specified, 2 will be chosen. SymRemove Function Remove a symbol table file from disk. Syntax SymRemove(symtabName, fileName) Returns Returns an error status. 0 for success, non zero if an error occurs. Either the file did not exist, or permission to delete was denied. Remarks If the symbol table, specified by symtabName is opened, SymRemove will close it before performing the delete. If fileName is not specified, the conventions described in SymOpen are followed. symtabName is used to specify an internal slot to use for the operation, fileName defines the disk file that is removed. Chapter 6 System Intrinsic Functions 75 System Function Perform a system call. Syntax System(string, silent) Returns For DOS, return value is zero if call is successful, otherwise non zero. For Windows, return value is zero if call was successful, else the returned value is one more than that returned by the Windows API WinExec function. i.e. Return value is 1 for Out of memory. Remarks If string is not given, the DOS command.com file is executed. Under DOS, be sure that the Nadir input file is not a disk file. Either use the -i switch on the command line when starting Nadir to specify a file, or use System("command<con"). Also if the output is a file, use System("command>con"). If string is present, it is passed as a command to the command processor. Under Windows, the WinExec API function is used. This may be used to start other windows applications, including another copy of Nadir. The silent argument is a boolean value, and is not used by the Windows version. If true, any output from the command is discarded. The screen contents are not saved before executing the command or restored after the command has finished. SystemRestart Function Perform system call and restart Nadir. Syntax SystemRestart(string, silent) Returns Return is never made, since the system is restarted. Remarks This function is available under DOS only. It is the same as the System function, except all data files are closed before the command processor is invoked. On return, Nadir is restarted, if the cycle on errors switch was specified on the command line. 76 Nadir Reference Manual SystemRestart may be used to allow batch files or other programs access to files that the Nadir has open. These functions would include backup, restore and file maintenance. SysType Function Get System Type Syntax SysType() Returns The a string that contains the system type for the Nadir program that is running. Will be one of :- "DOS" running DOS version, n.exe. "WIN" running Windows version, nw.exe and nsys.dll. TaskNum Function Obtain unique task number. Syntax TaskNum() Returns The current task's task number. Remarks On the DOS version, this function always returns 0. Using the Windows version, a number of tasks may be started simultaneously. Task numbers will range from 0 to the maximum number of tasks that may be started minus one. TimeNow Function Get current time Syntax TimeNow() Returns A string containing the current time in format "hh:mm:ss". TokenNext Function Advance to the next token. Syntax TokenNext(comment) Chapter 6 System Intrinsic Functions 77 Returns The error message. If no error occurred, the null value is returned. Remarks Use this function to advance from one token to the next. See the remarks in TokenScanCreate for the effect of TokenNext when TokenScanCreate has not been performed. If the comment argument is true, any comments will be skipped over. If comment is not specified or is false, all the tokens in a comment will be returned. Comments are either any text between /* and */, or between // and a newline character. If tokens in comments are returned, they have to contain valid tokens, for example quoted strings have to be correctly terminated. Note that an empty string contains one token, the end of text token. TokenScanCreate Function Create or initialize a token scan of a string. Syntax TokenScanCreate(string) Returns Null value. Remarks This function creates data structures and copies the string argument. The TokenNext function has to be called to advance to the first token. TokenType, TokenValue, TokenTerm may be used to examine the current token. If TokenNext, TokenType, TokenValue, TokenTerm are called without TokenScanCreate, the tokens in the Nadir input are examined. Nadir input is the string after the -p command line switch, or if that is not specified, the Nadir input file. If TokenScanCreate has been used, TokenScanDestory should be used to free the data structures that have been created. A token scan may be performed within another token scan. 78 Nadir Reference Manual Example The following example shows how the Token functions may be used to lexically analyse a string. It is intended to be the input to Nadir. The second invokation of TestToken will produce an error. Define TestToken(str) { str = StrFromQuoted(str); TokenScanCreate(str); do { if (err = TokenNext()) { Print("error :- ", err); break; } Print(`term = "`, StrToLit(TokenTerm()),`" `, `token = "`, StrToLit(TokenValue()),`" `, `type = `, TokenType(), "\n"); } while (TokenType() != "EOT"); TokenScanDestroy(); } TestToken(" aa\t 123 123.4 \"abcd\" \"20/9/1953\" while") TestToken(" aaaaa ' bbbbb") TokenScanDestroy Function Release the resouces allocated by TokenScanCreate. Syntax TokenScanDestroy() Returns Null value. TokenTerm Function Get the terminator before the current token. Syntax TokenTerm() Returns A string containing the value of the terminator. Remarks The terminator is the whitespace that separates the current token from the previous token. It may be null, for example where there is no whitespace between a name and an operator. See the comments in TokenScanCreate for the effect of TokenTerm when TokenScanCreate has not been performed. Chapter 6 System Intrinsic Functions 79 TokenType Function Get the type of the current token. Syntax TokenType() Returns A string describing the type of the current token. Valid values are shown in the table below. For more information see the Lexical Elements chapter. "NAME" Name, could be a keyword. "OPER" Operator like + or != "STRING" String literal, "abcd\nefg", `qwerty` or 'a' "DATE" Date string "20/9/1953" "FLOAT" Number with a decimal point 123.45 "INT" Integer value 12344 "EOT" End of text. When no errors occur, the last token will have this type. "CHAR" A character that is not one of the above types. Remarks See the comments in TokenScanCreate for the effect of TokenType when TokenScanCreate has not been performed. TokenValue Function Get the value of the current token. Syntax TokenValue() Returns A string containing the value of the current token. Remarks See the comments in TokenScanCreate for the effect of TokenValue when TokenScanCreate has not been performed. Unbunch Function Break a bunch into components. Syntax Unbunch (bunch, &var ...) Returns Number of items in the bunch. If the first argument is not a bunch, 0 is returned. Remarks Used to extract the component parts of the bunch into the variables, which should be passed by reference. 80 Nadir Reference Manual If the first argument is not a bunch, the first variable is set to that value. Any extra variables are set to the null value. Example l_ocal = Bunch(1, 2, "abcd", 45.2); r = Unbunch(l_ocal, &loc1, &loc2, &loc3, &loc4, &loc5); This code would set loc1 to 1, loc2 to 2, loc3 to "abcd", loc4 to 45.2, and loc5 to the null value. r would be set to 4. Chapter 6 System Intrinsic Functions 81 APPENDIX A SYSTEM PARAMETERS System parameters are values in the parm symbol table that are read when Nadir starts processing. The following section describes each of these parameters. mdir^threshold The mdir file is an internal work file that keeps track of the code and data portions of functions that are loaded in memory. If the threshold value is not specified, or zero, a function that is loaded from the mdat file into memory is retained in memory until the Nadir program is ended. The exception to this rule is when a function is redefined using the Define keyword in the input file after it has been loaded into memory, in which case the system will free the current version in memory, if it is not in use at the time of being redefined. When a threshold is specified, the system attempts to limit the use of memory to store function code and data to the number of bytes specified by the threshold. i.e. If threshold is 100000, the system will limit the memory used to store code and data areas to 100000 bytes. To do this, the following processing is performed. When a function is called, and it is not in memory, it is loaded into memory and the memory usage statistic updated. Each time it is called a use count is incremented. Each time a return is made from a function, its use count is decremented. When a function is called, and the memory usage is above the threshold, all functions in memory with a use count of zero are removed, and the memory usage statistic updated accordingly. date^format If date^format is "u", the US date format is used. When dates are input or output, the format mm/dd/yyyy is used. If date^format is not "u', the Australian format dd/mm/yyyy is used. 82 Nadir Reference Manual gui^browser Name of a program that can be used for browsing text files in the Windows version. This program will take one command line argument, the name of the file to browse. text^browser Name of a program that can be used for browsing text files in the DOS version. This program will take one command line argument, the name of the file to browse. word^Define If specified, defines what word to use for the Define keyword when processing input. The allows the user to redefine the Define keyword to another word. eg DEFINE_MACRO. word^Eval If specified, defines what word to use for the Eval keyword when processing input. word^If If specified, defines what word to use for the If keyword when processing input. word^Elseif If specified, defines what word to use for the Elseif keyword when processing input. word^Else If specified, defines what word to use for the Else keyword when processing input. word^Endif If specified, defines what word to use for the Endif keyword when processing input. Appendix A System Parameters 83 APPENDIX B SYSTEM LIMITS Windows Tasks Maximum Windows tasks - 16 tasks. This is the number of times the Windows version of the program can be started simultaneously. Handles Number of handles - 64 handles. The handle manager manages the internal pool of handles. A handle is returned from the FileOpen intrinsic functions, as well as the SdCreate, MsgCreate, PfCreate and PdCreate functions described in the function reference. File Handles Number of file handles - 16 handles. This is the number of handles that may be opened using the FileOpen intrinsic function. Symbol Tables Maximum number of symbol tables open at one time - 7 fixed, 16 user definable. The fixed symbol tables are univ, glob, parm, mdat, mlib, data and temp. Up to 16 other tables may be opened and accessed at the same time. Symbol Name Size Maximum size of the internal representation of a symbol name - 128 bytes. The internal representation will differ slightly from the text representation of a symbol name. The length of the internal representation of each component can be calculated using the following table. The caret separator is not stored in the internal form. string string length plus 2 integer 5 date 5 float 9 84 Nadir Reference Manual B-tree Levels Maximum levels in b-tree - 10 levels. A b-tree structure is used to store symbol names and values. The number of levels in the b-tree affects the total number of symbols that can be stored in a data file. It is felt that this will be hard to exceed. B-tree Nodes Maximum number of nodes - 65535 nodes. The number of nodes or blocks in a symbol table file is limited to 16 bits. For 4096 byte blocks the maximum file size is 256Mbytes. B-tree Node Size Maximum node size - 65500 bytes. This is the size in bytes of a block in the file, used to store one node of the b-tree structure. By increasing the size of a node, the levels in the b-tree can decrease, but the node search time and the memory requirements will increase. Symbol Name and Value Lengths The combination of the length of the internal representation of the symbol name and value in a symbol table is limited by the following :- nameLen + valueLen + 4 has to be less than (blkSize - 10) / 2 The internal lengths for the different value types are :- string string length plus 1 integer 5 date 5 float 9 String Size Maximum string size - 2048 bytes. This is the maximum length of a string value. The limit is used internally in a number of places, including string conversions, eg StrToLit, StrFromLit, PfFormat and Sd functions that deal with editing strings. Operand Stack Size Default stack size - 4096 bytes. Appendix B System Limits 85 This size can be specified by the user by using the -So command line switch. The maximum size is 65500. The operand stack is used to hold the results of expression evaluation. The items on the stack use the number of bytes shown in the following table. string string length plus 3 integer 7 date 7 float 11 Local Value Stack Size Default stack size - 4096 bytes. This size can be specified by the user by using the -Sl command line switch. The maximum size is 65500. The local value stack is used to store the values of local variables for all the active functions. The element size of each item on the stack is the same as for the Operand Stack. Parameter Value Stack Size Stack to store parm values - 512 bytes. The parameter value stack is used to store the values of the parm symbols read when Nadir starts. The parameters described in the System Limits Appendix in the Language Reference and the Function Reference are stored in this stack. Parser Word Size Maximum word size - 2048 bytes. The word is used to store the current token from the input file. The item most likely to reach the limit is a string literal. Parser Line Size Maximum line size - 512 bytes. This is the size of the buffer used to read data from the Nadir input file. If a line is longer than this value, it is a lottery whether Nadir will correctly process it. i.e. Is a token split into two when 512 characters are read? 86 Nadir Reference Manual Parser Argument Names Stack to store argument names - 512 bytes. The argument names for the function being compiled is stored in a stack like the Operand stack. Each name will use name length plus 3 bytes on the stack. Parser Local Names Stack to store local variable names - 1024 bytes. The local variable names for the function being compiled is stored in a stack like the Operand stack. Each name will use name length plus 3 bytes on the stack. Parser Goto Names Stack to store goto labels - 512 bytes. The goto label names for the function being compiled is stored in a stack like the Operand stack. Each name will use name length plus 3 bytes on the stack. Compiled Program and Data Size Program and Data size - 2048 bytes each. Each function is converted into an internal representation that has two parts, code and data. The code has the instructions, the data has constants and literal strings. These values are stored as strings in the mdat symbol table. Appendix B System Limits 87 APPENDIX C SYMBOL TABLE UTILITY - STU STU is a utility program that is used to manage symbol table files. Symbol table files use a b-tree structure. The b-tree files are balanced, i.e. the number of levels or depth of the tree to each key in the file at any given time is always the same. The first block of the file contains the top level node of the tree. The uppermost levels in the tree contain key and pointers to the lower level nodes. The leaf nodes contain the keys and the data associated with each key. When keys are stored in a node, repeated characters at the beginning of the key is not stored for each key. As keys are added in a random fashion, nodes are split as they become too large. The algorithm used attempts to keep each node at least half full, with the exception of the top level node. The stu fstat command can be used to see the efficiency of the storage. The stu pack command can be used to pack a key file into its most efficient storage use. The algorithm has specially written code to treat a new high key inserted into a key file. The algorithm currently used by Nadir to delete keys sets the value of the key to a null value. Using the stu pack command will also remove deleted keys. Command Line Syntax The Stmbol Table Utility Command Line has the following format stu <command> [switches] [file1 [file2]] The command may be:- Command Description bstat Print brief statistics for file1. check The internal structure of file1 is checked and reported on. copy The symbols in file1 are copied to a new file, file2. 88 Nadir Reference Manual dump Dumps the contents of each symbol or key in file1. fstat Print full statistics for file1. This requires a scan of the file. pack Packs file1. This is similar to copy, except output is to a temporary file. At the end of processing the original file is deleted, and the work file renamed to file1. rebuild Rebuilds file1. The program scans the file, picks any block that has a valid format, and inserts symbols in the block into a temporary file. At the end of processing the original file is deleted, and the work file renamed to file1. rtest Random Addition test. This creates file1, and randomly adds keys with random values. Used to test the software. The switches are:- Switch Description -p At end of program, pause and wait for a keystroke. -e Pause and wait at end of program only if the program errors. -c Pause and wait at end of program only on severe errors. -s Silent mode. The program will not produce any output. -n No progress reports. By default, stu shows the operation count as it performs its processing to give an indication of progress. Setting -n will turn off the progress reporting. -t Display time. Each line of output is preceded with the time. If a count of operations is shown, a rate of operations per second since the operation type was started is displayed in the format r=nnn. Appendix C Symbol Table Utility 89 -T<arg> Specify parameters for the rtest command. For more details see the section on rtest. -C<num> num specifies the number of keys to add when rtest is performed. STU Commands bstat - Brief Statistics The following shows example output using the bstat command. The bstat command shows statistics that can be easily and quickly obtained. Command stu bstat mdat.dat Output Brief File Statistics mdat.dat fileSize . . . . = 102400 blkSize . . . . . = 4096 depth . . . . . . = 2 fileSize is the size of the file in bytes. blkSize is the block size, the number of bytes in each node of the file. depth is the number of levels in the b-tree structure. The example file has 2 levels, the top most level, and the leaf node, which contains the symbol values. check - Check Integrity The check command can be used to check the structure of a symbol table. Command stu check mdat.dat Output Check Symbol Table mdat.dat 237 symbols found 237 symbols listed file structure correct The check command is performed in two phases. Firstly, each block is read and the contents checked. For each leaf node found, a count of symbols in the node is accumulated. This is the symbols found value. Secondly, the list function is performed, checking that each symbol name returned is after the previous in the collating sequence. This phase is exited if a symbol is found to be out of sequence. The count of the symbols is accumlated and is the symbols listed value. 90 Nadir Reference Manual If all nodes have a valid format and the symbols found agree with the symbols listed, the message "file structure correct" is displayed. The file in use flag will be reset if no errors are encountered. check messages The check command can output a number of informational messages. They are :- Message Text Comments file size not a multiple The first block of the of blocksize file contains the blocksize. There must be an integer number of blocks in the file. block not neatly filled The unused portion of a with nulls node must be filled with nulls. The block has been scanned correctly, but the data after the scan does not contain nulls symbol too large A block was scanned and an invalid symbol length was found. symbols not in order in During scanning a block block the symbol names were not in ascending collating sequence. block scan did not end Each block contains a on correct byte count of the bytes used in a block. The block scan completed, but not at the correct byte position. not a valid type byte Each block has a type byte, root block, index block, leaf block. An incorrect type byte was found. symbols found and listed The count of symbols don't match found by phase 1 and 2 are not equal. errors found Shown if any error condition was found file structure correct No errors have been found. The structure of the keyfile is correct. Appendix C Symbol Table Utility 91 copy - Copy Symbol Table The copy command can be used to copy the contents of one symbol file to another. The destination file is created. This is not a file copy. Each symbol in the source file is read and inserted into the destination file. The resulting file will have as much information possible in each of the nodes in the file. Command stu copy mdat.dat junk.dat Output Copy Symbol Table mdat.dat to junk.dat 237 symbols copied dump - Dump Symbol Table The dump command shows the contents of each of the symbol values in a hex style dump. Command stu dump mdat.dat Output Dump File mdat.dat (1) BlackOnWhite^c 0000 | 3a 01 00 00 03 16 00 00 00 07 03 30 00 00 00 07 |:..........0....| 0010 | 03 4b 00 00 00 07 03 64 00 00 00 07 03 78 00 00 |.K.....d.....x..| 0020 | 00 07 03 8e 00 00 00 07 03 9f 00 00 00 07 02 bc |................| 0030 | 00 02 c5 00 02 b5 00 0a 1e 03 07 01 01 |............. | (2) BlackOnWhite^d 0000 | 43 6f 6c 6f 75 72 41 72 65 61 42 6c 61 63 6b 4f |ColourAreaBlackO| ....file truncated.... fstat - Full Statistics The following shows example output using the fstat command. The fstat command shows more statistics that the bstat command. To compile the statistics, the file is scanned from the first symbol to the last. Command stu fstat mdat.dat 92 Nadir Reference Manual Output File Statistics mdat.dat fileSize . . . . = 102400 blkSize . . . . . = 4096 depth . . . . . . = 2 nameCnt . . . . . = 237 nameBytes . . . . = 3736 nameMin . . . . . = 6 nameMax . . . . . = 30 nameAvg . . . . . = 15 valueBytes . . . = 60797 valueMin . . . . = 1 valueMax . . . . = 1589 valueAvg . . . . = 256 nameCnt contains the number of symbols in the table. nameBytes is the total characters in all the names. This is the number of bytes used to store the internal representation of the symbol names. It does not include overhead. nameMin, nameAvg and nameMax are the minimum, average and maximum bytes used for the internal representation of the names. The text of the symbol name is not the same as the internal representation. valueBytes is the total characters in all the symbol values.. It does not include overhead. valueMin, valueAvg and valueMax are the minimum, average and maximum bytes used for the values. pack - Pack Symbol Table The pack command can be used to pack the contents of a file. This does the same processing as the copy command. The pack command will fit as much information as possible into each block of the file, and remove deleted symbol names. The source file, name.ext is copied to a file called name.$$$, using the stu copy algorithm. After the copy, name.bak is deleted, if it exists. The source name, name.ext is renamed to name.bak. The temporary file, name.$$$ is renamed to name.ext. Finally, name.bak is deleted. Command stu pack mdat.dat Output Pack Symbol Table mdat.dat 237 symbols copied Appendix C Symbol Table Utility 93 rbuild - Rebuild Symbol Table The rbuild command may be used to rebuild a file from a damaged file. The blocks of the file are read is the same manner as for the first phase of the check command. If the block is a leaf node, and passes all the block checks, the symbols in it are inserted into a temporary output file. After the rebuild, name.bak is deleted, if it exists. The source name, name.ext is renamed to name.bak. The temporary file, name.$$$ is renamed to name.ext. Finally, name.bak is deleted. Command stu rebuild mdat.dat Output Rebuild Symbol Table mdat.dat 237 symbols rebuilt rtest - Random Test The rtest command can be used to test the operation of the symbol insert functions. A number of switches may be used that control the type of names that are randomly generated and added to an existing file. The file can be checked at regular intervals. The rtest switches are described in the following table. rtest Description switch -Tc<num> A total count of num additions to the file will be attempted. Because the names of the symbols are generated randomly, some may fail because the name has been used already. Default value is 10000. -Tt<num> The file is checked (tested) after num additions. If not specified, num for -Tc is assumed. 94 Nadir Reference Manual -Tel<num> The lowest number of elements in the name. The number of elements is a random number between the low and high values inclusive. The type of element is chosen in order, the first string, second integer, third float, fourth date, fifth string and so on. Default value is 1. -Teh<num> The highest number of elements. Note that if -Tr is used, the name can have one more element. Default value is 4. -Trl<num> The low value for the number of repeats. The number of repeats is a random number between the low and high numbers. If non zero, then an extra element is added to the current name for the repeat number of times. Default value is 0. -Trh<num> The high value for the number of repeats. Default value is 0. -Tvl<num> The low value for the number of characters in the value for the randomly chosen name. The size of the value is a random value between the low and high values, inclusive. Default value is 1. -Tvh<num> The high value for the number of characters in the value. Default value is 50. If any of the high values are lower than the low values, the high value is set equal to the low value. Command stu rtest -Tc1000 junk.dat Output Random Test, file test.dat, add 1000, check every 1000 Name elements 1 - 4 Name repeats 0 - 0 Value length 1 - 50 1000 symbol adds attempted, 14 failed Check Symbol Table test.dat 986 symbols found 986 symbols listed file structure correct Appendix C Symbol Table Utility 95 APPENDIX D ERROR MESSAGES The error messages produced by Nadir use the same function internally as the Signal and Exit intrinsic functions. This appendix provides a list of the error messages and some extra description. The error messages contain a condition class. The errors are grouped by class. cnd - Condition Handler The condition handler provides a method for dealing with errors. When the Signal and Exit intrinsic functions are used, condition handler functions are called. The condition handler uses the setjmp and longjmp C functions, and uses a condition handler stack to save setjmp stack frames. Condition Stack Overflow A push of a new condition handler caused the condition handler stack to overflow. This can be caused by using the Process intrinsic function recursively. fm - File Manager The file manager is used to control the handles for text files. Each file opened with the FileOpen intrinsic function will use one of the file manager handles. All handles are open The limit for the number of open files has been reached. hm - Handle Manager The handle manager controls a system pool of handles. These include the FileOpen handles, and well as handles created in other modules of intrinsic functions such as Print Documents and Screen Dialogues. 96 Nadir Reference Manual All handles are used The limit for the number of system handles has been reached. key - Key File Functions The key functions are used to manipulate the b- tree structure that is used to implement the symbol table file. The key is the internal representation of a symbol name. Key and data too long <key> The sum of the length of the key and the length of the data has exceeded the maximum allowed. Key Stack Overflow Each level in the b-tree occupies one frame in the key stack. This error will occur when the maximum number of levels in a symbol table file has been exceeded. Key too long <key> The length of the key has exceeded the maximum allowed. Opening <name> block size incorrect (<filesize> != <size> * <cnt>) The file whose name is shown as name has been opened. The block size, size, and the block count, cnt have been extracted from the file header. When multiplied together, the file size should result. If not, this error will be shown. This will happen when files contain incorrect data. Opening <name> block size is <act>, not <spec> The file whose name is shown as name has been opened. The block size, act, has been extracted from the file header. This error occurs if the block size, spec, is specified in the SymOpen call, and it does not equal the actual size of the file. lex - Lexical Analysis Lexical Analysis breaks the input file into tokens. Examples of tokens are names, operators, integer and string constants. Appendix D Error Messages 97 Unterminated string This error occurs when the end of the Nadir input file is encountered before the closing character of a string literal or code string. mem - Memory Manager The memory manager performs all allocation and deallocation of memory. It can free all allocated memory when conditions are signalled and when the Nadir program is terminated. Out of Memory. Current <curr>, Maximum <max> A request for memory failed. The current amount of memory allocated in shown as curr, the maximum allocated at one time as max. Request size <size> too large A request was made for size bytes of memory and was too large. Under DOS, one allocation cannot be more than 64K, under Windows an allocation cannot exceed the memory block size, specified with the -Sm command line switch. mi - Macro Interpreter The macro interpreter is the module that interprets the output of the compilation of the macro source code. Compiled version <num>, execution version <num> The version of the Nadir program that was used to compile a function is different to that being used to execute it. The version is an internal number associated with the mi module, and is changed when the format of the compiled program is changed in a way that makes it not execute in the next version. i.e. The Nadir version may change, but the internal mi version number may remain unchanged. Stack overflow in <name> stack The size of the stack has been exhausted. name will refer to the type of stack. Possible values are described in the following table. 98 Nadir Reference Manual Stack Type Description Operand The values of function arguments and intermediate expression evaluation values for all functions currently being executed are stored in this stack. Local Value The values of local variables for all functions currently being executed are stored in this stack. Parm Value The values read from the parm symbol table when Nadir starts are stored in the parm value stack. Arg Name The names of arguments for the function being compiled are stored in this stack. Local Name The names of local variables for the function being compiled are stored in this stack. Label Name The names of labels in the function being compiled are stored in the label name stack. Program The constants and literals in the Data function being compiled are stored in the program data stack. mif - Macro Intrinsic Functions This module implements all the system intrinsic functions described in the Language Reference Manual. Browser not defined A text file was to be browsed by the user, but a browser program was not defined using the parm parameters. See gui^browser and text^browser in the Appendix A, System Parameters. Invalid symbol table <stid> The symbol table name, shown as stid is invalid. An valid name is univ or glob. This error occurs when an invalid name is passed to SymClose or SymLock. Appendix D Error Messages 99 mm - Macro Manager This module manages the reading and writing of all the data in the symbol table files. This includes the values of the compiled macros and symbol table values. A better name might be the symbol table manager. In any of the following error messages, stid will refer to the symbol table name, eg univ, and filename will be the filename of the symbol table file. errtext is error message text and is described in the vm section. Application cancelled at user's request The user does not want to wait any longer for a lock request. This error is shown after a user written lock query function has been executed and has returned with a true boolean value. Cannot create <filename>, <errtext> The filename is the name of a temporary symbol table file that could not be created when the Nadir program starts. Cannot open or create <filename>, <errtext> The filename is the name of a permanent symbol table file that could not be either opened or created when the Nadir program starts. Could not auto lock <stid>, <filename> A value was assigned to a symbol name. The symbol table had not been locked, and the system was attempting an automatic lock. This attempt failed. Could not lock <stid>, <filename> The system could not lock the symbol table. This error is shown if the user written function SysLockQuery does not exist. Invalid table in symbol <name> The first component of a symbol name, shown as name, is not the name of a valid symbol table. eg. It is not one of the system names or a user defined name. 100 Nadir Reference Manual Locking <stid>, <filename> for update, write not allowed An attempt has been made to lock a symbol table for update, but the user does not have write permission to the file. Macro Code not found <name> A function is to be executed and the macro code string could not be found in mdat or mlib. name is the name of the function. Macro Data not found <name> A function is to be executed and the macro data string could not be found. name is the name of the function. In this case the macro code string has been found. No ^ in symbol <name> A caret was not found in a symbol name. A caret must be present because the first component of the name is the symbol table name. No symbol table name on open or create A SymOpen or SymCreate function was called and the table name was empty. Open limit exceeded <stid> A SymOpen or SymCreate function was called, and the maximum allowable number of symbol table files were already opened. Symbol Table <stid>, <filename> not open A symbol was referenced, but the symbol table was not open. Symbol Table <stid>, <filename> not properly closed The symbol table was improperly closed, the single use command line switch was used, and there was no user written SysFileRecover function to perform. Test lock failed, <errtext> An attempt was made to lock a temporary file on startup to ensure that the DOS SHARE program has been loaded. SHARE had been loaded and the test lock failed for some other reason. Updating <stid>, <filename>, when locked for read A symbol value has been assigned in a symbol table that was locked by SymLock for read lock. Appendix D Error Messages 101 Updating <stid>, <filename>, write not allowed An attempt has been made to modify a symbol table, when the user does not have write permission to the file. When a symbol table is opened, Nadir checks whether the user has read/write access or read only access to the file. When the user has read only access, Nadir will continue, but will not allow symbol values to be modified. mp - Macro Parsing This module processes the Nadir input file. It performs the compilation of functions and produces the syntax error messages. Cannot process input with Runtime version This error occurs when the Runtime version of the program is used to process an input file. Invalid pre process flags <flags> One of the flags in a call to the PreProcessSet intrinsic function was not valid. Syntax Errors When a function is compiled with the Define keyword in the input file, many syntax errors may be produced. The message shown to the user is formatted in one of the following ways. In all cases msg refers to the text of the syntax error. <msg> at end of input This occurs when the syntax error occurs at the end of the input. <msg> at word <word> This is shown when a string is being processed. Strings can be processed using the Process intrinsic function. word is the current lexical token when the error occured. <msg> at word <word> on line <num>, <line> This is shown when the input file is being processed. word is the current lexical token when the error occured, num is the line number of the current line in the input file, and line the text of the current line. 102 Nadir Reference Manual Syntax Error Text Each of the syntax errors follow. break not in loop or switch A break statement was encountered but was not in a do, do while, for or switch statement. case not in switch A case statement was encountered but was not in a switch statement. continue not in loop A continue statement was encountered but was not in a do, do while or for statement. default not in switch A default statement was encountered that was not in a switch statement. Duplicate arg name One of the argument names in the argument name list after the Define keyword is duplicated. Expected ( The syntax of a statement expected a left parenthesis, but one was not seen. Expected ( or { The syntax of a statement expected a left parenthesis or left brace, but one was not seen. Expected ) The syntax of a statement expected a right parenthesis, but one was not seen. Expected ) or end of input This occurs when processing the Eval keyword. The end of input or a right parenthesis was not found after the Eval expression. Expected : The syntax of a statement expected a colon, but one was not seen. Expected ; The syntax of a statement expected a semicolon, but one was not seen. Appendix D Error Messages 103 Expected a compound statement The syntax after the Define keyword expects a compound statement, but one was not seen. Expected a label The syntax of a goto statement expected a label to be present, but one was not seen. Expected a statement The syntax of a statement expected a statement to be present, but one was not seen. Expected an expression The syntax of a statement expected an expression, but one was not seen. Expected Endif An Endif keyword was expected in the input file, but was not seen. This occurs at the end of the input file. Expected name after Define A function name was not found after the Define keyword in the input file. Expected ] The syntax of the statement expected a right bracket, but one was not seen. Expected ^ The syntax of the statement expected a caret, but one was not seen. Expected } The syntax of the statement expected a right brace, but one was not seen. Invalid arg list An invalid argument list was found. A valid argument list has a left parenthesis, none or more arguments separated by commas, ending with a right parenthesis. 104 Nadir Reference Manual Invalid arg name list The argument name list after the function name after the Define keyword was invalid. A valid argument list has a left parenthesis, none or more argument names separated by commas, ending with a right parenthesis. Invalid table name A macro name containing a caret was specified after the Define keyword. The name component before the first caret was an invalid symbol table name. Label <name> already defined The label, shown as name has already been defined in the current function. Label <name> not defined A label was referenced in a function, but was not defined. More than one default There was more than one default statement found in a switch statement. next arg not a symbol The argument of a next function is not a valid symbol name. No lvalue after & The reference operator was encountered, but was not followed by an lvalue. No matching If An Elseif, Else or Endif keyword was found in the input file without a matching If keyword. No subscript after argv The argv was not followed by a left bracket, an expression and a right bracket. No while after do The while reserved word of the do statement was not found. prev arg not a symbol The argument of a prev function is not a valid symbol name. Appendix D Error Messages 105 Subs expr too complex There were too many operands in a subscript expression. The complexity of the expression in a subscript is limited to a fairly generous size. Too much code The size of the code string exceeded the maximum allowable during the compilation of a function. The function has too much code and needs to be broken into smaller pieces. Too much data The size of the data string exceeded the maximum allowable during the compilation of a function. As with the code string, the function may have to be broken into smaller pieces. n - The main program This is the driver program that reads and parses the command line switches, and provides the main processing loop. Cannot find macro <name> A macro, with a name of name could not be found. This will the value of either the -a, -b or -e command line switch. Cannot open <name> A file, displayed as name, could not be opened. This can be the input file name, -i command line switch, the output file name, -o, or the library file name, -L, or -l. Cannot specify both -e and -p Only one of the command line switches -e and -p may be specified. -e will execute a macro, while -p is used to process a string. Single Use mode not available under Windows The -s command line option for single use mode, cannot be specified on the Windows version of Nadir. 106 Nadir Reference Manual st - Symbol Table The symbol table functions are used to convert a symbol name to and from the internal form used in the symbol table files. The module also has the function that is used to compare 2 names in their internal format. Element in symbol <name> too long One of the components in the symbol, shown as name is too long to represent the length in one character. Invalid key An internal representation was being converted to the symbol name, and an invalid component type was found. This occurs when a symbol table file is corrupt. Key for symbol <name> too long A symbol name, shown in name, was converted to the internal form. The result was longer than the maximum length. vm - Virtual Memory The vm module implements a buffering technique that is used by the module used to implement the symbol table files. This is the module that physically opens the symbol table files and performs the input and output to the files. Several of the errors include a name and error text. The name is the filename. It may the the right hand end of long file names. The text is the error text made using the errno from the C library routines. Error texts are :- Error text Remarks No such file or directory Too many open files Permission denied No such device File already exists Locking violation Appendix D Error Messages 107 errno = <num> If the error message is obscure or not likely to arise. num will be the value of errno when the failure occurred. Read error, file <name>, <text> An error occurred when performing a read from a symbol table file. Seek error, file <name>, <text> The error occurred when performing a seek, moving the file pointer in a symbol table file prior to a read or write. SHARE.EXE not loaded A region of a file was locked with the locking C library function. The return status indicated that the DOS program SHARE.EXE has not been loaded. This program has to be loaded before the locking functions will work. See the DOS SHARE command. Write error, file <name>, <text> An error occurred when writing a block to a symbol table file. Write error, file <name>, len != bufsize A write was performed, and the length returned was not equal to the amount requested. This will be the block size for the symbol table file. 108 Nadir Reference Manual INDEX Dump 55, 58 A E Addition operator + 43 argc 23, 40 Else 18, 83 Argument Elseif 18, 83 pass by reference 24, 40 Endif 18, 83 pass by value 23 Equality operators 44 argv 23, 38 Escape sequence 6 Assignment expression 45 Eval 17, 83 autoexec.bat 8 Exit 56, 96 Expansion rules 19 B Explode 56 Expression 34, 46 b-tree structure 85 evaluation 17 Boolean value 26 primary 37 Break statement 52 statement 49 Bunch 53 syntax 35 Expression evaluation 17 C F Case statement 51 Code string 6 FieldType 57 Collating sequence 28 FileClose 57 Command line 8 FileColumn 57 Comment 4, 19 FileDump 57 Compound statement 17, 47, 48 FileIndentSet 58 Condition Handler 96 FileLineGet 58 Conditional expression 45 FileOpen 57, 58, 84, 96 config.sys 8 FilePrint 59 Continue statement 52 FileRemove 60 Floating point number 7 D FloatToInt 60 For statement 51 Data directory 11 Function 22 Date format 82 arguments 22, 40 DateDay 53 call 39 DateDayName 53 return value 23 DateMonth 54 Function name 22, 39 DateMonthEnd 54 DateMonthName 54 G DateMonthStart 54 DateToday 55 Global symbol table 13 DateYear 55 Goto statement 52 Default statement 51 Default symbol tables 13 I Define 16, 22, 39, 47, 82, 83 Developer's Kit 1, 39, 53 If 18, 83 Division operator / 42 If statement 50 Do statement 50 Input file 4, 8, 9, 13, 14, DOS Share 8, 12, 108 20, 22, 47, 61, 63 DOS version 8, 66, 67, 76, 77, Integer 7 83 Intrinsic function 22 Index 109 K Parenthesis () 41 PreProcessSet 63 Keyword 4 prev operator 29, 41 redefining 16 Print 15, 60, 64 Process 65 L R Label statement 49 Level 60 Relational operators 43 Lexical analysis 20, 79, 97 Return statement 49 Lexical elements 4 Runtime version 8 LineCurr 20, 61, 62 LineGet 20, 61 S LineNum 63 Local value stack 12, 86 Signal 66, 74, 96 Local variable 12 Single user mode 12 Logical and operator && 44 Spawn 66 Logical negation operator ! 41 SpawnRestart 66 Logical operator 26 StrCat 67 Logical or operator || 45 StrFromAscii 67 Lvalue 38 StrFromLit 67, 72 StrFromQuoted 68 M String constant 6 Macro 22 literal 6 arguments 15 size 85 data symbol table 13 String concatenation operator . definition 16 43 library 10 StrLen 69 library symbol table 14 StrMatch 70 Macro data symbol table 11 StrPos 70 Macro name 16 StrSubs 71 Memory block 12 StrToAscii 71 Modulus operator % 42 StrToLit 68, 71 Multiplication operator * 42 StrToLower 72 StrToUpper 72 N Subscripting 27 function name 29 Name 4 symbol table name 29 next operator 29, 40 Subtraction operator - 43 Null statement 49 Switch statement 51 Null value 26 Symbol 13, 38 name 27, 84, 85 O table 27, 38, 84 value 85 Operand conversion rules 28, Symbol Table Utility 75, 88 31 SymClose 72, 74 Operand stack 12, 86 SymCreate 72 Operator 5 SymLock 73 precedence 35 SymLockQuery 74 Operators 34 SymOpen 72, 73, 74 Output file 8, 9, 55, 63, 64 SymRemove 75 OutputColumn 63 SysFileRecover 13 OutputIndentSet 63 System 76 SystemRestart 76 P SysType 77 Parameter symbol table 12, 14 Parameter value stack 86 110 Nadir Reference Manual T TaskNum 77 Temporary file directory 12 TimeNow 77 Token intrinsic functions 20 TokenNext 20, 77 TokenScanCreate 78 TokenScanDestroy 79 TokenTerm 79 TokenType 80 TokenValue 80 U Unary minus operator - 41 Unbunch 53, 80 Universal symbol table 12, 13 User written function 22 V Variable 26 date 25 float 25 integer 25 local 26 string 25 Variable types 24 W While statement 50 Whitespace 4, 14 Windows version 8, 12, 66, 76, 77, 83, 84 Index 111