icmake - A program maintenance (make) utility using a
C-like grammar
icmake [options] source[.im] [dest[.bim]] [--
[args]]
icmun bimfile
Icmake(1) was designed as a generic tool that can be used
as an alternative to make(1), handling program maintenance.
It’s a generic tool in that icmake-scripts, written in a
language closely resembling the C programming language, can perform
tasks that are traditionally the domain of scripting languages.
Icmake allows programmers to use a programming language
(closely resembling the well-known C-programming language) to define
the actions that are required for (complex) program maintenance. For this,
icmake offers various special operators as well as a set of support
functions that have shown their usefulness in program maintenance.
Although icmake-scripts can be written from scratch for
handling program maintenance, often the required activities are highly
comparable. This observation resulted in the construction of two
icmake-scripts: icmstart(1), initializing a directory for
program development and icmbuild(1), handling the actual program
maintenance. Both come predefined as scripts tailored to initializing and
maintaining C++ programs (or, after minimal adaptation, C
programs), but can easily be adapted to other programming languages. Both
icmstart and icmbuild can be run without explicitly calling
icmake.
This man-page covers icmake (the program), its support
programs and the syntax and facilities offered by icmake’s
scripting language. Refer to the icmstart(1)) man-page for
information about how a directory can be initialized (created) in which (by
default) a C++ or C program can be developed and refer to the
icmbuild(1) man-page for information about how icmbuild can be
used to handle program maintenance.
It should be stressed that icmake and its support programs
and scripts do not offer an Integrated Development Environment (IDE).
It merely performs tasks for which scripts can be written, and it offers
just a few pre-defined scripts (icmstart and icmbuild) that
repeatedly have shown to be extremely useful when developing and maintaining
programs.
In its standard operation mode, icmake calls the following
programs:
- o
- icm-pp to preprocess the icmake file
- o
- icm-comp to byte-code compile the icmake s
- o
- icm-dep to handle class-dependencies (see section ICM-DEP in
icmbuild(1)’s man-page for more information about
icm-dep).
- o
- icm-exec to execute the byte-code file
The program icmun(1) can be used to disassemble the
compiled byte-code (.bim) file. Icmun is mainly used for
illustration, education, and debugging. As it is not required for
icmake’s daily use it is not installed in a standard
PATH directory but (since icmake’s version 9.02.00) in
icmake’s lib directory, commonly
/usr/lib/icmake.
Traditional make-utilities recompile sources once header files are
modified. When developing C++ programs this is often a bad idea, as
adding a new member to a class does not normally require you to recompile
all of the class’s source files. To handle class dependencies
icmbuld(1) may inspect class dependencies, (re)compiling sources of
dependent classes whenever necessary. By default, class-dependencies are not
interpreted, but this can easily be changed by activating the PRECOMP
and/or USE_ALL defines in icmconf. Refer to the
icmconf(7) man-page for further details.
Precompiled header files can also easily be used. Precompiled
header files dramatically reduce the time that is required for compiling
classes’ source files. Refer to the icmconf(7) man-page (in
particular the description of the PRECOMP define) for further
details.
Icmake’s C-like scripting language is
described in the upcoming sections of this man-page:
- o
- PREPROCESSOR DIRECTIVES
- supported preprocessor directives, like #include and
#define;
- o
- DATA TYPES
- int, list, string, and void (for functions);
- o
- PREDEFINED CONSTANTS
- like O_FILE, OFF, and S_IFREG;
- o
- OPERATORS
- like +, younger, and casts
- o
- FLOW CONTROL
- if, for, while, etc. (the switch is not available);
- o
- PREDEFINED FUNCTIONS
- executing programs, changing directories, operations on string and
list type variables, etc.;
- o
- USER DEFINED FUNCTIONS
- at least main, with or without its common parameters argc,
argv, and envp.
Where available, single letter options are listed between
parentheses beyond their associated long-option variants.
The -- option is special:
- o
- --: icmake arguments separator separating icmake
arguments from arguments passed to the .bim filenl(). Those arguments are
passed to the .bim file as-is, and are available from the list argv
parameter available from the icmake script’s main
function’s second parameter (see below at section USER
DEFINED FUNCTIONS). For some options (see below) the --
separator is not required.
Icmake supports various options, and only one of these can
be specified when icmake is invocated.
- o
- --about (-a)
Show information about icmake and terminate.
- o
- --compile (-c)
The icmake source file is compiled, generating a .bim file.
- o
- --execute (-e)
Execute the icmake .bim file, given as icmake’s first
file argument. Any additional arguments are passed to the .bim file as-is,
and -- should not be specified.
- o
- --force (-f)
The icmake source file is recompiled (even if the .bim file is
up-to-date) either when no other options are specified, or when in
combination with options --source and --tmpbin.
- o
- --help (-h)
Provide usage info and terminate.
- o
- --icm-dep (-d)
Calls /usr/lib/icmake/icm-dep, passing it all remaining arguments. If
no additional arguments are specified icm-dep’s short usage
information is shown to the std. output stream. See section ICM-DEP
in icbuild(1)’s man-page for more information about the
icm-dep support program. An overview of icm-dep’s
option follows below, next to this overview of icmake’s
options.
- o
- --preprocess (-p)
The icmake source file is only preprocessed, and the preprocessed
file is written to icmake’s second file argument (by default
`source’.pim).
- o
- --source (-i)
The first argument is the icmake source file, the default binary file
is constructed if necessary. Any additional arguments are passed to the
.bim file as-is, and -- should not be specified.
- o
- --summary (-F)
The filenames and flags as well as an overview of all actions to be
performed by icmake are shown on the standard output stream.
- o
- -t tmpbim
The tmpbim argument following -t is the name of a temporary
.bim file, which is removed after icmake’s call. When
. is specified for tmpbim then the default temporary
directory, followed by icmake’s process-id, followed by
.bim is used.
- Following the name of the temporary .bim file the name of the
icmake source script must be specified. Any additional arguments
are passed to the .bim file as-is, and -- should not be specified;
After setting the source script file’s executable flag (chmod
+x script), and providing it with an initial line like this:
#!/usr/bin/icmake -t.
the icmake script can directly be called:
script arg1 arg2
in which case the icmake script `script’ is executed
while it receives the arguments script arg1 arg2.
- o
- -T directory
The specified directory is used to store temporary files. E.g., when
compiling an icmake script, the output of icmake’s
preprocessor is a temporary file which is removed on exit. By default
/tmp is used, unless /tmp is not a writable directory, in
which case the current user’s $HOME directory is used.
Implicit temporary filenames always start with the process id of the
current icmake process.
- o
- --version (-v)
Displays icmake’s version number, and terminates.
Icmun:
bimfile: binary icmake script file.
To start its work, the dependencies-analyzer icm_dep needs
one command-line argument: go. Any other argument results in
icm_dep performing a `dry run’: it will perform all its duties
(and verbose messages are displayed as if go had been specified), but
no files (precompiled headers or USE_ALL files) will be touched or
removed. If neither options nor arguments are specified icm_dep
writes its usage summary to the standard output.
Options of icm-dep can be specified immediately following
icmake’s --icm-dep option. The following options are
recognized by icm-dep:
- o
- --classes=filename (-c)
By default, icm-dep inspects dependencies of the classes whose
directories are mentioned in the file CLASSES. If specified in the
icmconf(7) file, it will also consider dependencies of the classes
Parser (directory parser) and Scanner (directory
scanner), or it uses their actual names as defined in the
icmconf(7) file. Use this option if instead of CLASSES
another file should be inspected.
- o
- --help (-h)
Icm-dep writes a summary of its usage to the standard output and
terminates.
- o
- --icmconf=filename (-i)
By default icm-dep inspects the contents of an icmconf file,
looking for the USE_ALL and PRECOMP specifications. Use this
option if instead of icmconf another file should be inspected.
- o
- --mainih=mainheader (-m)
The icmconf file uses the #define IH parameter to specify the
suffix of class header files that should be precompiled, their filenames
being equal to the names of the classes mentioned in the CLASSES
file. CLASSES does not specify a top-level directory. The name of
the top-level header file to precompile can be specified using this
option. By default it is main.ih.
- o
- --gch
By default precompiled header files are inspected if icmconf contains
a #define PRECOMP specification. If it does not, but precompiled
headers should nonetheless be inspected, the option --gch can be
specified.
- o
- --no-gch
By default precompiled header files are inspected if icmconf contains
a #define PRECOMP specification. If so, but precompiled headers
should not be inspected, the option --no-gch can be
specified.
- o
- --no-use-all
By default files named at the #define USE_ALL specification are
inspected if icmconf contains such a specification. If it does, but
the `USE_ALL’ files should not be inspected, this option can
be specified.
- o
- --use-all=filename
By default files named at the #define USE_ALL specification are
inspected if icmconf contains such a specification. If it does not,
but `USE_ALL’ files should nonetheless be inspected, this
option can be specified, together with the name of files (existing in one
or more directories that indicate that all the directory’s source
files must be recompiled).
- o
- --verbose (-V)
This option can be specified multiple times. The number of times it is
specified defines icm_dep’s verbosity. If none is specified,
icm_dep silently performs its duties. If specified once, then
icm_dep reports to the standard output what actions it performs; if
specified twice it reports the options it encountered; if specified three
times it also reports the class dependencies; if specified more often it
reports what files it encountered and what situations caused it to make
its decisions.
- o
- --version (-v)
Icm_dep reports its version number to the standard output and
terminates.
The following preprocessor directives are available:
- o
- comment:
standard C comment (all between /* and */) as well as
comment-to-end-of-line (all line contents following //) are
ignored.
- o
- Shell startup: The first line of the icmake-script may start with
#!path, where path defines the absolute location of the
icmake program. By making the script executable, it can be called
without explicitly calling icmake.
- E.g., if the first line of an (executable) icmakefile ’icm’
(without extension) contains
#!/usr/bin/icmake -i
then icm may be issued as a command, thus executing
/usr/bin/icmake -i icm ...
Alternatively,
#!/usr/bin/icmake -t /tmp/icm
may be used, resulting in the execution of
#!/usr/bin/icmake -t /tmp/icm icm ...
In this case the binary file is removed on exit.
- o
- #include "filename"
The file filename is included at the location of the directive
- o
- #include <filename>
The file filename is included at the location of the #include
directive; filename is searched in the colon-separated directories
specified by the IM environment variable. The first occurrence of
filename in the directories specified by the IM environment
variable is used.
- o
- #define identifier [definition]
The text identifier will be replaced by definition. The
definition may contain references to already defined identifiers, using
the ${identifier} format. If the ${identifier} hasn’t
been defined (yet), the text ${identifier} is literally kept. To
prevent infinite recursion at most 100 ${identifier} replacements
are allowed.
- Definitions continue at the next line if the last character on a line is a
backslash (\). (which is not included in the definition). The
preprocessor concatenates double-quuted strings, and double quoted strings
may not span multiple lines. Multiple blanks (outside of double quoted
strings) in definitions are contracted to a single blank space.
- The definition following the #define’s identifier is
optional. If omitted, the macro is defined, so it can be used in
#if(n)def directives (see below), but they are not replaced by any
text in icmake code statements.
- o
- #ifdef identifier
If the identifier macro was defined the next block of code (until a
matching #else or #endif directive was read) is
byte-compiled. Otherwise, the block of code is ignored.
- o
- #ifndef identifier
If the identifier macro was not defined the next block of code
(until a matching #else or #endif directive was detected) is
byte-compiled. Otherwise, the block of code is ignored.
- o
- #else
Terminates a #ifdef and #ifndef directive, reversing the
acceptance decision about the following code. Only one #else
directive can be associated with #if(n)def directives.
- o
- #endif
Terminates the preprocessor block starting at the matching #ifdef,
#ifndef or #else directive. The #endif directory and
its matching #if(n)def directive must be specified in the same
file.
- o
- #undef identifier
Remove identifier from the set of defined symbols. This does not
affect the specification of any previously defined symbols in which
identifier’s definition has been used. If identifier
hasn’t been defined a warning is issued.
Icmake supports these data types:
- o
- ASCII character constants
ASCII character constants consist of one character, surrounded by single or
double quotes. Single characters (e.g., ’a’)
represent the character itself. Standard escape sequences (e.g.,
’\n’) are supported and represent their standard
converted value (e.g., ’\n’ represents ascii value 10
(decimal)). Non-standard escape sequences (e.g.,
’\x’) represent the ascii character following the
escape character (so ’\x’ equals
’x’). Escape sequences consisting of three octal
digits represent the ascii character corresponding to the octal value
modulo 256 (e.g., ’\123’). Escape sequences
consisting of an x followed by two hexadecimal digits represent the ascii
character corresponding to the hexadecimal value (e.g.,
’\xa4’).
- o
- int
Integral values, ranging from -0x8000 through 0x7fff.
int constants may be specified as decimal numbers (starting with
digits 1 through 9), octal numbers (starting with 0, followed by one or
more octal digits) hexadecimal numbers (starting with 0x, followed by one
or more hexadecimal digits) or as ASCII character constants.
- o
- string
Text variables. String constants are delimited by double quotes. Multiple
string constants may be concatenated, but a single string constant may not
span multiple lines. String constants separated by white space only (i.e.,
blanks, newlines, comment) are concatenated and represent one single
string constant. To indicate an end-of-line in a string constant use the
\n escape sequence.
- ASCII character constants surrounded by double quotes can also be used in
arithmetic expressions if one of the operands is an int. The single
character string constant must be a constant, and cannot be a
string variable.
- Likewise, ASCII character constants surrounded by single quotes may be
used in situations where a string operand is expected.
- o
- list
A data structure containing a series of individually accessible
string values. When a list contains elements, its first element is
indicated by index 0.
- o
- void
Used with function definitions to indicate that the function does not return
a value.
Variables can be defined at the global level as well as at any
local level inside functions. When defined inside functions, the standard
C scoping and visibility rules apply. E.g., local variables can only
be used in their own or in more deeply nested blocks, their visibility is
masked in more deeply nested blocks by defining an identically named
variable inside those more deeply nested blocks. Variables are strongly
typed, and cannot have type void.
Variables may be initialized when they are defined.
Initializations are expressions, that can use pre- or user-defined
functions, constant values, and values of variables that are visible at the
point of definition.
The following constants are predefined by icmake. All are
constant int values:
symbol |
value |
intended for |
O_ALL |
8 |
makelist |
O_DIR |
2 |
makelist |
O_FILE |
1 |
makelist |
O_SUBDIR |
4 |
makelist |
OFF |
0 |
echo |
ON |
1 |
echo |
P_CHECK |
0 |
system calls |
P_NOCHECK |
1 |
system calls |
S_IEXEC |
32 |
stat |
S_IFCHR |
1 |
stat |
S_IFDIR |
2 |
stat |
S_IFREG |
4 |
stat |
S_IREAD |
8 |
stat |
S_IWRITE |
16 |
stat |
The following constants are architecture dependent:
symbol |
1 when defined on the platform, otherwise 0 |
unix |
Unix, usually with GNU’s gcc compiler |
UNIX |
may alternatively be available |
linux |
x86 running Linux (usually with gcc) |
LINUX |
may alternatively be available |
M_SYSV, M_UNIX |
x86 running SCO/Unix |
_POSIX |
_SOURCE Unix with Posix compliant compiler |
__hpux |
HP-UX, with the native HP compiler |
int-typed operand(s):
All C operators are available (except for pointer
operators, as icmake does not support pointers). They operate like
their C-programming language counterparts.
string-typed operand(s):
For string type variables and/or constants the following
operators are available (a and b represent string
variables or constants):
- o
- a + b: returns a new string value containing the
concatenation of string values a and b. Note that
string constants may be directly concatetated (without using the
+ operator), e.g., the following two lines both define the string
"hello world":
"hello " "world"
"hello " + "world"
- o
- a += b: a must be a string variable, to which the
string variable or value b is appended.
- o
- string comparisons: operators == != <= >= < > != and
== may be applied to string values or variables, returning 1
if the comparison succeeds, otherwise 0. Comparison is case sensitively,
and follows the ordering or characters as defined in the ASCII
character set.
- o
- !a: the boolean ! (not) operator returns 1 if the string
a is empty, otherwise 0 is returned.
- o
- a younger b, a newer b: returns 1 if file a is more recent
than file b. E.g., "source.cc" newer
"source.o". The files a and b do not have to
exist: if both don’t exist 0 is returned; if b
doesn’t exist, 1 is returned; if a doesn’t exist 0 is
returned; if they are equally old 0 is returned. (the exists()
predefined function (see below, section PREDEFINED FUNCTIONS) can
be used to test explicitly whether a file exists).
- o
- a older b: turns 1 if file a is older than file b.
E.g., "libprog.a" older "source.o". The files
a and b do not have to exist: if both don’t exist 0
is returned; if a doesn’t exist, 1 is returned; if b
doesn’t exist 0 is returned; if they are equally old 0 is
returned.
- o
- []: the index operator retrieves a character from a string variable
or constant: it returns a string as an rvalue. Therefore, the
following statement compiles OK:
// assume str1 and str2 are strings
str1 = str2[3];
but the following statement won’t compile:
str2[3] = "a";
- An empty string is returned if an invalid index value is provided.
- o
- The `backtick` operator (`string cmd`)
A string placed between two backticks is executed by the popen(3)
function. The standard output gererated by the command that is stored in
the string argument is returned as a list. An empty list indicates that
the command could not be executed. A command that could be executed but
did not produce any output returns a list containing one empty element.
The command’s standard error stream output is not collected by the
backtick operator. However, standard shell redirection could be used to
collect the standard error stream’s output. Example:
printf(`"ls"`); // prints the elements in
// the current directory
The predefined function eval(string cmd) behaves exactly like the
backtick operator: they are synonyms.
list-typed operand(s):
For list type variables and/or values the following
operators are available:
- o
- a + b: returns a new list value containing the concatenation
of list values a and b. This is not a set
operation: if an element appears both in a and in b, they
will appear twice in the resulting list (set-addition is provided by the
built-in function listunion).
- o
- a - b: returns a new list value containing the elements in
a that are not present in b. This is a set-difference
operation: the returned list contains all elements in a that are
not elements of b.
- o
- a += b: elements in b are added to the elements in a,
which must be a list variable. This is not a set
operation.
- o
- a -= b: elements in b are removed from the elements in
a, which must be a list variable. This is a set
operation: all elements of a that are found in b are removed
from a.
- o
- list equality comparisons: operators != and == may be
applied to list values or variables. Operator == returns 1
if both lists have element-by-element identical elements, otherwise 0 is
returned. Operator != reverses the result of ==.
- o
- !a: the boolean ! operator returns 1 if the list a is
empty, otherwise 0 is returned.
- o
- []: the index operator retrieves a list element from a list
variable: it returns a string as an rvalue. Therefore, the
following statement compiles OK:
// assume lst is a list, str is a string
str = lst[3];
but the following statement won’t compile:
lst[3] = str;
An empty string is returned if an invalid index value is provided.
Casting:
Type-casts may be performed using the standard C
cast-operator to cast:
- o
- Strings to ints and vice versa ((int)"123",
(string)55)
- o
- Strings to lists (list lst = (list)"hello")
Icmake offers the following subset of C’s
statements. They can be used as in the C programming language.
- o
- expression ;
The plain expression statement;
- o
- The compound statement
Variables of any type may be defined and initialized anywhere inside any
compound statement. The visibility of a variable starts at its
point of definition.
- o
- if (condition) statement
Inside the condition a variable may be defined and initialized. E.g,
if (string str = getText())
process(str);
In this example, process is not called if getText() returns an
empty string. The variable str does not exist either before or
after the if statement.
- o
- if (condition) statement else statement
As with the previous statement, inside the condition a variable may be
defined and initialized.
- o
- for (init; condition; increment) statement
Variables (of a single type) may be initialized (and optionally be defined)
in the init section. The init, condition and
increment sections may remain empty. The empty condition section is
interpreted as `always true’.
- o
- while (condition) statement
Inside the condition a variable may be defined and initialized.
A complementary do ... while() statement is not available. Note that
defining a variable, using an initialization expression means that the
initialization expressing is executed at each iteration of the
while statement. So the following statement will never end, and
will display a never ending stream of values 10:
while (int x = 10)
printf(x--, "\n");
- o
- return;, and return expression;
Plain return statements can be used in void functions, and
return expression statements are used in other type of functions.
The function main has return type void and so in main
only plain return statements can be used. By default an
icmake script’s exit value equals 0. Use the built-in
function exit (see below) to specify any other exit value.
- Be advised: the behavior of non-void functions not returning
values is undefined.
- o
- break
Leaves for and while statements, overruling the
statement’s condition.
- o
- continue
Continues with the next iteration of a for or while
statement.
- o
- exit(expression)
Ends the execution of an icmake-script. The expression must
evaluate to an int value, which becomes the script’s exit
value.
Icmake offers the following predefined functions, which can
be used anywhere in icmake scripts. The following overview is ordered
alphabetically by function name.
- o
- void arghead(string h)
Helper function of exec() (see also below at exec()): defines
the `argument head’, to be used with exec(). By default, the
`argument head’ is an empty string.
- o
- void argtail (string t)
Helper function of exec() (see also below at exec()): defines
the `argument tail’, to be used with exec(). By default, the
`argument tail’ is an empty string.
- o
- int ascii(string s)
Returns the first character of s as an int; e.g.,
ascii("A") returns 65;
- o
- string ascii(int i)
Returns i as a string, e.g., ascii(65) returns the string
"A";
- o
- string change_base(string file, string newbase)
Changes the basename of file, returns the changed name. E.g,
change_base("/path/demo.im", "out") returns
"/path/out.im";
- o
- string change_ext(string file, string newext)
Changes the extension of file, returns the changed name. E.g,
rss_changeExt("source.cc", "o") returns
"source.o";
- o
- string change_path(string file, string newpath)
Changes the path specification of file, returns the changed name.
E.g, change_path("tmp/binary", "/usr/bin")
returns "/usr/bin/binary". Note that the
/-separator is inserted if required.
- o
- string chdir(string newdir)
Changes the script’s working directory, returns the previous dir as
an absolute path.
- Use chdir(".") to obtain the current working directory,
chdir("") may be used to obtain the startup working
directory (this functionality was broken in releases before than 7.00, but
is now operational). The function terminates the icmake-script if
the specified newdir does not exist.
- o
- string chdir(int checking, string newdir)
Same functionality as the previous function, but by specifying
checking as P_NOCHECK. the function won’t terminate
the script. Rather, it will return the script’s current working
directory.
- o
- cmdhead(string h)
Helper function of exec() (see also below at exec()): Defines
a `command head’, to be used with exec(). By default, the
`command head’ is an empty string.
- o
- cmdtail(string t)
Helper function of exec() (see also below at exec()): Defines
a `command tail’, to be used with exec(). By default, the
`command tail’ is an empty string.
- o
- echo(int opt)
Controls echoing of called programs (and their arguments), specify
OFF if echoing is not requested. By default echo(ON) is
used.
- o
- string element(int index, list (or string) var)
Acts identical to the index operator: refer to the index ([])
operator in the section OPERATORS.
- o
- list eval(string str)
This function acts identically to the backtick operator. The example
provided with the backtick operator could therefore also have been written
like this:
printf(eval("ls")); // prints the elements in the current
// directory
- o
- exec(string cmd, ...)
Executes command with arguments. Each argument will be prefixed by
arghead()’s argument and postfixed by
argtail()’s argument. Note that no blanks are inserted
between arghead()’s contents, the argument proper, and
argtail()’s argument. All thus modified arguments are
concatenated, this time separated by single blanks, and then
cmdhead()’s contents are inserted between the command and
the first argument (on either side delimited by single blanks) and
cmdtail()’s contents are appended to the arguments (again,
separated by a single blank). PATH is searched to locate
cmd. 0 is returned.
- o
- exec(int checkcmd, string cmd, ...)
Same functionality as the previous function, but by specifying
checking as NOT_CHECKED the function won’t terminate
the script. Rather, it will return the called command’s exit
status, or 0x7f00 if the command wasn’t found.
- o
- execute(string cmd, string cmdhd, string arghd, ..., string
argtl, string cmdtl)
Same as exec(), but command head/tail and argument head/tail must be
specified.
- The actually executed command starts with cmd, followed by
cmdhd. Next is a series of arguments follows, each enclosed by
arghd and argtl. The command terminates with cmdtl. 0
is returned
- o
- execute(int checking, string cmd, string cmdhd, string arghd,
..., string argtl, string cmdtl)
Same functionality as the previous function, but by specifying
checking as NOT_CHECKED the function won’t terminate
the script. Rather, it will return the called command’s exit
status, or 0x7f00 if the command wasn’t found.
- o
- int exists(string file)
Returns a non-zero value if file exists, otherwise 0 is
returned.
- o
- list fgets(string file, list offset)
NOTE: in icmake version 8.00.00 the prototype of this function
was changed from list fgets(string file, int offset) to list
fgets(string file, list offset).
- The next line found at the offset contained in offset is read from
file. Pass an empty list to fgets to read file from
its beginning.
- It returns a list containing as its first element the contents of the read
line (without the \n line terminator), as its second element the
line’s terminator `\n’ (if encountered), and as its
third element the string OK if a line was successfully read,
FAIL if reading from file failed. When reading at EOF an empty list
is returned. The returned list may contain additional elements, which are
internally used by fgets when reading the next line.
- To read multiple lines, start by passing an empty list as
gets’s second argument. To read subsequent lines, pass the
previously returned list to fgets’s second argument.
- Here is an example showing how to read a complete file:
list ret;
while (1)
{
ret = fgets("filename", ret);
if (!ret)
break;
process(ret[0], ret[1]);
}
- o
- int fprintf(string filename, ...)
Appends all (comma separated) arguments to the file filename. Returns
the number of printed arguments.
- o
- int fprintf(string filename, string format, ...)
Appends all (comma separated) arguments to the file filename. Returns
the number of printed arguments.
- If format contains placeholders %1 .. %n the output is formatted
(see also strformat). Note that in this case argument counting
(also) starts beyond the format string: the first argument following
format is referred to as %1.
- o
- string get_base(string file)
Returns the base name of file. The base name is the file without its
path prefix and without its extension. The extension is all information
starting at the final dot in the filename. If no final dot is found, the
file name is the base name. E.g., the base name of a.b equals
a, the base name of a.b.c equals a.b, the base name
of a/b/c equals c.
- o
- string getch()
Returns the next pressed key as a string (pressing `Enter’ is not
required).
- o
- string get_dext(string file)
Returns the extension of file, including the separating dot. The
extension is all information starting at the filename’s final
dot.
- If no final dot is found, an empty string is returned.
- o
- list getenv(string envvar)
Returns the value of environment variable envvar in a list containing
two elements:
- the first element indicates whether the environment variable was defined
(value "1") or not (value "0");
the second element indicates the value of the environment variable.
- Enivironment variables are of the form variable=value, and if
defined the list’s second element contains value. If the
value is empty, the variable is defined, but has no text associated with
it.
- o
- string get_ext(string file)
Returns the extension of file, except for the separating dot. The
extension is all information starting at the final dot in the
filename.
- If no final dot is found, an empty string is returned.
- o
- int getpid()
Returns the process-id of the icmake byte code interpreter
icm-exec.
- o
- string gets()
Returns the next line read from the keyboard as a string. The line
entered on the keyboard must be terminated by an `Enter’ key, which
is not stored in the returned string.
- o
- string get_path(string file)
Returns the path-prefix of file. The path prefix is all information
up to (and including) the final directory separator (which is, depending
on the operating system, a forward- or backslash).
- If no path is found, an empty strring is returned.
- o
- int listfind(list lst, string str)
Returns the first index in lst where the string str is found,
or -1 if lst does not contain str.
- o
- int listlen(list l)
Returns the number of elements in list.
- o
- list listunion(list lhs, list rhs)
Returns a list containing the union of the elements in lhs and
rhs.
- o
- list listunion(list lst, string str)
Returns a list containing the union of the elements in lst and
str.
- o
- list makelist(string mask)
Returns a list of all files matching mask. E.g.,
makelist("*.c") returns a list containing all files
ending in .c.
- o
- list makelist(type, string mask)
Same as the previous function, but the type of the directory elements may be
specified as its first argument:
symbol |
meaning |
O_ALL |
obtain all directory entries |
O_DIR |
obtain all directories, including . and .. |
O_FILE |
obtain a list of files |
O_SUBDIR |
obtain all subdirectories |
Note that the pattern * will not match hidden entries under Unix-type
operating systems. Use .* for that.
- o
- list makelist(string mask, newer, string comparefile)
Returns list of all files matching mask which are newer than a provided
comparefile. Operator younger may be used instead of newer.
Note that newer and younger are operators, not strings.
- o
- list makelist([int = IS_FILE,] string mask, newer, string
comparefile)
Same as the previous function, but type may be specified as in
list makelist(type, string mask).
- o
- makelist(string mask, older, string comparefile)
See above; returns a list of files that are older than the comparefile.
- o
- makelist(type, string mask, older, string comparefile)
Same as the previous function, but type may be specified as in
list makelist(type, string mask).
- o
- int printf(...)
Shows all (comma separated) arguments to screen (i.e., the standard output
stream). Returns the number of printed arguments.
- o
- int printf(string format, ...)
Shows all (comma separated) arguments to screen (i.e., the standard output
stream). Returns the number of printed arguments (the format string
counts as one argument).
- If format contains placeholders %1 .. %n the output is formatted
(see also strformat).
- o
- int putenv(string envvar)
Adds envvar to the current (icmake) environment Use the
format: "VAR=value". Returns 0.
- o
- string resize(string str, int newlength) Returns a copy of string
str, resized to newlength characters. If newlength is
negative then an empty string is returned, if newlength exceeds
str’s length then the newly added characters are initialized
to blank spaces.
- o
- int sizeof(list l)
Deprecated: use listlen.
- o
- int sizeoflist(list l)
Deprecated: use listlen.
- o
- list stat(string entry)
Returns stat(2) information of directory entry entry as a
list. The returned list has two elements: element 0 is the attribute
value, element 1 contains the size of the file.
- Attributes are returned as bit-flags, composed from the following
predefined constants:
S_IFCHR S_IFDIR S_IFREG
S_IREAD S_IWRITE S_IEXEC
See the stat(2) manual page for the meanings of these constants.
- o
- list stat(checking, string entry)
Same as the previous function, but by specifying checking as
P_NOCHECK the function won’t terminate the script. Rather,
it returns stat(2)’s return value.
- o
- int strchr(string str, string chars)
Returns the first index in str where any of the characters in
chars is found, or -1 if str does not contain any of the
characters in chars.
- o
- int strlen(string str)
Returns the number of characters in str (not counting the final
0).
- o
- int strfind(string haystack, string needle)
Returns index in haystack where needle is found, or -1 if
needle is not contained in haystack.
This function was called strstr() in versions before
7.00.
- o
- int strformat(string format,...)
Returns a formatted string using placeholders %1 .. %2 to address arguments
following format.
Example:
void main()
{
int i = 10;
int j = 20;
string s1;
string s2;
// traditional approach:
s1 = (string)i + " " + (string)j + " " + (string)i;
// using strformat:
s2 = strformat("%1 %2 %1", i, j);
printf("s1 = %1, s2 = %2\n", s1, s2);
}
- o
- string strlwr(string s)
Returns a lower-case duplicate of s.
- o
- list strtok(string str, string separators)
Returns a list containing all substrings of str separated by one or
more (consecutive) characters in separators. E.g.,
strtok("hello icmake’s+world", " +")
returns the list containing the three strings "hello",
"icmake’s", and "world".
- o
- string strupr(string s)
Returns an upper-case duplicate of s.
- o
- string substr(string text, int offset, int count)
Returns a substring of text, starting at offset, consisting of
count characters. If offset exceeds (or equals) the
string’s size or if count <= 0, then an empty string is
returned. If offset is less than 0 then offset = 0 is
used.
- o
- int system(string command)
Executes command. The return value indicates the executed
command’s exit value. The string command may contain
redirection and/or piping characters.
- o
- int system(int checking, string command)
Same functionality as the previous function, but by specifying
checking as NOT_CHECKED the function won’t terminate
the script. Rather, it will return the called command’s exit
status, or 0x7f00 if the command wasn’t found.
- o
- string trim(string s)
Returns a copy of s without leading and trailing white spaces.
- o
- string trimleft(string str)
Returns a copy of s without leading white spaces.
- o
- string trim(string s)
Returns a copy of s without trailing white spaces.
void main
Icmake scripts must be provided with a user-defined
function main. The function main has three optional
parameters, which may be omitted from the last one (envp) to the
first (argc), like in C. Its full prototype is (note:
void return type):
void main(int argc, list argv, list envp)
In main(),
- o
- argc represents the number of elements in argv;
- o
- argv contains the arguments, with element 0 being equal to the name
of the .bim file;
- o
- envp contains the `environment’ variables. The function
listlen can be used to determine the number of its elements.
Elements in envp have the form variable=value.
Alternatively, the function getenv can be used to retrieve a
specific environment variable immediately. Example:
void main(int argc, list argv)
{
list toCompile;
int idx;
if (argc == 1)
usage(element(0, argv));
if (toCompile = altered("*.cc"))
{
for (idx = length(toCompile); idx--; )
compile(element(idx, toCompile));
if (getenv("dryrun")[0] == "0")
linking(element(2, argv));
}
}
Having initialized all global variables in order of their
definitions main is called by icmake’s run-time support
system to perform additional tasks.
Additionally defined user functions
Additional functions may be defined. Once defined, these functions
can be called. Forward referencing of either variables or functions is not
supported, but recursively calling functions is. As function declarations
are not supported indirect recursion is not supported either.
User-defined functions must have the following elements:
- o
- The function’s return type, which must be one of void, int,
string or list. There is no default type.
- o
- The function’s name, e.g., compile.
- o
- A parameter list, defining zero or more comma-separated parameters. The
parameters themselves consist of a type name (int, string,
or list) followed by the parameter’s identifier. E.g.,
(string outfile, string source).
- o
- A body surrounded by a pair of curly braces ({ and
}).
Function bodies may contain (optionally initialized) variable
definitions. Variable definitions start with a type name, followed by one or
more comma separated (optionally initialized) variable identifiers. If a
variable is not explicitly initialized it is initialized by default. By
default an int variable is initialized to 0, a string is
initialized to an empty string ("") and a list is
initialized to a list of zero elements.
In addition to variable definitions, bodies may contain zero or
more statements (cf. section FLOW CONTROL). Note that variables may
be defined (and optionally initialized) anywhere inside functions, and also
in if, for and while statements.
The behavior of icmake-scripts using non-void functions
that do not return values is not defined.
The mentioned paths are sugestive only and may vary over different
icmake-installations:
- o
- /usr/bin/icmake: the main icmake program;
- o
- /usr/bin/icmun: the icmake unassembler;
- o
- /usr/lib/icmake/icm-dep: the support program handling class- and
precompiled header dependencies;
- o
- /usr/lib/icmake/icm-pp: the preprocessor called by
icmake;
- o
- /usr/lib/icmake/icm-comp: the compiler called by
icmake;
- o
- /usr/lib/icmake/icm-exec: the byte-code interpreter called by
icmake;
The distribution (usually in /usr/share/doc/icmake)
contains a directory examples containing various examples of
icmake script. Note in particular the examples/icmbuild
subdirectory containing a general script for C++ and C program
maintenance.
Standard comment starting on lines containing preprocessor
directives may not extend over multiple lines.
Path names containing blanks are not supported.
This is free software, distributed under the terms of the GNU
General Public License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).