home | help
icmake(1)		  A program maintenance utility 	       icmake(1)

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  re-
     quired  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 ac-
     tivities  are highly comparable. This observation resulted in the construc-
     tion of two icmake scripts, which are now part of the standard icmake  dis-
     tribution:  icmstart(1),  initializing  a directory for program development
     and icmbuild(1), handling the actual program maintenance. Both come  prede-
     fined 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  ex-
     plicitly 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 initial-
     ized  (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 Devel-
     opment  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 devel-
     oping 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  re-
     quired for icmake's daily use it is not installed in a standard PATH direc-
     tory  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  modi-
     fied.  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 dramat-
     ically  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  de-
     scribed 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  be-
     yond 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  in-
	    formation  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  set-
	    ting 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 re-
	    ceives 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 com-
	    ment-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 pro-
	    gram. By making the script executable, it can be called without  ex-
	    plicitly 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 direc-
	    tive; filename is searched in the colon-separated directories speci-
	    fied  by  the IM environment variable. The first occurrence of file-
	    name 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 ${iden-
	    tifier} 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 direc-
	    tives (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.  Oth-
	    erwise, the block of code is ignored.

     o	    #ifndef identifier
	    If	the identifier macro was not defined the next block of code (un-
	    til a matching #else or #endif directive was detected) is  byte-com-
	    piled. 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 af-
	    fect  the  specification  of any previously defined symbols in which
	    identifier's definition has been used. If identifier hasn't been de-
	    fined 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 sup-
	    ported and represent their standard converted value (e.g., '\n' rep-
	    resents 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  oc-
	    tal  value modulo 256 (e.g., '\123'). Escape sequences consisting of
	    an x followed by two hexadecimal digits represent the ascii  charac-
	    ter 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 sepa-
	    rated by white space only (i.e., blanks, newlines, comment) are con-
	    catenated 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 func-
     tions,  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 ex-
     pressions which may use predefined or user-defined functions, constant val-
     ues, and values of variables. Functions or variables that are used for ini-
     tialization 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  ex-
	    ist:
	    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 re-
	    turns a list containing one empty element.	The  command's	standard
	    error  stream output is not collected by the backtick operator. How-
	    ever, 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 avail-
     able:

     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 re-
	    turned 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. Op-
	    erator != reverses the result of ==.

     o	    !a: the boolean ! operator returns 1 if the list a is empty,  other-
	    wise 0 is returned.

     o	    []:  the  index  operator retrieves a list element from a list vari-
	    able: 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 initial-
	    ization).

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  expres-
	    sion,  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 sec-
	    tions 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 func-
	    tion 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 condi-
	    tion.

     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  any-
     where  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 re-
	    turn modified filenames (e.g., by  changing  the  argument's  exten-
	    sion);

     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 ([]) op-
	    erator 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  terminat-
	    ing 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 addi-
	    tional 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  ic-
	    make'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_change-
	    Ext("source.cc",  "o")  returns "source.o". The extension of the re-
	    turned 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/bi-
	    nary",  "/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 informa-
	    tion 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  ex-
	    tension  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 direc-
	    tory 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  ex-
	    ample  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 re-
	    set 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 suc-
	    cessfully 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. Re-
	    turns 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 contain-
	    ing 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 envi-
	    ronment 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.   Make-
	    list  returns  a list of all type entries matching mask. E.g., make-
	    list("*.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  en-
	    tries 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  stan-
	    dard  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 for-
	    mat: "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 re-
	    turns 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 re-
	    turn  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 ex-
	    ecuted 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 defini-
	    tions 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. For-
     ward referencing of either variables or functions is not supported, but re-
     cursively	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 state-
     ments (cf. section FLOW CONTROL). Note that variables may be  defined  (and
     optionally  initialized)  anywhere inside functions, and also in the condi-
     tions 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 PRE-
     COMP 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 spec-
     ified. The following options are recognized:

     o	    --classes=filename (-c)
	    by default, icm-dep inspects dependencies of the classes  whose  di-
	    rectories  are  mentioned  in  the file CLASSES. Furthermore, if the
	    icmconf(7) file specifies PARSER_DIR and SCANNER_DIR then those  di-
	    rectories  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 con-
	    tains a #define PRECOMP specification. If it does not,  but  precom-
	    piled  headers should nonetheless be inspected, the option --gch can
	    be provided;

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

     o	    --no-use-all
	    by	default files named at the #define USE_ALL specification are in-
	    spected if icmconf contains such a specification.  To  suppress  in-
	    spections 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 ter-
	    minates.

icmun
     The icmun program expects one argument, the binary (bimfile) file	produced
     by  `icmake -c'. It disassembles the binary file an shows the assembler in-
     structions and structure of the binary file. Note that in standard  instal-
     lations icmun is not located in one of the directories of the PATH environ-
     ment 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  ic-
     make-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 ic-
	    make;

     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 Pub-
     lic License (GPL).

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

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

home | help