Provided by: icmake_9.02.06-1_amd64 bug

NAME

       icmake - A program maintenance (make) utility using a C-like grammar

SYNOPSIS

       icmake [options] source[.im] [dest[.bim]] [-- [args]]

       icmun bimfile

DESCRIPTION

       Icmake(1)  was  designed  as a generic tool that can be used as an alternative to make(1),
       handling program maintenance. 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 well-known
       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.

       Although  icmake-scripts  can  be  written  from scratch for handling program maintenance,
       often the required activities are highly comparable.  This  observation  resulted  in  the
       construction  of  two  icmake-scripts:  icmstart(1),  initializing a directory for program
       development and icmbuild(1), handling the actual program maintenance. Both come predefined
       as  scripts  tailored  to  initializing  and  maintaining  C++ programs (or, after minimal
       adaptation, C programs), but can easily be adapted to other  programming  languages.  Both
       icmstart and icmbuild can be run without explicitly calling icmake.

       This  man-page  covers  icmake  (the  program),  its  support  programs and the syntax and
       facilities offered by icmake’s scripting language. Refer to the icmstart(1)) man-page  for
       information about how a directory can be initialized (created) in which (by default) a C++
       or C program can be developed and refer to the icmbuild(1) man-page for information  about
       how icmbuild can be used to handle program maintenance.

       It  should  be  stressed  that icmake and its support programs and scripts do not offer an
       Integrated Development Environment (IDE). It merely performs tasks for which  scripts  can
       be  written,  and  it  offers  just a few pre-defined scripts (icmstart and icmbuild) that
       repeatedly have shown to be extremely useful when developing and maintaining programs.

       In its standard operation mode, icmake calls the following programs:

       o      icm-pp  to preprocess the icmake file

       o      icm-comp   to byte-code compile the icmake  s

       o      icm-dep to handle class-dependencies (see section ICM-DEP in icmbuild(1)’s man-page
              for more information about icm-dep).

       o      icm-exec   to execute the byte-code file

       The  program icmun(1) can be used to disassemble the compiled byte-code (.bim) file. Icmun
       is mainly used for illustration, education, and debugging.  As  it  is  not  required  for
       icmake’s  daily  use  it is not installed in a standard PATH directory but (since icmake’s
       version 9.02.00) in icmake’s lib directory, commonly /usr/lib/icmake.

       Traditional  make-utilities  recompile  sources  once  header  files  are  modified.  When
       developing  C++  programs this is often a bad idea, as adding a new member to a class does
       not normally require you to recompile all of the class’s source  files.  To  handle  class
       dependencies icmbuld(1) may inspect class dependencies, (re)compiling sources of dependent
       classes whenever necessary.  By default, class-dependencies are not interpreted, but  this
       can  easily  be changed by activating the PRECOMP and/or USE_ALL defines in icmconf. Refer
       to the icmconf(7) man-page for further details.

       Precompiled header files can also easily be used. Precompiled  header  files  dramatically
       reduce  the  time  that  is  required  for  compiling  classes’ source files. Refer to the
       icmconf(7) man-page (in particular the description of  the  PRECOMP  define)  for  further
       details.

       Icmake’s   C-like  scripting  language  is  described  in  the  upcoming  sections of this
       man-page:

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

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

       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.;

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

OPTIONS

       Where  available,  single  letter  options  are  listed  between  parentheses beyond their
       associated long-option variants.

       The -- option is special:

       o      --: icmake arguments separator separating icmake arguments from arguments passed to
              the  .bim  filenl().  Those  arguments  are  passed to the .bim file as-is, and are
              available from the list argv parameter available  from  the  icmake  script’s  main
              function’s second parameter (see below at section USER DEFINED FUNCTIONS). For some
              options (see below) the -- separator is not required.

       Icmake supports various options, and only one of these can be  specified  when  icmake  is
       invocated.

       o      --about (-a)
              Show information about icmake and terminate.

       o      --compile (-c)
              The icmake source file is compiled, generating a .bim file.

       o      --execute (-e)
              Execute the icmake .bim file, given as icmake’s first file argument. Any additional
              arguments are passed to the .bim file as-is, and -- should not be specified.

       o      --force (-f)
              The icmake source file is recompiled (even if the .bim file is  up-to-date)  either
              when  no  other options are specified, or when in combination with options --source
              and --tmpbin.

       o      --help (-h)
              Provide usage info and terminate.

       o      --icm-dep (-d)
              Calls /usr/lib/icmake/icm-dep, passing it all remaining arguments. If no additional
              arguments  are  specified  icm-dep’s  short  usage information is shown to the std.
              output stream. See section ICM-DEP in icbuild(1)’s man-page  for  more  information
              about  the  icm-dep support program. An overview of icm-dep’s option follows below,
              next to this overview of icmake’s options.

       o      --preprocess (-p)
              The icmake source file is only preprocessed, and the preprocessed file  is  written
              to icmake’s second file argument (by default `source’.pim).

       o      --source (-i)
              The  first  argument  is  the  icmake  source  file,  the  default  binary  file is
              constructed if necessary. Any additional arguments are  passed  to  the  .bim  file
              as-is, and -- should not be specified.

       o      --summary (-F)
              The  filenames  and  flags as well as an overview of all actions to be performed by
              icmake are shown on the standard output stream.

       o      -t tmpbim
              The tmpbim argument following -t is the name of a temporary  .bim  file,  which  is
              removed  after  icmake’s  call.  When  .  is  specified for tmpbim then the default
              temporary directory, followed by icmake’s process-id, followed by .bim is used.

              Following the name of the temporary .bim file the name of the icmake source  script
              must  be specified. Any additional arguments are passed to the .bim file as-is, and
              -- should not be specified; After setting the source script file’s executable  flag
              (chmod +x script), and providing it with an initial line like this:

                  #!/usr/bin/icmake -t.

              the icmake script can directly be called:

                  script arg1 arg2

              in  which  case  the  icmake  script  `script’  is  executed  while it receives the
              arguments script arg1 arg2.

       o      -T directory
              The specified directory is used to store temporary files. E.g., when  compiling  an
              icmake  script,  the  output  of icmake’s preprocessor is a temporary file which is
              removed on exit. By default /tmp is used, unless /tmp is not a writable  directory,
              in  which  case  the  current  user’s  $HOME  directory is used. Implicit temporary
              filenames always start with the process id of the current icmake process.

       o      --version (-v)
              Displays icmake’s version number, and terminates.

       Icmun:

       bimfile:  binary icmake script file.

ICM-DEP invocation and options

       To start its work, the dependencies-analyzer icm_dep needs one command-line argument:  go.
       Any  other  argument  results  in  icm_dep performing a `dry run’: it will perform all its
       duties (and verbose messages are displayed as if go had  been  specified),  but  no  files
       (precompiled  headers or USE_ALL files) will be touched or removed. If neither options nor
       arguments are specified icm_dep writes its usage summary to the standard output.

       Options of icm-dep can be specified immediately following icmake’s --icm-dep  option.  The
       following options are recognized by icm-dep:

       o      --classes=filename (-c)
              By  default,  icm-dep  inspects  dependencies  of the classes whose directories are
              mentioned in the file CLASSES. If specified in the icmconf(7) file,  it  will  also
              consider  dependencies  of  the  classes  Parser  (directory  parser)  and  Scanner
              (directory scanner), or it uses their actual names as  defined  in  the  icmconf(7)
              file. Use this option if instead of CLASSES another file should be inspected.

       o      --help (-h)
              Icm-dep writes a summary of its usage to the standard output and terminates.

       o      --icmconf=filename (-i)
              By  default  icm-dep  inspects  the  contents  of  an icmconf file, looking for the
              USE_ALL and PRECOMP specifications. Use this option if instead of  icmconf  another
              file should be inspected.

       o      --mainih=mainheader (-m)
              The  icmconf  file  uses  the  #define  IH parameter to specify the suffix of class
              header files that should be precompiled, their filenames being equal to  the  names
              of  the classes mentioned in the CLASSES file. CLASSES does not specify a top-level
              directory. The name of the top-level header file to  precompile  can  be  specified
              using this option. By default it is main.ih.

       o      --gch
              By  default  precompiled  header  files are inspected if icmconf contains a #define
              PRECOMP specification. If it does not, but precompiled headers  should  nonetheless
              be inspected, the option --gch can be specified.

       o      --no-gch
              By  default  precompiled  header  files are inspected if icmconf contains a #define
              PRECOMP specification. If so, but precompiled headers should not be inspected,  the
              option --no-gch can be specified.

       o      --no-use-all
              By  default  files  named  at  the  #define  USE_ALL specification are inspected if
              icmconf contains such a specification. If it does, but the `USE_ALL’  files  should
              not be inspected, this option can be specified.

       o      --use-all=filename
              By  default  files  named  at  the  #define  USE_ALL specification are inspected if
              icmconf contains such a specification. If it does not, but `USE_ALL’  files  should
              nonetheless  be  inspected, this option can be specified, together with the name of
              files (existing in one or more directories that indicate that all  the  directory’s
              source files must be recompiled).

       o      --verbose (-V)
              This  option  can  be specified multiple times. The number of times it is specified
              defines icm_dep’s verbosity. If none is specified, icm_dep  silently  performs  its
              duties. If specified once, then icm_dep reports to the standard output what actions
              it performs; if specified twice it reports the options it encountered; if specified
              three  times  it  also  reports  the class dependencies; if specified more often it
              reports what files it encountered  and  what  situations  caused  it  to  make  its
              decisions.

       o      --version (-v)
              Icm_dep reports  its version number to the standard output and terminates.

PREPROCESSOR DIRECTIVES

       The following preprocessor directives are available:

       o      comment:
              standard  C  comment (all between /* and */) as well as comment-to-end-of-line (all
              line contents following //) are ignored.

       o      Shell startup: The first line of the icmake-script may  start  with  #!path,  where
              path  defines  the  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)  icmakefile  ’icm’  (without  extension)
              contains

                          #!/usr/bin/icmake -i

              then icm may be issued as a command, thus executing

                          /usr/bin/icmake -i icm ...

              Alternatively,

                          #!/usr/bin/icmake -t /tmp/icm

              may be used, resulting in the execution of

                          #!/usr/bin/icmake -t /tmp/icm icm ...

              In this case the binary file is removed on exit.

       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 will be replaced by  definition.  The  definition  may  contain
              references  to  already defined identifiers, using the ${identifier} format. If the
              ${identifier} hasn’t been defined (yet), the text ${identifier} is literally  kept.
              To prevent infinite recursion at most 100 ${identifier} replacements are allowed.

              Definitions  continue  at  the  next  line  if  the  last  character on a line is a
              backslash (\).  (which  is  not  included  in  the  definition).  The  preprocessor
              concatenates double-quuted strings, and double quoted strings may not span multiple
              lines. Multiple blanks (outside  of  double  quoted  strings)  in  definitions  are
              contracted to a single blank space.

              The  definition  following  the  #define’s  identifier is optional. If omitted, the
              macro is defined, so it can be used in #if(n)def directives (see below),  but  they
              are not replaced by any text in 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  block  of  code  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  block  of
              code is ignored.

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

       o      #endif
              Terminates the preprocessor block starting at the matching #ifdef, #ifndef or #else
              directive. The #endif directory  and  its  matching  #if(n)def  directive  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 in  which  identifier’s  definition
              has been used. If identifier hasn’t been defined a warning is issued.

DATA TYPES

       Icmake supports these data types:

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

       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  variables.  String  constants are delimited by double quotes. Multiple string
              constants may be concatenated, but a single string constant may not  span  multiple
              lines.  String  constants  separated  by  white space only (i.e., blanks, newlines,
              comment) are concatenated and represent one single string constant. To indicate  an
              end-of-line in a string constant use the \n escape sequence.

              ASCII  character  constants  surrounded  by  double  quotes  can  also  be  used in
              arithmetic expressions if one of the operands  is  an  int.  The  single  character
              string constant must be a constant, and cannot be a string variable.

              Likewise,  ASCII  character  constants  surrounded  by single quotes may be used in
              situations where a string operand is expected.

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

       o      void
              Used  with  function  definitions  to  indicate that the function does not return a
              value.

       Variables can be defined at the global  level  as  well  as  at  any  local  level  inside
       functions.  When  defined  inside  functions,  the standard C scoping and visibility rules
       apply. E.g., local variables can only be used in  their  own  or  in  more  deeply  nested
       blocks, their visibility is masked in more deeply nested blocks by defining an identically
       named variable inside those more deeply nested blocks. Variables are strongly  typed,  and
       cannot have type void.

       Variables  may be initialized when they are defined. Initializations are expressions, that
       can use pre- or user-defined functions, constant values, and values of variables that  are
       visible at the point of definition.

PREDEFINED CONSTANTS

       The following constants are predefined by icmake. All are constant int values:

       ─────────────────────────────────
       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

       int-typed operand(s):

       All  C  operators  are available (except for pointer operators, as icmake does not support
       pointers). They operate like their C-programming language counterparts.

       string-typed operand(s):

       For string type variables and/or constants the following operators are available (a and  b
       represent string variables or constants):

       o      a  +  b: returns a new string value containing the concatenation of string values a
              and b. Note that string constants may be directly concatetated (without using the +
              operator), e.g., the following two lines both define the string "hello world":

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

       o      a  +=  b:  a must be a  string variable, to which the string variable or value b is
              appended.

       o      string comparisons: operators == != <= >= < > != and == may be  applied  to  string
              values  or  variables,  returning  1  if  the  comparison  succeeds,  otherwise  0.
              Comparison is case sensitively, and follows the ordering or characters  as  defined
              in the ASCII character set.

       o      !a: the boolean ! (not) operator returns 1 if the string a is empty, otherwise 0 is
              returned.

       o      a younger b, a newer b: returns 1 if file a is  more  recent  than  file  b.  E.g.,
              "source.cc" newer "source.o". The files a and b do not have to exist: if both don’t
              exist 0 is returned; if b doesn’t exist, 1 is returned; if a  doesn’t  exist  0  is
              returned;  if they are equally old 0 is returned. (the exists() predefined function
              (see below, section PREDEFINED FUNCTIONS) can be used to test explicitly whether  a
              file exists).

       o      a  older  b:  turns  1  if  file  a  is  older than file b. E.g., "libprog.a" older
              "source.o". The files a and b do not have to  exist:  if  both  don’t  exist  0  is
              returned;  if  a doesn’t exist, 1 is returned; if b doesn’t exist 0 is returned; if
              they are equally old 0 is returned.

       o      []: the index operator retrieves a character from a string variable or constant: it
              returns a string as an rvalue. Therefore, the following statement compiles OK:

                  // assume str1 and str2 are strings
              str1 = str2[3];

              but the following statement won’t compile:

              str2[3] = "a";

              An empty string is returned if an invalid index value is provided.

       o      The `backtick` operator (`string cmd`)
              A  string  placed  between  two backticks is executed by the popen(3) function. The
              standard output gererated by the command that is stored in the string  argument  is
              returned as a list. An empty list indicates that the command could not be executed.
              A command that could be executed but did not produce  any  output  returns  a  list
              containing  one  empty  element.  The command’s standard error stream output is not
              collected by the backtick operator. However, standard shell  redirection  could  be
              used to collect the standard error stream’s output. Example:

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

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

       list-typed operand(s):

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

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

       o      a  -  b: returns a new list value containing the elements in a that are not present
              in b. This is a set-difference operation: the returned list contains  all  elements
              in a that are not elements of b.

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

       o      a -= b: elements in b are removed from the elements in a,  which  must  be  a  list
              variable.   This  is  a  set  operation:  all elements of a that are found in b are
              removed from a.

       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      !a: the boolean ! operator returns 1 if  the  list  a  is  empty,  otherwise  0  is
              returned.

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

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

              but the following statement won’t compile:

              lst[3] = str;

              An empty string is returned if an invalid index value is provided.

       Casting:

       Type-casts may be performed using the standard C cast-operator to cast:

       o      Strings to ints and vice versa ((int)"123", (string)55)

       o      Strings to lists (list lst = (list)"hello")

FLOW CONTROL

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

       o      expression ;
              The plain expression statement;

       o      The compound statement
              Variables  of  any type may be defined and initialized anywhere inside any compound
              statement. The visibility of a variable starts at its point of definition.

       o      if (condition) statement
              Inside the condition a variable may be defined and initialized. E.g,

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

              In this example, process is not called if getText() returns an  empty  string.  The
              variable str does not exist either before or after the if statement.

       o      if (condition) statement else statement
              As  with the previous statement, inside the condition a variable may be defined and
              initialized.

       o      for (init; condition; increment) statement
              Variables (of a single type) may be initialized (and optionally be defined) in  the
              init  section.  The  init,  condition  and increment sections may remain empty. The
              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  defining  a
              variable,   using  an  initialization  expression  means  that  the  initialization
              expressing is executed at each iteration of the while statement. So  the  following
              statement will never end, and will display 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. The function main has  return  type
              void and so in main only plain return statements can be used.  By default an icmake
              script’s exit value equals 0. Use the built-in function exit (see below) to specify
              any other exit value.

              Be advised:  the behavior of non-void functions not returning values is undefined.

       o      break
              Leaves for and while statements, overruling the statement’s condition.

       o      continue
              Continues with the next iteration of a for or while statement.

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

PREDEFINED FUNCTIONS

       Icmake offers the following predefined functions, which can be  used  anywhere  in  icmake
       scripts. The following overview is ordered alphabetically by function name.

       o      void arghead(string h)
              Helper  function of exec() (see also below at exec()): defines the `argument head’,
              to be used with exec(). By default, the `argument head’ is an empty string.

       o      void argtail (string t)
              Helper function of exec() (see also below at exec()): defines the `argument  tail’,
              to be used with exec(). By default, the `argument tail’ is an empty string.

       o      int ascii(string s)
              Returns the first character of s as an int; e.g., ascii("A") returns 65;

       o      string ascii(int i)
              Returns i as a string, e.g., ascii(65) returns the string "A";

       o      string change_base(string file, string newbase)
              Changes    the    basename    of    file,    returns   the   changed   name.   E.g,
              change_base("/path/demo.im", "out") returns "/path/out.im";

       o      string change_ext(string file, string newext)
              Changes   the   extension   of   file,   returns    the    changed    name.    E.g,
              rss_changeExt("source.cc", "o") returns "source.o";

       o      string change_path(string file, string newpath)
              Changes   the   path  specification  of  file,  returns  the  changed  name.   E.g,
              change_path("tmp/binary", "/usr/bin")  returns  "/usr/bin/binary".  Note  that  the
              /-separator is inserted if required.

       o      string chdir(string newdir)
              Changes  the  script’s  working  directory, returns the previous dir as an absolute
              path.

              Use chdir(".") to obtain the current working directory, chdir("") may  be  used  to
              obtain  the  startup  working  directory (this functionality was broken in releases
              before  than  7.00,  but  is  now  operational).  The   function   terminates   the
              icmake-script if the specified newdir does not exist.

       o      string chdir(int checking, string newdir)
              Same  functionality  as  the  previous  function,  but  by  specifying  checking as
              P_NOCHECK. the function won’t terminate the script.  Rather,  it  will  return  the
              script’s current working directory.

       o      cmdhead(string h)
              Helper  function of exec() (see also below at exec()): Defines a `command head’, to
              be used with exec(). By default, the `command head’ is an empty string.

       o      cmdtail(string t)
              Helper function of exec() (see also below at exec()): Defines a `command tail’,  to
              be used with exec(). By default, the `command tail’ is an empty string.

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

       o      string element(int index, list (or string) var)
              Acts identical to the index operator: refer to  the  index  ([])  operator  in  the
              section OPERATORS.

       o      list eval(string str)
              This  function acts identically to the backtick operator. 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

       o      exec(string cmd, ...)
              Executes command with arguments. Each argument  will  be  prefixed  by  arghead()’s
              argument  and  postfixed  by argtail()’s argument. Note that no blanks are inserted
              between arghead()’s contents, the argument proper, and  argtail()’s  argument.  All
              thus modified arguments are concatenated, this time separated by single blanks, and
              then cmdhead()’s contents are inserted between the command and the  first  argument
              (on  either  side delimited by single blanks) and cmdtail()’s contents are appended
              to the arguments (again, separated by a single blank). PATH is searched  to  locate
              cmd. 0 is returned.

       o      exec(int checkcmd, string cmd, ...)
              Same  functionality  as  the  previous  function,  but  by  specifying  checking as
              NOT_CHECKED the function won’t terminate the script. Rather,  it  will  return  the
              called command’s exit status, or 0x7f00 if the command wasn’t found.

       o      execute(string cmd, string cmdhd, string arghd, ..., string argtl, string cmdtl)
              Same as exec(), but command head/tail and argument head/tail must be specified.

              The  actually executed command starts with cmd, followed by cmdhd. Next is a series
              of arguments follows, each enclosed by arghd and argtl. The command terminates with
              cmdtl. 0 is returned

       o      execute(int  checking,  string  cmd, string cmdhd, string arghd, ..., string argtl,
              string cmdtl)
              Same functionality  as  the  previous  function,  but  by  specifying  checking  as
              NOT_CHECKED  the  function  won’t  terminate the script. Rather, it will return the
              called command’s exit status, or 0x7f00 if the command wasn’t found.

       o      int exists(string file)
              Returns a non-zero value if file exists, otherwise 0 is returned.

       o      list fgets(string file, list offset)
              NOTE: in icmake version 8.00.00 the prototype of this  function  was  changed  from
              list fgets(string file, int offset) to list fgets(string file, list offset).

              The  next  line  found at the offset contained in offset is read from file. Pass an
              empty list to fgets to read file from its beginning.

              It returns a list containing as its first element the contents  of  the  read  line
              (without  the \n line terminator), as its second element the line’s terminator `\n’
              (if encountered), and as its third element the string OK if a line was successfully
              read,  FAIL  if  reading  from  file  failed.  When reading at EOF an empty list is
              returned. The returned list may contain additional elements, which  are  internally
              used by fgets when reading the next line.

              To  read  multiple lines, start by passing an empty list as gets’s second argument.
              To read subsequent lines, pass the  previously  returned  list  to  fgets’s  second
              argument.

              Here is an example showing how to read a complete file:

              list ret;
              while (1)
              {
                  ret = fgets("filename", ret);
                  if (!ret)
                      break;
                  process(ret[0], ret[1]);
              }

       o      int fprintf(string filename, ...)
              Appends all (comma separated) arguments to the file filename. Returns the number of
              printed arguments.

       o      int fprintf(string filename, string format, ...)
              Appends all (comma separated) arguments to the file filename. Returns the number of
              printed arguments.

              If  format  contains  placeholders  %1  ..  %n  the  output  is formatted (see also
              strformat). Note that in this case  argument  counting  (also)  starts  beyond  the
              format string: the first argument following format is referred to as %1.

       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 getch()
              Returns the next pressed key as a string (pressing `Enter’ is not required).

       o      string get_dext(string file)
              Returns  the  extension of file, including the separating dot. The extension is all
              information starting at the filename’s final dot.

              If no final dot is found, an empty string is returned.

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

              the first element indicates whether the environment  variable  was  defined  (value
              "1") or not (value "0");
              the second element indicates the value of the environment variable.

              Enivironment  variables  are  of the form variable=value, and if defined the list’s
              second element contains value. If the value is empty, the variable is defined,  but
              has no text associated with it.

       o      string get_ext(string file)
              Returns  the extension of file, except for the separating dot. The extension is all
              information starting at the final dot in the filename.

              If no final dot is found, an empty string is returned.

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

       o      string gets()
              Returns the next line read from the keyboard as a string. The line entered  on  the
              keyboard  must be terminated by an `Enter’ key, which is not stored in the returned
              string.

       o      string get_path(string file)
              Returns the path-prefix of file. The path prefix is  all  information  up  to  (and
              including)  the  final  directory  separator  (which is, depending on the operating
              system, a forward- or backslash).

              If no path is found, an empty strring is returned.

       o      int listfind(list lst, string str)
              Returns the first 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 rhs.

       o      list listunion(list lst, string str)
              Returns a list containing the union of the elements in lst and str.

       o      list makelist(string mask)
              Returns  a  list  of  all files matching mask. E.g., makelist("*.c") returns a list
              containing all files ending in .c.

       o      list makelist(type, string mask)
              Same as the previous function, but the  type  of  the  directory  elements  may  be
              specified as its first argument:

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

              Note  that  the  pattern  * will not match hidden entries under Unix-type operating
              systems. Use .* for that.

       o      list makelist(string mask, newer, string comparefile)
              Returns  list  of  all  files  matching  mask  which  are  newer  than  a  provided
              comparefile.  Operator  younger  may  be used instead of newer. Note that newer and
              younger are operators, not strings.

       o      list makelist([int = IS_FILE,] string mask, newer, string comparefile)
              Same as the previous function, but type may be specified as in list  makelist(type,
              string mask).

       o      makelist(string mask, older, string comparefile)
              See above; returns a list of files that are older than the comparefile.

       o      makelist(type, string mask, older, string comparefile)
              Same  as the previous function, but type may be specified as in list makelist(type,
              string mask).

       o      int printf(...)
              Shows all (comma separated) arguments to screen (i.e., the standard output stream).
              Returns the number of printed arguments.

       o      int printf(string format, ...)
              Shows all (comma separated) arguments to screen (i.e., the standard output stream).
              Returns the number of printed arguments (the format string counts as one argument).

              If format contains placeholders  %1  ..  %n  the  output  is  formatted  (see  also
              strformat).

       o      int putenv(string envvar)
              Adds  envvar  to  the  current  (icmake)  environment  Use the format: "VAR=value".
              Returns 0.

       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 sizeof(list l)
              Deprecated: use listlen.

       o      int sizeoflist(list l)
              Deprecated: use listlen.

       o      list stat(string entry)
              Returns  stat(2)  information of directory entry entry as a list. The returned list
              has two elements: element 0 is the attribute value, element 1 contains the size  of
              the file.

              Attributes  are   returned  as  bit-flags,  composed  from the following predefined
              constants:

              S_IFCHR     S_IFDIR     S_IFREG
              S_IREAD     S_IWRITE    S_IEXEC

              See the stat(2) manual page for the meanings of these constants.

       o      list stat(checking, string entry)
              Same as the previous function, but by specifying checking as P_NOCHECK the function
              won’t terminate the script. Rather, it returns stat(2)’s return value.

       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 strlen(string str)
              Returns the number of characters in str (not counting the final 0).

       o      int strfind(string haystack, string needle)
              Returns index in haystack where needle is found, or -1 if needle is  not  contained
              in haystack.
              This function was called strstr() in versions before 7.00.

       o      int strformat(string format,...)
              Returns  a  formatted  string  using  placeholders  %1  ..  %2 to address arguments
              following format.
              Example:

              void main()
              {
                  int i = 10;
                  int j = 20;
                  string s1;
                  string s2;
                                                  // traditional approach:
                  s1 = (string)i + " " + (string)j + " " + (string)i;
                                                  // using strformat:
                  s2 = strformat("%1 %2 %1", i, j);
                  printf("s1 = %1, s2 = %2\n", s1, s2);
              }

       o      string strlwr(string s)
              Returns a lower-case duplicate of s.

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

       o      string strupr(string s)
              Returns an upper-case duplicate of s.

       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 size or if count <= 0, then an empty string
              is returned. If offset is less than 0 then offset = 0 is used.

       o      int system(string command)
              Executes command. The return value indicates the executed command’s exit value. The
              string command may contain redirection and/or piping characters.

       o      int system(int checking, string command)
              Same  functionality  as  the  previous  function,  but  by  specifying  checking as
              NOT_CHECKED the function won’t terminate the script. Rather,  it  will  return  the
              called command’s exit status, or 0x7f00 if the command wasn’t found.

       o      string trim(string s)
              Returns a copy of s without leading and trailing white spaces.

       o      string trimleft(string str)
              Returns a copy of s without leading white spaces.

       o      string trim(string s)
              Returns a copy of s without trailing white spaces.

USER DEFINED FUNCTIONS

       void main

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

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

       In main(),

       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;

       o      envp contains the `environment’ variables. The function  listlen  can  be  used  to
              determine   the   number   of   its  elements.  Elements  in  envp  have  the  form
              variable=value. Alternatively, the function  getenv  can  be  used  to  retrieve  a
              specific environment variable immediately.  Example:

                  void main(int argc, list argv)
                  {
                      list toCompile;
                      int idx;

                      if (argc == 1)
                          usage(element(0, argv));

                      if (toCompile = altered("*.cc"))
                      {
                          for (idx = length(toCompile); idx--; )
                              compile(element(idx, toCompile));

                          if (getenv("dryrun")[0] == "0")
                              linking(element(2, argv));
                      }
                  }

       Having  initialized  all  global variables in order of their definitions main is called by
       icmake’s run-time support system to perform additional tasks.

       Additionally defined user functions

       Additional functions may be defined. Once defined, these functions can be called.  Forward
       referencing  of  either  variables  or functions is not supported, but recursively calling
       functions is. As function  declarations  are  not  supported  indirect  recursion  is  not
       supported either.

       User-defined functions must have the following elements:

       o      The  function’s return type, which must be one of 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  (optionally  initialized)  variable  definitions.  Variable
       definitions  start  with  a type name, followed by one or more comma separated (optionally
       initialized) variable identifiers.  If a variable is  not  explicitly  initialized  it  is
       initialized  by  default.  By  default  an  int  variable is initialized to 0, a string is
       initialized to an empty string ("") and a list is initialized to a list of zero elements.

       In addition to variable definitions, bodies may  contain  zero  or  more  statements  (cf.
       section  FLOW  CONTROL).  Note  that variables may be defined (and optionally initialized)
       anywhere inside functions, and also in if, for and while statements.

       The behavior of icmake-scripts using non-void functions that do not return values  is  not
       defined.

FILES

       The mentioned paths are sugestive only and may vary over different icmake-installations:

       o      /usr/bin/icmake: the main icmake program;

       o      /usr/bin/icmun: the icmake unassembler;

       o      /usr/lib/icmake/icm-dep: the support program handling class- and precompiled header
              dependencies;

       o      /usr/lib/icmake/icm-pp: the preprocessor called by icmake;

       o      /usr/lib/icmake/icm-comp: the compiler called by icmake;

       o      /usr/lib/icmake/icm-exec: the byte-code interpreter called by icmake;

EXAMPLES

       The  distribution  (usually  in  /usr/share/doc/icmake)  contains  a  directory   examples
       containing  various  examples  of  icmake script. Note in particular the examples/icmbuild
       subdirectory containing a general script for C++ and C program maintenance.

SEE ALSO

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

BUGS

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

COPYRIGHT

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

AUTHOR

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