.TH quake 1L \" -*- nroff -*- .SH Name quake \- a language and its interpreter for compiling assembling Modula-3 program descriptions .SH Synopsis .B quake [definitions | files ...] .SH Description This manual page documents quake. Quake is a simple, specialized language and its interpreter drawing on elements of the C language, the Bourne shell, and the C pre-processor. .LP Quake was designed to be a component of m3build(1)\-the replacement for m3make (q.v.). Building a complete, general-purpose language was not one of the goals. .LP m3build reads a set of quake language templates that define some operators, then executes an m3makefile in this context. The templates define procedures to build lists of modules, libraries, and so on. See the documentation for m3build for more details. .SS Values Quake is designed to make it easy to assemble arrays and tables of strings. The value space is strings, arrays of strings, and tables of strings. An array is a list of elements, and a table is a set of key/value pairs where the keys in a table are all distinct. .SS Strings A string is a sequence (delimited by `"') of characters excluding newline and double quote. Several special characters may be quoted (with `\\') as follows: .TP new-line ignored .TP \\\\\\\\\\\\\\\\ \\ .TP \\\\\\\\n new-line .TP \\\\\\\\r return .TP \\\\\\\\t tab .TP \\\\\\\\b backspace .TP \\\\\\\\f formfeed .TP \\\\\\\\" double quote .SS Arrays An array is constructed using `[' and `]'. `[]' is the empty array, `["a"]' is an array of the single string "a". Elements are separated by `,'. Thus `["a", "b"]' is an array of two elements---the strings "a" and "b". .LP Arrays are flattened whenever they are referenced. This means that `["a", ["b", "c"]]' is converted the the array `["a", "b", "c"]'. This means that an array can never be the element of another array. .LP Arrays are accessed by an integer index. `a[2]' is the third element of the array a. The index expression may also be a string which will be converted to an integer. The range of the index is checked at run-time. .SS Tables A table is constructed using `{' and `}'. `{}' is the empty table. Elements of a table are given as key/value pairs. An empty value may be omitted. `{"a", "b"}' is a table containing two keys---the strings "a" and "b". `{"p" : "q"}' is the constructor for a table with the single key "p" whose value is the string "q". Missing values are returned as "". .LP Tables are accessed using expressions of the form `s{"a"}'. This evaluates to the value of the key "a" in the table s. .SS Names Names in quake start with an letter (`a'..`z', `A'..`Z') or an underscore (`_'), followed by those characters, digits (`0'..`9'), hyphens (`-'), or periods (`.'). .LP If the lookup for a name fails (it is undefined in any of the enclosing scopes) it is installed in the current scope with an initial string value of the text of the name. .SS Comments C-style comments are supported (delimited by `/*' and `*/') and do not nest. .LP Single-line comments are introduced with `%' and terminated with a new-line. .SS Conditionals A Boolean value is represented as a string. The empty string is false, and any other string is true. .SS Expressions An expression is: .TP string: "baz" .TP name: foo .TP environment variable: $CPU_TYPE .TP array selector: array[5] .TP array constructor: ["a", "b"] .TP table selector: t{"a"} .TP table constructor: {"a" : "p", b} .TP function call: f(a, "b") .TP parentheses: a and (b or f(c)) .LP Operators are all left-associative, precedence is decreases from top to bottom in the following list. .TP & string catenation (`"Hello, " & foo') .TP contains table inclusion (`s contains "a"') .TP not logical negation (`not a') .TP and logical conjunction (`c and not d') .TP or logical disjunction (`a or b') .LP A note on string catenation. Operands of `&' are converted to strings whenever required and possible. Arrays and tables are converted to strings by catenating their elements (for tables, their keys) separated by a single spaces. For example, the expression .EX 5 "a" & " " & ["b", "c"] .EE evaluates to the string "a b c". .SS Statements A statement is either an assignment, a procedure definition, a procedure invocation, a conditional statement, or a loop. .SS Assignment Assign an expression (the string "bar") to the variable `foo' with .EX 5 foo = "bar" .EE If `foo' already exists, and is an array, then .EX 5 foo += "baz" .EE extends the array to include a new final element; the string "baz". .SS Scope Quake has a global name space, but local scopes are always introduced when a procedure is called, and a `foreach' loop is executed. .LP Scopes are searched from innermost to outermost each time a name is looked up. The outermost scope is always the global scope. .LP Assignments can be made local to the innermost scope by prefixing the assignment statement with the keyword `local'. For example, .EX 5 local foo = "bog" .EE In which case the values of any other instances of `foo' in other scopes are hidden. The previous value of `foo' is restored once the local scope is released by exiting the procedure or `foreach' loop. .LP To protect a name in the current scope, use .EX 5 readonly dec = "digital" .EE .SS Procedures Procedures may be defined in the global scope only. Here is the definition of a procedure `simple', taking two arguments bound to the local names `prefix' and `suffix' in the procedure's local scope. .EX 5 proc simple(prefix, suffix) is q = prefix & "." & suffix end .EE The string `prefix & "." & suffix' is assigned to the global variable `q'. .LP This procedure can then be invoked with .EX 5 simple("Hello", "m3") .EE Procedures can return values, in which case they become functions. For example, .EX 5 proc combine(prefix, suffix) is return prefix & "." & suffix end .EE defines a function `combine' which catenates and returns the three strings `prefix', ".", and `suffix'. Now the function `combine' can be used in an expression, for example .EX 5 q = combine("Hello", "m3") .EE assigns the string "Hello.m3" to `q'. .SS Conditional Statements Values may be tested using the `if' statement. For example, .EX 5 if compiling message = "compiling" end .EE If statements may have an else part, for example .EX 5 if not (ready or interested) return else message = "congratulations" end .EE returns from the current procedure if the test succeeds, otherwise executes the assignment statement. .SS Loops `Foreach' statements iterate over the string values in an array or in a table. For example, .EX 5 foreach file in [".login", ".profile", ".Xdefaults"] write("Copying " & file & " to " & backup_dir & "\n") copy_file(file, backup_dir) end .EE binds the name `file' to each of ".login", ".profile", and ".Xdefaults" in turn in a local scope. This example assumes that the procedures `copy_file', and the variable `backup_dir' have already been defined. `write' is .LP Here is a function `squeeze' to remove duplicates from an array .EX 5 proc squeeze(array) is local t = {} foreach i in array t{i} = "" end return [t] end .EE .SS Keywords Here is a list of reserved words in quake: .EX and contains else end foreach if in is local not or proc readonly return .EE .SS Built-in Procedures Quake has a small collection of built-in procedures. Built-ins cannot be redefined. The built-ins `write', `error', and `exec' are variadic. .TP write(...) Writes its arguments to the current output stream. Unlike the conversion of arrays to strings, there are no extra spaces inserted between arguments. .TP error(...) Writes its arguments to the standard error stream and stop running quake with an error return value. .TP include(file) The contents of `file' is interpreted by quake in place of the call to `include'. This is analogous the `#include' directive in the C preprocessor. Calls to `include' nest until you run out of file descriptors or something equally bad. .TP exec(...) The arguments are catenated and passed to the operating system to be executed as a child process. The command may start `-' or `@'. These are stripped before the command is passed to the command interpreter. A prefix of `@' indicates that the default action of printing the command to the standard output stream before execution should be overridden. A prefix character of `-' overrides quake's default action of aborting if it detects an error return code after executing the command. .SS Built-in Functions .TP arglist(pfx, array) This function may be used to avoid the problems of limited space for argument lists in some command interpreters. Some commands (notably `m3', the Modula-3 driver program) are prepared to accept arguments from a file. The syntax for this is `-Ffile'. .TP Thus, `arglist("-F", really_huge_array)' returns either the original array if it's not really all that huge, or it creates a temporary file containing a list of the strings in the array (one to a line) and returns the string "-Ftemp" where `temp' is the name of the temporary file. .TP defined(foo) Returns true if `foo' is defined, otherwise returns false. Remember that the Boolean values false and true are represented as empty and non-empty strings respectively. In this example, `foo' looks like a name, and is evaluated before begin passed to `defined'. So if you really want to find out whether `foo' is defined, use `defined("foo")'. .TP empty(foo) Returns true if the string, array, or table is empty, false otherwise. .TP equal(foo, bar) Returns true if the strings `foo' and `bar' are the equivalent. .TP path() Returns the directory of the currently executing file as a string. .TP stale(target, deps) `target' is interpreted as a file name, as is `deps' (or the elements of `deps' if it's an array). If the files `target' or `deps' cannot be found, or if (one of) `deps' is more recent than `target', `stale' returns true, otherwise false. .SS Output Redirection Sorry about the syntax for this. Suggestions (YACC permitting) welcome. .LP Output (from the `write' built-in procedure) may be temporarily redirected as follows: .EX 5 > "foo.txt" in write("Hello, world\n") end .EE The output of the calls to `write' is written to the file `foo.txt'. .LP Output may be appended to a file by using `>>' in place of `>'. .LP The special file names `_stdout' and `_stderr' are special and are bound to the file descriptors corresponding to normal and error terminal output respectively. .LP The default for output is the normal terminal stream. .SH Running Quake The syntax of the quake command is .EX 5 quake [definitions|files ...] .EE A definition has the form `-Dvar' or `-Dvar=string'. The first form defines `var' in the global scope of the program, the second form gives it a value. .LP Each file argument is executed as it is encountered. .SH Converting m3makefiles Old m3makefiles (m3makefiles used with the old m3make) work intact for the most part. The disgusting trick mentioned in the section on names takes care of that. The quake statement `module(foo)' means call the procedure `module' with the variable `foo' as an argument. This is more properly written `module("foo")', but this is incompatible with every existing m3makefile. .SH Notes Quake does not garbage collect. Reckless copying of large arrays can bloat the heap. .SH Author Stephen Harrison (harrison@src.dec.com). .SH See Also m3build(1)