Provided by: icmake_9.03.01-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)  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 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, often the required activities are
       highly comparable. This observation resulted in the construction of  two  icmake  scripts,
       which  are  now  part  of  the  standard  icmake distribution: 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.

       Icmake, its  support  programs,  and  scripts  do  not  offer  an  Integrated  Development
       Environment (IDE). Icmake merely performs tasks for which scripts can be written, and only
       a minimal set of pre-defined scripts (icmstart  and icmbuild) that repeatedly  have  shown
       to be extremely useful when developing and maintaining programs are included in the icmake
       distribution.

       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  sections   ICM-DEP   in   this   and
              icmbuild(1)’s man-pages for more information about icm-dep).

       o      icm-exec   to execute the byte-code file

       The  program  icmun(1)  disassembles compiled byte-code (.bim) files. 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, which commonly is /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 which are found in
       the file icmconf. Refer to the icmconf(7) man-page for further details.

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

       This  manpage  describes  icmake’s  options  in  the  next section. Following that section
       icmake’s C-like scripting language and support programs are  described  in  the  following
       separate sections:

       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.

       o      ICM-DEP
              - the icm-dep dependency analyzer.

       o      ICMUN
              - a brief section about icmun.

OPTIONS

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

       o      --
              This option separates icmake arguments from arguments passed to the .bim file.
              Arguments  beyond  -- 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.

       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)
              Provides usage info.

       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  sections  ICM-DEP in this and icbuild(1)’s man-pages for more
              information about the icm-dep support program. An  overview  of  icm-dep’s  options
              follows below, after 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.

PREPROCESSOR DIRECTIVES

       The following preprocessor directives are recognized:

       o      comment:
              standard    C    comment   (everything   from   /*   through   */)   as   well   as
              comment-to-end-of-line (line content starting at //) is 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  is  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 the following five data and value types:

       o      ASCII character constants
              ASCII character constants are individual 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 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  values: text (or `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  using  double  quotes  can  also be used in arithmetic
              expressions if one of the operands is an int.

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

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

              List constants can also be defined. They consist of comma-separated strings  (which
              may  be string variables or expressions returning string values) and are surrounded
              by square brackets. E.g.,

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

       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 inside functions (not only at the
       top of compound statements but also between statements and in the  initialization  section
       of  for-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.

PREDEFINED CONSTANTS

       The following predefined int constants are available:

       ─────────────────────────────────

       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-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  (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 == return 1 if the  comparison
              is  true,  otherwise  0.  Ordering  comparison  operators  use the (case sensitive)
              character ordering defined by the ASCII character set.

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

       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 a doesn’t exist 0 is returned;
              if b doesn’t exist, 1 is returned;
              if they are equally old 0 is returned.

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

       o      a  older  b:  returns  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. Thus, the following statement compiles OK:

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

              but the following statement won’t compile:

                  str2[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 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 may 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-operators:

       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;

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

       Casting:

       Type-casts using the standard C 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 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.
              Initialization and then using the variable in a subsequent expression, separated by
              a semicolon from the definition is not supported (e.g., if (string str =  getText()
              ; str) cannot be used).

       o      if (condition) statement else statement
              Like  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. 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. 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 provides the following predefined functions, which can be used anywhere  in  icmake
       scripts.  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:
              these functions only have one  purpose:  they  receive  int  arguments  and  simply
              process those arguments;

       o      Functions operating on lists:
              these  functions  only  have  one  purpose: their main argument is a list, which is
              somehow manipulated;

       o      Functions operating on strings:
              these functions only have one purpose: their main argument is a  string,  which  is
              somehow manipulated;

       o      Functions manipulating filenames:
              these  functions  receive  filenames as their string arguments, and return modified
              filenames (e.g., by changing the argument’s extension);

       o      System-related functions:
              these functions interface to facilities provided  by  the  operating  system,  like
              executing programs or changing the environment.

       Functions operating on ints:

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

       Functions operating on lists:

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

       o      list fgets(string file, list offset)
              see the system functions section;

       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 the elements of rhs;

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

       Functions operating on strings:

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

       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 strlen(string str)
              returns  the  number  of  characters  in  str   (not   counting   the   terminating
              NUL-character);

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

       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;

       Functions manipulating filenames:

       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:  rss_changeExt("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.,  rss_changeExt("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 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 no path is found, an empty strring  is
              returned;

       System-related functions:

       o      void arghead(string h)
              helper  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 exec arguments, like a directory in which
              provided arguments are found;

       o      void argtail (string t)
              helper 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 exec arguments, like  the  extensions  of
              files that are passed as arguments to exec;

       o      string chdir([int check,] string dir)
              returns  the  script’s  working  directory at the point where chdir is called as an
              absolute path, and 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  the  change  of  directory  cannot  be
              performed  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.

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

       o      cmdhead(string h)
              helper 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.  Cmdhead is used unmodified;

       o      cmdtail(string t)
              helper 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. 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      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;

       o      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      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:

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

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

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

              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);
                  }

       o      int fprintf(string filename, argument(s))
              appends all (comma 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", "%1 %2\n", "hello", "world");

       o      string getch()
              returns  the  next  pressed  key  as  a  string  (pressing  the  `Enter’-key is not
              required);

       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      string gets()
              returns the next line read from the keyboard as a string.  The  line  contains  all
              enteed 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  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 files
              O_SUBDIR   obtain all subdirectories

              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}, 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 files is returned matching mask  which  are,  resp.,  newer  or  older  than  a
              provided comparefile. Note that newer and younger are operators, not strings;

       o      int printf(argument(s))
              the function’s (comma separated) arguments are written to the standard output file.
              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      int putenv(string envvar)
              adds  envvar to the current icmake-script environment. Use the format: "VAR=value".
              The function returns 0;

       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 of the system stat function.

              The returned list has two elements:

              its  first  element ([0]) holds the entry’s attributes.  Attributes are returned as
              or-ed combinations of the following bit-flags (cf. stat(2)):

                  S_IFCHR     S_IFDIR     S_IFREG
                  S_IREAD     S_IWRITE    S_IEXEC

              its second element ([1]) contains the entry’s size in bytes;

       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

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

       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 (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(element(0, argv));

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

              After  initializing  all  global  variables  in  order of their definitions main is
              called by icmake’s run-time support system. Icmake scripts end  once  main  returns
              (or exit is called by the script).

       Additionally defined user functions

       Additional functions may be defined. Once defined, they 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.

       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 an empty list.

       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 the conditions of if and while  statements  and  in
       the initialization section of for statements.

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

ICM-DEP

       The icm-dep program is a support program for icmake to determine source-file dependencies.
       It  is  called automatically when USE_ALL or PRECOMP is specified in the icmconf file that
       is processed by icmake.

       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 then performs all its
       duties (and verbose messages are displayed as if go had  been  specified),  but  no  files
       (precompiled  headers  or  USE_ALL  files)  are touched or removed. If neither options nor
       arguments are specified icm_dep writes its usage summary to the standard output.

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

       o      --classes=filename (-c)
              by  default,  icm-dep  inspects  dependencies  of the classes whose directories are
              mentioned in the file  CLASSES.  Furthermore,  if  the  icmconf(7)  file  specifies
              PARSER_DIR  and  SCANNER_DIR  then those directories are also considered.  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 content of icmconf files, looking for  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 provided;

       o      --no-gch
              by default precompiled header files are inspected if  icmconf  contains  a  #define
              PRECOMP specification. If in that case precompiled headers should not be inspected,
              the option --no-gch can be provided;

       o      --no-use-all
              by default files named at  the  #define  USE_ALL  specification  are  inspected  if
              icmconf  contains  such a specification. To suppress inspections of `USE_ALL’ files
              provide this option;

       o      --use-all=filename
              by default files named at #define  USE_ALL  specifications  of  icmconf  files  are
              inspected.  If  the  USE_ALL  define  is  not  specified but `USE_ALL’ files should
              nonetheless be inspected, then provide this option, specifying the name of files to
              use as USE_ALL files;

       o      --verbose (-V)
              this  option  can  be specified multiple times. The number of times it is specified
              determines icm_dep’s verbosity. If not used  then  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  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.

icmun

       The icmun program expects one argument, the binary (bimfile) file produced by `icmake -c’.
       It  disassembles  the binary file an shows the assembler instructions and structure of the
       binary file. Note that in standard installations icmun  is  not  located  in  one  of  the
       directories  of  the  PATH  environment  variable,  but  is located in the /usr/lib/icmake
       directory.

       As an illustration, assume the following script is compiled by icmake  (e.g.,  by  calling
       icmake -c demo.im):

           void main()
           {
               printf("hello world");
           }

       the resulting demo.bim file can be processed by icmun (e.g., calling /usr/lib/icmake/icmun
       demo.bim. Icmun then writes the following to the standard output fle:

           icmun by Frank B. Brokken (f.b.brokken@rug.nl)
           icmun V9.03.00, copyright (c) GPL 1992-2020.

           Binary file statistics:
               strings           at offset 0x0025
               variables         at offset 0x0031
               filenames         at offset 0x0031
               first instruction at offset 0x001f

           String constants dump:
               "hello world"

           Disassembled code:
               [0014] 06 00 00   push string "hello world"
               [0017] 05 01 00   push int 0001
               [001a] 1b 1d      callrss 29 (printf)
               [001c] 1c 02      add sp, 2
               [001e] 23         ret
               [001f] 21 14 00   call [0014]
               [0022] 04         push int 0
               [0023] 24         pop reg
               [0024] 1d         exit

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/icmbuild: the wrapper program around the icmbuild script handling standard
              program maintenance;

       o      /usr/bin/icmstart: an icmake-script that is can be used to create the startup-files
              of new projects;

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

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

       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/icmun: the icmake unassembler.

EXAMPLES

       The   distribution  (usually  in  /usr/share/doc/icmake)  contains  a  directory  examples
       containing additional examples of icmake script.

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.

       Path names containing blanks are not supported.

       The  functions  sizeof(list  lst)  and  sizeoflist(list  lst) are deprecated and should no
       longer be used. They are removed in a future version  of  icmake.  Use  listlen(list  lst)
       instead.

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