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

icmake.9.03.01.tar.gz                               1992-2020                                          icmake(1)