includefile(release.yo)

htmlbodyopt(text)(#27408B)
htmlbodyopt(bgcolor)(#FFFAF0)
whenhtml(mailto(Frank B. Brokken: f.b.brokken@rug.nl))

DEFINEMACRO(lsvoption)(3)(\
    bf(--ARG1)=tt(ARG3) (bf(-ARG2))\
)
DEFINEMACRO(lsoption)(2)(\
    bf(--ARG1) (bf(-ARG2))\
)
DEFINEMACRO(lvoption)(2)(\
    bf(--ARG1)=tt(ARG2)\
)
DEFINEMACRO(loption)(1)(\
    bf(--ARG1)\
)
DEFINEMACRO(svoption)(2)(\
    bf(-ARG1) tt(ARG2)\
)
DEFINEMACRO(soption)(1)(\
    bf(-ARG1)\
)

DEFINEMACRO(itt)(1)(\
    it()tt(ARG1)\
)

DEFINEMACRO(itb)(1)(\
    it()bf(ARG1)nl()\
)

DEFINEMACRO(icm)(0)(bf(icmake))
DEFINEMACRO(Icm)(0)(bf(Icmake))

DELETEMACRO(tt)
DEFINEMACRO(tt)(1)(em(ARG1))

COMMENT( man-request, section, date, distribution file, general name)
manpage(icmake)(1)(_CurYrs_)(icmake._CurVers_.tar.gz)
        (A program maintenance utility)

COMMENT( man-request, larger title )
manpagename(icmake)(A program maintenance (em(make)) utility using a
                    bf(C)-like grammar)

COMMENT( all other: add after () )
manpagesynopsis()
       icm() [options] tt(source[.im] [dest[.bim]]) [-- [args]]

       bf(icmun) tt(bimfile)

manpagedescription()

      Icm()(1) was designed as a generic tool that can be used as an
alternative to bf(make)(1), handling program maintenance. It's a generic tool
in that tt(icmake)-scripts, written in a language closely resembling
the bf(C) programming language, can perform tasks that are traditionally the
domain of scripting languages. 

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

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

This man-page covers tt(icmake) (the program), its support programs and
the syntax and facilities offered by tt(icmake's) scripting language. Refer to
the bf(icmstart)(1)) man-page for information about how a directory can be
initialized (created) in which (by default) a bf(C++) or bf(C) program can be
developed and refer to the bf(icmbuild)(1) man-page for information about how
tt(icmbuild) can be used to handle program maintenance.
    
It should be stressed that tt(icmake) and its support programs and scripts do
not offer an em(Integrated Development Environment) (IDE). It merely performs
tasks for which scripts can be written, and it offers just a few pre-defined
scripts (tt(icmstart) and tt(icmbuild)) that repeatedly have shown to be
extremely useful when developing and maintaining programs. 

    In its standard operation mode, tt(icmake) calls the following programs:
    itemization(
        itt(icm-pp)  to preprocess the icmake file 
        itt(icm-comp)   to byte-code compile the icm()  file(s)
        it()tt(icm-dep) to handle class-dependencies (see section bf(ICM-DEP)
            in bf(icmbuild)(1)'s man-page for more information about
            tt(icm-dep)).
        it()tt(icm-exec)   to execute the byte-code file
    )

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

Traditional make-utilities recompile sources once header files are
modified. When developing bf(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 bf(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 tt(PRECOMP) and/or tt(USE_ALL) defines in
tt(icmconf). Refer to the bf(icmconf)(7) man-page for further details. 

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

tt(Icmake's)  bf(C)-like scripting language is described in the upcoming
sections of this man-page:
    itemization(
    itb(PREPROCESSOR DIRECTIVES) - supported preprocessor directives, like
        tt(#include) and tt(#define);
    itb(DATA TYPES) - tt(int, list, string), and tt(void) (for functions);
    itb(PREDEFINED CONSTANTS) - like tt(O_FILE, OFF), and tt(S_IFREG);
    itb(OPERATORS) - like tt(+, younger), and casts
    itb(FLOW CONTROL) - tt(if, for, while), etc. (the tt(switch) is not
        available);
    itb(PREDEFINED FUNCTIONS) - executing programs, changing directories,
        operations on tt(string) and tt(list) type variables, etc.;
    itb(USER DEFINED FUNCTIONS) - at least tt(main), with or without its
        common parameters tt(argc, argv,) and tt(envp).
    )

manpageoptions()

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

    The tt(--) option is special:
    itemization(
    itt(--): icm() arguments separator separating icm() arguments from
            arguments passed to the .bim filenl(). Those arguments are passed
            to the .bim file as-is, and are available from the tt(list argv)
            parameter available from the icm() script's tt(main) function's
            second parameter (see below at section bf(USER DEFINED
            FUNCTIONS)). For some options (see below) the tt(--) separator is
            not required.
    )

    Icm() supports various options, and only one of these can be specified
when icm() is invocated.

    itemization(
    it() lsoption(about)(a)nl()
        Show information about icm() and terminate.

    it() lsoption(compile)(c)nl()
        The icm() source file is compiled, generating a .bim file.

    it() lsoption(execute)(e)nl()
        Execute the icm() .bim file, given as icm()'s first file
        argument. Any additional arguments are passed to the .bim file as-is,
        and tt(--) should not be specified.

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

    it() lsoption(help)(h)nl()
        Provide usage info and terminate.

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

    it() lsoption(preprocess)(p)nl()
        The icm() source file is only preprocessed, and the preprocessed
        file is written to icm()'s second
        file argument (by default tt(`source'.pim)).

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

    it() lsoption(summary)(F)nl()
        The filenames and flags as well as an overview of all actions to
        be performed by icm() are shown on the standard output stream.

    it() svoption(t)(tmpbim)nl() 
       The tt(tmpbim) argument following tt(-t) is the name of a temporary
        .bim file, which is removed after icm()'s call. When tt(.) is
        specified for tt(tmpbim) then the default temporary directory,
        followed by icm()'s process-id, followed by tt(.bim) is used.

        Following the name of the temporary .bim file the name of the icm()
        source script must be specified. Any additional arguments are passed
        to the .bim file as-is, and tt(--) should not be specified; After
        setting the source script file's executable flag (tt(chmod +x
        script)), and providing it with an initial line like this: verb(
    #!/usr/bin/icmake -t.
            )
        the icm() script can directly be called:
            verb(
    script arg1 arg2 
            )
        in which case the icm() script tt(`script') is executed while it
        receives the arguments tt(script arg1 arg2).


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

    it() lsoption(version)(v)nl()
        Displays icm()'s version number, and terminates.
    )

    bf(Icmun):

    tt(bimfile):  binary icm() script file.

manpagesection(ICM-DEP invocation and options)

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


    Options of tt(icm-dep) can be specified immediately following icm()'s
tt(--icm-dep) option. The following options are recognized by tt(icm-dep):
    itemization(
    it() lsvoption(classes)(c)(filename)nl()
       By default, tt(icm-dep) inspects dependencies of the classes whose
        directories are mentioned in the file tt(CLASSES). If specified in the
        bf(icmconf)(7) file, it will also consider dependencies of the
        classes tt(Parser) (directory tt(parser)) and tt(Scanner) (directory
        tt(scanner)), or it uses their actual names as defined in the
        bf(icmconf)(7) file. Use this option if instead of tt(CLASSES) another
        file should be inspected.

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

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

    it() lsvoption(mainih)(m)(mainheader)nl()
       The tt(icmconf) file uses the tt(#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
        tt(CLASSES) file. tt(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 tt(main.ih). 

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

    it() loption(no-gch)nl() 
       By default precompiled header files are inspected if tt(icmconf)
        contains a tt(#define PRECOMP) specification. If so, but precompiled
        headers should em(not) be inspected, the option tt(--no-gch) can be
        specified.

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

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

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

    it() lsoption(version)(v)nl() 
        tt(Icm_dep) reports  its version number to the standard output and
        terminates. 
    )


manpagesection(PREPROCESSOR DIRECTIVES)

The following preprocessor directives are available:
    itemization(
    it() comment:nl()
       standard bf(C) comment (all between tt(/*) and tt(*/)) as well as
        comment-to-end-of-line (all line contents following tt(//)) are
        ignored.
        
    it() Shell startup: The first line of the icm()-script may start with
        tt(#!path), where tt(path) defines the absolute location of the icm()
        program. By making the script executable, it can be called without
        explicitly calling icm().  

       E.g., if the first line of an (executable) icmakefile 'icm'
                  (without extension) contains
        verb(
            #!/usr/bin/icmake -i
        )
       then tt(icm) may be issued as a command, thus executing
        verb(
            /usr/bin/icmake -i icm ...
        )
       Alternatively, 
        verb(
            #!/usr/bin/icmake -t /tmp/icm
        )
       may be used, resulting in the execution of
        verb(
            #!/usr/bin/icmake -t /tmp/icm icm ...
        )
       In this case the binary file is removed on exit.

    itt(#include "filename")nl()
        The file tt(filename) is included at the location of the directive

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

    itt(#define identifier [definition])nl() 
       The text tt(identifier) will be replaced by tt(definition). The
        definition may contain references to already defined identifiers,
        using the tt(${identifier}) format. If the tt(${identifier}) hasn't
        been defined (yet), the text tt(${identifier}) is literally kept. To
        prevent infinite recursion at most 100 tt(${identifier}) replacements
        are allowed.

        Definitions continue at the next line if the last character on a line
        is a backslash (tt(\)).  (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 tt(#define's) identifier is optional. If
        omitted, the macro is defined, so it can be used in tt(#if(n)def)
        directives (see below), but they are not replaced by any text in
        icm() code statements.

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

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

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

    itt(#endif)nl()
       Terminates the preprocessor block starting at the matching 
        tt(#ifdef), tt(#ifndef) or tt(#else) directive. The tt(#endif)
        directory and its matching tt(#if(n)def) directive must be specified
        in the same file.

    itt(#undef identifier) nl()
       Remove tt(identifier) from the set of defined symbols. This does not
        affect the specification of any previously defined symbols in which
        tt(identifier's) definition has been used. If tt(identifier) hasn't
        been defined a warning is issued.
    )

manpagesection(DATA TYPES)

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

    itt(int)nl() 
       Integral values, ranging from tt(-0x8000) through tt(0x7fff). tt(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 tt(ASCII) character constants.

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

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

        Likewise, ASCII character constants surrounded by single quotes may be
        used in situations where a string operand is expected.
        
    itt(list)nl()
       A data structure containing a series of individually accessible
        tt(string) values. When a list contains elements, its first element is
        indicated by index 0.

    itt(void)nl()
       Used with function definitions to indicate that the function does not
        return a value.
    )
    
    Variables can be defined at the global level as well as at any local level
inside functions. When defined inside functions, the standard bf(C) scoping
and visibility rules apply. E.g., local variables can only be used in their
own or in more deeply nested blocks, their visibility is masked in more deeply
nested blocks by defining an identically named variable inside those more
deeply nested blocks. Variables are strongly typed, and cannot have
type tt(void).

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


manpagesection(PREDEFINED CONSTANTS)

    The following constants are predefined by icm(). All are constant tt(int) 
        values:
    table(3)(lll)(
        rowline()
        row(cell(symbol)cell(value)cell(intended for))
        rowline()
        row(cell(O_ALL)cell(8)cell(makelist))
        row(cell(O_DIR)cell(2)cell(makelist))
        row(cell(O_FILE)cell(1)cell(makelist))
        row(cell(O_SUBDIR)cell(4)cell(makelist))
        rowline()
        row(cell(OFF)cell(0)cell(echo))
        row(cell(ON)cell(1)cell(echo))
        rowline()
        row(cell(P_CHECK)cell(0)cell(system calls))
        row(cell(P_NOCHECK)cell(1)cell(system calls))
        rowline()
        row(cell(S_IEXEC)cell(32)cell(stat))
        row(cell(S_IFCHR)cell(1)cell(stat))
        row(cell(S_IFDIR)cell(2)cell(stat        ))
        row(cell(S_IFREG)cell(4)cell(stat))
        row(cell(S_IREAD)cell(8)cell(stat        ))
        row(cell(S_IWRITE)cell(16)cell(stat))
        rowline()
    )

    The following constants are architecture dependent:
    table(2)(ll)(
        rowline()
        row(cell(symbol)cell(1 when defined on the platform, otherwise 0))
        rowline()
        row(cell(unix)  cell(Unix, usually with GNU's gcc compiler))
        row(cell(UNIX)  cell(may alternatively be available))
        row(cell(linux) cell(x86 running Linux (usually with gcc)))
        row(cell(LINUX)  cell(may alternatively be available))
        row(cell(M_SYSV, M_UNIX) cell(x86 running SCO/Unix))
        row(cell(_POSIX)cell(_SOURCE   Unix with Posix compliant compiler))
        row(cell(__hpux)cell(HP-UX, with the native HP compiler))
        rowline()
    )

manpagesection(OPERATORS)

bf(int-typed operand(s):)

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

bf(string-typed operand(s):)

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

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

    itt(a += b): tt(a) must be a  tt(string) variable, to which the tt(string)
variable or value tt(b) is appended.

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

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

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

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

    itt([]): the index operator retrieves a character from a string variable
or constant: it returns a string as an em(rvalue). Therefore, the following
statement compiles OK:
        verb(
    // assume str1 and str2 are strings
str1 = str2[3];
        )
    but the following statement won't compile:
        verb(
str2[3] = "a"; 
        )

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

    it() The `backtick` operator (tt(`string cmd`))nl()
       A string placed between two backticks is executed by the tt(popen)(3)
        function. The standard output gererated by the command that is stored
        in the string argument is returned as a list. An empty list indicates
        that the command could not be executed. A command that could be
        executed but did not produce any output returns a list containing one
        empty element. The command's standard error stream output is not
        collected by the backtick operator. However, standard shell
        redirection could be used to collect the standard error stream's
        output. Example:
       verb(
printf(`"ls"`);     // prints the elements in 
                    // the current directory
            )
        The predefined function tt(eval(string cmd)) behaves exactly like the
        backtick operator: they are synonyms.
    )

bf(list-typed operand(s):)

    For tt(list) type variables and/or values the following
operators are available:
    itemization(
    itt(a + b): returns a new tt(list) value containing the concatenation of
tt(list) values tt(a) and tt(b). This is em(not) a set operation: if an
element appears both in tt(a) and in tt(b), they will appear twice in the
resulting list (set-addition is provided by the built-in function
tt(listunion)).

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

    itt(a += b): elements in tt(b) are added to the elements in tt(a), which 
must be a  tt(list) variable.  This is em(not) a set operation.

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

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

    itt(!a): the boolean tt(!) operator returns 1 if the tt(list a) is
empty, otherwise 0 is returned.

    itt([]): the index operator retrieves a list element from a list variable:
it returns a string as an em(rvalue). Therefore, the following statement
compiles OK:
        verb(
    // assume lst is a list, str is a string
str = lst[3];
        )
    but the following statement won't compile:
        verb(
lst[3] = str;
        )
        An empty string is returned if an invalid index value is provided.
    )

bf(Casting:)

    Type-casts may be performed using the standard bf(C) cast-operator to
cast:
    itemization(
    it() Strings to ints and vice versa (tt((int)"123", (string)55))
    it() Strings to lists (tt(list lst = (list)"hello"))
    )

manpagesection(FLOW CONTROL)

    Icm() offers the following subset of bf(C)'s statements. They can be
used as in the bf(C) programming language.
    itemization(
    itt(expression ;)nl()
        The plain expression statement;

    it() The compound statement nl()
        Variables of any type may be defined and initialized anywhere inside
        any compound statement. The em(visibility) of a variable starts at its
        point of definition.

    itt(if (condition) statement)nl()
        Inside the condition a variable may be defined and initialized. E.g,
            verb(
    if (string str = getText())
        process(str);
            )
        In this example, tt(process) is not called if tt(getText()) returns an
        empty string. The variable tt(str) does not exist either before or
        after the tt(if) statement.

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

    itt(for (init; condition; increment) statement)nl() 
       Variables (of a single type) may be initialized (and optionally be
        defined) in the tt(init) section. The tt(init), tt(condition) and
        tt(increment) sections may remain empty. The empty condition section
        is interpreted as `always tt(true)'.

    itt(while (condition) statement)nl()
        Inside the condition a variable may be defined and initialized.nl()
        A complementary  tt(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
        tt(while) statement. So the following statement will never end, and
        will display a never ending stream of values 10:
       verb(
while (int x = 10)
    printf(x--, "\n");
        )

    itt(return;), and tt(return expression;)nl()
       Plain tt(return) statements can be used in tt(void) functions,
        and tt(return expression) statements are used in other type of 
        functions. The function tt(main) has return type tt(void) and so in
        tt(main) only plain tt(return) statements can be used. 
        By default an icm() script's exit value equals 0. Use the built-in
        function tt(exit) (see below) to specify any other exit value. 

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

    itt(break)nl()
       Leaves tt(for) and tt(while) statements, overruling the statement's
        condition.

    itt(continue)nl()
       Continues with the next iteration of a tt(for) or tt(while)
        statement.

    itt(exit(expression))nl()
       Ends the execution of an icm()-script. The tt(expression) must
        evaluate to an tt(int) value, which becomes the script's exit value.
    )    

manpagesection(PREDEFINED FUNCTIONS)

    Icm() offers the following predefined functions, which can be used
anywhere in icm() scripts. The following overview is ordered alphabetically
by function name.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    itt(list eval(string str))nl()
       This function acts identically to the backtick operator. The example
        provided with the backtick operator could therefore also
        have been written like this:
       verb( 
printf(eval("ls")); // prints the elements in the current 
                    // directory 
        )

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

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

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

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

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

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

    itt(list fgets(string file, list offset))nl()
       bf(NOTE:) in icm() version 8.00.00 the prototype of this function was
        changed from tt(list fgets(string file, int offset)) to
        tt(list fgets(string file, list offset)).

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

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

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

        Here is an example showing how to read a complete file:
            verb(
list ret;
while (1)
{
    ret = fgets("filename", ret);
    if (!ret)
        break;
    process(ret[0], ret[1]);
}
            )

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

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

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

    itt(string get_base(string file))nl()
        Returns the base name of tt(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
        tt(a.b) equals tt(a), the base name of tt(a.b.c) equals tt(a.b), the
        base name of tt(a/b/c) equals tt(c). 

    itt(string getch())nl()
       Returns the next pressed key as a string (pressing `Enter' is not
        required).

    itt(string get_dext(string file))nl()
       Returns the extension of tt(file), including the separating dot. The
        extension is all information starting at the filename's final dot.

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

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

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

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

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

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

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

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

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

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

    itt(int listfind(list lst, string str))nl()
       Returns the first index in tt(lst) where the string tt(str) is found,
        or -1 if tt(lst) does not contain tt(str).

    itt(int listlen(list l))nl()
        Returns the number of elements in tt(list).

    itt(list listunion(list lhs, list rhs))nl()
       Returns a list containing the union of the elements in tt(lhs) and
        tt(rhs).

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

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

    itt(list makelist(type, string mask))nl()
        Same as the previous function, but the type of the directory elements
        may be specified as its first argument:
    table()(ll)(
        rowline()
        row(cell(symbol)cell(meaning))
        rowline()
        row(cell(O_ALL)cell(obtain all directory entries))
        row(cell(O_DIR)cell(obtain all directories, including . and ..))
        row(cell(O_FILE)cell(obtain a list of files))
        row(cell(O_SUBDIR)cell(obtain all subdirectories))
        rowline()
    )
    Note that the pattern tt(*) will not match hidden entries under Unix-type
        operating systems. Use tt(.*) for that.

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

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

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

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

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

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

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

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

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

    itt(int sizeof(list l))nl()
        Deprecated: use tt(listlen).

    itt(int sizeoflist(list l))nl()
        Deprecated: use tt(listlen).

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

        Attributes are  returned as bit-flags, composed from the
        following predefined constants: 
        verb(
S_IFCHR     S_IFDIR     S_IFREG
S_IREAD     S_IWRITE    S_IEXEC
        )
        See the bf(stat)(2) manual page for the meanings of these constants.

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

    itt(int strchr(string str, string chars))nl()
       Returns the first index in tt(str) where any of the characters in
        tt(chars) is found, or -1 if tt(str) does not contain any of the
        characters in tt(chars).

    itt(int strlen(string str))nl()
       Returns the number of characters in tt(str) (not counting the final 0).

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

    itt(int strformat(string format,...))nl()
        Returns a formatted string using placeholders %1 .. %2 to address
        arguments following format.nl() 
        Example:nl()
        verb(
void main()
{
    int i = 10;
    int j = 20;
    string s1;
    string s2;
                                    // traditional approach:
    s1 = (string)i + " " + (string)j + " " + (string)i;
                                    // using strformat:  
    s2 = strformat("%1 %2 %1", i, j);
    printf("s1 = %1, s2 = %2\n", s1, s2);
}
        )

   itt(string strlwr(string s))nl()
        Returns a lower-case duplicate of tt(s).

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

    itt(string strupr(string s))nl()
        Returns an upper-case duplicate of tt(s).

    itt(string substr(string text, int offset, int count))nl()
        Returns a substring of tt(text), starting at tt(offset), consisting of
        tt(count) characters. If tt(offset) exceeds (or equals) the string's
        size or if tt(count <= 0), then an empty string is returned. If
        tt(offset) is less than 0 then tt(offset = 0) is used. 

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

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

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

    itt(string trimleft(string str))nl()
        Returns a copy of tt(s) without leading white spaces.

    itt(string trim(string s))nl()
        Returns a copy of tt(s) without trailing white spaces.
    )


manpagesection(USER DEFINED FUNCTIONS)

bf(void main)

    Icm() scripts must be provided with a user-defined function tt(main). The
function tt(main) has three optional parameters, which may be omitted from the
last one (tt(envp)) to the first (tt(argc)), like in bf(C). Its full prototype
is (note: bf(void) return type):
        verb(
    void main(int argc, list argv, list envp)
        )
    In tt(main()),
    itemization(
    itt(argc) represents the number of elements in tt(argv);

    itt(argv) contains the arguments, with element 0 being equal to the
        name of the .bim file;

    itt(envp) contains the `environment' variables. The function tt(listlen)
can be used to determine the number of its elements. Elements in tt(envp) have
the form tt(variable=value). Alternatively, the function tt(getenv) can be
used to retrieve a specific environment variable immediately.
    )
    Example:
        verb(
    void main(int argc, list argv)
    {
        list toCompile;
        int idx;

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

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

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

Having initialized all global variables in order of their definitions tt(main)
is called by icm()'s run-time support system to perform additional
tasks. 

bf(Additionally defined user functions)

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

User-defined functions must have the following elements:
    itemization(
    it() The function's return type, which must be one of tt(void, int,
        string) or tt(list).  There is no default type. 

    it() The function's name, e.g., tt(compile).

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

    it() A em(body) surrounded by a pair of curly braces (tt({) and tt(})).
    )
     
   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 tt(int) variable is initialized to 0, a tt(string) is initialized
to an empty string (tt("")) and a tt(list) is initialized to a list of zero
elements.

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

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

manpagefiles()

    The mentioned paths are sugestive only and may vary over different
icm()-installations:
    itemization(
    it() bf(/usr/bin/icmake): the main icm() program;
    it() bf(/usr/bin/icmun): the icm() unassembler;
    it() bf(/usr/lib/icmake/icm-dep): the support program handling class- and
            precompiled header dependencies;
    it() bf(/usr/lib/icmake/icm-pp): the preprocessor called by icm();
    it() bf(/usr/lib/icmake/icm-comp): the compiler called by icm();
    it() bf(/usr/lib/icmake/icm-exec): the byte-code interpreter called by
            icm(); 
    )

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

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

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

    Path names containing blanks are not supported.

includefile(trailer.inc)
