plucky (7) icmscript.7.gz

Provided by: icmake_13.01.00-1ubuntu1_amd64 bug

NAME

       icmscript - The C-like icmake scripting language

DESCRIPTION

       Icmake(1)  is a generic tool handling program maintenance that can be used as an alternative for make(1).
       It’s a generic tool in that icmake-scripts, written in a language closely resembling  the  C  programming
       language, can perform tasks that are traditionally the domain of scripting languages.

       Icmake  allows  programmers to use a programming language (closely resembling the C-programming language)
       to define the actions that are required for  (complex)  program  maintenance.  For  this,  icmake  offers
       various  special  operators  as  well  as  a set of support functions that have shown their usefulness in
       program maintenance.

       This man-page covers the icmake scripting language in de following sections:

       o      DATA TYPES
              - int, list, string, and void (for functions);

       o      OUTLINE
              - outline of icmake scripts: what are their requirements, the structure and organization of  their
              main-functions.

       o      PREPROCESSOR DIRECTIVES
              - supported preprocessor directives, like #include and #define;

       o      PREDEFINED CONSTANTS
              - like O_FILE, OFF, and S_IFREG;

       o      OPERATORS
              - like +, younger, and casts

       o      FLOW CONTROL
              - if, for, while, etc. (the switch is not available);

       o      PREDEFINED FUNCTIONS
              -  executing  programs,  changing directories, operations on string and list type variables, etc..
              Functions are marked as INT FUNCTIONS, LIST FUNCTIONS, STRING FUNCTIONS

       o      USER DEFINED FUNCTIONS
              - at least main, with or without its common parameters argc, argv, and envp.

DATA TYPES

       Icmake supports the following five data and value types:

       o      ASCII character constants
              ASCII character constants are ascii-characters, surrounded by  single  or  double  quotes.  Single
              characters  (e.g., ’a’) represent the character itself. Standard escape sequences (e.g., ’\n’) are
              supported and are converted to their well-known values  (e.g.,  ’\n’  represents  ascii  value  10
              (decimal)).  Non-standard  escape  sequences  (e.g.,  ’\x’)  are  converted to the ascii character
              following the escape character (so ’\x’ equals ’x’). Escaped sequences consisting of  three  octal
              digits  represent  the  ascii character corresponding to the octal value, modulo 256 (e.g., ’\113’
              represents ’K’). Escape sequences consisting of an x followed by two hexadecimal digits  represent
              the ascii character corresponding to the hexadecimal value (e.g., ’\x4b’, also representing ’K’);

       o      int
              Integral  values,  ranging  from -0x8000 through 0x7fff. int constants may be specified as decimal
              numbers (starting with digits 1 through 9), octal numbers (starting with 0,  followed  by  one  or
              more  octal  digits),  hexadecimal  numbers (starting with 0x, followed by one or more hexadecimal
              digits), or as ASCII character constants;

       o      string
              Text values: text (or `string’) constants are delimited  by  double  or  single  quotes.  Multiple
              string  constants  may  be concatenated, but a single string constant may not span multiple lines.
              Multiple string constants, only separated by white space (i.e.,  blanks,  newlines,  comment)  are
              concatenated and are considered one single string constant. To indicate an end-of-line in a string
              constant use the \n escape sequence;

              If arithmetic expressions use at least one int operand then those  expressions  may  also  contain
              single  character ASCII constants using double or single quotes. In those cases they represent the
              ascii-values of their characters.

              Conversely, ASCII character constants using single quotes may be used in situations where   string
              operands are expected;

       o      list
              A  list  is  a data structure containing a series of individually accessible string values. When a
              list contains elements, its first element has index 0;

              Lists may be written to the standard output stream or to file (using printf or fprintf). Lists can
              also  be  inserted  into  string variables using the function strformat. In these cases all (space
              delimited) elements of the lists are inserted into their destinations;

              Lists can also be defined as constants. They consist of an  optional  series  of  comma  separated
              string constants surrounded by a pair of square brackets. E.g.,

                  list words = ["a", "list", "constant"];

       o      void
              The type void is used when defining functions which do not return values. Alternatively, functions
              may return int, string or list values (cf. section USER DEFINED FUNCTIONS).

       Variables can be defined at the global level and inside functions  (not  only  at  the  top  of  compound
       statements but also between statements and in the initialization section of for- and if-statements). When
       defined inside functions, the standard C scoping and  visibility  rules  apply.  Variables  are  strongly
       typed, and cannot have type void.

       Variables  may  be  initialized  when  they  are  defined.  Initializations are expressions which may use
       predefined or user-defined functions, constant values, and values of variables.  Functions  or  variables
       that are used for initialization must be visible at the initialization point.

OUTLINE

       Icmake  scripts  require  a  user-defined function main. The function main has three optional parameters,
       which may be omitted from the last one (envp) to the first one (argc), like in C. Its full prototype is:

           void main(int argc, list argv, list envp)

       or

           int main(int argc, list argv, list envp)

       When a void main function ends (using a return; statement  or  when  its  execution  reaches  its  body’s
       closing  curly) the value 0 is returned to the operating system. When int main functions end using return
       statements then those statements must be provided with int-expressions. It’s OK when the execution of  an
       int  main  function  reaches  its  body’s closing curly, in which case 0 is automatically returned to the
       operating system

       In main the parameter

       o      argc represents the number of elements in argv;

       o      argv contains the arguments, with element 0 being equal to the name of the .bim  file,  that  were
              passed  to  the .bim file. The OPTIONS section of the icmake(1) manpage covers how these arguments
              are forwarded to the icmake script using options -e, -s, and -t.

       o      envp contains the `environment’ variables. The function listlen  can  be  used  to  determine  the
              number  of  its  elements.  Elements  in  envp  use  the format variable=value. Alternatively, the
              (predefined) function getenv can be used to retrieve a specific environment variable immediately.

       Example (the implementations of the user-defined functions usage, modified, and compile are  left  as  an
       exercise for the reader):

           void main(int argc, list argv)
           {
               if (argc == 1)
                   usage(argv[0]);

               if (list toCompile = modified("*.cc"))
               {
                   for (int idx = listlen(toCompile); idx--; )
                       compile(toCompile[idx]);
               }
           }

       When  executing  an  icmake  script  icmake’s  run-time  support  system first initializes all all global
       variables in the order of their definitions. Following this the function main is called. The script  ends
       when main returns or when the function exit is called by the script.

PREPROCESSOR DIRECTIVES

       Before  actually  compiling  icmake scripts they are first pre-processed by the icmake pre-processor. The
       pre-processor removes comment, includes files specified by include-directives, and processes #define  and
       comparable directives.

       The following preprocessor directives are recognized:

       o      comment:
              standard  C comment (everything from /* through */) as well as comment-to-end-of-line (starting at
              //, continuing to the end of the line) is ignored;

       o      Shell startup: The first line of the icmake-script may start with #!path, where path  defines  the
              (usually  absolute)  location  of  the  icmake program. By making the script executable, it can be
              called without explicitly calling icmake.

              E.g., if the first line of an (executable) icmake script ’icm’ (without extension) contains

                  #!/usr/bin/icmake -t.

              then icm can be issued as a command, interpreting the remaining lines of the script as  an  icmake
              source  which  is compiled and then executed by icmake. The icmake(1) man-page’s section EXECUTING
              ICMAKE SCRIPTS covers the elements of the first line of icmake scripts.

       o      #include "filename"
              The file filename is included at the location of the directive;

       o      #include <filename>
              The file filename is included at the location of the #include directive; filename is  searched  in
              the  colon-separated directories specified by the IM environment variable. The first occurrence of
              filename in the directories specified by the IM environment variable is used;

       o      #define identifier [definition]
              The text identifier is replaced by definition. The definition may contain  references  to  already
              defined  identifiers,  using  the  syntax  ${identifier}. If the ${identifier} hasn’t been defined
              (yet), the literal text  ${identifier}  is  used.  To  prevent  infinite  recursion  at  most  100
              ${identifier} replacements are accepted;

              If  the  last  character  on a line is a backslash (\) then definitions continue at the next line.
              (the backslash is not included in the definition).  The  preprocessor  concatenates  double-quoted
              strings. Double quoted strings themselves may not span multiple lines. Multiple blanks (outside of
              double quoted strings) in definitions are contracted to a single space character;

              Following the #define’s identifier a definition may optional be provided. If omitted, the macro is
              defined,  so  it  can  be  used  in  #if(n)def  directives  (see  below), but in those cases these
              intentifiers are simply removed from icmake code statements.

       o      #ifdef identifier
              If the identifier macro was defined the next block of code  (until  a  matching  #else  or  #endif
              directive was read) is byte-compiled. Otherwise, the code block is ignored;

       o      #ifndef identifier
              If  the  identifier macro was not defined the next block of code (until a matching #else or #endif
              directive was detected) is byte-compiled. Otherwise, the code block is ignored;

       o      #else
              Terminates #ifdef and #ifndef code blocks, reversing the acceptance decision about  the  following
              code block. Only one #else directive can be associated with #if(n)def directives;

       o      #endif
              Terminates  the  code  block  starting  beyond  the  matching  #ifdef, #ifndef or #else directive.
              Associated #if(n)def, #else, and #endif directives must be specified in the same file;

       o      #undef identifier
              Remove identifier from the set of defined symbols. This does not affect the specification  of  any
              previously  defined  symbols  using  identifier’s  definition. If identifier hasn’t been defined a
              warning is issued.

PREDEFINED CONSTANTS

       The following predefined int constants are available (the functions listed in the intended for column are
       described in the upcoming sections covering the predefined functions):

       ─────────────────────────────────
       symbol      value   intended for
       ─────────────────────────────────
       O_ALL       8       makelist
       O_DIR       2       makelist
       O_FILE      1       makelist
       O_SUBDIR    4       makelist
       ─────────────────────────────────
       OFF         0       echo
       ON          1       echo
       ─────────────────────────────────
       P_CHECK     0       system calls
       P_NOCHECK   1       system calls
       ─────────────────────────────────
       S_IEXEC     32      stat
       S_IFCHR     1       stat
       S_IFDIR     2       stat
       S_IFREG     4       stat
       S_IREAD     8       stat
       S_IWRITE    16      stat
       ─────────────────────────────────

       The following constants are architecture dependent:

       ──────────────────────────────────────────────────────────────
       symbol           1 when defined on the platform, otherwise 0
       ──────────────────────────────────────────────────────────────
       unix             Unix, usually with GNU’s gcc compiler
       UNIX             may alternatively be available
       linux            x86 running Linux (usually with gcc)
       LINUX            may alternatively be available
       M_SYSV, M_UNIX   x86 running SCO/Unix
       _POSIX           _SOURCE   Unix with Posix compliant compiler
       __hpux           HP-UX, with the native HP compiler
       ──────────────────────────────────────────────────────────────

OPERATORS

       Since  icmake  version  10.00.00  the  <<  operator  can be used like the C++ insertion operator. See the
       description of the functions printf and fprintf below.

              int-operators:

       All C operators (including the ternary operator) are available (except for pointer operators,  as  icmake
       does  not  support  pointers).  They operate like their C-programming language’s counterparts. Comparison
       operators return 1 if the comparison is true, otherwise 0 is returned.

              string-operators:

       For string variables and/or constants the following operators are  available  (lhs  and  rhs  are  string
       variables or constants):

       o      lhs  +  rhs:  returns a new string value containing the concatenation of strings lhs and rhs. Note
              that string constants can also directly be concatetated (not using  the  +  operator),  e.g.,  the
              following two lines both define the string "hello world":

                  "hello "   "world"
                  "hello " + "world"

       o      lhs += rhs: lhs must be a string variable, to which the string variable or value rhs is appended;

       o      string  comparisons:  operators  ==  !=  <=  >=  < > != and == return 1 if the comparison is true,
              otherwise 0. The ordering operators (like < and >=) use the (case  sensitive)  character  ordering
              defined by the ASCII character set;

       o      !lhs:  the boolean ! (not) operator returns 1 if the string lhs is empty, otherwise 0 is returned.
              Strings merely containing white-space characters are not empty;

       o      lhs younger rhs, lhs newer rhs: returns 1 if  file  lhs  is  more  recent  than  file  rhs.  E.g.,
              "source.cc" newer "source.o". The files lhs and rhs do not have to exist:

              o      if both don’t exist 0 is returned,

              o      if lhs doesn’t exist 0 is returned,

              o      if rhs doesn’t exist, 1 is returned,

              o      if they are equally old 0 is returned.

              The function exists() (see below, section PREDEFINED FUNCTIONS) can be used to test whether a file
              exists;

       o      lhs older rhs: returns 1 if file lhs is older than file rhs. E.g., "libprog.a"  older  "source.o".
              The files lhs and rhs do not have to exist:

              o      if both don’t exist 0 is returned,

              o      if lhs doesn’t exist 1 is returned,

              o      if rhs doesn’t exist, 0 is returned,

              o      if they are equally old 0 is returned.

       o      []:  the  index  operator  returns  a  character  from  a string variable or constant. A string is
              returned as an rvalue. Thus, the following statement compiles OK:

                  lhs = rhs[3];

              but the following statement won’t compile (as lhs[3] is an rvalue):

                  lhs[3] = "a";

              If an invalid (out of bounds) index value is specified an empty string is returned.

       o      The backtick operator (`string cmd`)
              A string placed between two backticks is executed as a separate command. Different from  the  exec
              and  system  calls  the backtick operator collects the standard output produced by `cmd’ returning
              this output as a list.

              The elements of the list contain the subsequent lines of output (including  a  final  newline,  if
              present)  produced  by `cmd’. A command that could be executed but that did not produce any output
              returns a list containing one string element, which is empty.

              An empty list indicates that the command could not be executed.

              The command’s standard error stream output is ignored by the backtick operator. However,  standard
              shell redirection may be used to collect the standard error stream’s output.

              Example:

                  printf << `"ls"`;   // prints the elements in
                                      // the current directory

              Note  that  the backtick operator requires a string argument: either a string constant or a string
              variable.

              The function eval(string cmd) behaves exactly like the backtick operator: they are synonyms.

              list-operators:

       For list variables and/or values the following operators are available:

       o      lhs + rhs: returns a new list value containing the concatenation of the values of  lists  lhs  and
              rhs.  This  is  not  a set operation: if an element appears both in lhs and in rhs, then both will
              appear in the resulting list (set-addition is provided by the function listunion);

       o      lhs - rhs: returns a new list value containing the elements in lhs that are not  present  in  rhs.
              This is a set-difference operation. The ordering of the remaining elements in the returned list is
              equal to the ordering of those elements in lhs;

       o      lhs += rhs: elements in rhs are added to the elements in lhs, which must be a list variable.  This
              is not a set operation;

       o      lhs  -=  rhs:  elements in rhs are removed from the elements in lhs.  This is a set operation: all
              elements of lhs that are found in rhs are removed from lhs. The ordering of the remaining elements
              in lhs is not altered;

       o      list  equality  comparisons:  operators  !=  and  ==  may  be applied to list values or variables.
              Operator == returns 1 if both lists have element-by-element identical  elements,  otherwise  0  is
              returned. Operator != reverses the result of ==;

       o      !lhs: the boolean ! operator returns 1 if the list lhs is empty, otherwise 0 is returned;

       o      []:  the  index  operator  retrieves  an  element  from a list variable: it returns a string as an
              rvalue. Thus, the following statement compiles OK:

                  // assume lst is a list, str is a string
                  str = lst[3];

              but the following statement won’t compile (as lst[3] is an rvalue):

                  lst[3] = str;

              If an invalid (out of bounds) index value is specified an empty string is returned.

              casting:

       Type-casts using the standard C-style cast-operator can be used to cast:

       o      strings to ints and vice versa ((int)"123", (string)55)
              If the content of a string does not represent a (decimal) int value 0 the cast returns  0;

       o      Strings to lists (list lst = (list)"hello"): this returns a list having one element (hello)  (note
              that  casting  a  string  to a list as shown is overkill as list lst = ["hello"] performs the same
              initialization).

FLOW CONTROL

       Icmake offers a subset of C’s flow control statements. They can be used as in the C programming language.

       o      expression ;
              The plain expression statement.

              Insert-expression statements  are  defined  for  the  functions  fprintf  and  printf.  Expression
              statements  may  start  with  printf  <<  or  fprintf << filename <<. The values of all subsequent
              expressions, separated by << operators (which in this context are called insertion operators)  are
              written  to  the  standard  output  stream  (when  using  printf <<), or to the file whose name is
              provided in the string filename (when using fprintf << filename <<).  Examples:

                  printf << "hello" << ’ ’ << "world" << ’\n’;
                  fprintf << "out.txt" << "hello" << ’ ’ << "world" << ’\n’;

       o      The compound statement
              Variables may be defined and initialized inside compound statements at locations where  expression
              statements can also be used. The visibility of variables starts at their points of definition;

       o      if ([definition;] condition) statement
              The [definition;] phrase is optional. If used it defines a type followed by a comma-separated list
              of variables which may be provided with initialization expressions.

              The condition phrase is required, and may define and initialize a variable. E.g,

                  if (string str = getText())
                      process(str);

              In this example, process is not called if getText() returns an empty string.

              Variables defined in the definition and condition phrases do not exist either before or after  the
              if statement.

       o      if ([definition;] condition) statement1 else statement2
              Acts  like  the  previous  statement.  If  the  condition  is  true statement1 is executed; if the
              condition is false statement2 is executed;

       o      for (init; condition; increment) statement
              Variables (of a single type) may be initialized (and optionally defined) in the init section.  The
              condition  phrase may define and initialize a variable. The init, condition and increment sections
              may remain empty. An empty condition section is interpreted as `always true’;

       o      while (condition) statement
              Inside the condition a variable may be defined and initialized.

              A complementary do ... while() statement is not available. Note that when a  variable  is  defined
              and  initialized  in  the  condition  section  the  initialization  expression is executed at each
              iteration of the while statement. Thus the following statement never ends, and  displays  a  never
              ending stream of values 10:

                  while (int x = 10)
                      printf(x--, "\n");

       o      return;, and return expression;
              Plain  return  statements can be used in void functions, and return expression statements are used
              in other type of functions.

       o      break
              break; statements can only be used in for and while statements, ending those statements;

       o      continue
              continue; statements can only  be  used  in  for  and  while  statements,  continuing  their  next
              iteration.

PREDEFINED FUNCTIONS

       Icmake  provides the following predefined functions, which can be used anywhere in icmake scripts. In the
       following overview the functions are ordered by  categories,  and  within  categories  they  are  ordered
       alphabetically by function name.

       Five categories are distinguished:

       o      Functions operating on ints (see INT FUNCTIONS below):
              these functions receive int arguments, processing those arguments;

       o      Functions operating on strings (see STRING FUNCTIONS below):
              these functions operate on the strings which are passed to these functions as arguments;

       o      Functions operating on lists (see LIST FUNCTIONS below):
              these functions operate on the lists which are passed to these functions as arguments;

       o      Functions manipulating file system entries (see FILESYSTEM FUNCTIONS below):
              these  functions  receive  the  names  of  file-system entries (files, directories, etc.) as their
              string arguments.

              Note that these functions are not listed in the STRING FUNCTIONS section, as they do not  directly
              operate on their string arguments, but merely use those arguments to identify file system entries.

              On  the  other  hand,  functions  like  change_base  do not operate on file-system entries and are
              therefore entries in the STRING FUNCTIONS section;

       o      System-related functions (see SYSTEM FUNCTIONS below):
              these functions interface to facilities provided by the operating system, like executing  programs
              or  changing  the  script’s environment variables. Some of these functions use specialized support
              functions, which are also included in this section.

              INT FUNCTIONS:

       o      string ascii(int value)
              returns value as a string: ascii(65) returns the string "A";

       o      echo(int opt)
              controls echoing of called  programs  (and  their  arguments),  specify  OFF  if  echoing  is  not
              requested. By default echo(ON) is active.

              STRING FUNCTIONS:

       o      int ascii(string str)
              returns the first character of str as an in: ascii("A") returns 65;

       o      string change_base(string file, string base)
              returns  file  whose  base  name is changed into base: change_base("/path/demo.im", "out") returns
              "/path/out.im";

       o      string change_ext(string file, string ext)
              returns file whose extension is changed into ext: change_ext("source.cc", "o") returns "source.o".
              The extension of the returned string is separated from the file’s base name by a single dot (e.g.,
              change_ext("source.", ".cc") returns "source.cc");

       o      string change_path(string file, string path)
              return file whose  path  is  changed  into  path:  change_path("tmp/binary",  "/usr/bin")  returns
              "/usr/bin/binary". To remove the path specify path as an empty string;

       o      string element(int index, string var)
              acts identically to the index operator: refer to the index ([]) operator in section OPERATORS;

       o      string get_base(string file)
              returns  the  base name of file. The base name is the file without its path prefix and without its
              extension. The extension is all information starting at the final dot in the filename. If no final
              dot  is  found, the file name is the base name. E.g., the base name of a.b equals a, the base name
              of a.b.c equals a.b, the base name of a/b/c equals c;

       o      string get_dext(string file)
              returns the extension of file, including the separating dot (hence the d in dext).  The  extension
              is all information starting at the filename’s final dot. If file does not have a final dot then an
              empty string is returned;

       o      string get_ext(string file)
              returns the extension of file, without the separating dot. The extension  are  all  characters  in
              file starting at file’s final dot. If no final dot is found, an empty string is returned;

       o      string get_path(string file)
              returns  file’s  path-prefix.  The  path prefix is all information up to (and including) the final
              directory separator (which is, depending on the operating system, a forward slash or a backslash).
              If file does not contain a path-element, then an empty string is returned;

       o      string  resize(string  str,  int  newlength)  returns  a  copy of string str, resized to newlength
              characters.  If newlength is negative then an empty string is returned, if newlength exceeds str’s
              length then the newly added characters are initialized to blank spaces;

       o      int strchr(string str, string chars)
              returns  the  first  index in str where any of the characters in chars is found, or -1 if str does
              not contain any of the characters in chars;

       o      int strfind(string haystack, string needle)
              returns index in haystack where needle is found, or -1 if needle is not found in haystack;

       o      string strformat(string format, argument(s))
              returns a string constructed from the format string containing placeholders %1 .. %2 to  refer  to
              arguments following the format string. The specification %1 refers to the first argument following
              the format string. If fewer arguments than n are provided then additional 0 arguments are provided
              by icmake. Example:

                  void main()
                  {
                      string s2 = = strformat("%1 %2 %1\n", 10, 20);
                      printf("s2 = ", s2);        // shows: s2 = 10 20 10
                  }

       o      int strlen(string str)
              returns the number of characters in str (not counting the terminating NUL-character);

       o      string strlwr(string str)
              returns a lower-case duplicate of str;

       o      list strtok(string str, string separators)
              returns  a list containing all substrings of str separated by one or more (consecutive) characters
              in separators: strtok("hello icmake’s+world", " +") returns a list containing  the  three  strings
              "hello", "icmake’s", and "world";

       o      string strupr(string str)
              returns an upper-case duplicate of str.

       o      string substr(string text, int offset, int count)
              returns a substring of text, starting at offset, consisting of count characters. If offset exceeds
              (or equals) the string’s length or if count <= 0, then an empty string is returned. If  offset  is
              less  than  0  then offset = 0 is used. If offset + count exceeds text’s length then the available
              substring starting at text[offset] is returned (which may be empty);

       o      string trim(string str)
              returns a copy of str without leading and trailing white spaces;

       o      string trimleft(string str)
              returns a copy of str without leading white spaces;

       o      string trimright(string str)
              Returns a copy of str without trailing white spaces.

              LIST FUNCTIONS:

       o      string element(int index, list var)
              acts identically to the index operator: refer to the index ([]) operator in section OPERATORS;

       o      int listfind(list lst, string str)
              returns the smallest index in lst where the string str is found, or -1 if  lst  does  not  contain
              str;

       o      int listlen(list l)
              returns the number of elements in list;

       o      list listunion(list lhs, list rhs)
              returns  a  list containing the union of the elements in lhs and the elements of rhs. The original
              order of the elements in lhs is kept. Subsequent elements in rhs that are not available in lhs are
              added to the end of lhs;

       o      list listunion(list lst, string str)
              returns  a  list  containing  the  union of the elements in lst and str. The original order of the
              elements in lhs is kept. If rhs is not available in lhs then it is added to the end of lhs.

              FILESYSTEM FUNCTIONS:

       o      string chdir([int check,] string dir)
              changes the script’s working directory to dir (which may be specified as absolute or  relative  to
              the  script’s  current working directory). The first argument is optional: if omitted and changing
              the working directory fails then the icmake-script ends with exit value 1; by specifying P_NOCHECK
              the function won’t terminate the script but merely returns the script’s current working directory.
              The script’s working directory after completing the change-dir request is returned as an  absolute
              path, ending in a `/’ directory separator.

              Use  chdir(".") to merely obtain the current working directory; use chdir("") to change-dir to the
              script’s startup working directory;

       o      int exists(string file)
              if file exists, 1 is returned, otherwise 0 is returned;

       o      list fgets(string file, list offset)
              the next line found at offset value offset[3] is read from file. Pass an empty list  to  fgets  to
              read file from its beginning.

              The returned list has four elements:

              o      its first element ([0]) contains the read line (without the line’s \n line terminator);

              o      its  second element ([1]) contains the line’s \n line terminator (or an empty string if the
                     line was not terminated by a \n);

              o      its third element ([2]) contains the string OK if the line was successfully read  and  FAIL
                     if reading from file failed;

              o      its fourth element ([3]) contains the offset beyond the last read byte.

              To read multiple lines, pass the returned list as argument to fgets:

                  list ret;
                  while (ret = fgets("filename", ret))
                      process(ret);

              Be careful not to define list ret in while’s condition, as this will reset ret to an empty list at
              each iteration;

       o      int fprintf(string filename, argument(s))
              appends all (comma or left-shift (insertion) operator separated) arguments to the  file  filename.
              Returns the number of printed arguments.

              If  the  first  argument  (following  filename)  contains  placeholders (%1, %2, ... %n) then that
              argument is considered a format string (see also the function strformat in  the  string  functions
              section for additional information about format strings). Some examples:

                  fprintf("out", "hello", "world", ’\n’);
                  fprintf << "out" << "hello" << "world" << ’\n’;

                  fprintf("out", "%1 %2\n", "hello", "world");           // 1
                  fprintf << "out" << "hello" << ’ ’ << "world" << ’\n’; // 2
                  fprintf << "out" << "%1 %2\n" << "hello" << "world";   // 3

              When  writing  statement  1 using insertion operators (cf. the expression statement description in
              section FLOW CONTROL)  statement 2 would normally be encountered, although statement 3, using  the
              format string, would still be accepted;

       o      string getch()
              returns  the  next pressed key as a string (pressing the `Enter’-key is not required). The pressed
              key is not echoed. If the key should be echoed use, e.g., printf(getch());

       o      string gets()
              returns the next line read from the keyboard as a string. The line contains all entered characters
              until  the  `Enter’-key  was pressed. The `Enter’-key’s value itself is not stored in the returned
              string;

       o      list makelist([int type = O_FILE], string mask)
              the argument type is optional, in which case O_FILE is used.  Makelist returns a list of all  type
              file-system  entries  matching  mask.  E.g.,  makelist("*.c")  returns a list containing all files
              ending in .c. For type one of the following set of values can be used to obtain  a  more  specific
              selection of directory entries:

              symbol     meaning
              O_ALL      obtain all directory entries
              O_DIR      obtain all directories, including . and ..
              O_FILE     obtain a list of regular files
              O_SUBDIR   obtain all directories except for . and ..

              In  Unix-type  operating  systems the pattern * does not match entries starting with a dot (hidden
              entries). To obtain a list of such entries use the pattern .*;

       o      list makelist([int type = O_FILE,] string mask, {newer,older,younger}, string comparefile)
              the (optional) parameter type may be specified as in the previous variant of makelist.  The  third
              parameter  must  be either newer (or younger) or older. A list of all file-system entries matching
              mask which are, resp., newer or older than a provided comparefile is returned. Note that newer and
              younger are operators, not strings;

       o      int printf(argument(s))
              the  function’s  (comma or left-shift (insertion) operator separated) arguments are written to the
              standard output file (cf.  the expression statement description in section FLOW CONTROL  and  this
              section’s  description  of  the  fprintf  function). If the first argument contains %1, %2, ... %n
              specifications then it’s considered a format string (see also the function strformat in the STRING
              FUNCTIONS  section  for  additional information about format strings). Like fprintf printf returns
              the number of printed arguments;

       o      list stat([int check,] string entry)
              Returns stat(2) information of directory entry entry as a list. The first argument is optional: if
              omitted  and calling the system stat function fails then the icmake-script ends with exit value 1;
              by specifying P_NOCHECK the function won’t terminate the script but returns the return value  (-1)
              of the system stat function.

              The returned list has two elements:

              its  first  element  ([0]) holds the entry’s attributes.  Attributes are returned as the file type
              and mode of the specified file (cf. stat(2) and inode(7)). E.g.,

                  S_IRUSR  - owner has read permission
                  S_IWUSR  - owner has write permission
                  S_IXUSR  - owner has execute permission

                  S_IFSOCK - socket
                  S_IFLNK  - symbolic link
                  S_IFREG  - regular file
                  S_IFBLK  - block device
                  S_IFDIR  - directory
                  S_IFCHR  - character device
                  S_IFIFO  - FIFO

              its second element ([1]) contains the entry’s size  in  bytes.  If  P_NOCHECK  was  specified  and
              ’entry’ doesn’t exists then a list having one element is returned containing -1.

              SYSTEM FUNCTIONS:

       o      void arghead(string str)
              support  function  of  exec() (see also below at exec()): defines the `argument head’ that is used
              with exec(). By default, the `argument head’ is an empty string. The argument head is text that is
              prefixed to all exec arguments, like a directory in which provided arguments are found;

       o      void argtail (string str)
              support  function  of  exec() (see also below at exec()): defines the `argument tail’ that is used
              with exec(). By default, the `argument tail’ is an empty string. The argument tail is text that is
              appended to all exec arguments, like the extensions of files that are passed as arguments to exec;

       o      cmdhead(string str)
              support function of exec() (see also below at exec()).  Defines a `command head’ that is used with
              exec(). By default it is an empty string. It can be used to specify, e.g., compiler  options  when
              the  arguments themselves are modified by arghead and argtail.  The cmdhead argument itself is not
              modified by arghead or argtail;

       o      cmdtail(string str)
              support function of exec() (see also below at exec()).  Defines a `command tail that is used  with
              exec(). By default it is an empty string. It can be used to specify a final argument (not modified
              by arghead and argtail);

       o      list eval(string str)
              this function can be used instead of the backtick operator (cf. section  OPERATORS).  The  example
              provided with the backtick operator could therefore also have been written like this:

                  printf << eval("ls");   // prints the elements in the current
                                          // directory

              As  mentioned  at  the backtick operator: the elements of the list contain the subsequent lines of
              output (including a final newline, if present) produced by `cmd’. A command that could be executed
              but that did not produce any output returns a list containing one string element, which is empty.

              An empty list indicates that the command could not be executed.

       o      int exec([int check,] string cmd, argument(s))
              Executes  the  command  cmd  with  (optional)  arguments. Each argument is prefixed by arghead and
              postfixed by argtail. Note that no blanks are inserted between arghead, argument(s), and  argtail.
              The  thus  modified  arguments  are  concatenated, separated by single blanks. Cmdhead is inserted
              between cmd and the first argument (delimited by single blanks) and cmdtail  is  appended  to  the
              arguments, separated by a single blank. PATH is searched to locate cmd. 0 is returned.

              The  first  argument  is  optional: if omitted and the command does not return 0 the icmake script
              terminates. By specifying P_NOCHECK exec  won’t  terminate  the  script  but  returns  the  called
              command’s exit status, or 0x7f00 if the command wasn’t found.

              The remaining arguments may be ints, strings or lists. Int and list arguments are cast to strings.
              Their string representations are then appended to cmd;

       o      int execute([int checking,] string  cmd,  string  cmdhead,  string  arghead,  argument(s),  string
              argtail, string cmdtail)
              Same  functionality  as  the previous function, but the cmdhead, arghead, argtail, and cmdtail are
              explicitly specified (and are reset to empty strings after executing cmd);

       o      exit(expression)
              Ends the execution of an icmake-script. The expression must evaluate to an  int  value,  which  is
              used as the script’s exit value;

       o      list getenv(string envvar)
              returns the value of environment variable envvar in a list containing two elements:

              if the first element ([0]) is "1" then the environment variable was defined;

              environment  variables  are  of  the form variable=value.  If element [0] is "1" then the returned
              list’s second element [1] holds the value part of the environment variable, which is empty if  the
              environment variable is merely defined;

       o      int getpid()
              returns the process-id of the icmake byte code interpreter icm-exec;

       o      int putenv(string envvar)
              adds or modifies envvar to the current icmake-script environment. Use the format: "VAR=value". Use
              "VAR" to remove "VAR" from the environment. The function returns 0  unless  envvar  is  empty,  in
              which case 1 is returned;

       o      int system([int check,] string command)
              executes  command  using  the  system(3)  function. The first argument is optional: if omitted and
              calling the system(3) function does not return 0 then the icmake-script ends with exit value 1; by
              specifying  P_NOCHECK  icmake’s  system function won’t terminate the script but returns the return
              value of the system(3) function (normally the executed command’s exit value). The  string  command
              may use redirection and/or piping.

USER DEFINED FUNCTIONS

       In  addition  to  main  additional  functions  can  be defined. Once defined, they can be called. Forward
       referencing of either variables or functions is not supported, but calling functions recursively  is.  As
       function declarations are not supported indirect recursion cannot be used.

       Function overloading (based on differently typed parameters) is supported.

       User-defined functions must have the following elements:

       o      The function’s return type, which must be void, int, string or list. There is no default type;

       o      The function’s name, e.g., compile;

       o      A  parameter  list,  defining  zero  or more comma-separated parameters. The parameters themselves
              consist of a type name (int, string, or  list)  followed  by  the  parameter’s  identifier.  E.g.,
              (string outfile, string source);

       o      A body surrounded by a pair of curly braces ({ and }).

       Function  bodies may contain variable definitions (optionally initialized at their definitions). Variable
       definitions start with a type name, followed by one or more comma separated  and  optionally  initialized
       variable identifiers.

       If  a  variable is not explicitly initialized it is initialized by default: int variables are initialized
       to 0, string variables are initialized to empty strings ("") and list variables are initialized to  empty
       lists.

       Function  bodies may also contain zero or more statements (cf. section FLOW CONTROL). Note that variables
       may be defined (and optionally initialized) anywhere inside functions where expression statements can  be
       used,  and  also  in  the  condition  sections of if, for, and while statements and in the initialization
       sections of if andd for statements.

EXAMPLE

       In the following example all C++ source files in the current directory are compiled unless  their  object
       files are more recent. The main function creates a list of source files and then passes each of them to a
       function inspect. That function inspects whether the source file is younger than its object file, and  if
       so  it  calls  compile.  The  function compile uses exec to call the compiler. If a compilation fails the
       script stops so the error can be repaired.
           void compile(string src)
           {
               exec("g++ -c " + src);      // compile ’src’
           }

           void inspect(string src)
           {                               // get the obj-file’s name:
                                           // only compile if necessary
               if (src younger change_ext(src, ".o"))
                   compile(src);
           }

           int main()
           {                               // find all .cc source files
               list sources = makelist("*.cc");

               for (                       // visit all source files
                   int idx = 0, end = listlen(sources);
                       idx != end;
                           ++idx
               )
                   inspect(sources[idx]);  // compile if needed
           }

SEE ALSO

       icmake(1), icmbuild(1), icmconf(7), icmstart(1), icmstart.rc(7)

BUGS

       Standard comment starting  on lines containing preprocessor  directives  may  not  extend  over  multiple
       lines.

       Path names containing blanks are not supported.

       This is free software, distributed under the terms of the GNU General Public License (GPL).

AUTHOR

       Frank B. Brokken (f.b.brokken@rug.nl).