|
|
| |
icmake(1) |
A program maintenance utility |
icmake(1) |
icmake - A program maintenance (make) utility using a C-like
grammar
icmake [options] source[.im] [dest[.bim]] [-- [args]]
icmun bimfile
Icmake(1) is a generic tool handling program maintenance that can be used
as an alternative for make(1). It’s a generic tool in that
icmake-scripts, written in a language closely resembling the C
programming language, can perform tasks that are traditionally the domain of
scripting languages.
Icmake allows programmers to use a programming language
(closely resembling the well-known C-programming language) to define
the actions that are required for (complex) program maintenance. For this,
icmake offers various special operators as well as a set of support
functions that have shown their usefulness in program maintenance.
Although icmake scripts can be written from scratch, often
the required activities are highly comparable. This observation resulted in
the construction of two icmake scripts, which are now part of the
standard icmake distribution: icmstart(1), initializing a
directory for program development and icmbuild(1), handling the
actual program maintenance. Both come predefined as scripts tailored to
initializing and maintaining C++ programs (or, after minimal
adaptation, C programs), but can easily be adapted to other
programming languages. Both icmstart and icmbuild can be run
without explicitly calling icmake.
This man-page covers icmake (the program), its support
programs, and the syntax and facilities offered by icmake’s
scripting language. Refer to the icmstart(1)) man-page for
information about how a directory can be initialized (created) in which (by
default) a C++ or C program can be developed and refer to the
icmbuild(1) man-page for information about how icmbuild can be
used to handle program maintenance.
Icmake, its support programs, and scripts do not offer an
Integrated Development Environment (IDE). Icmake merely
performs tasks for which scripts can be written, and only a minimal set of
pre-defined scripts (icmstart and icmbuild) that repeatedly
have shown to be extremely useful when developing and maintaining programs
are included in the icmake distribution.
In its standard operation mode, icmake calls the following
programs:
- o
- icm-pp to preprocess the icmake file
- o
- icm-comp to byte-code compile the icmake s
- o
- icm-dep to handle class-dependencies (see sections ICM-DEP
in this and icmbuild(1)’s man-pages for more information
about icm-dep).
- o
- icm-exec to execute the byte-code file
The program icmun(1) disassembles compiled byte-code (.bim)
files. Icmun is mainly used for illustration, education, and
debugging. As it is not required for icmake’s daily use it is
not installed in a standard PATH directory but (since
icmake’s version 9.02.00) in icmake’s lib
directory, which commonly is /usr/lib/icmake.
Traditional make-utilities recompile sources once header files are
modified. When developing C++ programs this is often a bad idea, as
adding a new member to a class does not normally require you to recompile
all of the class’s source files. To handle class dependencies
icmbuld(1) may inspect class dependencies, (re)compiling sources of
dependent classes whenever necessary. By default, class-dependencies are not
interpreted, but this can easily be changed by activating the PRECOMP
and/or USE_ALL defines which are found in the file icmconf.
Refer to the icmconf(7) man-page for further details.
Precompiled header files can also be used. Precompiled header
files dramatically reduce the time that is required for compiling the source
files of classes. Refer to the icmconf(7) man-page (in particular the
description of the PRECOMP define) for further details.
This manpage describes icmake’s options in the next
section. Following that section icmake’s C-like
scripting language and support programs are described in the following
separate sections:
- o
- PREPROCESSOR DIRECTIVES
- supported preprocessor directives, like #include and
#define;
- o
- DATA TYPES
- int, list, string, and void (for functions);
- o
- PREDEFINED CONSTANTS
- like O_FILE, OFF, and S_IFREG;
- o
- OPERATORS
- like +, younger, and casts
- o
- FLOW CONTROL
- if, for, while, etc. (the switch is not available);
- o
- PREDEFINED FUNCTIONS
- executing programs, changing directories, operations on string and
list type variables, etc.;
- o
- USER DEFINED FUNCTIONS
- at least main, with or without its common parameters argc,
argv, and envp.
- o
- ICM-DEP
- the icm-dep dependency analyzer.
- o
- ICMUN
- a brief section about icmun.
Where available, single letter options are listed between parentheses beyond
their associated long-option variants.
- o
- --
This option separates icmake arguments from arguments passed to the
.bim file.
Arguments beyond -- are passed to the .bim file as-is, and are
available from the list argv parameter available from the
icmake script’s main function’s second
parameter (see below at section USER DEFINED FUNCTIONS). For some
options (see below) the -- separator is not required.
- o
- --about (-a)
Show information about icmake and terminate.
- o
- --compile (-c)
The icmake source file is compiled, generating a .bim file.
- o
- --execute (-e)
Execute the icmake .bim file, given as icmake’s first
file argument. Any additional arguments are passed to the .bim file as-is,
and -- should not be specified.
- o
- --force (-f)
The icmake source file is recompiled (even if the .bim file is
up-to-date) either when no other options are specified, or when in
combination with options --source and --tmpbin.
- o
- --help (-h)
Provides usage info.
- o
- --icm-dep (-d)
Calls /usr/lib/icmake/icm-dep, passing it all remaining arguments. If
no additional arguments are specified icm-dep’s short usage
information is shown to the std. output stream. See sections
ICM-DEP in this and icbuild(1)’s man-pages for more
information about the icm-dep support program. An overview of
icm-dep’s options follows below, after this overview of
icmake’s options.
- o
- --preprocess (-p)
The icmake source file is only preprocessed, and the preprocessed
file is written to icmake’s second file argument (by default
`source’.pim).
- o
- --source (-i)
The first argument is the icmake source file, the default binary file
is constructed if necessary. Any additional arguments are passed to the
.bim file as-is, and -- should not be specified.
- o
- --summary (-F)
The filenames and flags as well as an overview of all actions to be
performed by icmake are shown on the standard output stream.
- o
- -t tmpbim
The tmpbim argument following -t is the name of a temporary
.bim file, which is removed after icmake’s call. When
. is specified for tmpbim then the default temporary
directory, followed by icmake’s process-id, followed by
.bim is used.
- Following the name of the temporary .bim file the name of the
icmake source script must be specified. Any additional arguments
are passed to the .bim file as-is, and -- should not be specified;
After setting the source script file’s executable flag (chmod
+x script), and providing it with an initial line like this:
#!/usr/bin/icmake -t.
the icmake script can directly be called:
script arg1 arg2
in which case the icmake script `script’ is executed
while it receives the arguments script arg1 arg2.
- o
- -T directory
The specified directory is used to store temporary files. E.g., when
compiling an icmake script, the output of icmake’s
preprocessor is a temporary file which is removed on exit. By default
/tmp is used, unless /tmp is not a writable directory, in
which case the current user’s $HOME directory is used.
Implicit temporary filenames always start with the process id of the
current icmake process.
- o
- --version (-v)
Displays icmake’s version number.
The following preprocessor directives are recognized:
- o
- comment:
standard C comment (everything from /* through */) as
well as comment-to-end-of-line (line content starting at //) is
ignored.
- o
- Shell startup: The first line of the icmake-script may start with
#!path, where path defines the absolute location of the
icmake program. By making the script executable, it can be called
without explicitly calling icmake.
- E.g., if the first line of an (executable) icmakefile ’icm’
(without extension) contains
#!/usr/bin/icmake -i
then icm may be issued as a command, thus executing
/usr/bin/icmake -i icm ...
Alternatively,
#!/usr/bin/icmake -t /tmp/icm
may be used, resulting in the execution of
#!/usr/bin/icmake -t /tmp/icm icm ...
In this case the binary file is removed on exit.
- o
- #include "filename"
The file filename is included at the location of the directive
- o
- #include <filename>
The file filename is included at the location of the #include
directive; filename is searched in the colon-separated directories
specified by the IM environment variable. The first occurrence of
filename in the directories specified by the IM environment
variable is used.
- o
- #define identifier [definition]
The text identifier is replaced by definition. The definition
may contain references to already defined identifiers, using the
${identifier} format. If the ${identifier} hasn’t
been defined (yet), the text ${identifier} is literally kept. To
prevent infinite recursion at most 100 ${identifier} replacements
are allowed.
- Definitions continue at the next line if the last character on a line is a
backslash (\). (which is not included in the definition). The
preprocessor concatenates double-quuted strings, and double quoted strings
may not span multiple lines. Multiple blanks (outside of double quoted
strings) in definitions are contracted to a single blank space.
- The definition following the #define’s identifier is
optional. If omitted, the macro is defined, so it can be used in
#if(n)def directives (see below), but they are not replaced by any
text in icmake code statements.
- o
- #ifdef identifier
If the identifier macro was defined the next block of code (until a
matching #else or #endif directive was read) is
byte-compiled. Otherwise, the block of code is ignored.
- o
- #ifndef identifier
If the identifier macro was not defined the next block of code
(until a matching #else or #endif directive was detected) is
byte-compiled. Otherwise, the block of code is ignored.
- o
- #else
Terminates a #ifdef and #ifndef directive, reversing the
acceptance decision about the following code. Only one #else
directive can be associated with #if(n)def directives.
- o
- #endif
Terminates the preprocessor block starting at the matching #ifdef,
#ifndef or #else directive. The #endif directory and
its matching #if(n)def directive must be specified in the same
file.
- o
- #undef identifier
Remove identifier from the set of defined symbols. This does not
affect the specification of any previously defined symbols in which
identifier’s definition has been used. If identifier
hasn’t been defined a warning is issued.
Icmake supports the following five data and value types:
- o
- ASCII character constants
ASCII character constants are individual characters, surrounded by single or
double quotes. Single characters (e.g., ’a’)
represent the character itself. Standard escape sequences (e.g.,
’\n’) are supported and represent their standard
converted value (e.g., ’\n’ represents ascii value 10
(decimal)). Non-standard escape sequences (e.g.,
’\x’) represent the ascii character following the
escape character (so ’\x’ equals
’x’). Escape sequences consisting of three octal
digits represent the ascii character corresponding to the octal value
modulo 256 (e.g., ’\123’). Escape sequences
consisting of an x followed by two hexadecimal digits represent the ascii
character corresponding to the hexadecimal value (e.g.,
’\xa4’).
- o
- int
Integral values, ranging from -0x8000 through 0x7fff.
int constants may be specified as decimal numbers (starting with
digits 1 through 9), octal numbers (starting with 0, followed by one or
more octal digits) hexadecimal numbers (starting with 0x, followed by one
or more hexadecimal digits) or as ASCII character constants.
- o
- string
Text values: text (or `string’) constants are delimited by double
quotes. Multiple string constants may be concatenated, but a single string
constant may not span multiple lines. String constants separated by white
space only (i.e., blanks, newlines, comment) are concatenated and
represent one single string constant. To indicate an end-of-line in a
string constant use the \n escape sequence.
- ASCII character constants using double quotes can also be used in
arithmetic expressions if one of the operands is an int.
- Likewise, ASCII character constants using single quotes may be used in
situations where string operands are expected.
- o
- list
A data structure containing a series of individually accessible
string values. When a list contains elements, its first element has
index 0.
- List constants can also be defined. They consist of comma-separated
strings (which may be string variables or expressions returning
string values) and are surrounded by square brackets. E.g.,
list words = ["a", "list", "constant"];
- o
- void
Used with function definitions to indicate that the function does not return
a value.
Variables can be defined at the global level as well as inside
functions (not only at the top of compound statements but also between
statements and in the initialization section of for-statements). When
defined inside functions, the standard C scoping and visibility rules
apply. Variables are strongly typed, and cannot have type void.
Variables may be initialized when they are defined.
Initializations are expressions which may use predefined or user-defined
functions, constant values, and values of variables. Functions or variables
that are used for initialization must be visible at the initialization
point.
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 |
int-operators:
All C operators (including the ternary operator) are
available (except for pointer operators, as icmake does not support
pointers). They operate like their C-programming language’s
counterparts. Comparison operators return 1 if the comparison is true,
otherwise 0 is returned.
string-operators:
For string variables and/or constants the following
operators are available (a and b represent string
variables or constants):
- o
- a + b: returns a new string value containing the
concatenation of string values a and b. Note that
string constants may be directly concatetated (without using the
+ operator), e.g., the following two lines both define the string
"hello world":
"hello " "world"
"hello " + "world"
- o
- a += b: a must be a string variable, to which the
string variable or value b is appended.
- o
- string comparisons: operators == != <= >= < > != and
== return 1 if the comparison is true, otherwise 0. Ordering
comparison operators use the (case sensitive) character ordering defined
by the ASCII character set.
- o
- !a: the boolean ! (not) operator returns 1 if the string
a is empty, otherwise it returns 0. Strings containing white-space
characters are not empty.
- o
- a younger b, a newer b: returns 1 if file a is more recent
than file b. E.g., "source.cc" newer
"source.o". The files a and b do not have to
exist:
if both don’t exist 0 is returned;
if a doesn’t exist 0 is returned;
if b doesn’t exist, 1 is returned;
if they are equally old 0 is returned.
- The predefined function exists() (see below, section
PREDEFINED FUNCTIONS) can be used to test explicitly whether
a file exists.
- o
- a older b: returns 1 if file a is older than file b.
E.g., "libprog.a" older "source.o". The files
a and b do not have to exist:
if both don’t exist 0 is returned;
if a doesn’t exist, 1 is returned;
if b doesn’t exist 0 is returned;
if they are equally old 0 is returned.
- o
- []: the index operator retrieves a character from a string variable
or constant: it returns a string as an rvalue. Thus, the following
statement compiles OK:
// assume str1 and str2 are strings
str1 = str2[3];
but the following statement won’t compile:
str2[3] = "a";
If an invalid (out of bounds) index value is specified an empty string is
returned.
- o
- The `backtick` operator (`string cmd`)
A string placed between two backticks is executed by the popen(3)
function. The standard output gererated by the command that is stored in
the string argument is returned as a list. An empty list indicates that
the command could not be executed.
A command that could be executed but did not produce any output returns a
list containing one empty element. The command’s standard error
stream output is not collected by the backtick operator. However, standard
shell redirection may be used to collect the standard error
stream’s output. Example:
printf(`"ls"`); // prints the elements in
// the current directory
The predefined function eval(string cmd) behaves exactly like the
backtick operator: they are synonyms. )
list-operators:
For list type variables and/or values the following
operators are available:
- o
- a + b: returns a new list value containing the concatenation
of list values a and b. This is not a set
operation: if an element appears both in a and in b, they
will appear twice in the resulting list (set-addition is provided by the
built-in function listunion).
- o
- a - b: returns a new list value containing the elements in
a that are not present in b. This is a set-difference
operation: the returned list contains all elements in a that are
not elements of b.
- o
- a += b: elements in b are added to the elements in a,
which must be a list variable. This is not a set
operation.
- o
- a -= b: elements in b are removed from the elements in
a, which must be a list variable. This is a set
operation: all elements of a that are found in b are removed
from a.
- o
- list equality comparisons: operators != and == may be
applied to list values or variables. Operator == returns 1
if both lists have element-by-element identical elements, otherwise 0 is
returned. Operator != reverses the result of ==.
- o
- !a: the boolean ! operator returns 1 if the list a is
empty, otherwise 0 is returned.
- o
- []: the index operator retrieves a list element from a list
variable: it returns a string as an rvalue. Therefore, the
following statement compiles OK:
// assume lst is a list, str is a string
str = lst[3];
but the following statement won’t compile:
lst[3] = str;
If an invalid (out of bounds) index value is specified an empty string is
returned.
Casting:
Type-casts using the standard C cast-operator can be used
to cast
- o
- strings to ints and vice versa ((int)"123", (string)55)
If the content of a string does not represent a (decimal) int value 0
the cast returns 0;
- o
- Strings to lists (list lst = (list)"hello"): this returns
a list having one element (hello) (note that casting a string to a
list as shown is overkill as list lst = ["hello"]
performs the same initialization).
Icmake offers the following subset of C’s statements. They
can be used as in the C programming language.
- o
- expression ;
The plain expression statement;
- o
- The compound statement
Variables of any type may be defined and initialized anywhere inside any
compound statement. The visibility of a variable starts at its
point of definition.
- o
- if (condition) statement
Inside the condition a variable may be defined and initialized. E.g,
if (string str = getText())
process(str);
In this example, process is not called if getText() returns an
empty string. The variable str does not exist either before or
after the if statement.
Initialization and then using the variable in a subsequent expression,
separated by a semicolon from the definition is not supported (e.g., if
(string str = getText() ; str) cannot be used).
- o
- if (condition) statement else statement
Like the previous statement, inside the condition a variable may be defined
and initialized.
- o
- for (init; condition; increment) statement
Variables (of a single type) may be initialized (and optionally be defined)
in the init section. The init, condition and
increment sections may remain empty. The empty condition section is
interpreted as `always true’.
- o
- while (condition) statement
Inside the condition a variable may be defined and initialized.
A complementary do ... while() statement is not available. Note that
defining a variable, using an initialization expression means that the
initialization expressing is executed at each iteration of the
while statement. Thus the following statement never ends, and
displays a never ending stream of values 10:
while (int x = 10)
printf(x--, "\n");
- o
- return;, and return expression;
Plain return statements can be used in void functions, and
return expression statements are used in other type of functions.
The function main has return type void and so in main
only plain return statements can be used. By default an
icmake script’s exit value equals 0. Use the built-in
function exit (see below) to specify any other exit value.
- Be advised: the behavior of non-void functions not returning
values is undefined.
- o
- break
Leaves for and while statements, overruling the
statement’s condition.
- o
- continue
Continues with the next iteration of a for or while
statement.
- o
- exit(expression)
Ends the execution of an icmake-script. The expression must
evaluate to an int value, which becomes the script’s exit
value.
Icmake provides the following predefined functions, which can be used
anywhere in icmake scripts. The functions are ordered by categories,
and within categories they are ordered alphabetically by function name. Five
categories are distinguished:
- o
- Functions operating on ints:
these functions only have one purpose: they receive int arguments and
simply process those arguments;
- o
- Functions operating on lists:
these functions only have one purpose: their main argument is a list,
which is somehow manipulated;
- o
- Functions operating on strings:
these functions only have one purpose: their main argument is a
string, which is somehow manipulated;
- o
- Functions manipulating filenames:
these functions receive filenames as their string arguments, and
return modified filenames (e.g., by changing the argument’s
extension);
- o
- System-related functions:
these functions interface to facilities provided by the operating system,
like executing programs or changing the environment.
Functions operating on ints:
- o
- string ascii(int value)
returns value as a string: ascii(65) returns the string
"A";
- o
- echo(int opt)
controls echoing of called programs (and their arguments), specify
OFF if echoing is not requested. By default echo(ON) is
used;
Functions operating on lists:
- o
- string element(int index, list (or string) var)
acts identically to the index operator: refer to the index ([])
operator in section OPERATORS.
- o
- list fgets(string file, list offset)
see the system functions section;
- o
- int listfind(list lst, string str)
returns the first index in lst where the string str is found,
or -1 if lst does not contain str;
- o
- int listlen(list l)
returns the number of elements in list;
- o
- list listunion(list lhs, list rhs)
returns a list containing the union of the elements in lhs and the
elements of rhs;
- o
- list listunion(list lst, string str)
returns a list containing the union of the elements in lst and
str;
Functions operating on strings:
- o
- int ascii(string str)
returns the first character of str as an in:
ascii("A") returns 65;
- o
- string resize(string str, int newlength) returns a copy of string
str, resized to newlength characters. If newlength is
negative then an empty string is returned, if newlength exceeds
str’s length then the newly added characters are initialized
to blank spaces;
- o
- int strchr(string str, string chars)
returns the first index in str where any of the characters in
chars is found, or -1 if str does not contain any of the
characters in chars;
- o
- int strlen(string str)
returns the number of characters in str (not counting the terminating
NUL-character);
- o
- int strfind(string haystack, string needle)
returns index in haystack where needle is found, or -1 if
needle is not found in haystack;
- o
- int strformat(string format, argument(s))
returns a string constructed from the format string containing
placeholders %1 .. %2 to refer to arguments following the format string.
The specification %1 refers to the first argument following the format
string. If fewer arguments than n are provided then additional 0
arguments are provided by icmake. Example:
void main()
{
string s2 = = strformat("%1 %2 %1\n", 10, 20);
printf("s2 = ", s2); // shows: s2 = 10 20 10
}
- o
- string strlwr(string str)
returns a lower-case duplicate of str;
- o
- list strtok(string str, string separators)
returns a list containing all substrings of str separated by one or
more (consecutive) characters in separators: strtok("hello
icmake’s+world", " +") returns a list containing
the three strings "hello",
"icmake’s", and "world";
- o
- string strupr(string str)
returns an upper-case duplicate of str.
- o
- string substr(string text, int offset, int count)
returns a substring of text, starting at offset, consisting of
count characters. If offset exceeds (or equals) the
string’s size or if count <= 0, then an empty string is
returned. If offset is less than 0 then offset = 0 is
used;
- o
- string trim(string str)
returns a copy of str without leading and trailing white spaces;
- o
- string trimleft(string str)
returns a copy of str without leading white spaces;
- o
- string trimright(string str)
Returns a copy of str without trailing white spaces;
Functions manipulating filenames:
- o
- string change_base(string file, string base)
returns file whose base name is changed into base:
change_base("/path/demo.im", "out") returns
"/path/out.im";
- o
- string change_ext(string file, string ext)
returns file whose extension is changed into ext:
rss_changeExt("source.cc", "o") returns
"source.o". The extension of the returned string
is separated from the file’s base name by a single dot (e.g.,
rss_changeExt("source.", ".cc") returns
"source.cc");
- o
- string change_path(string file, string path)
return file whose path is changed into path:
change_path("tmp/binary", "/usr/bin") returns
"/usr/bin/binary". To remove the path specify path
as an empty string;
- o
- string get_base(string file)
returns the base name of file. The base name is the file without its
path prefix and without its extension. The extension is all information
starting at the final dot in the filename. If no final dot is found, the
file name is the base name. E.g., the base name of a.b equals
a, the base name of a.b.c equals a.b, the base name
of a/b/c equals c;
- o
- string get_dext(string file)
returns the extension of file, including the separating dot (hence
the d in dext). The extension is all information starting at
the filename’s final dot. If file does not have a final dot
then an empty string is returned;
- o
- string get_ext(string file)
returns the extension of file, without the separating dot. The
extension are all characters in file starting at
file’s final dot. If no final dot is found, an empty string
is returned;
- o
- string get_path(string file)
returns file’s path-prefix. The path prefix is all information
up to (and including) the final directory separator (which is, depending
on the operating system, a forward slash or a backslash). If no path is
found, an empty strring is returned;
System-related functions:
- o
- void arghead(string h)
helper function of exec() (see also below at exec()): defines
the `argument head’ that is used with exec(). By default,
the `argument head’ is an empty string. The argument head is text
that is prefixed to exec arguments, like a directory in which
provided arguments are found;
- o
- void argtail (string t)
helper function of exec() (see also below at exec()): defines
the `argument tail’ that is used with exec(). By default,
the `argument tail’ is an empty string. The argument tail is text
that is appended to exec arguments, like the extensions of files
that are passed as arguments to exec;
- o
- string chdir([int check,] string dir)
returns the script’s working directory at the point where
chdir is called as an absolute path, and changes the
script’s working directory to dir (which may be specified as
absolute or relative to the script’s current working directory).
The first argument is optional: if omitted and the change of directory
cannot be performed then the icmake-script ends with exit value 1;
by specifying P_NOCHECK the function won’t terminate the
script but merely returns the script’s current working
directory.
- Use chdir(".") to merely obtain the current working
directory; use chdir("") to obtain the script’s
startup working directory;
- o
- cmdhead(string h)
helper function of exec() (see also below at exec()). Defines
a `command head’ that is used with exec(). By default it is
an empty string. It can be used to specify, e.g., compiler options when
the arguments themselves are modified by arghead and
argtail. Cmdhead is used unmodified;
- o
- cmdtail(string t)
helper function of exec() (see also below at exec()). Defines
a `command tail that is used with exec(). By default it is an empty
string. It can be used to specify a final argument (not modified by
arghead and argtail);
- o
- list eval(string str)
this function can be used instead of the backtick operator. The example
provided with the backtick operator could therefore also have been written
like this:
printf(eval("ls")); // prints the elements in the current
// directory
- o
- int exec([int check,] string cmd, argument(s))
Executes the command cmd with (optional) arguments. Each argument is
prefixed by arghead and postfixed by argtail. Note that no
blanks are inserted between arghead, argument(s), and
argtail. The thus modified arguments are concatenated, separated by
single blanks. Cmdhead is inserted between cmd and the first
argument (delimited by single blanks) and cmdtail is appended to
the arguments, separated by a single blank. PATH is searched to
locate cmd. 0 is returned.
- The first argument is optional: if omitted and the command does not return
0 the icmake script terminates. By specifying P_NOCHECK
exec won’t terminate the script but returns the called
command’s exit status, or 0x7f00 if the command
wasn’t found;
- o
- execute([int checking,] string cmd, string cmdhead, string
arghead, argument(s), string argtail, string cmdtail)
Same functionality as the previous function, but the cmdhead,
arghead, argtail, and cmdtail are explicitly specified (and
are reset to empty strings after executing cmd);
- o
- int exists(string file)
if file exists, 1 is returned, otherwise 0 is returned;
- o
- list fgets(string file, list offset)
the next line found at offset value offset[3] is read from
file. Pass an empty list to fgets to read file from
its beginning.
- The returned list has four elements:
- its first element ([0]) contains the read line (without the line’s
\n line terminator);
- its second element ([1]) contains the line’s \n line
terminator (or an empty string if the line was not terminated by a
\n);
- its third element ([2]) contains the string OK if the line was
successfully read and FAIL if reading from file failed;
- its fourth element ([3]) contains the offset beyond the last read
byte.
- To read multiple lines, pass the returned list as argument to
fgets:
list ret;
while (ret = fgets("filename", ret))
{
process(ret);
}
- o
- int fprintf(string filename, argument(s))
appends all (comma separated) arguments to the file filename. Returns
the number of printed arguments.
- If the first argument (following filename) contains placeholders
(%1, %2, ... %n) then that argument is considered a format string
(see also the function strformat in the string functions section
for additional information about format strings). Some examples:
fprintf("out", "hello", "world", ’\n’);
fprintf("out", "%1 %2\n", "hello", "world");
- o
- string getch()
returns the next pressed key as a string (pressing the `Enter’-key is
not required);
- o
- list getenv(string envvar)
returns the value of environment variable envvar in a list containing
two elements:
- if the first element ([0]) is "1" then the environment
variable was defined;
- environment variables are of the form variable=value. If element
[0] is "1" then the returned list’s second
element [1] holds the value part of the environment variable, which
is empty if the environment variable is merely defined;
- o
- int getpid()
returns the process-id of the icmake byte code interpreter
icm-exec;
- o
- string gets()
returns the next line read from the keyboard as a string. The line
contains all enteed characters until the `Enter’-key was pressed.
The `Enter’-key’s value itself is not stored in the returned
string;
- o
- list makelist([int type = O_FILE], string mask)
the argument type is optional, in which case O_FILE is used.
Makelist returns a list of all type entries matching
mask. E.g., makelist("*.c") returns a list
containing all files ending in .c. For type one of the
following set of values can be used to obtain a more specific selection of
directory entries:
symbol |
meaning |
O_ALL |
obtain all directory entries |
O_DIR |
obtain all directories, including . and .. |
O_FILE |
obtain a list of files |
O_SUBDIR |
obtain all subdirectories |
In Unix-type operating systems the pattern * does not match entries
starting with a dot (hidden entries). To obtain a list of such entries use
the pattern .*;
- o
- list makelist([int type = O_FILE,] string mask, {newer,older},
string comparefile)
the (optional) parameter type may be specified as in the previous
variant of makelist. The third parameter must be either
newer (or younger) or older. A list of all files is
returned matching mask which are, resp., newer or older than a provided
comparefile. Note that newer and younger are
operators, not strings;
- o
- int printf(argument(s))
the function’s (comma separated) arguments are written to the
standard output file. If the first argument contains %1, %2, ... %n
specifications then it’s considered a format string (see also the
function strformat in the string functions section for additional
information about format strings). Like fprintf printf returns the
number of printed arguments;
- o
- int putenv(string envvar)
adds envvar to the current icmake-script environment. Use the
format: "VAR=value". The function returns 0;
- o
- list stat([int check,] string entry)
Returns stat(2) information of directory entry entry as a
list. The first argument is optional: if omitted and calling the system
stat function fails then the icmake-script ends with exit
value 1; by specifying P_NOCHECK the function won’t
terminate the script but returns the return value of the system
stat function.
- The returned list has two elements:
- its first element ([0]) holds the entry’s attributes. Attributes
are returned as or-ed combinations of the following bit-flags (cf.
stat(2)):
S_IFCHR S_IFDIR S_IFREG
S_IREAD S_IWRITE S_IEXEC
its second element ([1]) contains the entry’s size in bytes;
- o
- int system([int check,] string command)
executes command using the system(3) function. The first
argument is optional: if omitted and calling the system(3) function
does not return 0 then the icmake-script ends with exit value 1; by
specifying P_NOCHECK icmake’s system function
won’t terminate the script but returns the return value of the
system(3) function (normally the executed command’s exit
value). The string command may use redirection and/or piping;
void main
Icmake scripts must be provided with a user-defined
function main. The function main has three optional
parameters, which may be omitted from the last one (envp) to the
first (argc), like in C. Its full prototype is (note:
void return type):
void main(int argc, list argv, list envp)
In main the parameter
- o
- argc represents the number of elements in argv;
- o
- argv contains the arguments, with element 0 being equal to the name
of the .bim file;
- o
- envp contains the `environment’ variables. The function
listlen can be used to determine the number of its elements.
Elements in envp have the form variable=value.
Alternatively, the function getenv can be used to retrieve a
specific environment variable immediately. Example (the implementations of
the user-defined functions usage, modified, and
compile are left as an exercise for the reader):
void main(int argc, list argv)
{
if (argc == 1)
usage(element(0, argv));
if (list toCompile = modified("*.cc"))
{
for (int idx = listlen(toCompile); idx--; )
compile(toCompile[idx]);
}
}
After initializing all global variables in order of their definitions
main is called by icmake’s run-time support system.
Icmake scripts end once main returns (or exit is
called by the script).
Additionally defined user functions
Additional functions may be defined. Once defined, they can be
called. Forward referencing of either variables or functions is not
supported, but recursively calling functions is. As function declarations
are not supported indirect recursion is not supported.
User-defined functions must have the following elements:
- o
- The function’s return type, which must be one of void, int,
string or list. There is no default type.
- o
- The function’s name, e.g., compile.
- o
- A parameter list, defining zero or more comma-separated parameters. The
parameters themselves consist of a type name (int, string,
or list) followed by the parameter’s identifier. E.g.,
(string outfile, string source).
- o
- A body surrounded by a pair of curly braces ({ and
}).
Function bodies may contain (optionally initialized) variable
definitions. Variable definitions start with a type name, followed by one or
more comma separated (optionally initialized) variable identifiers. If a
variable is not explicitly initialized it is initialized by default. By
default an int variable is initialized to 0, a string is
initialized to an empty string ("") and a list is
initialized to an empty list.
In addition to variable definitions, bodies may contain zero or
more statements (cf. section FLOW CONTROL). Note that variables may
be defined (and optionally initialized) anywhere inside functions, and also
in the conditions of if and while statements and in the
initialization section of for statements.
The behavior of icmake-scripts using non-void functions
that do not return values is not defined.
The icm-dep program is a support program for icmake to determine
source-file dependencies. It is called automatically when USE_ALL or
PRECOMP is specified in the icmconf file that is processed by
icmake.
To start its work, the dependencies-analyzer icm_dep needs
one command-line argument: go. Any other argument results in
icm_dep performing a `dry run’: it then performs all its
duties (and verbose messages are displayed as if go had been
specified), but no files (precompiled headers or USE_ALL files) are
touched or removed. If neither options nor arguments are specified
icm_dep writes its usage summary to the standard output.
Options of icm-dep may immediately after
icmake’s --icm-dep option be specified. The following
options are recognized:
- o
- --classes=filename (-c)
by default, icm-dep inspects dependencies of the classes whose
directories are mentioned in the file CLASSES. Furthermore, if the
icmconf(7) file specifies PARSER_DIR and SCANNER_DIR
then those directories are also considered. Use this option if instead of
CLASSES another file should be inspected;
- o
- --help (-h)
icm-dep writes a summary of its usage to the standard output and
terminates;
- o
- --icmconf=filename (-i)
by default icm-dep inspects the content of icmconf files,
looking for USE_ALL and PRECOMP specifications. Use this
option if instead of icmconf another file should be inspected;
- o
- --mainih=mainheader (-m)
the icmconf file uses the #define IH parameter to specify the
suffix of class header files that should be precompiled, their filenames
being equal to the names of the classes mentioned in the CLASSES
file. CLASSES does not specify a top-level directory. The name of
the top-level header file to precompile can be specified using this
option. By default it is main.ih;
- o
- --gch
by default precompiled header files are inspected if icmconf contains
a #define PRECOMP specification. If it does not, but precompiled
headers should nonetheless be inspected, the option --gch can be
provided;
- o
- --no-gch
by default precompiled header files are inspected if icmconf contains
a #define PRECOMP specification. If in that case precompiled
headers should not be inspected, the option --no-gch can be
provided;
- o
- --no-use-all
by default files named at the #define USE_ALL specification are
inspected if icmconf contains such a specification. To suppress
inspections of `USE_ALL’ files provide this option;
- o
- --use-all=filename
by default files named at #define USE_ALL specifications of
icmconf files are inspected. If the USE_ALL define is not
specified but `USE_ALL’ files should nonetheless be
inspected, then provide this option, specifying the name of files to use
as USE_ALL files;
- o
- --verbose (-V)
this option can be specified multiple times. The number of times it is
specified determines icm_dep’s verbosity. If not used then
icm-dep silently performs its duties. If specified once, then
icm-dep reports to the standard output what actions it performs; if
specified twice it also reports the class dependencies; if specified more
often it reports what files it encountered and what situations caused it
to make its decisions;
- o
- --version (-v)
icm-dep reports its version number to the standard output and
terminates.
The icmun program expects one argument, the binary (bimfile) file
produced by `icmake -c’. It disassembles the binary file
an shows the assembler instructions and structure of the binary file. Note
that in standard installations icmun is not located in one of the
directories of the PATH environment variable, but is located in the
/usr/lib/icmake directory.
As an illustration, assume the following script is compiled by
icmake (e.g., by calling icmake -c demo.im):
void main()
{
printf("hello world");
}
the resulting demo.bim file can be processed by icmun (e.g.,
calling /usr/lib/icmake/icmun demo.bim. Icmun then writes the
following to the standard output fle:
icmun by Frank B. Brokken (f.b.brokken@rug.nl)
icmun V9.03.00, copyright (c) GPL 1992-2020.
Binary file statistics:
strings at offset 0x0025
variables at offset 0x0031
filenames at offset 0x0031
first instruction at offset 0x001f
String constants dump:
"hello world"
Disassembled code:
[0014] 06 00 00 push string "hello world"
[0017] 05 01 00 push int 0001
[001a] 1b 1d callrss 29 (printf)
[001c] 1c 02 add sp, 2
[001e] 23 ret
[001f] 21 14 00 call [0014]
[0022] 04 push int 0
[0023] 24 pop reg
[0024] 1d exit
The mentioned paths are sugestive only and may vary over different
icmake-installations:
- o
- /usr/bin/icmake: the main icmake program;
- o
- /usr/bin/icmbuild: the wrapper program around the icmbuild
script handling standard program maintenance;
- o
- /usr/bin/icmstart: an icmake-script that is can be used to
create the startup-files of new projects;
- o
- /usr/lib/icmake/icm-comp: the compiler called by
icmake;
- o
- /usr/lib/icmake/icm-exec: the byte-code interpreter called by
icmake;
- o
- /usr/lib/icmake/icm-dep: the support program handling class- and
precompiled header dependencies;
- o
- /usr/lib/icmake/icm-pp: the preprocessor called by
icmake;
- o
- /usr/lib/icmake/icmun: the icmake unassembler.
The distribution (usually in /usr/share/doc/icmake) contains a directory
examples containing additional examples of icmake script.
icmbuild(1), icmconf(7), icmstart(1),
icmstart.rc(7), make(1)
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.
This is free software, distributed under the terms of the GNU General Public
License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |