ICMAKE 第 4 部分
发布于 1994 年 8 月 1 日
在最后这一节,我们将给出三个例子,完成对 icmake 的讨论。第一个例子展示了一个与 icmake 一起使用的“传统 make 脚本”。这个例子取自 Karel 开发的“callback utility”(也可从 beatrix.icce.rug.bl 获取)。第二个例子是一个简单的 dos2unix 脚本,可用于将 DOS 文本文件转换为 Unix 文本文件:它使用 awk 来完成繁重的工作。最后,展示了 attic-move 脚本,它实现了一种非破坏性的删除,方法是将文件移动到“attic.zip”中。更多例子可以在 icmake 发行版 tar.gz 文件中找到。这些例子都带有自己的注释,并以当前使用的形式呈现。
#!/usr/local/bin/icmake -qi
#define CC "gcc"
#define CFLAGS "-c -Wall"
#define STRIP "strip"
#define AR "ar"
#define ARREPLACE "rvs"
#define DEBUG ""
#define CALLBACKDIR "/conf/callback"
#define BINDIR "/usr/local/bin"
#define VER "1.05v
int compdir (string dir)
{
int
i,
ret;
list
ofiles,
cfiles;
string
hfile,
curdir,
cfile,
ofile,
libfile;
curdir = chdir (".");
libfile = "lib" + dir + ".a";
hfile = dir + ".h";
chdir (dir);
if (hfile younger libfile)
cfiles = makelist ("*.c");
else
cfiles = makelist ("*.c", younger, libfile);
for (i = 0; i < sizeof (cfiles); i++)
{
cfile = element (i, cfiles);
ofile = change_ext (cfile, ".o");
if (! exists (ofile) || ofile older cfile)
exec (CC, DEBUG, CFLAGS, cfile);
}
if (ofiles = makelist ("*.o"))
{
exec (AR, ARREPLACE, libfile, "*.o");
exec ("rm", "*.o");
ret = 1;
}
chdir (curdir);
return (ret);
}
void linkprog (string dir)
{
chdir (dir);
exec (CC, DEBUG, "-o", dir, "-l" + dir, "-lrss", "-L. -L../rss");
chdir ("..");
}
void buildprogs ()
{
int
cblogin,
cbstat,
rss;
chdir ("src");
cblogin = compdir ("cblogin");
cbstat = compdir ("cbstat");
rss = compdir ("rss");
if (cblogin || rss)
linkprog ("cblogin");
if (cbstat || rss)
linkprog ("cbstat");
chdir ("..");
}
void instprog (string prog, string destdir)
{
chdir ("src/" + prog);
exec (STRIP, prog);
exec ("chmod", "700", prog);
exec ("cp", prog, destdir);
chdir ("../..");
}
void install ()
{
buildprogs ();
instprog ("cblogin", CALLBACKDIR);
instprog ("cbstat", BINDIR);
}
void cleandir (string dir)
{
chdir ("src/" + dir);
exec ("rm", "-f", "*.o lib*.a", dir);
chdir ("../..");
}
void clean ()
{
exec ("rm", "-f", "build.bim");
cleandir ("cblogin");
cleandir ("cbstat");
cleandir ("rss");
}
void makedist ()
{
list
examples;
int
i;
clean ();
chdir ("examples");
examples = makelist ("*");
for (i = 0; i < sizeof (examples); i++)
if (exists ("/conf/callback/" + element (i, examples)) &&
"/conf/callback/" + element (i, examples) younger
element (i, examples))
exec ("cp", "/conf/callback/" + element (i, examples),
element (i, examples));
chdir ("..");
exec ("rm", "-f", "callback-" + VER + ".tar*");
exec ("tar", "cvf", "callback-" + VER + ".tar", "*");
exec ("gzip", "callback-" + VER + ".tar");
exec ("mv", "callback-" + VER + ".tar.z",
"callback-" + VER + ".tar.gz");
}
void main (int argc, list argv)
{
if (element (1, argv) == "progs")
buildprogs ();
else if (element (1, argv) == "install")
install ();
else if (element (1, argv) == "clean")
clean ();
else if (element (1, argv) == "dist")
makedist ();
else
{
printf ("\n"
"Usage: build progs - builds programs\n"
" build install - installs program\n"
" build clean - cleanup .o files etc.\n"
"\n"
" build dist - makes .tar.gz distrib file\n"
"\n");
exit (1);
}
exit (0);
}
#!/usr/local/bin/icmake -qi
/*
DOS2UNIX
This script is used to change dos textfiles into unix textfiles.
*/
string
pidfile;
void usage(string prog)
{
prog = change_ext(get_base(prog), ""); // keep the scriptname
printf("\n"
"ICCE ", prog,
": Dos to Unix textfile conversion. Version 1.00\n"
"Copyright (c) ICCE 1993, 1994. All rights reserved\n"
"\n",
prog, " by Frank B. Brokken\n"
"\n"
"Usage: ", prog, " file(s)\n" // give help
"Where:\n"
"file(s): MS-DOS textfiles to convert to UNIX textfiles\n"
"\n");
exit (1); // and exit
}
void dos2unix(string file)
{
if (!exists(file))
printf("'", file, "' does not exist: skipped\n");
else
{
printf("converting: ", file, "\n");
exec("/bin/mv", file, pidfile);
system("/usr/bin/awk 'BEGIN {FS=\"\\r\"}; {print $1}' " +
pidfile + " > " + file);
}
}
void process(list argv)
{
int
i;
// make general scratchname
pidfile = "/tmp/dos2unix." + (string)getpid();
echo(OFF); // no echoing of exec-ed progs
for (i = 1; i < sizeof(argv); i++)
dos2unix(element(i, argv)); // convert dos 2 unix
if (exists(pidfile))
exec("/bin/rm", pidfile); // remove final junk
}
int main(int argc, list argv)
{
if (argc == 1)
usage(element(0, argv));
process(argv); // process all arguments
return (0); // return when ready
}
#! /usr/local/bin/icmake -qi
/*
This script is used to implement a non-destructive rm
*/
#define YEAR "1993, 1994"
#define VERSION "1.10"
int
flags_done,
extract,
viewmode,
debug;
string
home,
attic,
cwd,
progname,
recurs,
forced,
unzipflag;
void kill(string s)
{
printf(s, "\n\n");
exit(1);
}
void preamble(list argv, list envp)
{
int
index;
cwd = chdir("."); // get cwd
for (index = 0; home = element(index, envp); index += 2)
{
if (home == "HOME") // HOME found
{ // get it
home = element(index + 1, envp);
break; // and done
}
}
if (!home)
kill("$HOME not found");
progname = change_ext(element(0, argv), "");
attic = home + "/attic"; // set $HOME/attic, change to
}
void check_attic()
{
if (!exists(attic)) // attic should exist
{
printf(attic, " does not exist. Create it [y/n] ? ");
if (getch() != "y") // not a "y" ?
kill("ok.");
system("mkdir " + attic); // make the attic subdir
exec("chmod", 700, attic); // private use
} // else attic must be dir
else if (!((int)element(0, stat(attic)) & S_IFDIR))
kill("'" + attic + "' is not a directory");
attic += "/attic"; // append the zip-name
chdir("/"); // go to the root
}
void set_flags(string arg)
{
int
index;
string
flag;
// process all arguments
for (index = 1; flag = element(index, arg); index++)
{
if (flag == "r") // process encountered options
recurs = "-r";
if (flag == "d")
debug++;
else if (flag == "f")
forced = "-f";
else if (flag == "x")
extract++;
else if (flag == "v")
{
extract++;
viewmode++;
unzipflag = "-l ";
}
else
kill("Unrecognized flag '-" +
flag +
"': " +
progname +
"aborted");
}
if (extract && unzipflag == "")
unzipflag = "-u "; // use proper unzip flag
}
list options(int argc, list argv)
{
int
index;
list
ret;
string
arg;
for (index = 0; index < argc; index++)
{
arg = element(index, argv); // get next argument
if (element(0, arg) == "-") // first element is a - ?
set_flags(arg); // then set flags
else
ret += (list)arg; // or add to list to return
}
return (ret); // returned list
}
void usage()
{
printf
(
"\n"
"ICCE AM (Attic Move) non-destructive remove. Version "
VERSION "\n"
"Copyright (c) ICCE " YEAR ". All Rights Reserved\n"
"\n"
"AM by Frank B. Brokken\n"
"\n"
"Usage: ", progname, " [options] file(s)\n"
"Where:\n"
" options:\n"
" -d: Debug mode: no execution but display of commands\n"
" -f: Forced processing of indicated files\n"
" -r: Recursive removal of directory contents\n"
" -v: View current contents of the attic\n"
" -x: Extract files from the attic to their original place\n"
" (i.e., if you are permitted to do so...\n"
"\n"
" file(s): names of files and directories to move to/from
the attic\n"
"\n"
" ", home, "/attic/attic.zip is used to store the files.\n"
"\n"
);
exit (1);
}
string prefix_path(string file)
{
string
el,
ret;
int
index;
if (element(0, file) != "/") // if file isn't an absolute path
file = cwd + file; // then make an absolute path
for (index = 1; el = element(index, file); index++)
ret += el; // remove first char from abs path
return (ret); // return modified string
}
void retrieve(string file)
{
string
cmd;
cmd = "unzip " // update only
+ unzipflag
+ attic;
if (!viewmode)
cmd += " "
+ prefix_path(file); // and the file (+ path prefix)
if (debug)
printf("( cd /; ", cmd, " )\n"); // debug: show command
else
system(cmd); // else exec cmd
}
void remove(string file)
{
string
cmd;
cmd = "zip -my " // remove, remove links as links
+ forced // maybe forced
+ " "
+ recurs // maybe recursive
+ " "
+ attic // target zip
+ " "
+ prefix_path(file); // and the file (+ path prefix)
if (debug)
printf("( cd /; ", cmd, " )\n"); // debug: show command
else
system(cmd); // else exec cmd
}
void one_file(string file)
{
if (extract) // either retrieve or remove
retrieve(file); // the file
else
remove(file);
}
void process(int argc, list argv)
{
int
index;
for (index = 1; index < argc; index++)
one_file(element(index, argv)); // process one file
}
int main(int argc, list argv, list envp)
{
echo (OFF);
preamble(argv, envp); // set progname and attic dir.
argv = options(argc, argv); // get the options
argc = sizeof(argv); // determine remaining arguments
if (argc == 1 && !viewmode) // none left and no viewmode?
usage(); // give usage and exit 1
check_attic(); // check accessability of attic
if (viewmode) // view contents
retrieve("");
else // or
process(argc, argv); // process remaining arguments
return (0); // done
}
