| SHTOOL(1) | 14-Jun-2001 | SHTOOL(1) |
|---|
Only for libtool one always has to grab the latest copy. But because it's just two files (ltmain.sh and ltconfig), keeping a source trees in sync is not too complicated (especially not if using the handy libtoolize program). But the etc/ shell script mess is nasty, especially because there is no master version on the net. Additionally everytime one starts a new project, one has to establish a new source tree. For a GNU hacker it's immediately clear that autoconf and friends are part of the game. But which etc/ shell scripts are needed this time? And from which existing source tree to copy them from? Hmmm... the same procedure as last year?!
This is a pure aesthetical issue, of course. But keep in mind that hacking is a piece of art. And a well layouted source tree is a piece of art for real hackers, too. Oh, and for those who really insist on a technical reason: it's also easier to upgrade a single file than multiple files ;)
The str can contain special ``%x'' constructs which which are expanded before the output is written if option ``-e'' is used. Currently the following constructs are recognized: ``%B'' for switching to terminal bold mode, ``%b'' for switching terminal mode back to normal display mode, ``%u'' for the current user name, ``%U'' for the current user id (numerical), ``%g'' for the current group name, ``%G'' for the current group id (numerical), ``%h'' for the current hostname, ``%d'' for the current domain name, ``%D'' for the current day of the month, ``%M'' for the current month (numerical), ``%m'' for the current month name and ``%Y'' for the current year.
The trick of this command is that it provides a portable ``-n'' option and hides the gory details needed to find out the environment details.
Examples:
# shell script shtool echo -n -e "Enter your name [%B%u%b]: "; read name shtool echo -e "Your Email address might be %u@%h%d" shtool echo -e "The current date is %D-%m-%Y"
The default for spec is ``dmy'' which means an output of ``<day> <month> <year>''. Any combination of the chars ``d'', ``m'' and ``y'' or allowed for spec.
The trick of this command is that it provides a portable way to find out the date of a file or directory while still allowing one to specify the format of the date display.
Examples:
# shell script shtool mdate -n / shtool mdate -f '/' -z -d -o ymd foo.txt shtool mdate -f '-' -s foo.txt
The trick of this command is that it avoids to use the unportable tr(1) and fmt(1) commands and instead is based entirely on sh(1), awk(1) and sed(1) functionality.
Example:
# shell script shtool table -F , -w 5 -c 4 "1,2,3,4,5,6,7,8,9,10,11,12"
The trick of this command is that it provides a portable and easy to use way to display such nice and psychologically important process indicators.
Example:
# shell script
configure 2>&1 |\
tee logfile |\
shtool prop -p "Configuring sources"
The trick of this command is that it can rename multiple files at once and preserves the timestamps if the contents isn't changed.
Examples:
# shell script shtool move -v -e '*.txt' %1.asc
# Makefile
scanner.c: scanner.l
lex scanner.l
shtool move -t -p lex.yy.c scanner.c
Additionally program executables is stripped with strip(1) after installation if option ``-s'' is used. Option ``-C'' is like ``-c'', except if the destination file already exists and the files are the same, the source is just removed. Option ``-e'' can be used one or multiple times to apply one or more sed(1) commands on-the-fly to the contents of the input file before the output file is created. Option ``-v'' (verbose) can be used to enable the output of extra processing information. Option ``-t'' (trace) can be used to enable the output of the essential shell commands which are executed.
The trick of this command is that it provides the functionality of BSD install(1) in a portable emulated way.
Example:
# Makefile
install:
:
shtool install -c -s -m 4755 foo $(bindir)/
shtool install -c -m 644 foo.man $(mandir)/man1/foo.1
shtool install -c -m 644 -e "s/@p@/$prefix/g" foo.conf $(etcdir)/
The trick of this command is that it provides both a portable ``-p'' functionality and the ability to be smart if the directory already exists which is important for installation procedures.
Example:
# Makefile
install:
shtool mkdir -f -p -m 755 $(bindir)
shtool mkdir -f -p -m 755 $(mandir)/man1
:
The trick of this command is that it tried hard to calculate the paths to get the maximum possible relative paths.
Example:
# shell script shtool mkln -s foo/bar baz/quux
Option ``-v'' (verbose) can be used to enable some displaying of processing information. Option ``-t'' (trace) can be used to display all commands which are executed in order to construct dst-dir. Option ``-a'' (all) can be used to really shadow all files and directories in src-dir. Per default CVS related files and directories, backup files, object files, etc. are not shadowed.
The trick of this is that is provides such a high-level functionality with a single command and hides all gory details.
Example:
# shell script shtool mkshadow -v -a . /tmp/shadow
The trick is that this is more convinient that having to set the permissions manually or with a large file list.
Example:
# Makefile.in
dist:
shtool fixperm -v *
...
The input files are given by the file or directory arguments path. Directories are expanded before the comma-separated exclude (option -e) patterns (grep regular expressions) are used to filter the list. The default filter is ``CVS,\\.cvsignore,\\.[oa]\$''. Then the tarball is created with its files owned by user (option -u) and group (option -g). Finally the resulting tarball is piped through an optional compression (option -c) program and written to the output file tarball (option -o). Option ``-v'' can be used to display the files which are stored in the tarball. Option ``-t'' (trace) can be used to enable the output of the essential shell commands which are executed.
The trick of this command is that it combines the complex process of rolling a good tarball into a single command.
Example:
# Makefile.in
dist:
...
V=`shtool version -d short ...'; \
shtool tarball -o foobar-$$V.tar.gz -c 'gzip -9' \
-u bar -g gnu -e 'CVS,\.cvsignore' .
# configure.in OS=`shtool guessos`
The trick of this command is the automatic handling of archive members which is especially interesting if one wants to construct a (usually top-level) library archive out of pre-build sub-library archives (usually staying inside subdirs) in a large source tree.
Example:
# Makefile
AR=ar
RANLIB=ranlib
:
OBJS=foo.o bar.o
LIBS=baz/libbaz.a quux/libquux.a
:
libfoo.a: $(OBJS) $(LIBS)
shtool arx -C $(AR) rc libfoo.a $(OBJS) $(LIBS)
$(RANLIB) libfoo.a
``SLO_DIRS_OBJ'' and ``SLO_LIBS_OBJ'' contains the ``-L'' and ``-l'' options of static libraries, ``SLO_DIRS_PIC'' and ``SLO_LIBS_PIC'' contains the ``-L'' and ``-l'' options of static libraries containing PIC (``Position Independent Code'') and ``SLO_DIRS_DSO'' and ``SLO_LIBS_DSO'' contains the ``-L'' and ``-l'' options of shared libraries. The -p option can be used to change the default variable prefix from "SLO_" to str.
The intent of this separation is to provide a way between static and shared libraries which is important if one wants to link custom DSOs against libraries, because not all platforms all one to link these DSOs against shared libraries. So one first has to separate out the shared libraries and link the DSO only against the static libraries. One can use this command also to just sort the options.
Example:
# configure.in
LINK_STD="$LDFLAGS $LIBS"
eval `shtool slo $LINK_STD`
LINK_DSO="$SLO_DIRS_OBJ $SLO_LIBS_OBJ $SLO_DIRS_PIC $SLO_LIBS_PIC"
:
The operation is to parse special constructs in files, generate a few things out of these constructs and insert them at position mark in tfile by writing the output to ofile. Additionally the files are never touched or modified. Instead the constructs are removed later by the cpp(1) phase of the build process. The only prerequisite is that every file has a ``#include "ofile"'' at the top.
This command provides the following features: First it avoids namespace pollution and reduces prototyping efforts for internal symbols by recognizing functions and variables which are defined with the storage class identifier ``cname''. For instance if cname is ``intern'', a function ``intern void *foobar(int quux)'' in one of the files is translated into both a ``#define foobar __foobar'' and a ``extern void *foobar(int quux);'' in ofile. Additionally a global ``#define cname /**/'' is also created in ofile to let the compiler silently ignore this additional storage class identifier.
Second, the library source files usually want to share typedefs, #defines, etc. over the source file boundaries. To achieve this one can either place this stuff manually into tfile or use the second feature of scpp: All code in files encapsulated with ``#if dname ... #endif'' is automatically copied to ofile. Additionally a global ``#define dname 0'' is also created in ofile to let the compiler silently skip this parts (because it was already found in the header).
Option ``-v'' can be used to enable some processing output. Option ``-p'' can be used to make the decision whether to overwrite ofile independent of the generated ``#line'' lines. This is useful for Makefiles if the real contents of ofile will not change, just line numbers. Option ``-f'' (which can occur multiple times) can be used to apply one or more pre-processing sed(1) filter commands (usually of type ``s/.../.../'') to each input file before their input is parsed.
Example:
# Makefile
SRCS=foo_bar.c foo_quux.c
foo_p.h: foo_p.h.in
shtool scpp -o foo_p.h -t foo_p.h.in \
-M %%MARK%% -D cpp -C intern $(SRCS)
/* foo_p.h.in */ #ifndef FOO_P_H #define FOO_P_H %%MARK%% #endif /* FOO_P_H */
/* foo_bar.c */
#include "foo_p.h"
#if cpp
#define OURS_INIT 4711
#endif
intern int ours;
static int myone = 0815;
intern int bar(void)
{
ours += myone;
}
/* foo_quux.c */
#include "foo_p.h"
int main(int argc, char *argv[])
{
int i;
ours = OURS_INIT
for (i = 0; i < 10; i++) {
bar();
printf("ours now %d\n", ours);
}
return 0;
}
When option ``-i'' is used, the current version in file is updated by increasing one element of the version where knob can be one of the following: ``v'' for increasing the version by 1 (and resetting revision and level to 0), ``r'' for increasing the revision by 1 (and resetting level to 0) or ``l'' for increasing the level by 1. Option ``-e'' can be used to interactively enter a new version.
Unless option ``-e'', ``-i'' or ``-s'' is specified, the performed action is to display the current version. Option ``-d'' then can be used to control the display type: "short`` for a short version display, ''long`` for a longer version display, ''hex`` for a hexadecial display of the version and ''libtool" for a format suitable for use with GNU libtool.
The hexadecimal format for a version v.rtl is VVRRTLL where VV and RR directly correspond to v and r, T encodes the level type as 9, 2, 1, 0 (representing s, p/., b, a in this order) and LL is either directly corresponding to l or set to 99 if level type is s.
Example:
# shell script shtool version -l c -n FooBar -p foobar -s 1.2b3 version.c
# configure.in V=`shtool version -l c -d long version.c` echo "Configuring FooBar, Version $V"
The option ``-s'' can be used to suppress the output which is useful to just test whether a program exists with the help of the return code. The option ``-m'' enables some magic where currently for the programs ``perl'' and ``cpp'' an advanced magic search is done. The option ``-r'' can be used to transform a forward path to a subdirectory into a reverse path. Option ``-d'' and ``-b'' just output the directory or base name of str.
Examples:
# shell script
awk=`shtool path -p "${PATH}:." gawk nawk awk`
perl=`shtool path -m perl`
cpp=`shtool path -m cpp`
revpath=`shtool path -r path/to/subdir`
Ralf S. Engelschall rse@engelschall.com www.engelschall.com