mirror of
				https://github.com/zenorogue/hyperrogue.git
				synced 2025-11-04 07:43:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			228 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "../hyper.h"
 | 
						|
#include <iostream>
 | 
						|
#include <thread>
 | 
						|
 | 
						|
namespace hr {
 | 
						|
 | 
						|
char buf[10000000];
 | 
						|
int bufpos;
 | 
						|
 | 
						|
bool chk(const char *s) {
 | 
						|
  char *t = buf+bufpos;
 | 
						|
  while(*s == *t) s++, t++;
 | 
						|
  return *s == 0;
 | 
						|
  }
 | 
						|
 | 
						|
bool eat(const char *s) {
 | 
						|
  bool ret = chk(s);
 | 
						|
  if(ret) bufpos += strlen(s);
 | 
						|
  return ret;
 | 
						|
  }
 | 
						|
 | 
						|
char eatchar() {
 | 
						|
  return buf[bufpos++];
 | 
						|
  }
 | 
						|
 | 
						|
set<string> seen;
 | 
						|
 | 
						|
void check_ex(string s, string help) {
 | 
						|
  if(seen.count(s)) return;
 | 
						|
  seen.insert(s);
 | 
						|
  if(!translation_exists(s)) println(hlog, "S(", as_nice_cstring(s), ", ", help, ")");
 | 
						|
  }
 | 
						|
 | 
						|
void check_nonliteral(string s, string fname, int line) {
 | 
						|
  if(seen.count(s)) return;
 | 
						|
  seen.insert(s);
 | 
						|
  string thu = "", end = "";
 | 
						|
  for(char c: s) if(c == '[') break; else thu += c;
 | 
						|
  for(char c: s) if(c == ']') end = ""; else end += c;
 | 
						|
  
 | 
						|
  if(s == "s") ;
 | 
						|
  else if(thu == "minetexts")
 | 
						|
    for(string m: minetexts) check_ex(m, s);
 | 
						|
  else if(thu == "dfnames")
 | 
						|
    for(string m: dfnames) check_ex(m, s);
 | 
						|
  else if(thu == "ncnames")
 | 
						|
    for(string m: ncnames) check_ex(m, s);
 | 
						|
  else if(thu == "slides" && end == ".help") ;
 | 
						|
    // for(auto sl: tour::slides) check_ex(sl.help);
 | 
						|
  else if(thu == "slides" && end == ".name") ;
 | 
						|
    // for(auto sl: tour::slides) check_ex(sl.name);
 | 
						|
  else if(end == ".menu_displayed_name") ;
 | 
						|
    // for(auto g: ginf) check_ex(g.menu_displayed_name);
 | 
						|
  else if(end == ".tiling_name") ;
 | 
						|
    // for(auto g: ginf) check_ex(g.tiling_name);
 | 
						|
  else if(end == ".name_hyperbolic")
 | 
						|
    for(auto md: mdinf) check_ex(md.name_hyperbolic, s);
 | 
						|
  else if(end == ".name_spherical")
 | 
						|
    for(auto md: mdinf) { if(md.name_spherical != md.name_hyperbolic) check_ex(md.name_spherical, s); }
 | 
						|
  else if(end == ".name_euclidean")
 | 
						|
    for(auto md: mdinf) { if(md.name_euclidean != md.name_hyperbolic && md.name_euclidean != md.name_hyperbolic) check_ex(md.name_euclidean, s); }
 | 
						|
  else if(thu == "olrdesc") ;
 | 
						|
  else if(thu == "wdmodes") 
 | 
						|
    for(string m: wdmodes) check_ex(m, s);
 | 
						|
  else if(thu == "axemodes") 
 | 
						|
    for(string m: multi::axemodes) check_ex(m, s);
 | 
						|
  else if(thu == "axmodes") 
 | 
						|
    for(string m: multi::axmodes) check_ex(m, s);
 | 
						|
  else if(thu == "mpnames") 
 | 
						|
    for(string m: texture::mpnames) check_ex(m, s);
 | 
						|
  else if(thu == "axemodes3") 
 | 
						|
    for(string m: multi::axemodes3) check_ex(m, s);
 | 
						|
  else if(thu == "mdmodes") 
 | 
						|
    for(string m: mdmodes) check_ex(m, s);
 | 
						|
  else if(thu == "hlmodes") 
 | 
						|
    for(string m: hlmodes) check_ex(m, s);
 | 
						|
  else if(thu == "current_filter->name") 
 | 
						|
    for(auto f: available_filters) check_ex(f->name, s);
 | 
						|
  else if(thu == "olrDescriptions")
 | 
						|
    for(string m: olrDescriptions) check_ex(m, s);
 | 
						|
  else if(thu == "shmupcmdtable") ;
 | 
						|
  else if(thu == "stringx") ;
 | 
						|
  else if(thu == "lv.msg") ; /* trust */
 | 
						|
  else if(thu == "opt") ; /* todo */
 | 
						|
  else if(thu == "menu_item_name") ; /* todo */
 | 
						|
  else if(s == "winf[w].help") ;
 | 
						|
  else if(s == "linf[l].help") ;
 | 
						|
  else if(s == "iinf[it].help") ;
 | 
						|
  else if(s == "minf[m].help") ;
 | 
						|
  else if(among(s, "mapeditorhelp", "patthelp", "drawhelp", "warpdesc", "hyperstone_optional", "irrhelp", "helptext", "inv::helptext", "power_help", "trollhelp2")) ; /* trust */
 | 
						|
  else
 | 
						|
    println(hlog, "// unrecognized nonliteral: ", s, " in ", fname, ":", line);
 | 
						|
  }
 | 
						|
 | 
						|
void check_xlat_content(string s, string fname, int line) {
 | 
						|
  // println(hlog, "// xlat content found: ", s);
 | 
						|
  string literal = "";
 | 
						|
  string nonliteral = "";
 | 
						|
  bool in_quote = false;
 | 
						|
  int i = 0;
 | 
						|
  while(i < isize(s)) {
 | 
						|
    auto chk = [&] (string mname, string mvalue) {
 | 
						|
      if(in_quote) return false;
 | 
						|
      for(int k=0; k<isize(mname); k++) if(s[i+k] != mname[k]) return false;
 | 
						|
      literal += mvalue; i += isize(mname);
 | 
						|
      return true;
 | 
						|
      };
 | 
						|
    if(chk("LEADERFULL", "Steam Leaderboards")) continue;
 | 
						|
    if(chk("LEADER", "Steam")) continue;
 | 
						|
    if(chk("IMAGEEXT", IMAGEEXT)) continue;
 | 
						|
    if(chk("SHMUPTITLE", SHMUPTITLE)) continue;
 | 
						|
    if(s[i] == '"') in_quote = !in_quote;
 | 
						|
    else if(s[i] == '\\') {
 | 
						|
      i++;
 | 
						|
      if(s[i] == '"' || s[i] == '\'' || s[i] == '\\')  literal += s[i];
 | 
						|
      else if(s[i] == 'n') literal += "\n";
 | 
						|
      else println(hlog, "unknown escape: ", s0+s[i]);
 | 
						|
      }
 | 
						|
    else if(in_quote) literal += s[i];
 | 
						|
    else if(among(s[i], ' ', '\n', '\r')) ;
 | 
						|
    else nonliteral += s[i];
 | 
						|
    i++;
 | 
						|
    }
 | 
						|
  if(literal != "" && nonliteral != "") {
 | 
						|
    println(hlog, "// confused about: ", s, " ", fname, ":", line);
 | 
						|
    println(hlog, "literal = ", literal);
 | 
						|
    println(hlog, "nonliteral = ", nonliteral);
 | 
						|
    }
 | 
						|
  else if(nonliteral != "")
 | 
						|
    check_nonliteral(nonliteral, fname, line);
 | 
						|
  else {
 | 
						|
    if(seen.count(literal)) return;
 | 
						|
    seen.insert(literal);
 | 
						|
    if(!translation_exists(literal)) 
 | 
						|
      println(hlog, "S(", s, ", literal in ", fname, ":", line, ")");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
void check_file(string s) {
 | 
						|
  FILE *f = fopen(s.c_str(), "rt");
 | 
						|
  int qty = fread(buf, 1, 10000000, f);
 | 
						|
  buf[qty] = 0;
 | 
						|
  fclose(f);
 | 
						|
  // println(hlog, "// checking file ", s, ", ", qty, " B");
 | 
						|
  
 | 
						|
  bufpos = 0;
 | 
						|
  
 | 
						|
  bool in_xlat = false;
 | 
						|
  bool in_quote = false;
 | 
						|
  string xlat_content;
 | 
						|
  
 | 
						|
  int linenum = 0;
 | 
						|
  
 | 
						|
  while(true) {
 | 
						|
    if(bufpos == qty) break;
 | 
						|
    if(buf[bufpos] == '\n') linenum++;
 | 
						|
    if(!in_xlat) {
 | 
						|
      if(eat("XLAT(")) {
 | 
						|
        in_xlat = true;
 | 
						|
        xlat_content = "";
 | 
						|
        }
 | 
						|
      else 
 | 
						|
        eatchar();
 | 
						|
      }
 | 
						|
    else {
 | 
						|
      if(eat("\"")) {
 | 
						|
        xlat_content += "\"";
 | 
						|
        in_quote = !in_quote;
 | 
						|
        }
 | 
						|
      else if(in_quote && eat("\\")) {
 | 
						|
        xlat_content += "\\";
 | 
						|
        xlat_content += eatchar();
 | 
						|
        }
 | 
						|
      else if(!in_quote && eat("(")) {
 | 
						|
        println(hlog, "// found parenthesis inside XLAT: ", xlat_content, " at ", s, ":", linenum);
 | 
						|
        }
 | 
						|
      else if(!in_quote && eat("?")) {
 | 
						|
        println(hlog, "// found '?' inside XLAT: ", xlat_content, " at ", s, ":", linenum);
 | 
						|
        }
 | 
						|
      else if(!in_quote && (eat(")") || eat(","))) {
 | 
						|
        check_xlat_content(xlat_content, s, linenum);
 | 
						|
        in_xlat = false;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        xlat_content += eatchar();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
void gentrans() {
 | 
						|
  DIR           *d;
 | 
						|
  struct dirent *dir;
 | 
						|
  
 | 
						|
  println(hlog, "// checking all the files");
 | 
						|
 | 
						|
  d = opendir(".");
 | 
						|
 | 
						|
  if(d) {
 | 
						|
    while ((dir = readdir(d)) != NULL) {
 | 
						|
      string s = dir->d_name;
 | 
						|
      if(s.size() > 4 && s.substr(s.size()-4) == ".cpp")
 | 
						|
        check_file(s);
 | 
						|
      }
 | 
						|
    closedir(d);
 | 
						|
    }
 | 
						|
 | 
						|
  println(hlog, "// checking configurables");
 | 
						|
  
 | 
						|
  for(auto& fs: params) {
 | 
						|
    auto& sett = fs.second;
 | 
						|
    if(sett->menu_item_name != sett->config_name)
 | 
						|
      check_ex(sett->menu_item_name, "menu_item_name for " + sett->parameter_name);
 | 
						|
    check_ex(sett->help_text, "help_text for " + sett->parameter_name);
 | 
						|
    auto ls = dynamic_cast<list_setting*> ( (setting*) &*sett);
 | 
						|
    if(ls)
 | 
						|
      for(auto opt: ls->options) {
 | 
						|
        check_ex(opt.first, "option first for " + sett->parameter_name);
 | 
						|
        check_ex(opt.second, "option second for " + sett->parameter_name);
 | 
						|
        }
 | 
						|
    }
 | 
						|
  
 | 
						|
  exit(0);
 | 
						|
  }
 | 
						|
 | 
						|
auto ar = arg::add3("-gentrans", gentrans);
 | 
						|
 | 
						|
}
 |