//
// aegis - project change supervisor
// Copyright (C) 2004-2006, 2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
#include
#include
nstring_list process_body::search_path;
static nstring
trim_dir(const nstring &path)
{
const char *cp = strchr(path.c_str(), '/');
if (!cp)
return "";
return nstring(cp + 1);
}
static nstring
top_dir(const nstring &path)
{
const char *cp = path.c_str();
const char *ep = strchr(cp, '/');
if (!ep)
return ".";
return nstring(cp, ep - cp);
}
static nstring
basename(const nstring &path)
{
const char *cp = strrchr(path.c_str(), '/');
if (!cp)
return path;
return nstring(cp + 1);
}
process_body::~process_body()
{
}
process_body::process_body(printer &arg) :
process(arg)
{
}
void
process_body::read_dependency_file(const nstring &file, nstring_list &dep)
{
nstring filename(file + ",Md");
FILE *fp = fopen(filename.c_str(), "r");
if (!fp)
{
if (errno != ENOENT)
nfatal("open %s", filename.c_str());
for (size_t j = 0; ; ++j)
{
if (j >= search_path.size())
return;
nstring fn2(search_path[j] + "/" + filename);
fp = fopen(fn2.c_str(), "r");
if (fp)
break;
if (errno != ENOENT)
nfatal("open %s", fn2.c_str());
}
}
for (;;)
{
char buffer[2000];
char *bp = buffer;
int c;
for (;;)
{
c = getc(fp);
if (c == EOF || c == '\n')
break;
if (bp < buffer + sizeof(buffer))
*bp++ = c;
}
if (bp == buffer && c == EOF)
break;
nstring line(buffer, bp - buffer);
dep.push_back(line.replace("[arch]/", ""));
}
fclose(fp);
}
void
process_body::per_file(const nstring &filename)
{
nstring file(filename);
if (file.ends_with(".in"))
{
nstring fn2 = nstring(file.c_str(), file.size() - 3);
print << "\n";
print << fn2 << ": " << file << " ./config.status\n\t";
if (fn2.ends_with(".h"))
{
print << "CONFIG_FILES= CONFIG_HEADERS=$@:" << file << " ";
}
else
{
print << "CONFIG_FILES=$@:" << file << " CONFIG_HEADERS= ";
}
print << "$(SH) ./config.status\n";
file = fn2;
}
if (file.ends_with(".y"))
{
nstring stem(file.c_str(), file.size() - 2);
nstring root = basename(stem);
nstring dir(file.dirname());
nstring yy = trim_dir(stem).identifier();
nstring numconf("no");
if (file == "common/gettime.y")
numconf = "8 shift/reduce";
else if (file == "libaegis/aer/report.y")
numconf = "2 reduce/reduce";
else if (file == "aefind/cmdline.y")
numconf = "5 shift/reduce, 23 reduce/reduce";
else if (file == "common/gettime.y")
numconf = "8 shift/reduce";
print << "\n";
print << stem << ".gen.cc " << stem << ".gen.h: " << file << "\n";
print << "\t@echo Expect " << numconf << " conflicts.\n";
print << "\t$(YACC) -d " << file << "\n";
print << "\tsed -e 's/[yY][yY]/" << yy << "_/g' -e '//d' "
"-e '//d' -e '//d' y.tab.c > "
<< stem << ".gen.cc\n";
print << "\tsed -e 's/[yY][yY]/" << yy << "_/g' -e 's/Y_TAB_H/" << yy
<< "_TAB_H/g' y.tab.h > " << stem << ".gen.h\n";
print << "\trm -f y.tab.c y.tab.h\n";
#if 0
//
// We don't need this bit. The cookbook adds these to the list
// of files given to us to process, which also ensures that the
// dependency (,Md) file has been created.
//
nstring_list dep;
read_dependency_file(stem + ".gen.cc", dep);
print << "\n";
print << stem << ".gen.$(OBJEXT): " << stem << ".gen.cc " << dep
<< "\n";
print << "\t$(CXX) -I. $(CXXFLAGS) -c " << stem << ".gen.cc\n";
print << "\tmv " << basename(stem) << ".gen.$(OBJEXT) $@\n";
#endif
}
else if (file.ends_with(".cc"))
{
nstring stem(file.c_str(), file.size() - 3);
nstring root(basename(stem));
nstring dir(top_dir(file));
nstring_list dep;
read_dependency_file(file, dep);
print << "\n";
print << stem << ".$(OBJEXT): " << file << " " << dep << "\n";
print << "\t$(CXX) -I. $(CXXFLAGS) -c " << file << "\n";
print << "\tmv " << root << ".$(OBJEXT) $@\n";
}
else if (file.gmatch("lib/icon2/*.uue"))
{
nstring rest(file.c_str() + 10, file.size() - 14);
nstring tmp = "lib/icon/" + rest;
print << "\n";
print << tmp << ": " << file << " bin/test_base64\n";
print << "\tbin/test_base64 -uu -i -nh " << file << " $@\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/icon/" << rest << ": " << tmp
<< " " << tmp.dirname() << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) " << tmp << " $@\n";
}
else if (file.gmatch("lib/icon/*.uue"))
{
nstring rest(file.c_str() + 9, file.size() - 13);
nstring dir(file.dirname());
print << "\n";
print << "lib/icon/" << rest << ": " << file << " bin/test_base64\n";
print << "\tbin/test_base64 -uu -i -nh " << file << " $@\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/icon/" << rest << ": lib/icon/"
<< rest << " " << dir << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) " << "lib/icon/" << rest << " $@\n";
}
else if (file.gmatch("lib/*.uue"))
{
// do nothing
}
else if (file == "lib/cshrc" || file == "lib/profile")
{
// should only be setting ${sharedstatedir}
// so be inconsistent and install them in share
nstring rest(basename(file));
nstring dir(file.dirname());
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << rest << ": " << file << " "
<< dir << "/.mkdir.datadir\n";
print << "\t$(INSTALL_SCRIPT) " << file << " $@\n";
if (file == "lib/profile")
{
print << "\n";
print << "$(RPM_BUILD_ROOT)$(sysconfdir)/profile.d/aegis.sh: "
"$(RPM_BUILD_ROOT)$(datadir)/" << rest << "\n";
print << "\t-@mkdir -p $(RPM_BUILD_ROOT)$(sysconfdir)/profile.d\n";
print << "\t-ln -s $(datadir)/" << rest << " $@\n";
}
else
{
print << "\n";
print << "$(RPM_BUILD_ROOT)$(sysconfdir)/profile.d/aegis.csh: "
"$(RPM_BUILD_ROOT)$(datadir)/" << rest << "\n";
print << "\t-@mkdir -p $(RPM_BUILD_ROOT)$(sysconfdir)/profile.d\n";
print << "\t-ln -s $(datadir)/" << rest << " $@\n";
}
}
else if (file.gmatch("lib/*.sh"))
{
nstring rest(trim_dir(file));
nstring dir(file.dirname());
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << rest << ": " << file << " "
<< dir << "/.mkdir.datadir\n";
print << "\t$(INSTALL_SCRIPT) " << file << " $@\n";
}
else if (file.gmatch("lib/*/libaegis.po"))
{
// obsolete
}
else if (file.gmatch("lib/*.po"))
{
//
// Assume that we are using the GNU Gettext program. All others
// will fail, because they do not have the -o option.
//
nstring stem(file.c_str() + 4, file.size() - 7);
nstring dir(file.dirname());
print << "\n";
print << "lib/" << stem << ".mo: etc/msgfmt.sh " << file << "\n";
print << "\t$(SH) etc/msgfmt.sh --msgfmt=$(MSGFMT) --msgcat=$(MSGCAT) "
"--output=$@ " << file << "\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(NLSDIR)/" << stem << ".mo: lib/" << stem
<< ".mo " << dir << "/.mkdir.libdir\n";
print << "\t$(INSTALL_DATA) lib/" << stem << ".mo $@\n";
}
else if (file.gmatch("lib/*/man[1-9]/*.[1-9]"))
{
nstring dir(file.dirname());
nstring base(basename(file));
nstring stem(trim_dir(file));
nstring part(trim_dir(stem));
nstring ugly(file.field('/', 2));
nstring_list dep;
read_dependency_file(file, dep);
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << stem << ": " << file << " "
<< dir << "/.mkdir.datadir " << dep << "\n";
print << "\t$(SOELIM) -I" << dir << " -Ietc " << file
<< " | sed '/^\\.lf/d' > $${TMPDIR-/tmp}/aegis.tmp\n";
print << "\t$(INSTALL_DATA) $${TMPDIR-/tmp}/aegis.tmp $@\n";
print << "\t@rm -f $${TMPDIR-/tmp}/aegis.tmp\n";
if (file.field('/', 1) == "en")
{
print << "\n";
print << "$(RPM_BUILD_ROOT)$(mandir)/" << part << ": " << file
<< " " << dep << " ." << ugly << "dir\n";
print << "\t$(SOELIM) -I" << dir << " -Ietc " << file
<< " | sed '/^\\.lf/d' > $${TMPDIR-/tmp}/aegis.tmp\n";
print << "\t$(INSTALL_DATA) $${TMPDIR-/tmp}/aegis.tmp $@\n";
print << "\t@rm -f $${TMPDIR-/tmp}/aegis.tmp\n";
}
}
else if (file.gmatch("lib/*/man?/*"))
{
// do nothing
}
else if (file.gmatch("lib/*/*/*.so"))
{
// do nothing
}
else if (file.gmatch("lib/*/*/*.bib"))
{
// do nothing
}
else if (file.gmatch("lib/*/*/main.*"))
{
const char *cp = strrchr(file.c_str(), '.');
nstring macros(cp ? cp + 1 : "");
nstring stem(trim_dir(file));
nstring dir(file.dirname());
nstring dirdir(dir.dirname());
nstring_list dep;
read_dependency_file(file, dep);
if (macros == "roff")
macros = "";
else if (macros == "mm")
macros = "$(MM)";
else if (macros == "ms")
macros = "$(MS)";
else
macros = "-" + macros;
nstring stem2(stem.dirname());
nstring stem3(stem2.dirname());
print << "\n";
print << "lib/" << stem2 << ".ps: " << file << " " << dep << "\n";
print << "\t$(SOELIM) -I" << dir << " -Ietc -I" << dirdir << "/man1 -I"
<< dirdir << "/man5 -I" << dirdir << "/readme " << file
<< " | $(GROFF) -R -t -p " << macros << " -mpic -mpspic > $@\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << stem2 << ".ps: lib/" << stem2
<< ".ps lib/" << stem3 << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) lib/" << stem2 << ".ps $@\n";
print << "\n";
print << "lib/" << stem2 << ".dvi: " << file << " " << dep << "\n";
print << "\t$(SOELIM) -I" << dir << " -Ietc -I" << dirdir << "/man1 -I"
<< dirdir << "/man5 -I" << dirdir << "/readme " << file
<< " | $(GROFF) -Tdvi -R -t -p " << macros << " -mpic > $@\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << stem2 << ".dvi: lib/"
<< stem2 << ".dvi lib/" << stem3 << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) lib/" << stem2 << ".dvi $@\n";
print << "\n";
print << "lib/" << stem2 << ".txt: " << file << " " << dep << "\n";
print << "\t-$(SOELIM) -I" << dir << " -Ietc -I" << dirdir << "/man1 -I"
<< dirdir << "/man5 -I" << dirdir << "/readme " << file
<< " | $(GROFF) -Tascii -R -t -p " << macros << " -mpic > $@\n";
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << stem2 << ".txt: lib/"
<< stem2 << ".txt lib/" << stem3 << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) lib/" << stem2 << ".txt $@\n";
}
else if (file.starts_with("lib/"))
{
nstring stem(file.c_str() + 4, file.size() - 4);
nstring dir(file.dirname());
print << "\n";
print << "$(RPM_BUILD_ROOT)$(datadir)/" << stem << ": " << file << " "
<< dir << "/.mkdir.datadir\n";
print << "\t$(INSTALL_DATA) " << file << " $@\n";
}
else if (file.ends_with(".def"))
{
nstring stem(file.c_str(), file.size() - 4);
nstring root(basename(file));
nstring dir(file.dirname());
nstring_list dep;
read_dependency_file(file, dep);
print << "\n";
print << stem << ".cc " << stem << ".h: " << file
<< " bin/fmtgen$(EXEEXT) " << dep << "\n";
print << "\tbin/fmtgen$(EXEEXT) -I. " << file << " "
<< stem << ".cc " << stem << ".h\n";
#if 0
//
// We don't need this bit. The cookbook adds these to the list
// of files given to us to process, which also ensures that the
// dependency (,Md) file has been created.
//
dep.clear();
read_dependency_file(stem + ".cc", dep);
print << "\n";
print << stem << ".$(OBJEXT): " << stem << ".cc " << dep << "\n";
print << "\t$(CXX) -I. $(CXXFLAGS) -c " << stem << ".cc\n";
print << "\tmv " << basename(stem) << ".$(OBJEXT) $@\n";
#endif
}
else if (file.gmatch("test/*/*.sh"))
{
nstring stem(file.c_str(), file.size() - 3);
print << "\n";
print << stem << ".ES: " << file << " all-bin etc/test.sh\n";
print << "\tCXX=\"$(CXX)\" $(SH) etc/test.sh -shell $(SH) -run "
<< file << " " << stem << ".ES\n";
}
else if (file.starts_with("script/"))
{
nstring name = file.basename();
nstring ext = name.get_extension();
if (ext == "tcl" || ext == "sh" || ext == "pl" || ext == "py")
name = name.trim_extension();
nstring bin_name = "bin/" + name + "$(EXEEXT)";
print << "\n";
print << bin_name << ": " << file << " .bin\n";
print << "\tcp " << file << " $@\n";
print << "\tchmod a+rx $@\n";
nstring installed_name = "$(RPM_BUILD_ROOT)$(bindir)/$(PROGRAM_PREFIX)"
+ name + "$(PROGRAM_SUFFIX)$(EXEEXT)";
print << "\n";
print << installed_name << ": " << bin_name << " .bindir\n";
print << "\t$(INSTALL_SCRIPT) " << bin_name << " $@\n";
}
}
void
process_body::directory(const char *arg)
{
search_path.push_back(arg);
}