diff --git a/bin/extract.pike b/bin/extract.pike index 7c9c6e55e777e266216e7b67d2371e2f991ae79a..df3c58ea7d80326d855e5720eb7ad29de4e5ff25 100755 --- a/bin/extract.pike +++ b/bin/extract.pike @@ -1,9 +1,8 @@ -#!/home/lange/pike71 -//#!/usr/local/bin/pike +#!/usr/local/bin/pike // Copyright � 2000, Roxen IS. // By Martin Nilsson and Andreas Lange // -// $Id: extract.pike,v 1.4 2000/07/17 16:55:35 lange Exp $ +// $Id: extract.pike,v 1.5 2000/08/04 04:18:21 lange Exp $ // @@ -11,54 +10,24 @@ mapping args = ([]); // All the files to gather strings from array(string) files = ({}); -// All ids used, id:text -mapping(string:string) ids = ([]); +// All ids used, id:mapping(info) +mapping ids = ([]); // Reversed id mapping, text:id -mapping(string:string) r_ids = ([]); -// Keep track of every id's origin, id:array(filenames) -// (id_origin[id]==0 => from _eng.xml) -mapping(string:array) id_origin = ([]); -// Order of the ids in the _eng.xml file -array(string) id_xml_order = ({}); -// Code to add to _eng.xml, id:code +mapping(string:string|int) r_ids = ([]); +// Order of the ids in the xml outdata file +array(string|int) id_xml_order = ({}); +// Code to add to xml outfile, id:code mapping(string:string) add = ([]); -// List of ids already in the _eng.xml +// List of ids already in the xml outfile multiset(string) added = (<>); -// The highest int with all lower ids set; see make_id_string() +// The highest int with all lower ids set; see make_id() int high_int_id = 0; -constant id_characters = "abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ0123456789"; -string make_id_string(int int_id) { - // Make a string (as short as possible) based on id_characters and int_id - string ret = ""; - int rest = int_id - 1; - int val; - for(int pos = 1 + (int)floor(log( (float)int_id ) / - log( 1.0+sizeof(id_characters) )); - pos; pos--) { - if (pos < 2) - val = rest; - else { - int div = (int)pow(sizeof(id_characters)+1, (pos-1)) - 1; - val = rest / div; - rest -= val * div; - val--; - } - val %= sizeof(id_characters); - ret += id_characters[val..val]; - } - return ret; -} - - -string make_id() { +int make_id() { // Returns the next unused unique id - string ret; - do { - ret = make_id_string( ++high_int_id ); - } while ( has_value(id_xml_order, ret) ); - return ret; + while ( has_value(id_xml_order, ++high_int_id) ); + return high_int_id; } @@ -189,12 +158,45 @@ function get_decoder(string encoding) { } -string parse_xml_file(string filename, void|mixed wipe_pass) { +array(string) languagefiles(string searchpath, void|string skiplang) { + // Based on the searchpath, returns list of files - skiplang-file + string pattern = replace(searchpath, "%%", "%"); + string dirbase = (pattern/"%L")[0]; + if(dirbase[-1]!='/') { + array split = dirbase/"/"; + dirbase = split[..sizeof(split)-2]*"/"+"/"; + } + string s_patt; + if(search(pattern, "/", sizeof(dirbase))==-1) + s_patt=pattern[sizeof(dirbase)..]; + else + s_patt=pattern[sizeof(dirbase)..search(pattern, "/", sizeof(dirbase))-1]; + s_patt = replace(s_patt, "%L", "%3s"); + + array dirlist = get_dir(dirbase); + if(!dirlist) + return ({}); + array list = ({}); + foreach(dirlist, string path) { + string lang; + if(!sscanf(path, s_patt, lang)) continue; + if(lang==skiplang) continue; + string file = replace(pattern, "%L", lang); + if(!file_stat(file)) continue; + list += ({ file }); + } + return list; +} + + +string parse_xml_file(string filename) { // Reads a language-xml (like project_eng.xml) - // Marks used ids in ids([]), also adds r_ids([text]) from id-comment - // Returns file, with markers instead of <--! [id] ""-->\n<t></t> + // Marks used ids in ids([]), also adds r_ids([text]) + // Returns file, with markers instead of <str>-blocks // write_xml_file uses the returned data+id_xml_order to build a new one - // Set parameter wipe_pass=1 to remove ids not in ids[] from file + added = (<>); + id_xml_order = ({}); + if(!filename || filename=="") return ""; Stdio.File in=Stdio.FILE(); @@ -227,61 +229,99 @@ string parse_xml_file(string filename, void|mixed wipe_pass) { else if(line!=indata) indata += line+"\n"+indata; - if(wipe_pass) - write(" - doing wipe pass..."); - else - write(" - parsing xml..."); + write(" - parsing xml..."); - // Comment id mapping - text from <!-- [id] "text" -->, id:text - // text inserted into ids[id] in the t_tag function - mapping c_ids = ([]); + // Parse... First the <str>-parser + mapping current = ([]); + Parser.HTML str_parser = Parser.HTML(); + str_parser->case_insensitive_tag(1); - Parser.HTML xml_parser = Parser.HTML(); - function t_tag = + str_parser-> + add_tag("changed", + lambda(object foo, mapping m) { + current->changetag = str_parser->current()+"\n"; + return 0; + }); + + function t_container = lambda(object foo, mapping m, string c) { - if(!m->id || m->id=="") { - werror("\n* Warning: String %O has no id.", c); + if((int)m->id) m->id = (int)m->id; + if(!current->id) { + if(!m->id || m->id=="") { + werror("\n* Warning: String %O has no id.", c||current->original); + return 0; + } + current->id = m->id; + } + if(m->id && (m->id != current->id)) { + werror("\n* Warning: Ignoring string %O. " + "Contained in id %O but marked with id %O.", + c, current->id, m->id); return 0; } - if(wipe_pass) { - // This pass is done to remove id's not used anymore - if(!ids[m->id]) { - id_xml_order -= ({ m->id }); - return "\b"; - } - } else { - // Normal pass, update all structures - if(has_value(id_xml_order, m->id)) { - werror("\n* Error: Id %O used more than once.\n", m->id); - exit(1); - } - id_xml_order += ({m->id}); - c = c_ids[m->id]; - if(!args->wipe) // Check if there will be a wipe pass later - ids[m->id] = c; - if(c != "") - r_ids[c] = m->id; + if(has_value(id_xml_order, current->id)) { + werror("\n* Error: Id %O used more than once.\n", current->id); + exit(1); } - // Return marker for write_xml_file() - where to insert id-string again - // This is done to make sure the file really is updated. - return "\7\7\7\7"; // Marker unique enough? + id_xml_order += ({ current->id }); + c = replace(c, ({"<",">","&"}), ({"<",">","&"})); + current->text = c; + current->textargs = m-({"id"}); + return 0; }; + str_parser->add_containers( ([ "t" : t_container, + "translate" : t_container ]) ); + function o_container = + lambda(object foo, mapping m, string c) { + if(String.trim_whites(c)!="") { + // Replace encoded entities + c = replace(c, ({"<",">","&"}), ({"<",">","&"})); + current->original = c; + current->originalargs = m-({"id"}); + } + return 0; + }; + str_parser->add_containers( ([ "o" : o_container, + "original" : o_container ]) ); + + // Main xml file parser // "\b" is used as a marker for lines to remove from returned data + Parser.HTML xml_parser = Parser.HTML(); xml_parser->case_insensitive_tag(1); - xml_parser->add_containers( ([ "t" : t_tag, - "translate" : t_tag]) ); xml_parser-> - add_container("locale", - // Verify the <locale>-xml version + add_container("str", lambda(object foo, mapping m, string c) { - array n = m->version/"."; - if(n[0]!="1") { - werror("\n* Unknown locale version %O!\n", m->version); - exit(1); + current = ([]); // New <str>, clear slate + if(m->id && m->id!="") { + if((int)m->id) m->id = (int)m->id; + current->id = m->id; + } + str_parser->feed( c )->finish(); + if(current->id) { + ids[current->id] = current; + if(String.trim_whites(current->original)!="") + r_ids[current->original] = current->id; } - return "\b"+c; + if(has_value(id_xml_order, current->id)) + // Return marker for write_xml_file() + // - where to re-insert <str> again. + // This is done to make sure the file + // really is updated. + return "\7\7\7\7"; // Should be unique enough + return "\b"; }); + xml_parser-> + add_tag("locale", + // Verify the <locale>-xml version + lambda(object foo, mapping m) { + array n = m->version/"."; + if(n[0]!="1") { + werror("\n* Unknown locale version %O!\n", m->version); + exit(1); + } + return "\b"; + }); xml_parser-> add_container("project", // Verify that the file is for the this project @@ -302,27 +342,6 @@ string parse_xml_file(string filename, void|mixed wipe_pass) { added[m->id] = 1; return "\b"; }); - xml_parser-> - add_quote_tag("!--", - // Might be a normal comment or a <!-- [id] "text" --> - lambda(object foo, string c) { - string id; - sscanf(c," [%s]%s", id, c); - if(id == 0) { - return 0; // Normal comment tag - } - // Really make sure quotings are right - object RE = Regexp("^[^\"]*\"(.*)\"[^\"]*$"); - array hits = RE->split(c); - if(hits) - c = get_first_string(sprintf("%O", hits[0])); - // Replace encoded entities - c = replace(c,({"<",">","&"}),({"<",">","&"})); - if(id!="" && c!="") - // Save text for use in the t_tag function - c_ids[id] = c; - return "\b"; - }, "--"); // These tags will always be rewritten anyway, so remove them. xml_parser->add_quote_tag("?xml", "\b", "?"); xml_parser->add_containers( (["file" : "\b", @@ -339,18 +358,22 @@ string parse_xml_file(string filename, void|mixed wipe_pass) { } // Remove silly lines in end of data RE = Regexp("^(.*[^\n \t]\n)[ \n\t]*$"); - array hits = RE->split(ret); + array hits = RE->split( ret ); if(hits) ret = hits[0]; - - write("\n\n"); + ret = replace(ret, "\n\n\n\n", "\n\n"); + + write("\n"); return ret; } -void write_xml_file(string out_name, string outdata) { - // Updates/creates the project_eng.xml-file with id:text-info +void write_xml_file(string out_name, string outdata, void|mapping old_ids) + // Updates/creates a project_%L.xml-file with id:text-info // Reuses a present structure if fead with it in outdata // Some headers is always rewritten. + // The old_ids mapping is supplied when the file is updated in comparison + // with a base xml file. +{ if(!sizeof(id_xml_order)) // No ids changed or read with parse_xml_file() return; @@ -360,13 +383,13 @@ void write_xml_file(string out_name, string outdata) { exit(1); } - write("\nWriting %s... (%d ids)", out_name, sizeof(id_xml_order)); + write("Writing %s... (%d ids)", out_name, sizeof(id_xml_order)); // Dump some headers string newfile = ""; - newfile += "<locale version=\"1.0\">\n"; + newfile += "<locale version=\"1.0\"/>\n"; newfile += "<project>"+args->project+"</project>\n"; - newfile += "<language>English</language>\n"; + newfile += "<language>English</language>\n"; // FIXME Get Lang from ISO-mod. newfile += "<dumped>"+time()+"</dumped>\n"; // List files included in the project @@ -377,17 +400,47 @@ void write_xml_file(string out_name, string outdata) { foreach(indices(added)+indices(add), string blockname) newfile += "<added id=\""+blockname+"\"/>\n"; - string tag = "t"; - string info = ""; + string o_tag = "o"; + string t_tag = "t"; if(args->verbose) { - tag = "translate"; - info = "Original: "; + o_tag = "original"; + t_tag = "translate"; } + + function gen_tag = + lambda(mixed id) { + string diff = ((old_ids && old_ids[id] && old_ids[id]->changetag) ? + old_ids[id]->changetag : ""); + if(old_ids && diff=="") { + if(!old_ids[id] || !old_ids[id]->text || + String.trim_whites(old_ids[id]->text)=="" ) + diff = "<changed/>\n"; + else if(old_ids[id] && old_ids[id]->original != ids[id]->original) { + diff = replace(old_ids[id]->original||"", + ({"<",">","&"}), ({"<",">","&"})); + diff = "<changed from=\""+ diff +"\"/>\n"; + + } + } + // Make parser-safe + string original = + replace(ids[id]->original, ({"<",">","&"}), ({"<",">","&"})); + string text = + replace( ( (old_ids && old_ids[id] && old_ids[id]->text) ? + old_ids[id]->text : ""), + ({"<",">","&"}),({"<",">","&"})); + return sprintf("<str id=\"%s\">\n" + "%s<%s>%s</%[2]s>\n" + "<%s>%s</%[4]s>\n" + "</str>", + (string)id, diff, o_tag, original, t_tag, text); + }; // Reuse structure of old xml int i = 0; if(outdata) { - string marker = "\7\7\7\7"; // Magic Marker from parse_xml_file() + string marker = "\7\7\7\7"; // Marker from parse_xml_file() + string newstr; while( int n=search(outdata, marker) ) { if(n<0) break; if(i==sizeof(id_xml_order)) { @@ -395,13 +448,11 @@ void write_xml_file(string out_name, string outdata) { outdata = replace(outdata, marker, ""); continue; } - string id = id_xml_order[i]; - string str = ids[id]; - // Make parser-safe - str = replace(str, ({"<",">","&"}), ({"<",">","&"})); - outdata = (outdata[0..n-1] + - sprintf("<!-- [%s] %s\"%s\" -->\n<%s id=\"%s\"></%s>", - id, info, str, tag, id, tag) + + if(args->wipe && !ids[id_xml_order[i]]->origin) + newstr = ""; // Wipe this old string + else + newstr = gen_tag(id_xml_order[i]); + outdata = (outdata[0..n-1] + newstr + outdata[n+sizeof(marker)..sizeof(outdata)-1]); i++; } @@ -409,32 +460,24 @@ void write_xml_file(string out_name, string outdata) { } // Dump new strings - while( i<sizeof(id_xml_order) ) { - string id = id_xml_order[i]; - string str = ids[id]; - // Make parser-safe - str = replace(str, ({"<",">","&"}), ({"<",">","&"})); - newfile += sprintf("\n<!-- [%s] %s\"%s\" -->\n<%s id=\"%s\"></%s>\n", - id, info, str, tag, id, tag); - i++; + for(; i<sizeof(id_xml_order); i++) { + if(!(args->wipe && !ids[id_xml_order[i]]->origin)) + newfile += "\n" + gen_tag(id_xml_order[i]) + "\n"; } // If any, add missing <add>-blocks from config foreach(indices(add), string blockname) newfile += "\n"+add[blockname]; - // Close locale tag - newfile += "\n</locale>\n"; - // Determine encoding if(!args->encoding || args->encoding=="") { int width = String.width( newfile ); if(width==16) - args->encoding = "utf-8"; + args->encoding = "UTF-8"; else if(width==32) - args->encoding = "utf-16"; + args->encoding = "UTF-16"; else - args->encoding = "iso-8859-1"; + args->encoding = "ISO-8859-1"; } function encode = get_encoder( args->encoding ); if(encode) @@ -444,7 +487,15 @@ void write_xml_file(string out_name, string outdata) { out->write( newfile ); out->truncate( out->tell() ); out->close(); - write("\n\n"); + + if(args->wipe) { + int no = 0; + foreach(id_xml_order, mixed id) + if(ids[id]->origin) no++; + if(no < sizeof(id_xml_order)) + write(" (wiped to %d)", no); + } + write("\n"); } @@ -471,7 +522,7 @@ array(string) get_tokens(string in, mapping args, string filename) { return 0; c = String.trim_whites(c); if(has_value(tokens, c)) - werror("\n* Warning: Token \"%s\" already found\n", c); + werror("\n* Warning: Token %O already found\n", c); tokens += ({c}); if (m->project) args->project = m->project; @@ -479,7 +530,7 @@ array(string) get_tokens(string in, mapping args, string filename) { args->project = ""; return 0; }) - ->feed(comments)->finish(); + ->feed( comments )->finish(); if(!sizeof(tokens)) { if(args->project) werror("\n* Warning: No token for project %O in %s\n", @@ -492,7 +543,7 @@ array(string) get_tokens(string in, mapping args, string filename) { void update_pike_sourcefiles(array filelist) { // Extracts strings from pike sourcefiles in filelist - // Updates ids, r_ids, id_xml_order with ids and strings + // Updates ids, r_ids and id_xml_order with ids and strings // If new ids, updates the sourcefile or a copy foreach(filelist, string filename) { Stdio.File file = Stdio.File(); @@ -515,7 +566,8 @@ void update_pike_sourcefiles(array filelist) { array id_pike_order = ({}); int no_of_ids = 0; - string id, fstr, token; + string|int id; + string fstr, token; for(int i=0; i<sizeof(pdata); i++) { //// Search for tokens foreach(tokens, token) @@ -524,10 +576,12 @@ void update_pike_sourcefiles(array filelist) { if(pdata[++i]!="(") continue; // Verify "(" //// Get id - id = (string)pdata[++i]; + id = (string)pdata[++i]; if(id=="\"\"") id = ""; - else + else if((int)id) + id = (int)id; + else id = get_first_string(id); //// Get string @@ -535,16 +589,16 @@ void update_pike_sourcefiles(array filelist) { i++; // Skip "," while( ++i<sizeof(pdata) && pdata[i]!=")" ) instr += (string)pdata[i]; - if(fstr=="\"\"") { - if(id=="") - continue; // Neither string nor id, skip! - fstr = ""; // Empty string with id, need to save id as used - } else + if(instr=="\"\"") + fstr = ""; + else fstr = get_first_string(instr); + if(fstr=="" && id=="") + continue; // Neither string nor id, skip! //// Check and store id and string no_of_ids++; - if(id == "") { + if(!id || id=="") { if (r_ids[fstr]) id = r_ids[fstr]; // Re-use old id with identical string else @@ -553,33 +607,36 @@ void update_pike_sourcefiles(array filelist) { id_pike_order += ({ ({id, token, quotemeta(instr)}) }); } else { // Verify old id - if(!id_origin[id]) { + if(!ids[id] || (ids[id] && !ids[id]->origin)) { // Remove preread string in r_ids lookup, might be updated m_delete(r_ids, ids[id]); } else { - if(ids[id] && ids[id] != fstr) { + if(ids[id] && ids[id]->original!=fstr) { werror("\n* Error: inconsistant use of id.\n"); - werror(" In file:%{ %s%}\n", id_origin[id]); - werror(" id %O -> string %O\n", id, ids[id]); + werror(" In file:%{ %s%}\n", ids[id]->origin); + werror(" id %O -> string %O\n", id, ids[id]->original); werror(" In file: %s\n", filename); werror(" id %O -> string %O\n", id, fstr); exit(1); } } - if(r_ids[fstr] && r_ids[fstr]!=id && id_origin[r_ids[fstr]]) + if(r_ids[fstr] && r_ids[fstr]!=id && ids[r_ids[fstr]]->origin) werror("\n* Warning: %O has id %O in%{ %s%}, id %O in %s", - fstr, r_ids[fstr], id_origin[r_ids[fstr]], id, filename); + fstr, r_ids[fstr], ids[r_ids[fstr]]->origin, id, filename); } - if(!has_value(id_xml_order,id) && fstr!="") + if(!has_value(id_xml_order, id)) // Id not in xml-structure, add to list - id_xml_order += ({id}); - id_origin[id] += ({filename}); // Remember origin - ids[id] = fstr; // Store id:text - if(fstr!="") r_ids[fstr] = id; // Store text:id + id_xml_order += ({ id }); + if(!ids[id]) + ids[id] = ([]); + ids[id]->original = fstr; // Store id:text + ids[id]->origin += ({filename}); // Add origin + if(String.trim_whites(fstr)!="") + r_ids[fstr] = id; // Store text:id } // Done parsing, rebuild sourcefile if needed - write(" (%d id%s)\n", no_of_ids, no_of_ids==1?"":"s"); + write(" (%d localization%s)\n", no_of_ids, (no_of_ids==1?"":"s")); if(!sizeof(id_pike_order)) { continue; } @@ -595,14 +652,17 @@ void update_pike_sourcefiles(array filelist) { // Insert ids based on tokens and the now regexp-safe string object(Regexp) RE; // RE = ^(.*TOKEN\( ")(", string \).*)$ - RE = Regexp("^(.*" + id[1] + "\\([ \n\t]*\")" + - "(\"[ ,\n\t]*"+id[2]+"[ \t\n]*\\).*)$"); + RE = Regexp("^(.*" + id[1] + "\\([ \n\t]*)[\"0]*" + + "([ ,\n\t]*"+id[2]+"[ \t\n]*\\).*)$"); array hits = RE->split(indata); if(hits) - indata = hits[0] + id[0] + hits[1]; - else - werror("\n* Failed to set id %O for string %O in %s", - id[0], ids[id[0]], filename); + indata = hits[0] + (intp(id[0])?id[0]:"\""+id[0]+"\"") + hits[1]; + else { + werror("\n* Warning: Failed to set id %O for string %O in %s", + id[0], ids[id[0]]->original, filename); + if(sizeof(ids[id[0]]->origin)<2) + id_xml_order -= ({ id[0] }); + } } write("\n"); @@ -627,7 +687,7 @@ void update_xml_sourcefiles(array filelist) { string line = file->gets(); string data = file->read(); file->close(); - if(!data) + if(!data && !line) continue; // Check encoding @@ -676,17 +736,18 @@ void update_xml_sourcefiles(array filelist) { if(m->project && m->project!="") { if(m->project!=args->project) return 0; // Tag belongs to another project - // else Correct project, proceed + // else correct project, proceed } else - if(ignoretag) // No proj specified, check ignoretag - return 0; - string id = m->id||""; + if(ignoretag) + return 0; // No proj specified, bail out if ignoretag + string|int id = m->id; + if((int)id) id = (int)id; string fstr = c; int updated = 0; if (String.trim_whites(fstr)=="") return 0; // No need to store empty strings no_of_ids++; - if(id == "") { + if(!id || id=="") { if (r_ids[fstr]) id = r_ids[fstr]; // Re-use old id with same string else @@ -695,31 +756,35 @@ void update_xml_sourcefiles(array filelist) { updated = ++new; } else { // Verify old id - if(!id_origin[id]) { + if(!ids[id] || (ids[id] && !ids[id]->origin)) { // Remove preread string in r_ids, might be updated m_delete(r_ids, ids[id]); } else { - if(ids[id] && ids[id] != fstr) { + if(ids[id] && ids[id]->original!=fstr) { werror("\n* Error: inconsistant use of id.\n"); - werror(" In file:%{ %s%}\n", id_origin[id]); - werror(" id %O -> string %O\n", id, ids[id]); + werror(" In file:%{ %s%}\n", ids[id]->origin); + werror(" id %O -> string %O\n", + id, ids[id]->original); werror(" In file: %s\n", filename); werror(" id %O -> string %O\n", id, fstr); exit(1); } } if(r_ids[fstr] && r_ids[fstr]!=id && - id_origin[r_ids[fstr]]) + ids[r_ids[fstr]]->origin) werror("\n* Warning: %O has id %O in%{ %s%}, " "id %O in %s", fstr, r_ids[fstr], - id_origin[r_ids[fstr]], id, filename); + ids[r_ids[fstr]]->origin, id, filename); } if(!has_value(id_xml_order, id)) // Id not in xml-structure, add to list - id_xml_order += ({id}); - id_origin[id] += ({filename}); // Remember origin - ids[id] = fstr; // Store id:text - r_ids[fstr] = id; // Store text:id + id_xml_order += ({ id }); + if(!ids[id]) + ids[id] = ([]); + ids[id]->original = fstr; // Store id:text + ids[id]->origin += ({filename}); // Add origin + if(String.trim_whites(fstr)!="") + r_ids[fstr] = id; // Store text:id if(updated) { string ret="<translate id=\""+id+"\""; foreach(indices(m)-({"id"}), string param) @@ -732,7 +797,7 @@ void update_xml_sourcefiles(array filelist) { xml_parser->feed(data)->finish(); // Done parsing, rebuild sourcefile if needed - write(" (%d id%s)\n", no_of_ids, no_of_ids==1?"":"s"); + write(" (%d localization%s)\n", no_of_ids, no_of_ids==1?"":"s"); if(!new) { continue; } @@ -844,11 +909,23 @@ string parse_config(string filename) { return 0; }); xml_parser-> - add_container("includepath", - // Add includepath needed for pikefiles + add_container("path", + // Project file path lambda(object foo, mapping m, string c) { - if(c && c!="") - add_include_path(c); + if(!args->path) { + c = String.trim_whites(c); + args->path = c; + } + return 0; + }); + xml_parser-> + add_container("baselang", + // Project file path + lambda(object foo, mapping m, string c) { + if(!args->baselang) { + c = String.trim_whites(c); + args->baselang = c; + } return 0; }); xml_parser-> @@ -881,9 +958,13 @@ string parse_config(string filename) { return 0; }); xml_parser->feed(indata)->finish(); - if(xml_name=="" && args->project) - // Default name of outfile - xml_name = args->project+"_eng.xml"; + + if(xml_name=="") + // Try to crate name of outfile + if(args->path && args->baselang) + xml_name = replace(args->path, "%L", args->baselang); + else if( args->project) + xml_name = args->project+"_eng.xml"; return xml_name; } @@ -916,11 +997,15 @@ int main(int argc, array(string) argv) { if(!configname && args->project) configname = args->project+".xml"; string filename = parse_config(configname); - if(filename!="" && (!xml_name || xml_name=="")) - xml_name = filename; - - if(!sizeof(files) || args->help) { - sscanf("$Revision: 1.4 $", "$"+"Revision: %s $", string v); + if(!xml_name || xml_name=="") + if(filename!="") + xml_name = filename; + else if(args->path && args->baselang) + xml_name = replace(args->path, "%L", args->baselang); + + if( (!(xml_name && args->sync && args->path && args->baselang)) && + (!sizeof(files) || args->help) ) { + sscanf("$Revision: 1.5 $", "$"+"Revision: %s $", string v); werror("\n Locale Extractor Utility "+v+"\n\n"); werror(" Syntax: extract.pike [arguments] infile(s)\n\n"); werror(" Arguments: --project=name default: first found in infile\n"); @@ -937,18 +1022,21 @@ int main(int argc, array(string) argv) { // Try to read and parse xml-file string xml_data = ""; xml_data = parse_xml_file(xml_name); + write("\n"); // Read, parse and (if necessary) update the sourcefiles object R = Regexp("(\.pike|\.pmod)$"); - array pikefiles = Array.filter(files, R->match); - update_pike_sourcefiles( pikefiles ); - update_xml_sourcefiles( files-pikefiles ); + foreach(files, string filename) + if(R->match(filename)) + update_pike_sourcefiles( ({ filename }) ); + else + update_xml_sourcefiles( ({ filename }) ); // If requested, remove ids not used anymore from the xml - if(args->wipe) - xml_data = parse_xml_file(xml_name, "Lets clean this mess up"); + // if(args->wipe) + // xml_data = parse_xml_file(xml_name, args->wipe); - // Save all strings to xml + // Save all strings to outfile xml if(!xml_name) if(args->project && args->project!="") xml_name = args->project+"_eng.xml"; @@ -957,7 +1045,24 @@ int main(int argc, array(string) argv) { sscanf(xml_name, "%s.pike", xml_name); xml_name += "_eng.xml"; } + write("\n"); write_xml_file(xml_name, xml_data); + // Synchronize xmls in other languages + if (args->sync) { + write("\n"); + mapping base_ids = ids; + array base_order = id_xml_order; + foreach(languagefiles(args->path, args->baselang), string file) { + ids = ([]); + parse_xml_file(file); + id_xml_order = base_order; + mapping old_ids = ids; + ids = base_ids; + write_xml_file(file, xml_data, old_ids); + } + } + + write("\n"); return 0; }