<commit_before>#include <stdio.h>
#include <stdlib.h>

#include <string>
#include <iostream>
#include <utility>
#include <unordered_set>
#include <unordered_map>
using namespace std;

#include "scx/Dir.hpp"
#include "scx/FileInfo.hpp"
using namespace scx;

#include "Tools.h"
#include "ConsUnit.h"
#include "Parallel.h"

static const unordered_set<string> C_EXT = { "c" };
static const unordered_set<string> CXX_EXT = { "cc", "cxx", "cpp", "C" };

static void Usage(const string& cmd)
{
    const string sp(cmd.size(), ' ');
    cout << ""
        "Usage:\n"
        "\t" + cmd + " [ file1 file1 | dir1 dir2 ]\n"
        "\t" + sp + " cc=?        C compiler.\n"
        "\t" + sp + " cxx=?       C++ compiler.\n"
        "\t" + sp + " flag=?      Compiler flag.\n"
        "\t" + sp + " ldflag=?    Linker flag.\n"
        //"   " + sp + " with=?,?,? without=?,?,?\n"
        //"   " + sp + " obj=\"outA:dep1, dep2:cmdA; outB:dep1, dep2:cmdB; ...\"\n"
        "\t" + sp + " jobs=?      Parallel build.\n"
        "\t" + sp + " clean       Clean build output.\n"
        "\t" + sp + " help        Show this help message.\n"
        "\n"
        "\t" + sp + " shared      Generate shared library. (*)\n"
        "\t" + sp + " debug       Build with debug symbols. (*)\n"
        "\t" + sp + " c++11       Use clang & libc++. (*)\n"
        "\t" + sp + " thread      Link against pthread. (*)\n"
        "\n";

    cout << ""
        "Note:\n"
        "\t* Just for convenient. You may also use flags to approach the function.\n"
        "\n";

    cout << ""
        "Author:\n"
        "\tYanhui Shen <@diffcat on Twitter>\n";
}

int main(int argc, char** argv)
{
    unordered_map<string, string> ArgTable = {
        {   "out",      "b.out" },
        {   "with",     ""      },
        {   "without",  ""      },
        {   "cc",       "cc"    },
        {   "cxx",      "c++"   },
        {   "flag",     ""      },
        {   "ld",       "cc"    },
        {   "ldflag",   ""      },
        {   "jobs",     "0"     }
    };

    bool shared = false;
    bool debug = false;
    bool clean = false;
    bool usePipe = true;
    bool useClangXX11 = false;
    bool useThread = false;
    vector<string> with, without, all;

    // Parse arguments.
    for (int i = 1; i < argc; ++i) {
        const string& arg(argv[i]);

        // So obvisously, file name should not contain '='.
        size_t pos = arg.find('=');
        if (pos != string::npos && pos != arg.size()-1) {
            // Update key-value.
            auto iter = ArgTable.find(arg.substr(0, pos));
            if (iter != ArgTable.end()) {
                iter->second = arg.substr(pos+1);
            }
        } else if (arg == "help") {
            Usage(argv[0]);
            return 0;
        } else if (arg == "clean") {
            clean = true;
        } else if (arg == "debug") {
            debug = true;
        } else if (arg == "shared") {
            shared = true;
        } else if (arg == "c++11") {
            useClangXX11 = true;
        } else if (arg == "thread") {
            useThread = true;
        } else {
            switch (FileInfo(arg).Type()) {
            case FileType::Directory:
            {
                const auto& files = Dir::ListDir(arg);
                all.reserve(all.size() + files.size());
                all.insert(all.end(), files.begin(), files.end());
            }
                break;

            case FileType::Regular:
            {
                all.push_back(arg);
            }
                break;

            default:
            {
                cerr << "FATAL: bad argument: " << endl;
                cerr << "arg: " << arg << endl;
                return -1;
            }
                break;
            }
        }
    }

    if (!ArgTable["flag"].empty())
        ArgTable["flag"].insert(0, 1, ' ');
    if (debug)
        ArgTable["flag"] += " -g";
    if (shared)
        ArgTable["flag"] += " -fPIC";
    if (usePipe) {
        ArgTable["flag"] += " -pipe";
    }
    if (useClangXX11) {
        ArgTable["cc"] = "clang";
        ArgTable["cxx"] = "clang++";
        ArgTable["flag"] += " -std=c++11 -stdlib=libc++";
    }

    if (!ArgTable["ldflag"].empty())
        ArgTable["ldflag"].insert(0, 1, ' ');
    if (useThread) {
        ArgTable["ldflag"] += " -pthread";
    }

    if (all.empty())
        all = Dir::ListDir(".");
    if (all.empty()) {
        cerr << "FATAL: nothing to build!" << endl;
        return -1;
    }

    // Prepare construct units.
    bool hasCpp = false;
    vector<ConsUnit> newUnits;
    string allObjects;

    for (const auto& file: all) {
        ConsUnit unit(file);
        string compiler;

        // Pick up source file.
        const string ext(FileInfo(file).Suffix());
        if (C_EXT.find(ext) != C_EXT.end()) {
            compiler = ArgTable["cc"];
        } else if (CXX_EXT.find(ext) != CXX_EXT.end()) {
            compiler = ArgTable["cxx"];
            hasCpp = true;
        } else {
            continue;
        }

        // Calculate dependence.
        if (ConsUnit::Init(unit, compiler, ArgTable["flag"])) {
            allObjects += " " + unit.out;
            if (!unit.cmd.empty()) {
                newUnits.push_back(std::move(unit));
            }
        } else {
            cerr << "FATAL: failed to calculate dependence!" << endl;
            cerr << "\tfile:     " << file << endl;
            cerr << "\tcompiler: " << compiler << endl;
            cerr << "\tflag:     " << ArgTable["flag"] << endl;
            return -1;
        }
    }

    if (hasCpp)
        ArgTable["ld"] = ArgTable["cxx"];

#ifdef DEBUG
    // Debug info.
    {
        auto fn = [](const vector<ConsUnit>& units)->void {
            for (const auto& unit: units) {
                cout << "in: " <<  unit.in << ", " << "out: " << unit.out << endl;
                cout << "\t" << unit.cmd << endl;
                cout << "\t";
                for (const auto& dep: unit.deps)
                    cout << dep << ", ";
                cout << endl;
            }
        };
        cout << "new units: " << endl;
        fn(newUnits);
    }
#endif

    // Let's build them all.
    if (!clean) {
        if (newUnits.empty())
            return 0;

        cout << "* Build: ";
        const size_t nfiles = std::min((size_t)5, newUnits.size());
        for (size_t i = 0; i < nfiles; ++i) {
            cout << newUnits[i].in << ((i+1 < nfiles) ? ", " : "");
        }
        if (nfiles < newUnits.size()) {
            cout << " and " << newUnits.size() - nfiles<< " files";
        }
        cout << endl;

        ParallelCompiler pc(newUnits);
        if (pc.Run(::stoi(ArgTable["jobs"])) != 0)
            return -1;

        string ldCmd = ArgTable["ld"] + " -o " + ArgTable["out"] +
                       ArgTable["flag"] + ArgTable["ldflag"];
        if (shared)
            ldCmd += " -shared";
        ldCmd += allObjects;

        if (!newUnits.empty() || !FileInfo(ArgTable["out"]).Exists()) {
            cout << "- Link - " << ldCmd << endl;
            if (::system(ldCmd.c_str()) != 0)
                return -1;
        }
    } else {
        const string& cmd = "rm -f " + ArgTable["out"]+ allObjects;
        cout << cmd << endl;
        ::system(cmd.c_str());
    }

    return 0;
}
<commit_msg>! fix compile&link logic<commit_after>#include <stdio.h>
#include <stdlib.h>

#include <string>
#include <iostream>
#include <utility>
#include <unordered_set>
#include <unordered_map>
using namespace std;

#include "scx/Dir.hpp"
#include "scx/FileInfo.hpp"
using namespace scx;

#include "Tools.h"
#include "ConsUnit.h"
#include "Parallel.h"

static const unordered_set<string> C_EXT = { "c" };
static const unordered_set<string> CXX_EXT = { "cc", "cxx", "cpp", "C" };

static void Usage(const string& cmd)
{
    const string sp(cmd.size(), ' ');
    cout << ""
        "Usage:\n"
        "\t" + cmd + " [ file1 file1 | dir1 dir2 ]\n"
        "\t" + sp + " cc=?        C compiler.\n"
        "\t" + sp + " cxx=?       C++ compiler.\n"
        "\t" + sp + " flag=?      Compiler flag.\n"
        "\t" + sp + " ldflag=?    Linker flag.\n"
        //"   " + sp + " with=?,?,? without=?,?,?\n"
        //"   " + sp + " obj=\"outA:dep1, dep2:cmdA; outB:dep1, dep2:cmdB; ...\"\n"
        "\t" + sp + " jobs=?      Parallel build.\n"
        "\t" + sp + " clean       Clean build output.\n"
        "\t" + sp + " help        Show this help message.\n"
        "\n"
        "\t" + sp + " shared      Generate shared library. (*)\n"
        "\t" + sp + " debug       Build with debug symbols. (*)\n"
        "\t" + sp + " c++11       Use clang & libc++. (*)\n"
        "\t" + sp + " thread      Link against pthread. (*)\n"
        "\n";

    cout << ""
        "Note:\n"
        "\t* Just for convenient. You may also use flags to approach the function.\n"
        "\n";

    cout << ""
        "Author:\n"
        "\tYanhui Shen <@diffcat on Twitter>\n";
}

int main(int argc, char** argv)
{
    unordered_map<string, string> ArgTable = {
        {   "out",      "b.out" },
        {   "with",     ""      },
        {   "without",  ""      },
        {   "cc",       "cc"    },
        {   "cxx",      "c++"   },
        {   "flag",     ""      },
        {   "ld",       "cc"    },
        {   "ldflag",   ""      },
        {   "jobs",     "0"     }
    };

    bool shared = false;
    bool debug = false;
    bool clean = false;
    bool usePipe = true;
    bool useClangXX11 = false;
    bool useThread = false;
    vector<string> with, without, all;

    // Parse arguments.
    for (int i = 1; i < argc; ++i) {
        const string& arg(argv[i]);

        // So obvisously, file name should not contain '='.
        size_t pos = arg.find('=');
        if (pos != string::npos && pos != arg.size()-1) {
            // Update key-value.
            auto iter = ArgTable.find(arg.substr(0, pos));
            if (iter != ArgTable.end()) {
                iter->second = arg.substr(pos+1);
            }
        } else if (arg == "help") {
            Usage(argv[0]);
            return 0;
        } else if (arg == "clean") {
            clean = true;
        } else if (arg == "debug") {
            debug = true;
        } else if (arg == "shared") {
            shared = true;
        } else if (arg == "c++11") {
            useClangXX11 = true;
        } else if (arg == "thread") {
            useThread = true;
        } else {
            switch (FileInfo(arg).Type()) {
            case FileType::Directory:
            {
                const auto& files = Dir::ListDir(arg);
                all.reserve(all.size() + files.size());
                all.insert(all.end(), files.begin(), files.end());
            }
                break;

            case FileType::Regular:
            {
                all.push_back(arg);
            }
                break;

            default:
            {
                cerr << "FATAL: bad argument: " << endl;
                cerr << "arg: " << arg << endl;
                return -1;
            }
                break;
            }
        }
    }

    if (!ArgTable["flag"].empty())
        ArgTable["flag"].insert(0, 1, ' ');
    if (debug)
        ArgTable["flag"] += " -g";
    if (shared)
        ArgTable["flag"] += " -fPIC";
    if (usePipe) {
        ArgTable["flag"] += " -pipe";
    }
    if (useClangXX11) {
        ArgTable["cc"] = "clang";
        ArgTable["cxx"] = "clang++";
        ArgTable["flag"] += " -std=c++11 -stdlib=libc++";
    }

    if (!ArgTable["ldflag"].empty())
        ArgTable["ldflag"].insert(0, 1, ' ');
    if (useThread) {
        ArgTable["ldflag"] += " -pthread";
    }

    if (all.empty())
        all = Dir::ListDir(".");
    if (all.empty()) {
        cerr << "FATAL: nothing to build!" << endl;
        return -1;
    }

    // Prepare construct units.
    bool hasCpp = false;
    bool hasOut = FileInfo(ArgTable["out"]).Exists();
    vector<ConsUnit> newUnits;
    string allObjects;

    for (const auto& file: all) {
        ConsUnit unit(file);
        string compiler;

        // Pick up source file.
        const string ext(FileInfo(file).Suffix());
        if (C_EXT.find(ext) != C_EXT.end()) {
            compiler = ArgTable["cc"];
        } else if (CXX_EXT.find(ext) != CXX_EXT.end()) {
            compiler = ArgTable["cxx"];
            hasCpp = true;
        } else {
            continue;
        }

        // Calculate dependence.
        if (ConsUnit::Init(unit, compiler, ArgTable["flag"])) {
            allObjects += " " + unit.out;
            if (!unit.cmd.empty()) {
                newUnits.push_back(std::move(unit));
            }
        } else {
            cerr << "FATAL: failed to calculate dependence!" << endl;
            cerr << "\tfile:     " << file << endl;
            cerr << "\tcompiler: " << compiler << endl;
            cerr << "\tflag:     " << ArgTable["flag"] << endl;
            return -1;
        }
    }

    if (hasCpp)
        ArgTable["ld"] = ArgTable["cxx"];

#ifdef DEBUG
    // Debug info.
    {
        auto fn = [](const vector<ConsUnit>& units)->void {
            for (const auto& unit: units) {
                cout << "in: " <<  unit.in << ", " << "out: " << unit.out << endl;
                cout << "\t" << unit.cmd << endl;
                cout << "\t";
                for (const auto& dep: unit.deps)
                    cout << dep << ", ";
                cout << endl;
            }
        };
        cout << "new units: " << endl;
        fn(newUnits);
    }
#endif

    // Let's build them all.
    if (!clean) {
        if (!newUnits.empty()) {
            cout << "* Build: ";
            const size_t nfiles = std::min((size_t)5, newUnits.size());
            for (size_t i = 0; i < nfiles; ++i) {
                cout << newUnits[i].in << ((i+1 < nfiles) ? ", " : "");
            }
            if (nfiles < newUnits.size()) {
                cout << " and " << newUnits.size() - nfiles<< " files";
            }
            cout << endl;

            ParallelCompiler pc(newUnits);
            if (pc.Run(::stoi(ArgTable["jobs"])) != 0)
                return -1;
        }

        if (!hasOut || !newUnits.empty()) {
            string ldCmd = ArgTable["ld"] + " -o " + ArgTable["out"] +
                ArgTable["flag"] + ArgTable["ldflag"];
            if (shared)
                ldCmd += " -shared";
            ldCmd += allObjects;

            cout << "- Link - " << ldCmd << endl;
            if (::system(ldCmd.c_str()) != 0)
                return -1;
        }
    } else {
        const string& cmd = "rm -f " + ArgTable["out"] + allObjects;
        cout << cmd << endl;
        ::system(cmd.c_str());
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "PDICHeader.h"
#include "PDICIndex.h"
#include "PDICDatablock.h"
#include "util.h"
#include "util_stl.h"
#include "bocu1.h"
#include "dump.h"
#include <ctime>

#define rep(var,n)  for(int var=0;var<(n);var++)
#define traverse(c,i)  for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define all(c)  (c).begin(),(c).end()
#define found(s,e)  ((s).find(e)!=(s).end())

#define DEBUG
#define VERBOSE

#ifdef DEBUG
#include "cout.h"
#endif

class Dict {
 public:
  FILE *fp;
  PDICIndex *index;
  std::string path, name;
 public:
  Dict(FILE *fp, const std::string& name, const std::string& path) {
    this->fp = fp;
    this->index = new PDICIndex(fp);
    this->name = name;
    this->path = path;
  }
  ~Dict() { fclose(fp); delete index; }
  std::string info() { return name + " " + path; }
};

// prototypes
void load_rc();
std::vector<int> resolve_aliases(const std::string& name);
void do_use(std::string name);
void do_lookup(char *needle, int needle_len=0);
void lookup(FILE *fp, PDICIndex *index, unsigned char *needle, bool exact_match);

void dump(unsigned char *entry, unsigned char *jword);
void dump_word(unsigned char *entry, unsigned char *);
void count_word(unsigned char *entry, unsigned char *);

int do_load(const std::string& filename);
void do_alias(const std::string& alias, const std::string& valid_name);
void do_alias(const std::string& alias, const std::vector<std::string>& valid_names);
bool do_command(char *cmdstr);

// globals
std::vector<std::string> loadpaths;
std::vector<Dict*> dicts;
std::map<std::string,std::vector<std::string> > aliases; // name -> name
std::map<std::string,int> nametable; // name -> dict_id

std::vector<int> current_dict_ids;
std::string current_dict_name = "";

int main(int argc, char **argv)
{
  load_rc();

  if (argc >= 2) {
    std::string filename = argv[1];
    do_load(filename);
  }

  // REPL
  for (bool looping=true; looping; ) {
    char line[256];
    printf("%s> ", current_dict_name.c_str());
    if (!fgets(line, 256, stdin)) { newline(); break; }
    int linelen = strlen(line); line[--linelen] = 0;
    if (linelen == 0) continue;

    switch (line[0]) {
      case '.': // command mode
        looping = do_command(line+1);
        break;

      default:
        do_lookup(line);
        newline();
        break;
    }
  }

  traverse(dicts, dict) delete *dict;

  return 0;
}

void load_rc()
{
  char rcpath[128];
  strncpy(rcpath, getenv("HOME"), 120);
  strcat(rcpath, "/.pdicrc");

  FILE *fp = fopen(rcpath, "r");
  if (fp != NULL) {
    char line[256];
    while (fgets(line, 256, fp)) {
      int linelen = strlen(line); line[--linelen] = 0;
      if (linelen == 0) continue;

      char *rem = strchr(line, ';');
      if (rem) { *rem = 0; linelen = (int)(rem - line); }

      while (linelen > 0) {
        if (line[linelen-1] != ' ') break;
        line[--linelen] = 0;
      }
      if (linelen == 0) continue;

      do_command(line);
    }
  } else {
    printf(".pdicrc not found\n");
  }
  fclose(fp);
}

std::vector<int> resolve_aliases(const std::string& name)
{
  std::vector<int> dict_ids;

  if (found(nametable,name)) {
    dict_ids.push_back( nametable[name] );
  } else if (found(aliases,name)) {
    std::vector<std::string> names = aliases[name];
    traverse(names, name) {
      std::vector<int> ids = resolve_aliases(*name);
      dict_ids.insert(dict_ids.end(), all(ids));
    }
  } else {
    printf("ERROR: '%s' not found.\n", name.c_str());
  }

  return dict_ids;
}

void do_use(std::string name)
{
  std::vector<int> dict_ids = resolve_aliases(name);

  current_dict_ids.assign(all(dict_ids));
  current_dict_name = name;
}

void do_lookup(char *needle, int needle_len)
{
  if (!needle_len) needle_len = strlen(needle);

  if (current_dict_ids.size() == 0) {
    printf("no dictionary selected\n");
    return;
  }
#ifdef VERBOSE
  std::cout << "LOOKUP: " << current_dict_name << " " << current_dict_ids << std::endl;
#endif
  traverse(current_dict_ids, current_dict_id) {
    Dict *dict = dicts[*current_dict_id];
    bool exact_match = true;
    if (needle[needle_len-1] == '*') {
      exact_match = false;
      needle[needle_len-1] = 0;
    }
    lookup(dict->fp, dict->index, (unsigned char *)needle, exact_match);
  }
}

void lookup(FILE *fp, PDICIndex *index, unsigned char *needle, bool exact_match)
{
  int target_code = index->isBOCU1() ? TARGET_BOCU1 : TARGET_SHIFTJIS;

  Criteria *criteria = new Criteria(needle, target_code, exact_match);

  int from, to, cnt;
  cnt = index->bsearch_in_index(criteria->needle, exact_match, from, to);
#ifdef VERBOSE
  printf("lookup. from %d to %d, %d/%d...\n", from, to, cnt, index->_nindex);
#endif
  for (int ix=from; ix<=to; ix++) {
    if (ix < 0) continue;
    if (ix >= index->_nindex) break;

    PDICDatablock* datablock = new PDICDatablock(fp, index, ix);
    datablock->iterate(&dump, criteria);
    //datablock->iterate(&dump, NULL);
    delete datablock;
  }
}

void dump(unsigned char *entry, unsigned char *jword)
{
  printf("%s\n", entry);

  unsigned char *jword_indented = (unsigned char *)indent((char *)"   ", (char *)jword);
  printf("%s\n", jword_indented);
  free((char *)jword_indented);
}
void dump_word(unsigned char *entry, unsigned char *jword)
{
  puts((char *)entry);
}

//int _wordcount = 0;
//std::set<std::string> _words;
//std::priority_queue<std::string> _words;

void count_word(unsigned char *entry, unsigned char *jword)
{
  // 1996426 words
  // ++_wordcount; // 3.20538 sec; 1.6 usec/entry
  // set<string>#insert(std::string((const char *)entry)); // 5.21911 sec; 2.6 usec/entry
  // priority_queue<string>#push(std::string((const char *)entry)); // 5.5034 sec; 2.76 usec/entry
}

int do_load(const std::string& filename)
{
  for (int i=0; i<loadpaths.size(); ++i) {
    std::string path = loadpaths[i] + "/" + filename;

    FILE *fp = fopen(path.c_str(), "r");
    if (fp != NULL) {
      int new_dict_id = dicts.size();

      dicts.push_back( new Dict(fp, filename, path) );
      nametable[filename] = new_dict_id;

      //#ifdef VERBOSE
      printf("loading %s... => { name: %s, dict_id: %d }\n", path.c_str(), filename.c_str(), new_dict_id);
      //#endif
      return new_dict_id;
    }
  }
  return -1;
}

void do_alias(const std::string& alias, const std::string& valid_name)
{
  std::vector<std::string> names(1, valid_name);
  do_alias(alias, names);
}
void do_alias(const std::string& alias, const std::vector<std::string>& valid_names)
{
  aliases[alias] = valid_names;
#ifdef VERBOSE
  std::cout << "-" << alias << " -> " << join(valid_names, ", ") << std::endl;
#endif
}

bool do_command(char *cmdstr)
{
  std::vector<std::string> cmd = split(cmdstr);

  if (cmd[0] == "quit" || cmd[0] == "bye") {
    printf("bye.\n");
    return false;
  }
  else if (cmd[0] == "add") {
    if (cmd.size() == 3 && cmd[1] == "loadpath") {
      loadpaths.push_back(cmd[2]);
    } else {
      printf("[command] add loadpath <path>\n");
    }
  }
  else if (cmd[0] == "group" && cmd.size() >= 2) {
    if (cmd.size() >= 2) {
      std::string groupname = cmd[1];
      std::vector<std::string> names;
      for (int i=2; i<cmd.size(); ++i) {
        if (cmd[i] == "=") continue;
        else names.push_back(cmd[i]);
      }
      do_alias(groupname, names);
    } else {
      printf("[command] group <groupname> = <name_1> <name_2> ... <name_n>\n");
    }
  }
  else if (cmd[0] == "load") {
    if (cmd.size() >= 2) {
      std::string filename = cmd[1];
      int dict_id = do_load(filename);

      if (dict_id >= 0) {
#ifdef VERBOSE
        std::cout << "+" << filename << std::endl;
#endif
        for (int i=2; i<cmd.size(); ++i) {
          do_alias(cmd[i], filename);
        }
      } else {
        printf("ERROR: file %s not found in loadpaths\n", cmd[1].c_str());
      }
    } else {
      printf("[command] load <filename>\n");
    }
  }
  else if (cmd[0] == "use") {
    if (cmd.size() >= 2) {
      std::string name = cmd[1];
      if (found(aliases, name)) {
        do_use(name);
      } else {
        printf("ERROR: '%s' not found.\n", name.c_str());
      }
    } else {
      printf("[command] use <name>\n");
    }
  }
  else if (cmd[0] == "list") {
    set<int> dict_ids(all(current_dict_ids));
    for (int dict_id=0; dict_id<dicts.size(); ++dict_id) {
      printf("%2d%c %s\n", dict_id, (found(dict_ids,dict_id) ? '*' : ':'), dicts[dict_id]->info().c_str());
    }
  }
  else if (cmd[0] == "aliases") {
    traverse(aliases, alias) {
      std::cout << alias->first << ": " << join(alias->second, ", ") << std::endl;
    }
    /*
    traverse(nametable, name) {
      int dict_id = name->second;
      std::cout << name->first << ": " << dict_id << " " << dicts[dict_id]->info() << std::endl;
    }
    */
  }
  else if (cmd[0] == "dump") {
    if (cmd.size() >= 2) {
      if (current_dict_ids.size() == 0) {
        printf("ERROR: no dictionary selected\n");
      } else {
#ifdef VERBOSE
        std::cout << "DUMP: " << current_dict_name << " " << current_dict_ids << std::endl;
#endif
        traverse(current_dict_ids, current_dict_id) {
          PDICIndex *index = dicts[*current_dict_id]->index;
          std::string what_to_dump = cmd[1];
          if (what_to_dump == "header") {
            index->header->dump();
          } else if (what_to_dump == "index") {
            index->dump();
          } else if (what_to_dump == "words") {
            index->iterate_all_datablocks(&dump_word, NULL);
            /*
              } else if (what_to_dump == "count") {
              clock_t start, end;
              start = clock();
              _wordcount = 0;
              //_words.clear();
              index->iterate_all_datablocks(&count_word, NULL);
              end = clock();
              //printf("%d words; %g msec.\n", (int)_words.size(), (double)(end - start)/CLOCKS_PER_SEC*1000);
              printf("%d words; %g msec.\n", _wordcount, (double)(end - start)/CLOCKS_PER_SEC*1000);
            */
          } else if (what_to_dump == "all") {
            index->iterate_all_datablocks(&dump, NULL);
          } else {
            printf("ERROR: I don't know how to dump '%s'...\n", what_to_dump.c_str());
          }
        }
      }
    } else {
      printf("[command] dump {header|index|words|all}\n");
    }
  }
  else if (cmd[0] == "lookup") {
    do_lookup(cmdstr + 7);
    newline();
  }
  else {
    printf("ERROR: unknown command, '%s'\n", cmd[0].c_str());
  }

  return true;
}

<commit_msg>clock()はプロセスの所要時間を採るので、実時間（体感時間）より短い。ツール設計の上で体感時間を知りたいのでgettimeofday()の数値も欲しい<commit_after>#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "PDICHeader.h"
#include "PDICIndex.h"
#include "PDICDatablock.h"
#include "PDICDatafield.h"
#include "util.h"
#include "util_stl.h"
#include "bocu1.h"
#include "dump.h"
#include "charcode.h"

#include <ctime>
#include <sys/time.h>
timeval _timeval_start;
clock_t _clock_start;
void TIME_RESET() {
  _clock_start = clock();
  gettimeofday(&_timeval_start, NULL);
}
std::pair<int,int> TIME_USEC() {
  int timeval_usec, clock_usec;
  timeval timeval_end;
  gettimeofday(&timeval_end, NULL);
  clock_t clock_end = clock();
  timeval_usec = (timeval_end.tv_sec - _timeval_start.tv_sec)*1000000 + (timeval_end.tv_usec - _timeval_start.tv_usec);
  if (CLOCKS_PER_SEC == 1000000)
    clock_usec = clock_end - _clock_start;
  else
    clock_usec = (int)((long long)(clock_end - _clock_start) * 1000000 / CLOCKS_PER_SEC);

  return std::make_pair(timeval_usec, clock_usec);
}

#define rep(var,n)  for(int var=0;var<(n);var++)
#define traverse(c,i)  for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define all(c)  (c).begin(),(c).end()
#define found(s,e)  ((s).find(e)!=(s).end())

#define DEBUG
#define VERBOSE

#ifdef DEBUG
#include "cout.h"
#endif

class Dict {
 public:
  FILE *fp;
  PDICIndex *index;
  std::string path, name;
 public:
  Dict(FILE *fp, const std::string& name, const std::string& path) {
    this->fp = fp;
    this->index = new PDICIndex(fp);
    this->name = name;
    this->path = path;
  }
  ~Dict() { fclose(fp); delete index; }
  std::string info() { return name + " " + path; }
};

// prototypes
void load_rc();
std::vector<int> resolve_aliases(const std::string& name);
void do_use(std::string name);
void do_lookup(char *needle, int needle_len=0);
void lookup(FILE *fp, PDICIndex *index, unsigned char *needle, bool exact_match);

void dump(PDICDatafield *datafield);
void dump_word(PDICDatafield *datafield);
void count_word(PDICDatafield *datafield);
int calculate_space_for_index(PDICIndex *index);

int do_load(const std::string& filename);
void do_alias(const std::string& alias, const std::string& valid_name);
void do_alias(const std::string& alias, const std::vector<std::string>& valid_names);
bool do_command(char *cmdstr);

// globals
std::vector<std::string> loadpaths;
std::vector<Dict*> dicts;
std::map<std::string,std::vector<std::string> > aliases; // name -> name
std::map<std::string,int> nametable; // name -> dict_id

std::vector<int> current_dict_ids;
std::string current_dict_name = "";

int main(int argc, char **argv)
{
  load_rc();

  if (argc >= 2) {
    std::string filename = argv[1];
    do_load(filename);
  }

  // REPL
  for (bool looping=true; looping; ) {
    char line[256];
    printf("%s> ", current_dict_name.c_str());
    if (!fgets(line, 256, stdin)) { newline(); break; }
    int linelen = strlen(line); line[--linelen] = 0;
    if (linelen == 0) continue;

    switch (line[0]) {
      case '.': // command mode
        looping = do_command(line+1);
        break;

      default:
        do_lookup(line);
        newline();
        break;
    }
  }

  traverse(dicts, dict) delete *dict;

  return 0;
}

void load_rc()
{
  char rcpath[128];
  strncpy(rcpath, getenv("HOME"), 120);
  strcat(rcpath, "/.pdicrc");

  FILE *fp = fopen(rcpath, "r");
  if (fp != NULL) {
    char line[256];
    while (fgets(line, 256, fp)) {
      int linelen = strlen(line); line[--linelen] = 0;
      if (linelen == 0) continue;

      char *rem = strchr(line, ';');
      if (rem) { *rem = 0; linelen = (int)(rem - line); }

      while (linelen > 0) {
        if (line[linelen-1] != ' ') break;
        line[--linelen] = 0;
      }
      if (linelen == 0) continue;

      do_command(line);
    }
  } else {
    printf(".pdicrc not found\n");
  }
  fclose(fp);
}

std::vector<int> resolve_aliases(const std::string& name)
{
  std::vector<int> dict_ids;

  if (found(nametable,name)) {
    dict_ids.push_back( nametable[name] );
  } else if (found(aliases,name)) {
    std::vector<std::string> names = aliases[name];
    traverse(names, name) {
      std::vector<int> ids = resolve_aliases(*name);
      dict_ids.insert(dict_ids.end(), all(ids));
    }
  } else {
    printf("ERROR: '%s' not found.\n", name.c_str());
  }

  return dict_ids;
}

void do_use(std::string name)
{
  std::vector<int> dict_ids = resolve_aliases(name);

  current_dict_ids.assign(all(dict_ids));
  current_dict_name = name;
}

void do_lookup(char *needle, int needle_len)
{
  if (!needle_len) needle_len = strlen(needle);

  if (current_dict_ids.size() == 0) {
    printf("no dictionary selected\n");
    return;
  }
#ifdef VERBOSE
  std::cout << "LOOKUP: " << current_dict_name << " " << current_dict_ids << std::endl;
#endif
  traverse(current_dict_ids, current_dict_id) {
    Dict *dict = dicts[*current_dict_id];
    bool exact_match = true;
    if (needle[needle_len-1] == '*') {
      exact_match = false;
      needle[needle_len-1] = 0;
    }
    lookup(dict->fp, dict->index, (unsigned char *)needle, exact_match);
  }
}

void lookup(FILE *fp, PDICIndex *index, unsigned char *needle, bool exact_match)
{
  int target_charcode = index->isBOCU1() ? CHARCODE_BOCU1 : CHARCODE_SHIFTJIS;

  Criteria *criteria = new Criteria(needle, target_charcode, exact_match);

  int from, to, cnt;
  cnt = index->bsearch_in_index(criteria->needle, exact_match, from, to);
#ifdef VERBOSE
  printf("lookup. from %d to %d, %d/%d...\n", from, to, cnt, index->_nindex);
#endif
  for (int ix=from; ix<=to; ix++) {
    if (ix < 0) continue;
    if (ix >= index->_nindex) break;

    PDICDatablock* datablock = new PDICDatablock(fp, index, ix);
    datablock->iterate(&dump, criteria);
    //datablock->iterate(&dump, NULL);
    delete datablock;
  }
}

void dump(PDICDatafield *datafield)//unsigned char *entry, unsigned char *jword)
{
  puts((char *)datafield->entry_word_utf8());

  unsigned char *jword_indented = (unsigned char *)indent((char *)"   ", (char *)datafield->jword_utf8());
  puts((char *)jword_indented);
  free((char *)jword_indented);
}
void dump_word(PDICDatafield *datafield)
{
  puts((char *)datafield->entry_word_utf8());
  //puts((char *)entry);
}

int do_load(const std::string& filename)
{
  for (int i=0; i<loadpaths.size(); ++i) {
    std::string path = loadpaths[i] + "/" + filename;

    FILE *fp = fopen(path.c_str(), "r");
    if (fp != NULL) {
      int new_dict_id = dicts.size();

      dicts.push_back( new Dict(fp, filename, path) );
      nametable[filename] = new_dict_id;

      //#ifdef VERBOSE
      printf("loading %s... => { name: %s, dict_id: %d }\n", path.c_str(), filename.c_str(), new_dict_id);
      //#endif
      return new_dict_id;
    }
  }
  return -1;
}

void do_alias(const std::string& alias, const std::string& valid_name)
{
  std::vector<std::string> names(1, valid_name);
  do_alias(alias, names);
}
void do_alias(const std::string& alias, const std::vector<std::string>& valid_names)
{
  aliases[alias] = valid_names;
#ifdef VERBOSE
  std::cout << "-" << alias << " -> " << join(valid_names, ", ") << std::endl;
#endif
}

bool do_command(char *cmdstr)
{
  std::vector<std::string> cmd = split(cmdstr);

  if (cmd[0] == "quit" || cmd[0] == "bye") {
    printf("bye.\n");
    return false;
  }
  else if (cmd[0] == "add") {
    if (cmd.size() == 3 && cmd[1] == "loadpath") {
      loadpaths.push_back(cmd[2]);
    } else {
      printf("[command] add loadpath <path>\n");
    }
  }
  else if (cmd[0] == "group" && cmd.size() >= 2) {
    if (cmd.size() >= 2) {
      std::string groupname = cmd[1];
      std::vector<std::string> names;
      for (int i=2; i<cmd.size(); ++i) {
        if (cmd[i] == "=") continue;
        else names.push_back(cmd[i]);
      }
      do_alias(groupname, names);
    } else {
      printf("[command] group <groupname> = <name_1> <name_2> ... <name_n>\n");
    }
  }
  else if (cmd[0] == "load") {
    if (cmd.size() >= 2) {
      std::string filename = cmd[1];
      int dict_id = do_load(filename);

      if (dict_id >= 0) {
#ifdef VERBOSE
        std::cout << "+" << filename << std::endl;
#endif
        for (int i=2; i<cmd.size(); ++i) {
          do_alias(cmd[i], filename);
        }
      } else {
        printf("ERROR: file %s not found in loadpaths\n", cmd[1].c_str());
      }
    } else {
      printf("[command] load <filename>\n");
    }
  }
  else if (cmd[0] == "use") {
    if (cmd.size() >= 2) {
      std::string name = cmd[1];
      if (found(aliases, name)) {
        do_use(name);
      } else {
        printf("ERROR: '%s' not found.\n", name.c_str());
      }
    } else {
      printf("[command] use <name>\n");
    }
  }
  else if (cmd[0] == "list") {
    set<int> dict_ids(all(current_dict_ids));
    for (int dict_id=0; dict_id<dicts.size(); ++dict_id) {
      printf("%2d%c %s\n", dict_id, (found(dict_ids,dict_id) ? '*' : ':'), dicts[dict_id]->info().c_str());
    }
  }
  else if (cmd[0] == "aliases") {
    traverse(aliases, alias) {
      std::cout << alias->first << ": " << join(alias->second, ", ") << std::endl;
    }
    /*
    traverse(nametable, name) {
      int dict_id = name->second;
      std::cout << name->first << ": " << dict_id << " " << dicts[dict_id]->info() << std::endl;
    }
    */
  }
  else if (cmd[0] == "dump") {
    if (cmd.size() >= 2) {
      if (current_dict_ids.size() == 0) {
        printf("ERROR: no dictionary selected\n");
      } else {
#ifdef VERBOSE
        std::cout << "DUMP: " << current_dict_name << " " << current_dict_ids << std::endl;
#endif
        traverse(current_dict_ids, current_dict_id) {
          PDICIndex *index = dicts[*current_dict_id]->index;
          std::string what_to_dump = cmd[1];
          if (what_to_dump == "header") {
            index->header->dump();
          } else if (what_to_dump == "index") {
            index->dump();
          } else if (what_to_dump == "words") {
            index->iterate_all_datablocks(&dump_word, NULL);
          } else if (what_to_dump == "count") {
            printf("[%d]", *current_dict_id);
            calculate_space_for_index(index);
          } else if (what_to_dump == "all") {
            index->iterate_all_datablocks(&dump, NULL);
          } else {
            printf("ERROR: I don't know how to dump '%s'...\n", what_to_dump.c_str());
          }
        }
      }
    } else {
      printf("[command] dump {header|index|words|all}\n");
    }
  }
  else if (cmd[0] == "lookup") {
    do_lookup(cmdstr + 7);
    newline();
  }
  else {
    printf("ERROR: unknown command, '%s'\n", cmd[0].c_str());
  }

  return true;
}

int _wordcount = 0;
int _wordsize_sum = 0;
//std::set<std::string> _words;
//std::priority_queue<std::string> _words;

int calculate_space_for_index(PDICIndex *index)
{
  TIME_RESET();

  _wordcount = 0;
  _wordsize_sum = 0;
  //_words.clear();

  index->iterate_all_datablocks(&count_word, NULL);

  std::pair<int,int> time = TIME_USEC();

  printf("%d words, %d bytes; %.2f b/w; real:%d process:%d.\n", _wordcount, _wordsize_sum, (double)_wordsize_sum/_wordcount, time.first, time.second);

  return _wordsize_sum;
}

void count_word(PDICDatafield *datafield)
{
  // Eijiro131: 1996426 words
  // set<string>: 5.2sec (= 2.6 usec/entry)
  // priority_queue<string>: 5.5sec (= 2.76 usec/entry)
  // e,jともにutf8文字列を用意: 3205 ms (= 1.6 usec/entry)
  // memcpyあり: 250 ms (= 0.125 usec/entry)
  // memcpyなし: 147 ms
  ++_wordcount;
  _wordsize_sum += (datafield->entry_index_size + 1);
}

<|endoftext|>


<commit_before>// -*- C++ -*-
// Implementation of: ????
//
// Copyright (C) 2010 by John Weiss
// This program is free software; you can redistribute it and/or modify
// it under the terms of the Artistic License, included as the file
// "LICENSE" in the source code archive.
//
// 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.
//
// You should have received a copy of the file "LICENSE", containing
// the License John Weiss originally placed this program under.
//
static const char* const
xFOOx_cc__="RCS $Id$";

// Includes
//
#include <iostream>
#include <string>
#include <vector>
#include <exception>

//#include <boost/something.hpp>

#include "xFOOx.h"

//
// Using Decls.
//
using std::string;
using std::vector;
using std::exception;
using std::cerr;
using std::cout;
using std::endl;
using std::flush;

//
// Static variables
//

//
// Typedefs
//

/////////////////////////

//
// General Function Definitions
//

/////////////////////////

//
// Functions "main()" and "cxx_main()"
//

// This is where all of your main handling should go.
int cxx_main(const string& myName,
             const string& myPath,
             const vector<string>& argv)
{
}

int main(int argc, char* argv[])
{
    // Split off the name of the executable from its path.
    string myName(argv[0]);
    string::size_type last_pathsep = myName.find_last_of('/');
    string myPath;
    if(last_pathsep != string::npos) {
        myPath = myName.substr(0, last_pathsep+1);
        myName.erase(0, last_pathsep+1);
    }

    // Build a vector of strings for the arg list, which is much easier to
    // handle than the old-style char** argv.
    vector<string> argVec;
    argVec.reserve(argc);
    for(int i=1; i < argc; ++i) {
        argVec.push_back(string(argv[i]));
    }

    // Call cxx_main(), which is where almost all of your code should go.
    try {
        return cxx_main(myName, myPath, argVec);
    } catch(FooException& ex) {
        cerr << "Caught Foo: " << ex.what() << endl;
        return 3;
    } catch(exception& ex) {
         cerr << endl << "(Std) Exception caught: \""
              << ex.what() << "\"" << endl;
    } catch(...) {
        cerr << "Unknown exception caught." << endl;
    }
    return -1;
}

/////////////////////////
//
// End
<commit_msg>Added boilerplate for using boost::program_options in my programs.<commit_after>// -*- C++ -*-
// Implementation of: ????
//
// Copyright (C) 2010 by John Weiss
// This program is free software; you can redistribute it and/or modify
// it under the terms of the Artistic License, included as the file
// "LICENSE" in the source code archive.
//
// 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.
//
// You should have received a copy of the file "LICENSE", containing
// the License John Weiss originally placed this program under.
//
static const char* const
xFOOx_cc__="RCS $Id$";

// Includes
//
#include <iostream>
#include <string>
#include <vector>
#include <exception>

#include <boost/program_options.hpp>
//#include <boost/something.hpp>

#include "xFOOx.h"

//
// Using Decls.
//
using std::string;
using std::vector;
using std::exception;
using std::cerr;
using std::cout;
using std::endl;
using std::flush;

//
// Static variables
//

//
// Typedefs
//

/////////////////////////

//
// General Function Definitions
//

/////////////////////////

//
// Function:  "process_opts()"
//

void process_opts(const string& myName,
                  int argc, char* argv[],
                  boost::program_options::variables_map& optMap)
{
    using boost::program_options;

    // // // // N.B.:
    // Change the signature of this fn. to take a struct containing all of
    // your program options.  You can then pass the address of the individual
    // struct members to the value<T>(...) operators.
    //
    // - It's possible to allow "unregistered" options on the cmdline.  See
    //   the Boost docs for details.

    options_description cmdlineOpts("Options:");
    bool show_help(false);
    bool show_help_config(false);
    string cfgfile;

    // About the Documentation String:
    // - Long lines are automatically wrapped.
    // - It can contain '\n' chars.
    // - Any space following a '\n' indents the first line accordingly, but
    //   not any wrapped lines.
    // - The '\t' character is always removed.
    // - A '\t' character in the first "line" adds extra indentation to all
    //   subsequently-wrapped lines.  It must appear near the start of the
    //   line.  (Usually, you'll put it after the first word or before the
    //   second.)

    // BEGIN:  Define the Commandline Options
    cmdlineOpts.add_options()
        ("help,h", bool_switch(&show_help), "This message.")
        ("verbose,v", value<int>()->default_value(0)->zero_tokens(),
         "Make this program more verbose.")
        ("config", value<string>(&cfgfile),
         "Configuration file, containing additional options.\n\n")
        ("help-config", bool_switch(&show_help_config),
         "Additional information about the configuration file.")
        ;
    // END:  Define the Commandline Options

    // // // REMOVE_IF_UNUSED:
    // Define the Positional Parameters, which must be "bound" to a
    // commandline option.
    positional_options_description posnParams;
    options_description posnParamOpts("Positional Parameters");

    // BEGIN:  Define the Positional Parameters
    posnParamOpts.add_options()
        ("pp1", "The description of the first positional parameter.")
        ("pp2", "The description of the second positional parameter.")
        ("pp_list::all_remaining",
         // value< std::vector<std::string> >,
         "The description of the remaining positional parameters.")
        ;
    posnParams.add("pp1", 1);
    posnParams.add("pp2", 1);
    posnParams.add("pp_list::all_remaining", -1);
    // END:  Define the Positional Parameters

    // Add the positional parameters to the commandline options.
    cmdlineOpts.add(posnParamOpts);
    // // // REMOVE_IF_UNUSED: END

    // // // REMOVE_IF_UNUSED: BEGIN
    options_description cfgOpts("ConfigFile Variables");
    // BEGIN:  Define the Configfile Options
    cfgOpts.add_options()
        ("example", "An example")
        ;
    // END:  Define the Configfile Options
    // // // REMOVE_IF_UNUSED: END

    // // // REMOVE_IF_UNUSED: BEGIN
    options_description sharedOpts;
    // BEGIN:  Define the Configfile Options
    sharedOpts.add_options()
        ("example2", "An example")
        ;
    // END:  Define the Configfile Options

    cfgOpts.add(sharedOpts);
    cmdlineOpts.add(sharedOpts);
    // // // REMOVE_IF_UNUSED: END

    // Parse the commandline
    store(parse_command_line(argc,argv, cmdlineOpts),optMap);
    // // // OR:
    command_line_parser complexParser(argc, argv);
    complexParser.options(cmdlineOpts);
    complexParser.positional(posnParams);
    store(complexParser.run(), optMap);
    // // // REMOVE_IF_UNUSED: BEGIN
    if(cfgfile.empty()) {
        // Error message goes here.
        // Maybe throw an exception?
    } else {
        std::ifstream cfg_ifs(cfgfile);
        if(!cfg_ifs) {
            string errmsg("Invalid/unknown configuration file: \"");
            errmsg += cfgfile;
            errmsg += '"';
            throw invalid_option_value(errmsg);
        }
        try {
            store(parse_config_file(cfg_ifs, cfgOpts), optMap);
            cfg_ifs.close();
        } catch(std::ios_base::failure& ex) {
            string errmsg("Failed to read configuration file: \"");
            errmsg += cfgfile;
            errmsg += "\"\nReason:\n\t\"";
            errmsg += ex.what();
            errmsg += '"';
            throw invalid_option_value(errmsg);
        }
    }
    // // // REMOVE_IF_UNUSED: END
    notify(vm);

    // Common Options Handling.
    //

    // // // // // REMOVABLE_NOTE:
    // You can actually have the boost::program_options library do some of this
    // for you by using 'value<T>()->notifier(function1<void, const T&>)'.
    // See the Boost documentation for details.
    //
    // Note:  By using a placeholder options_description object, we can
    // control which options we describe using "--help".
    // This also lets us create "--help-all" or "--help-config" output.

    // --help:
    //     This is easy:  Just send the appropriate options_description to
    //     cout.
    //
    // We will still need to hand-write the traditional "usage: ..." line.
    if(show_help)
    {
        cout << "usage: " << myName
             << " [options] [posn params]"
             << endl << endl
             << cmdlineOpts
             << endl;
        exit(0);
    }

    // // // REMOVE_IF_UNUSED: BEGIN
    // --help-config:
    //     Additional help about the configuration file.
    if(show_help_config)
    {
        cout << myName << " - Configuration File:"
             << endl << endl
             << "Settings in the configuration file are of the form:"
             << endl
             << "    settingName=value"
             << endl
             << "Multiple settings can be grouped into sections.  "
             << "Each option in a group"
             << endl
             << "has the form \"sectionName.settingName\", and appears in "
             << "the configuration "
             << endl
             << "file as follows:"
             << endl
             << "    [sectionName]"
             << endl
             << "    settingName=value"
             << endl << endl
             << "The comment delimiter is '#' and may appear anywhere "
             << "on a line."
             << endl << endl
             << cfgOpts
             << endl;
        exit(0);
    }
    // // // REMOVE_IF_UNUSED: END

    // Validate other options (i.e. relationships between options) here.
}

/////////////////////////

//
// Functions "main()" and "cxx_main()"
//

// This is where all of your main handling should go.
int cxx_main(const string& myName,
             const string& myPath,
             const boost::program_options::variables_map& optMap)
{
    // How to retrieve entries from 'optMap':
    //     optMap["option"].as<type>()
    //
    // To check if the option is unset or wasn't passed:
    //     optMap["option"].empty()
    //
    // To check if an option with a default value wasn't passed:
    //     optMap["option"].defaulted()
}

int main(int argc, char* argv[])
{
    // Split off the name of the executable from its path.
    string myName(argv[0]);
    string::size_type last_pathsep = myName.find_last_of('/');
    string myPath;
    if(last_pathsep != string::npos) {
        myPath = myName.substr(0, last_pathsep+1);
        myName.erase(0, last_pathsep+1);
    }

    // Call cxx_main(), which is where almost all of your code should go.
    try {
        boost::program_options::variables_map& optionsMap;
        process_opts(myName, argc, argv, optionsMap);

        return cxx_main(myName, myPath, argVec);
    } catch(FooException& ex) {
        cerr << "Caught Foo: " << ex.what() << endl;
        return 3;
    } catch(boost:program_options::error& ex) {
        cerr << "Error while parsing program options: " << ex.what()
             << endl << endl
             << "Rerun \"" << myName << " --help\" for usage."
             << endl;
        return 1;
    } catch(exception& ex) {
         cerr << endl << "(Std) Exception caught: \""
              << ex.what() << "\"" << endl;
    } catch(...) {
        cerr << "Unknown exception caught." << endl;
    }
    return -1;
}

/////////////////////////

//
// Older Versions of "main()" and "cxx_main()"
// Rever to these if you're not/can't use Boost.
//

#ifdef NOT_USING_BOOST__PROGRAM_OPTIONS
// This is where all of your main handling should go.
int cxx_main(const string& myName,
             const string& myPath,
             const vector<string>& argv)
{
}

int main(int argc, char* argv[])
{
    // Split off the name of the executable from its path.
    string myName(argv[0]);
    string::size_type last_pathsep = myName.find_last_of('/');
    string myPath;
    if(last_pathsep != string::npos) {
        myPath = myName.substr(0, last_pathsep+1);
        myName.erase(0, last_pathsep+1);
    }

    // Build a vector of strings for the arg list, which is much easier to
    // handle than the old-style char** argv.
    vector<string> argVec;
    argVec.reserve(argc);
    for(int i=1; i < argc; ++i) {
        argVec.push_back(string(argv[i]));
    }

    // Call cxx_main(), which is where almost all of your code should go.
    try {
        return cxx_main(myName, myPath, argVec);
    } catch(FooException& ex) {
        cerr << "Caught Foo: " << ex.what() << endl;
        return 3;
    } catch(exception& ex) {
         cerr << endl << "(Std) Exception caught: \""
              << ex.what() << "\"" << endl;
    } catch(...) {
        cerr << "Unknown exception caught." << endl;
    }
    return -1;
}
#endif

/////////////////////////
//
// End
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/utility/source/process_thread_impl.h"

#include "webrtc/base/checks.h"
#include "webrtc/modules/interface/module.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/tick_util.h"

namespace webrtc {
namespace {

// We use this constant internally to signal that a module has requested
// a callback right away.  When this is set, no call to TimeUntilNextProcess
// should be made, but Process() should be called directly.
const int64_t kCallProcessImmediately = -1;

int64_t GetNextCallbackTime(Module* module, int64_t time_now) {
  int64_t interval = module->TimeUntilNextProcess();
  // Currently some implementations erroneously return error codes from
  // TimeUntilNextProcess(). So, as is, we correct that and log an error.
  if (interval < 0) {
    LOG(LS_ERROR) << "TimeUntilNextProcess returned an invalid value "
                  << interval;
    interval = 0;
  }
  return time_now + interval;
}
}

ProcessThread::~ProcessThread() {}

// static
rtc::scoped_ptr<ProcessThread> ProcessThread::Create() {
  return rtc::scoped_ptr<ProcessThread>(new ProcessThreadImpl()).Pass();
}

ProcessThreadImpl::ProcessThreadImpl()
    : wake_up_(EventWrapper::Create()), stop_(false) {
}

ProcessThreadImpl::~ProcessThreadImpl() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_.get());
  DCHECK(!stop_);

  while (!queue_.empty()) {
    delete queue_.front();
    queue_.pop();
  }
}

void ProcessThreadImpl::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_.get());
  if (thread_.get())
    return;

  DCHECK(!stop_);

  {
    // TODO(tommi): Since DeRegisterModule is currently being called from
    // different threads in some cases (ChannelOwner), we need to lock access to
    // the modules_ collection even on the controller thread.
    // Once we've cleaned up those places, we can remove this lock.
    rtc::CritScope lock(&lock_);
    for (ModuleCallback& m : modules_)
      m.module->ProcessThreadAttached(this);
  }

  thread_ = ThreadWrapper::CreateThread(
      &ProcessThreadImpl::Run, this, "ProcessThread");
  CHECK(thread_->Start());
}

void ProcessThreadImpl::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if(!thread_.get())
    return;

  {
    rtc::CritScope lock(&lock_);
    stop_ = true;
  }

  wake_up_->Set();

  CHECK(thread_->Stop());
  thread_.reset();
  stop_ = false;

  // TODO(tommi): Since DeRegisterModule is currently being called from
  // different threads in some cases (ChannelOwner), we need to lock access to
  // the modules_ collection even on the controller thread.
  // Once we've cleaned up those places, we can remove this lock.
  rtc::CritScope lock(&lock_);
  for (ModuleCallback& m : modules_)
    m.module->ProcessThreadAttached(nullptr);
}

void ProcessThreadImpl::WakeUp(Module* module) {
  // Allowed to be called on any thread.
  // TODO(tommi): Disallow this ^^^
  {
    rtc::CritScope lock(&lock_);
    for (ModuleCallback& m : modules_) {
      if (m.module == module)
        m.next_callback = kCallProcessImmediately;
    }
  }
  wake_up_->Set();
}

void ProcessThreadImpl::PostTask(rtc::scoped_ptr<ProcessTask> task) {
  // Allowed to be called on any thread.
  // TODO(tommi): Disallow this ^^^
  {
    rtc::CritScope lock(&lock_);
    queue_.push(task.release());
  }
  wake_up_->Set();
}

void ProcessThreadImpl::RegisterModule(Module* module) {
  // Allowed to be called on any thread.
  DCHECK(module);

#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
  {
    // Catch programmer error.
    rtc::CritScope lock(&lock_);
    for (const ModuleCallback& mc : modules_)
      DCHECK(mc.module != module);
  }
#endif

  // Now that we know the module isn't in the list, we'll call out to notify
  // the module that it's attached to the worker thread.  We don't hold
  // the lock while we make this call.
  if (thread_.get())
    module->ProcessThreadAttached(this);

  {
    rtc::CritScope lock(&lock_);
    modules_.push_back(ModuleCallback(module));
  }

  // Wake the thread calling ProcessThreadImpl::Process() to update the
  // waiting time. The waiting time for the just registered module may be
  // shorter than all other registered modules.
  wake_up_->Set();
}

void ProcessThreadImpl::DeRegisterModule(Module* module) {
  // Allowed to be called on any thread.
  DCHECK(module);
  {
    rtc::CritScope lock(&lock_);
    modules_.remove_if([&module](const ModuleCallback& m) {
        return m.module == module;
      });
  }

  // Notify the module that it's been detached, while not holding the lock.
  if (thread_.get())
    module->ProcessThreadAttached(nullptr);
}

// static
bool ProcessThreadImpl::Run(void* obj) {
  return static_cast<ProcessThreadImpl*>(obj)->Process();
}

bool ProcessThreadImpl::Process() {
  int64_t now = TickTime::MillisecondTimestamp();
  int64_t next_checkpoint = now + (1000 * 60);

  {
    rtc::CritScope lock(&lock_);
    if (stop_)
      return false;
    for (ModuleCallback& m : modules_) {
      // TODO(tommi): Would be good to measure the time TimeUntilNextProcess
      // takes and dcheck if it takes too long (e.g. >=10ms).  Ideally this
      // operation should not require taking a lock, so querying all modules
      // should run in a matter of nanoseconds.
      if (m.next_callback == 0)
        m.next_callback = GetNextCallbackTime(m.module, now);

      if (m.next_callback <= now ||
          m.next_callback == kCallProcessImmediately) {
        m.module->Process();
        // Use a new 'now' reference to calculate when the next callback
        // should occur.  We'll continue to use 'now' above for the baseline
        // of calculating how long we should wait, to reduce variance.
        int64_t new_now = TickTime::MillisecondTimestamp();
        m.next_callback = GetNextCallbackTime(m.module, new_now);
      }

      if (m.next_callback < next_checkpoint)
        next_checkpoint = m.next_callback;
    }

    while (!queue_.empty()) {
      ProcessTask* task = queue_.front();
      queue_.pop();
      lock_.Leave();
      task->Run();
      delete task;
      lock_.Enter();
    }
  }

  int64_t time_to_wait = next_checkpoint - TickTime::MillisecondTimestamp();
  if (time_to_wait > 0)
    wake_up_->Wait(static_cast<unsigned long>(time_to_wait));

  return true;
}
}  // namespace webrtc
<commit_msg>ProcessThreadImpl - hold the lock while checking thread_ and calling ProcessThreadAttached(). This is needed since DeRegisterModule is currently being called on arbitrary threads.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/utility/source/process_thread_impl.h"

#include "webrtc/base/checks.h"
#include "webrtc/modules/interface/module.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/system_wrappers/interface/tick_util.h"

namespace webrtc {
namespace {

// We use this constant internally to signal that a module has requested
// a callback right away.  When this is set, no call to TimeUntilNextProcess
// should be made, but Process() should be called directly.
const int64_t kCallProcessImmediately = -1;

int64_t GetNextCallbackTime(Module* module, int64_t time_now) {
  int64_t interval = module->TimeUntilNextProcess();
  // Currently some implementations erroneously return error codes from
  // TimeUntilNextProcess(). So, as is, we correct that and log an error.
  if (interval < 0) {
    LOG(LS_ERROR) << "TimeUntilNextProcess returned an invalid value "
                  << interval;
    interval = 0;
  }
  return time_now + interval;
}
}

ProcessThread::~ProcessThread() {}

// static
rtc::scoped_ptr<ProcessThread> ProcessThread::Create() {
  return rtc::scoped_ptr<ProcessThread>(new ProcessThreadImpl()).Pass();
}

ProcessThreadImpl::ProcessThreadImpl()
    : wake_up_(EventWrapper::Create()), stop_(false) {
}

ProcessThreadImpl::~ProcessThreadImpl() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_.get());
  DCHECK(!stop_);

  while (!queue_.empty()) {
    delete queue_.front();
    queue_.pop();
  }
}

void ProcessThreadImpl::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_.get());
  if (thread_.get())
    return;

  DCHECK(!stop_);

  {
    // TODO(tommi): Since DeRegisterModule is currently being called from
    // different threads in some cases (ChannelOwner), we need to lock access to
    // the modules_ collection even on the controller thread.
    // Once we've cleaned up those places, we can remove this lock.
    rtc::CritScope lock(&lock_);
    for (ModuleCallback& m : modules_)
      m.module->ProcessThreadAttached(this);
  }

  thread_ = ThreadWrapper::CreateThread(
      &ProcessThreadImpl::Run, this, "ProcessThread");
  CHECK(thread_->Start());
}

void ProcessThreadImpl::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if(!thread_.get())
    return;

  {
    rtc::CritScope lock(&lock_);
    stop_ = true;
  }

  wake_up_->Set();

  CHECK(thread_->Stop());
  stop_ = false;

  // TODO(tommi): Since DeRegisterModule is currently being called from
  // different threads in some cases (ChannelOwner), we need to lock access to
  // the modules_ collection even on the controller thread.
  // Since DeRegisterModule also checks thread_, we also need to hold the
  // lock for the .reset() operation.
  // Once we've cleaned up those places, we can remove this lock.
  rtc::CritScope lock(&lock_);
  thread_.reset();
  for (ModuleCallback& m : modules_)
    m.module->ProcessThreadAttached(nullptr);
}

void ProcessThreadImpl::WakeUp(Module* module) {
  // Allowed to be called on any thread.
  {
    rtc::CritScope lock(&lock_);
    for (ModuleCallback& m : modules_) {
      if (m.module == module)
        m.next_callback = kCallProcessImmediately;
    }
  }
  wake_up_->Set();
}

void ProcessThreadImpl::PostTask(rtc::scoped_ptr<ProcessTask> task) {
  // Allowed to be called on any thread.
  {
    rtc::CritScope lock(&lock_);
    queue_.push(task.release());
  }
  wake_up_->Set();
}

void ProcessThreadImpl::RegisterModule(Module* module) {
  // Allowed to be called on any thread.
  // TODO(tommi): Disallow this ^^^
  DCHECK(module);

#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
  {
    // Catch programmer error.
    rtc::CritScope lock(&lock_);
    for (const ModuleCallback& mc : modules_)
      DCHECK(mc.module != module);
  }
#endif

  // Now that we know the module isn't in the list, we'll call out to notify
  // the module that it's attached to the worker thread.  We don't hold
  // the lock while we make this call.
  if (thread_.get())
    module->ProcessThreadAttached(this);

  {
    rtc::CritScope lock(&lock_);
    modules_.push_back(ModuleCallback(module));
  }

  // Wake the thread calling ProcessThreadImpl::Process() to update the
  // waiting time. The waiting time for the just registered module may be
  // shorter than all other registered modules.
  wake_up_->Set();
}

void ProcessThreadImpl::DeRegisterModule(Module* module) {
  // Allowed to be called on any thread.
  // TODO(tommi): Disallow this ^^^
  DCHECK(module);

  {
    rtc::CritScope lock(&lock_);
    modules_.remove_if([&module](const ModuleCallback& m) {
        return m.module == module;
      });

    // TODO(tommi): we currently need to hold the lock while calling out to
    // ProcessThreadAttached.  This is to make sure that the thread hasn't been
    // destroyed while we attach the module.  Once we can make sure
    // DeRegisterModule isn't being called on arbitrary threads, we can move the
    // |if (thread_.get())| check and ProcessThreadAttached() call outside the
    // lock scope.

    // Notify the module that it's been detached.
    if (thread_.get())
      module->ProcessThreadAttached(nullptr);
  }
}

// static
bool ProcessThreadImpl::Run(void* obj) {
  return static_cast<ProcessThreadImpl*>(obj)->Process();
}

bool ProcessThreadImpl::Process() {
  int64_t now = TickTime::MillisecondTimestamp();
  int64_t next_checkpoint = now + (1000 * 60);

  {
    rtc::CritScope lock(&lock_);
    if (stop_)
      return false;
    for (ModuleCallback& m : modules_) {
      // TODO(tommi): Would be good to measure the time TimeUntilNextProcess
      // takes and dcheck if it takes too long (e.g. >=10ms).  Ideally this
      // operation should not require taking a lock, so querying all modules
      // should run in a matter of nanoseconds.
      if (m.next_callback == 0)
        m.next_callback = GetNextCallbackTime(m.module, now);

      if (m.next_callback <= now ||
          m.next_callback == kCallProcessImmediately) {
        m.module->Process();
        // Use a new 'now' reference to calculate when the next callback
        // should occur.  We'll continue to use 'now' above for the baseline
        // of calculating how long we should wait, to reduce variance.
        int64_t new_now = TickTime::MillisecondTimestamp();
        m.next_callback = GetNextCallbackTime(m.module, new_now);
      }

      if (m.next_callback < next_checkpoint)
        next_checkpoint = m.next_callback;
    }

    while (!queue_.empty()) {
      ProcessTask* task = queue_.front();
      queue_.pop();
      lock_.Leave();
      task->Run();
      delete task;
      lock_.Enter();
    }
  }

  int64_t time_to_wait = next_checkpoint - TickTime::MillisecondTimestamp();
  if (time_to_wait > 0)
    wake_up_->Wait(static_cast<unsigned long>(time_to_wait));

  return true;
}
}  // namespace webrtc
<|endoftext|>


<commit_before><commit_msg>Add prompt to ask prefix if there is no argument when executing<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLFootnoteConfigurationImportContext.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 14:40:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLFOOTNOTECONFIGURATIONIMPORTCONTEXT_HXX
#define _XMLOFF_XMLFOOTNOTECONFIGURATIONIMPORTCONTEXT_HXX

#ifndef _XMLOFF_XMLSTYLE_HXX
#include <xmloff/xmlstyle.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace uno { template<class X> class Reference; }
    namespace xml { namespace sax { class XAttributeList; } }
    namespace beans { class XPropertySet; }
} } }
namespace rtl { class OUString; }
class SvXMLImport;

/// import footnote and endnote configuration elements
class XMLFootnoteConfigurationImportContext : public SvXMLStyleContext
{
    const ::rtl::OUString sPropertyAnchorCharStyleName;
    const ::rtl::OUString sPropertyCharStyleName;
    const ::rtl::OUString sPropertyNumberingType;
    const ::rtl::OUString sPropertyPageStyleName;
    const ::rtl::OUString sPropertyParagraphStyleName;
    const ::rtl::OUString sPropertyPrefix;
    const ::rtl::OUString sPropertyStartAt;
    const ::rtl::OUString sPropertySuffix;
    const ::rtl::OUString sPropertyPositionEndOfDoc;
    const ::rtl::OUString sPropertyFootnoteCounting;
    const ::rtl::OUString sPropertyEndNotice;
    const ::rtl::OUString sPropertyBeginNotice;

    ::rtl::OUString sCitationStyle;
    ::rtl::OUString sAnchorStyle;
    ::rtl::OUString sDefaultStyle;
    ::rtl::OUString sPageStyle;
    ::rtl::OUString sPrefix;
    ::rtl::OUString sSuffix;
    ::rtl::OUString sNumFormat;
    ::rtl::OUString sNumSync;
    ::rtl::OUString sBeginNotice;
    ::rtl::OUString sEndNotice;

    SvXMLTokenMap* pAttrTokenMap;

    sal_Int16 nOffset;
    sal_Int16 nNumbering;
    sal_Bool bPosition;
    sal_Bool bIsEndnote;

public:

    TYPEINFO();

    XMLFootnoteConfigurationImportContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrfx,
        const ::rtl::OUString& rLName,
        const ::com::sun::star::uno::Reference<
                ::com::sun::star::xml::sax::XAttributeList> & xAttrList);

    virtual ~XMLFootnoteConfigurationImportContext();

    /// parse attributes
    virtual void StartElement(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList );

    /// for footnotes, also parse begin and end notices
    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList );

    /// get token map for attributes
    const SvXMLTokenMap& GetFtnConfigAttrTokenMap();

    /// set configuration at document; calls ProcessSettings
    // --> OD 2005-01-31 #i40579# - move code from <CreateAndInsertLate(..)>
    // to <Finish(..)>, because at this time all styles it references have been set.
    virtual void Finish( sal_Bool bOverwrite);
    // <--

    /// set configuration at document
    void ProcessSettings(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::beans::XPropertySet> & rConfig);

    /// for helper class: set begin notice
    void SetBeginNotice( ::rtl::OUString sText);

    /// for helper class: set end notice
    void SetEndNotice( ::rtl::OUString sText);
};

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.8.162); FILE MERGED 2008/04/01 13:04:19 thb 1.8.162.2: #i85898# Stripping all external header guards 2008/03/31 16:27:53 rt 1.8.162.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: XMLFootnoteConfigurationImportContext.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _XMLOFF_XMLFOOTNOTECONFIGURATIONIMPORTCONTEXT_HXX
#define _XMLOFF_XMLFOOTNOTECONFIGURATIONIMPORTCONTEXT_HXX

#include <xmloff/xmlstyle.hxx>

namespace com { namespace sun { namespace star {
    namespace uno { template<class X> class Reference; }
    namespace xml { namespace sax { class XAttributeList; } }
    namespace beans { class XPropertySet; }
} } }
namespace rtl { class OUString; }
class SvXMLImport;

/// import footnote and endnote configuration elements
class XMLFootnoteConfigurationImportContext : public SvXMLStyleContext
{
    const ::rtl::OUString sPropertyAnchorCharStyleName;
    const ::rtl::OUString sPropertyCharStyleName;
    const ::rtl::OUString sPropertyNumberingType;
    const ::rtl::OUString sPropertyPageStyleName;
    const ::rtl::OUString sPropertyParagraphStyleName;
    const ::rtl::OUString sPropertyPrefix;
    const ::rtl::OUString sPropertyStartAt;
    const ::rtl::OUString sPropertySuffix;
    const ::rtl::OUString sPropertyPositionEndOfDoc;
    const ::rtl::OUString sPropertyFootnoteCounting;
    const ::rtl::OUString sPropertyEndNotice;
    const ::rtl::OUString sPropertyBeginNotice;

    ::rtl::OUString sCitationStyle;
    ::rtl::OUString sAnchorStyle;
    ::rtl::OUString sDefaultStyle;
    ::rtl::OUString sPageStyle;
    ::rtl::OUString sPrefix;
    ::rtl::OUString sSuffix;
    ::rtl::OUString sNumFormat;
    ::rtl::OUString sNumSync;
    ::rtl::OUString sBeginNotice;
    ::rtl::OUString sEndNotice;

    SvXMLTokenMap* pAttrTokenMap;

    sal_Int16 nOffset;
    sal_Int16 nNumbering;
    sal_Bool bPosition;
    sal_Bool bIsEndnote;

public:

    TYPEINFO();

    XMLFootnoteConfigurationImportContext(
        SvXMLImport& rImport,
        sal_uInt16 nPrfx,
        const ::rtl::OUString& rLName,
        const ::com::sun::star::uno::Reference<
                ::com::sun::star::xml::sax::XAttributeList> & xAttrList);

    virtual ~XMLFootnoteConfigurationImportContext();

    /// parse attributes
    virtual void StartElement(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList );

    /// for footnotes, also parse begin and end notices
    virtual SvXMLImportContext *CreateChildContext(
        USHORT nPrefix,
        const ::rtl::OUString& rLocalName,
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::xml::sax::XAttributeList> & xAttrList );

    /// get token map for attributes
    const SvXMLTokenMap& GetFtnConfigAttrTokenMap();

    /// set configuration at document; calls ProcessSettings
    // --> OD 2005-01-31 #i40579# - move code from <CreateAndInsertLate(..)>
    // to <Finish(..)>, because at this time all styles it references have been set.
    virtual void Finish( sal_Bool bOverwrite);
    // <--

    /// set configuration at document
    void ProcessSettings(
        const ::com::sun::star::uno::Reference<
            ::com::sun::star::beans::XPropertySet> & rConfig);

    /// for helper class: set begin notice
    void SetBeginNotice( ::rtl::OUString sText);

    /// for helper class: set end notice
    void SetEndNotice( ::rtl::OUString sText);
};

#endif
<|endoftext|>


<commit_before><commit_msg>add totals row to IOMatrix.csv fixed error<commit_after><|endoftext|>


<commit_before>
#include "StdAfx.h"
#include "main.h"
#include "viewer.h"
#include "lang_val.h"
#include "registry.h"
#include "config.h"
#include "illa/codecmgr.h"
#include "orz/intl.h"
#include "control.h"
#include "w32_assure_folder.h"

int start_app(const std::wstring& params) {
	if (params == TX("--cleanup")) {
		// If the user refused to uninstall the previous version when upgrading, the uninstaller will likely call pictus.exe with --cleanup
		// as parameter. Let's not throw up a blank Pictus windows in that situation.
		// This applies when 1.1.4.0 or older was installed.
		return EXIT_SUCCESS;
	}

	Img::CodecFactoryStore cfs;
	cfs.AddBuiltinCodecs();

	try {
		auto cfg = Reg::Load(App::cg_SettingsLocation);

		// TODO: Control logging by some other mechanism, such as an .ini setting
		//Log.SetOutput(assure_folder(App::cg_RunLogLocation));

		Intl::LanguageTable(c_lang_strings);
		Intl::CurrentLanguage(cfg.View.Language);

		App::Viewer viewer(&cfs, cfg, params.c_str());

		// Attempt to display viewer
		if (viewer.Create(0)) {
			viewer.Show(true);
		}

		viewer.StartApplication();

		//Reg::Save(App::cg_SettingsLocation);
	}
	catch(Err::DuplicateInstance&) {
		// This is not something out of the ordinary.
	}
	catch(Err::Exception& e) {
		Log << TX("Exception caught:\n") << e.Desc() << TX("\n");
		MessageBox(0, (TX("An error occurred: ") + e.Desc()).c_str(), TX("Pictus Error"), MB_OK);
		//throw;	// Good for debugging
	}

	Win::Control::DestructControls();

	return EXIT_SUCCESS;
}
<commit_msg>Remove deprecated line for saving settings, now handled in Viewer::PerformOnClose<commit_after>
#include "StdAfx.h"
#include "main.h"
#include "viewer.h"
#include "lang_val.h"
#include "registry.h"
#include "config.h"
#include "illa/codecmgr.h"
#include "orz/intl.h"
#include "control.h"
#include "w32_assure_folder.h"

int start_app(const std::wstring& params) {
	if (params == TX("--cleanup")) {
		// If the user refused to uninstall the previous version when upgrading, the uninstaller will likely call pictus.exe with --cleanup
		// as parameter. Let's not throw up a blank Pictus windows in that situation.
		// This applies when 1.1.4.0 or older was installed.
		return EXIT_SUCCESS;
	}

	Img::CodecFactoryStore cfs;
	cfs.AddBuiltinCodecs();

	try {
		auto cfg = Reg::Load(App::cg_SettingsLocation);

		// TODO: Control logging by some other mechanism, such as an .ini setting
		//Log.SetOutput(assure_folder(App::cg_RunLogLocation));

		Intl::LanguageTable(c_lang_strings);
		Intl::CurrentLanguage(cfg.View.Language);

		App::Viewer viewer(&cfs, cfg, params.c_str());

		// Attempt to display viewer
		if (viewer.Create(0)) {
			viewer.Show(true);
		}

		viewer.StartApplication();
	}
	catch(Err::DuplicateInstance&) {
		// This is not something out of the ordinary.
	}
	catch(Err::Exception& e) {
		Log << TX("Exception caught:\n") << e.Desc() << TX("\n");
		MessageBox(0, (TX("An error occurred: ") + e.Desc()).c_str(), TX("Pictus Error"), MB_OK);
		//throw;	// Good for debugging
	}

	Win::Control::DestructControls();

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2013 Baptiste Burles, Sylvain Fay-Chatelard

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QFileInfo>
#include <QSettings>
#include <QtCore/QDebug>

#ifdef Q_OS_UNIX

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#include "../include/Utils.h"
#include "../include/Settings.h"

QString Utils::getFullPathFile(QString &file)
{
        QString temp;
        QFileInfo *info = new QFileInfo(file);

        temp = info->canonicalFilePath();
        delete info;
        return temp;
}

QString Utils::getRelativeFile(QString &projectPath,QString &file)
{
        QString temp;
        QString sep = "/";
        QFileInfo *info = new QFileInfo(file);

        QString f = QString(info->path()+sep);
    temp = Utils::getRelativePath(projectPath,f, sep);

        temp = temp + sep +info->fileName();
        delete info;

        return temp ;
}

QString Utils::getRelativeBaseName(QString &projectPath,QString &file)
{
        QString temp;
        QString sep = "/";
        QFileInfo *info = new QFileInfo(file);

        QString f = QString(info->path()+sep);
    temp = Utils::getRelativePath(projectPath,f, sep);

        temp = temp + sep +info->baseName();
        delete info;

        return  temp;
}

QString Utils::getRelativePath(QString &PathReference , QString &PathLink, QString &sep )
{
        if( PathReference == PathLink)
        {
                return "" ;
        }

        QStringList ArrPathRef ;
        QStringList ArrPathLink ;
        QString Path ;
        int k , maxLenght ;
        int numUp ;
        int numDiv = 1 ;

        ArrPathRef = PathReference.split(sep);
        ArrPathLink = PathLink.split(sep);

        if( ArrPathRef[0] != ArrPathLink[0] )
        {
                return PathLink ;
        }

        if( ArrPathLink.size() > ArrPathRef.size() )
        {
                maxLenght = ArrPathLink.size();;
        }
        else
        {
                maxLenght = ArrPathRef.size();
        }

        for(k=0 ; k < maxLenght ; k++ )
        {
                if( k > ArrPathLink.size() -1
                   || k > ArrPathRef.size()-1
                   || (ArrPathLink[k] != ArrPathRef[k]) )
                {
                        break ;
                }

                numDiv = numDiv + 1 ;
        }

        numUp = ArrPathRef.size() - numDiv + 1 ;
        Path = "" ;

        if( numUp == 0 )
        {
                Path = "." ;
        }
        else
        {
                for(k=0 ; k < numUp /*- 1*/ ; k++ )
                {
                        if( k == 0 ) Path = ".." ;
                        else Path = Path + sep +".." ;
                }
        }

        for(k = (numDiv-1) ; k < ArrPathLink.size() - 1 ; k++ )
        {
                Path = Path +sep + ArrPathLink[k] ;
        }

        return Path ;
}

#include <QProcess>

bool Utils::runProcess(QString &workingDir,QString &exe, QString *output, int *exitCode)
{
     //   workingDir.replace(QString("\\"),QString("/"));
        exe.replace(QString("\\"),QString("/"));

        QProcess process;

        process.setWorkingDirectory(workingDir);

        process.setProcessChannelMode(QProcess::MergedChannels);

        process.start(exe);

        if(process.waitForStarted(10000)==false)
        {
                //todo error
                *output = process.errorString();

                return false;
        }

        if(process.waitForFinished(10000)==false)
        {
                //todo error
                *output = process.errorString();

                return false;
        }

        QByteArray temp = process.readAll();

//	printf("Result=%s\n", temp.data());

        *output = QString(temp);

        *exitCode = process.exitCode();

        return true;
}

int Utils::setPortComList(QComboBox *portCombo)
{
     struct dirent *read;
     DIR *rep;
     int list;
     char *dirname = new char(100);

     list=0 ;
     dirname = (char*)"/dev/\0";

     rep = opendir(dirname);
     char * pch;
     QStringList listPorts;
     QString str = "/dev/";
     while((read = readdir(rep)))
     {
         pch=strstr(read->d_name,"cu");
         if(pch!=NULL)
         {
             pch=strstr(read->d_name,"Bluetooth");
             if(pch==NULL)
             {
                str = "/dev/";
                str += read->d_name;
                listPorts<<str;
            }
         }
     }
     closedir(rep);

     /*QStringList listPorts;
     struct stat my_stat;

     //Stor on a string each path of serial port files
     for(int i = 0; i < NUMBER_OF_DEVICES; i++)
     {
         if(stat(devices_list[i], &my_stat) == 0)	//if there are informations about the file (path on the first param), they are stocked on the second param and return 0
         {
             listPorts.append((QString)devices_list[i]);
         }
     }*/

     if(listPorts.size() == 0)
     {
         //"No valid serial device found in /dev, sorry !\nYou should have at least one of these :\n/dev/ttyS*\n/dev/tts/*\n/dev/ttyUSB*\n/dev/usb/tts/*\n"
         return false;
     }
     else
     {
         // Add serial port to the combo box

         // Get user portcom from Settings:
         QString comport = Settings::getPortCom();

         portCombo->clear();

         //Insert serial port ont the combo box
         for(int i=0; i < listPorts.size() ; i++)
         {
             portCombo->insertItem(i,listPorts[i]);
             portCombo->setCurrentIndex(i);
             if(comport==listPorts[i])
             {
                 portCombo->setCurrentIndex(i);
             }
             else
             {
                 portCombo->setCurrentIndex(-1);
             }
           }//..for
     }//..else

     return listPorts.size();
}

#endif
<commit_msg>Correct com port selection (my bad)<commit_after>/*
The MIT License (MIT)

Copyright (c) 2013 Baptiste Burles, Sylvain Fay-Chatelard

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <QFileInfo>
#include <QSettings>
#include <QtCore/QDebug>

#ifdef Q_OS_UNIX

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#include "../include/Utils.h"
#include "../include/Settings.h"

QString Utils::getFullPathFile(QString &file)
{
        QString temp;
        QFileInfo *info = new QFileInfo(file);

        temp = info->canonicalFilePath();
        delete info;
        return temp;
}

QString Utils::getRelativeFile(QString &projectPath,QString &file)
{
        QString temp;
        QString sep = "/";
        QFileInfo *info = new QFileInfo(file);

        QString f = QString(info->path()+sep);
    temp = Utils::getRelativePath(projectPath,f, sep);

        temp = temp + sep +info->fileName();
        delete info;

        return temp ;
}

QString Utils::getRelativeBaseName(QString &projectPath,QString &file)
{
        QString temp;
        QString sep = "/";
        QFileInfo *info = new QFileInfo(file);

        QString f = QString(info->path()+sep);
    temp = Utils::getRelativePath(projectPath,f, sep);

        temp = temp + sep +info->baseName();
        delete info;

        return  temp;
}

QString Utils::getRelativePath(QString &PathReference , QString &PathLink, QString &sep )
{
        if( PathReference == PathLink)
        {
                return "" ;
        }

        QStringList ArrPathRef ;
        QStringList ArrPathLink ;
        QString Path ;
        int k , maxLenght ;
        int numUp ;
        int numDiv = 1 ;

        ArrPathRef = PathReference.split(sep);
        ArrPathLink = PathLink.split(sep);

        if( ArrPathRef[0] != ArrPathLink[0] )
        {
                return PathLink ;
        }

        if( ArrPathLink.size() > ArrPathRef.size() )
        {
                maxLenght = ArrPathLink.size();;
        }
        else
        {
                maxLenght = ArrPathRef.size();
        }

        for(k=0 ; k < maxLenght ; k++ )
        {
                if( k > ArrPathLink.size() -1
                   || k > ArrPathRef.size()-1
                   || (ArrPathLink[k] != ArrPathRef[k]) )
                {
                        break ;
                }

                numDiv = numDiv + 1 ;
        }

        numUp = ArrPathRef.size() - numDiv + 1 ;
        Path = "" ;

        if( numUp == 0 )
        {
                Path = "." ;
        }
        else
        {
                for(k=0 ; k < numUp /*- 1*/ ; k++ )
                {
                        if( k == 0 ) Path = ".." ;
                        else Path = Path + sep +".." ;
                }
        }

        for(k = (numDiv-1) ; k < ArrPathLink.size() - 1 ; k++ )
        {
                Path = Path +sep + ArrPathLink[k] ;
        }

        return Path ;
}

#include <QProcess>

bool Utils::runProcess(QString &workingDir,QString &exe, QString *output, int *exitCode)
{
     //   workingDir.replace(QString("\\"),QString("/"));
        exe.replace(QString("\\"),QString("/"));

        QProcess process;

        process.setWorkingDirectory(workingDir);

        process.setProcessChannelMode(QProcess::MergedChannels);

        process.start(exe);

        if(process.waitForStarted(10000)==false)
        {
                //todo error
                *output = process.errorString();

                return false;
        }

        if(process.waitForFinished(10000)==false)
        {
                //todo error
                *output = process.errorString();

                return false;
        }

        QByteArray temp = process.readAll();

//	printf("Result=%s\n", temp.data());

        *output = QString(temp);

        *exitCode = process.exitCode();

        return true;
}

int Utils::setPortComList(QComboBox *portCombo)
{
     struct dirent *read;
     DIR *rep;
     int list;
     char *dirname = new char(100);

     list=0 ;
     dirname = (char*)"/dev/\0";

     rep = opendir(dirname);
     char * pch;
     QStringList listPorts;
     QString str = "/dev/";
     while((read = readdir(rep)))
     {
         pch=strstr(read->d_name,"cu");
         if(pch!=NULL)
         {
             pch=strstr(read->d_name,"Bluetooth");
             if(pch==NULL)
             {
                str = "/dev/";
                str += read->d_name;
                listPorts<<str;
            }
         }
     }
     closedir(rep);

     /*QStringList listPorts;
     struct stat my_stat;

     //Stor on a string each path of serial port files
     for(int i = 0; i < NUMBER_OF_DEVICES; i++)
     {
         if(stat(devices_list[i], &my_stat) == 0)	//if there are informations about the file (path on the first param), they are stocked on the second param and return 0
         {
             listPorts.append((QString)devices_list[i]);
         }
     }*/

     if(listPorts.size() == 0)
     {
         //"No valid serial device found in /dev, sorry !\nYou should have at least one of these :\n/dev/ttyS*\n/dev/tts/*\n/dev/ttyUSB*\n/dev/usb/tts/*\n"
         return false;
     }
     else
     {
         // Add serial port to the combo box

         // Get user portcom from Settings:
         QString comport = Settings::getPortCom();

         portCombo->clear();

         //Insert serial port ont the combo box
         portCombo->setCurrentIndex(-1);
         for(int i=0; i < listPorts.size() ; i++)
         {
             portCombo->insertItem(i,listPorts[i]);
             if(comport == listPorts[i])
             {
                 portCombo->setCurrentIndex(i);
             }
           }//..for
     }//..else

     return listPorts.size();
}

#endif
<|endoftext|>