⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extractcode.cpp

📁 Thinking in C++ 2.0书籍源码光盘
💻 CPP
📖 第 1 页 / 共 2 页
字号:
};

// Static initialization:
map<string,CompilerData> 
  CompilerData::compilerInfo;
set<string> CompilerData::_compilerNames;

void CompilerData::readDB(istream& in) {
  string compiler; // Name of current compiler
  string s;
  while(getline(in, s)) {
    if(s.find("#//" "/:~") == 0)
      return; // Found end tag
    s = trim(s);
    if(s.length() == 0) continue; // Blank line
    if(s[0] == '#') continue; // Comment
    if(s[0] == '{') { // Different compiler
      compiler = s.substr(0, s.find('}'));
      compiler = trim(compiler.substr(1));
      if(compiler.length() != 0)
        _compilerNames.insert(compiler);
      continue; // Changed compiler name
    }
    if(s[0] == '(') { // Object file extension
      string obj = s.substr(1);
      obj = trim(obj.substr(0, obj.find(')')));
      compilerInfo[compiler].objExtension =obj;
      continue;
    }
    if(s[0] == '[') { // Executable extension
      string exe = s.substr(1);
      exe = trim(exe.substr(0, exe.find(']')));
      compilerInfo[compiler].exeExtension =exe;
      continue;
    }
    if(s[0] == '&') { // Special directive
      if(s.find("dos") != string::npos)
        compilerInfo[compiler]._dos = true;
      else if(s.find("unix") != string::npos)
        compilerInfo[compiler]._unix = true;
      else
        error("Compiler Information Database", 
          "unknown special directive: " + s);
      continue;
    }
    if(s[0] == '@') { // Makefile rule
      string rule(s.substr(1)); // Remove the @
      if(rule[0] == ' ') // Space means tab
        rule = '\t' + trim(rule);
      compilerInfo[compiler].rules
        .push_back(rule); 
      continue;
    }
    // Otherwise, it's a failure line:
    compilerInfo[compiler].fails.insert(s);
  }
  error("CompileDB.txt","Missing end tag");
}

void CompilerData::addFailures(CodeFile& cf) {
  set<string>::iterator it = 
    _compilerNames.begin();
  while(it != _compilerNames.end()) {
    if(compilerInfo[*it]
       .fails.count(cf.rawName()) != 0)
      cf.addFailure(*it);
    it++;
  }
}

string CompilerData::obj(string compiler) {
  if(compilerInfo.count(compiler) != 0) {
    string ext(
      compilerInfo[compiler].objExtension);
    if(ext.length() != 0)
      ext = '.' + ext; // Use '.' if it exists
    return ext;
  } else
    return "No such compiler information";
}

string CompilerData::exe(string compiler) {
  if(compilerInfo.count(compiler) != 0) {
    string ext(
      compilerInfo[compiler].exeExtension);
    if(ext.length() != 0)
      ext = '.' + ext; // Use '.' if it exists
    return ext;
  } else
    return "No such compiler information";
}

void CompilerData::writeRules(
  string compiler, ostream& os) {
  if(_compilerNames.count(compiler) == 0) {
    os << "No info on this compiler" << endl;
    return;
  }
  vector<string>& r = 
    compilerInfo[compiler].rules;
  copy(r.begin(), r.end(), 
    ostream_iterator<string>(os, "\n"));
}

string CompilerData::adjustPath(
  string compiler, string path) {
  // Use STL replace() algorithm:
  if(compilerInfo[compiler]._dos)
    replace(path.begin(), path.end(), '/', '\\');
  return path;
}

void CompilerData::dump(ostream& os) {
  ostream_iterator<string> out(os, "\n");
  *out++ = "Compiler Names:";
  copy(_compilerNames.begin(), 
    _compilerNames.end(), out);
  map<string, CompilerData>::iterator compIt;
  for(compIt = compilerInfo.begin(); 
    compIt != compilerInfo.end(); compIt++) {
    os << "******************************\n";
    os << "Compiler: [" << (*compIt).first <<
      "]" << endl;
    CompilerData& cd = (*compIt).second;
    os << "objExtension: " << cd.objExtension
      << "\nexeExtension: " << cd.exeExtension 
      << endl;
    *out++ = "Rules:";
    copy(cd.rules.begin(), cd.rules.end(), out);
    cout << "Won't compile with: " << endl;
    copy(cd.fails.begin(), cd.fails.end(), out);
  }
}

// ---------- Manage makefile creation ----------
// Create the makefile for this directory, based
// on each of the CodeFile entries:
class Makefile {
  vector<CodeFile> codeFiles;
  // All the different paths 
  // (for creating the Master makefile):
  static set<string> paths;
  void 
  createMakefile(string compiler, string path);
public:
  Makefile() {}
  void addEntry(CodeFile& cf) {
    paths.insert(cf.path()); // Record all paths
    // Tell it what compilers don't work with it:
    CompilerData::addFailures(cf);
    codeFiles.push_back(cf);
  }
  // Write the makefile for each compiler:
  void writeMakefiles(string path);
  // Create the master makefile:
  static void writeMaster(string flag = "");
};

// Static initialization:
set<string> Makefile::paths;

void Makefile::writeMakefiles(string path) {
  if(trim(path).length() == 0)
    return; // No makefiles in root directory
  PushDirectory pd(path);
  set<string>& compilers = 
    CompilerData::compilerNames();
  set<string>::iterator it = compilers.begin();
  while(it != compilers.end())
    createMakefile(*it++, path);
}

void Makefile::createMakefile(
  string compiler, string path) {
  string // File name extensions:
    exe(CompilerData::exe(compiler)),
    obj(CompilerData::obj(compiler));
  string filename(compiler + ".makefile");
  ofstream makefile(filename.c_str());
  makefile << 
    "# From Thinking in C++, 2nd Edition\n"
    "# At http://www.BruceEckel.com\n"
    "# (c) Bruce Eckel 1999\n"
    "# Copyright notice in Copyright.txt\n"
    "# Automatically-generated MAKEFILE \n"
    "# For examples in directory "+ path + "\n"
    "# using the " + compiler + " compiler\n"
    "# Note: does not make files that will \n"
    "# not compile with this compiler\n"
    "# Invoke with: make -f " 
    + compiler + ".makefile\n"
    << endl;
  CompilerData::writeRules(compiler, makefile);
  vector<string> makeAll, makeTest, 
    makeBugs, makeDeps, linkCmd;
  // Write the "all" dependencies:
  makeAll.push_back("all: ");
  makeTest.push_back("test: all ");
  makeBugs.push_back("bugs: ");
  string line;
  vector<CodeFile>::iterator it;
  for(it = codeFiles.begin(); 
    it != codeFiles.end(); it++) {
    CodeFile& cf = *it;
    if(cf.targetType() == executable) {
      line = "\\\n\t"+cf.targetName()+ exe + ' ';
      if(cf.compilesOK(compiler) == false) {
        makeBugs.push_back(
          CompilerData::adjustPath(
            compiler,line));
      } else {
        makeAll.push_back(
          CompilerData::adjustPath(
            compiler,line));
        line = "\\\n\t" + cf.targetName() + exe +
          ' ' + cf.testArgs() + ' ';
        makeTest.push_back(
          CompilerData::adjustPath(
            compiler,line));
      }
      // Create the link command:
      int linkdeps = cf.link().size();
      string linklist;
      for(int i = 0; i < linkdeps; i++)
        linklist += 
          cf.link().operator[](i) + obj + " ";
      line = cf.targetName() + exe + ": "
        + linklist + "\n\t$(CPP) $(OFLAG)"
        + cf.targetName() + exe
        + ' ' + linklist + "\n\n";
      linkCmd.push_back(
        CompilerData::adjustPath(compiler,line));
    }
    // Create dependencies
    if(cf.targetType() == executable
      || cf.targetType() == object) {
      int compiledeps = cf.compile().size();
      string objlist(cf.base() + obj + ": ");
      for(int i = 0; i < compiledeps; i++)
        objlist += 
          cf.compile().operator[](i) + " ";
      makeDeps.push_back(
        CompilerData::adjustPath(
          compiler, objlist) +"\n");
    }      
  }
  ostream_iterator<string> mkos(makefile, "");
  *mkos++ = "\n";
  // The "all" target:
  copy(makeAll.begin(), makeAll.end(), mkos);
  *mkos++ = "\n\n";
  // Remove continuation marks from makeTest:
  vector<string>::iterator si = makeTest.begin();
  int bsl;
  for(; si != makeTest.end(); si++)
    if((bsl= (*si).find("\\\n")) != string::npos)
      (*si).erase(bsl, strlen("\\"));
  // Now print the "test" target:
  copy(makeTest.begin(), makeTest.end(), mkos);
  *mkos++ = "\n\n";
  // The "bugs" target:
  copy(makeBugs.begin(), makeBugs.end(), mkos);
  if(makeBugs.size() == 1)
    *mkos++ = "\n\t@echo No compiler bugs in "
      "this directory!";
  *mkos++ = "\n\n";
  // Link commands:
  copy(linkCmd.begin(), linkCmd.end(), mkos);
  *mkos++ = "\n";
  // Demendencies:
  copy(makeDeps.begin(), makeDeps.end(), mkos);
  *mkos++ = "\n";
}

void Makefile::writeMaster(string flag) {
  string filename = "makefile";
  if(flag.length() != 0)
    filename += '.' + flag;
  ofstream makefile(filename.c_str());
  makefile << "# Master makefile for "
    "Thinking in C++, 2nd Ed. by Bruce Eckel\n"
    "# at http://www.BruceEckel.com\n"
    "# Compiles all the code in the book\n"
    "# Copyright notice in Copyright.txt\n\n"
    "help: \n"
    "\t@echo To compile all programs from \n"
    "\t@echo Thinking in C++, 2nd Ed., type\n"
    "\t@echo one of the following commands,\n"
    "\t@echo according to your compiler:\n";
  set<string>& n = CompilerData::compilerNames();
  set<string>::iterator nit;
  for(nit = n.begin(); nit != n.end(); nit++)
    makefile << 
      string("\t@echo make " + *nit + "\n");
  makefile << endl;
  // Make for each compiler:
  for(nit = n.begin(); nit != n.end(); nit++) {
    makefile << *nit << ":\n";
    for(set<string>::iterator it = paths.begin();
      it != paths.end(); it++) {
      // Ignore the root directory:
      if((*it).length() == 0) continue;
      makefile << "\tcd " << *it;
      // Different commands for unix vs. dos:
      if(CompilerData::isUnix(*nit))
        makefile << "; ";
      else
        makefile << "\n\t";
      makefile << "make -f " << *nit 
        << ".makefile";
      if(flag.length() != 0) {
        makefile << ' ';
        if(flag == "bugs")
          makefile << "-i ";
        makefile << flag;
      }
      makefile << "\n";
      if(CompilerData::isUnix(*nit) == false)
        makefile << "\tcd ..\n";
    }
    makefile << endl;
  }
}

int main(int argc, char* argv[]) {
  if(argc < 2) {
    error("Command line error", usage);
    exit(1);
  }
  // For development & testing, leave off notice:
  if(argc == 3)
    if(string(argv[2]) == "-nocopyright")
      copyright = "";
  // Open the input file to read the compiler
  // information database:
  ifstream in(argv[1]);
  if(!in) {
    error(string("can't open ") + argv[1],usage);
    exit(1);
  }
  string s;
  while(getline(in, s)) {
    // Break up the strings to prevent a match when
    // this code is seen by this program:
    if(s.find("#:" " :CompileDB.txt") 
      != string::npos) {
      // Parse the compiler information database:
      CompilerData::readDB(in);
      break; // Out of while loop
    }
  }
  if(in.eof())
    error("CompileDB.txt", "Can't find data");
  in.seekg(0, ios::beg); // Back to beginning
  map<string, Makefile> makeFiles;
  while(getline(in, s)) {
    // Look for tag at beginning of line:
    if(s.find("//" ":") == 0
       || s.find("/*" ":") == 0
       || s.find("#" ":") == 0) {
      CodeFile cf(in, s);
      cf.write();  // Tell it to write itself
      makeFiles[cf.path()].addEntry(cf);
    }
  }
  // Write all the makefiles, telling each
  // the path where it belongs:
  map<string, Makefile>::iterator mfi;
  for(mfi = makeFiles.begin(); 
    mfi != makeFiles.end(); mfi++)
    (*mfi).second.writeMakefiles((*mfi).first);
  // Create the master makefile:
  Makefile::writeMaster();
  // Write the makefile that tries the bug files:
  Makefile::writeMaster("bugs");
} ///:~

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -