pike.git / lib / modules / Calendar.pmod / Timezone.pmod

version» Context lines:

pike.git/lib/modules/Calendar.pmod/Timezone.pmod:704:    int d,w;    if (sscanf(r,"FIX_L(%d)",d)) r=sprintf("FIXED(%d)",d+l);    else if (sscanf(r,"LDAYL(%d,%d)",d,w)==2)    r=sprintf("LDAY (%d,%d)",d+l,w);    }    return sprintf("({%-12s,%-10s,%-5d,%-6O}), %s",    r,t,offset,s,comment!=""?"// "+comment:"");    }    }    +  object compile_handler = class { +  mapping(string:mixed) get_default_module() { +  return constants; +  } +  +  mapping constants = all_constants() + +  (["TZrules":Dummymodule(find_rule), +  "TZRules":TZRules, +  "TZHistory":TZHistory, +  "Rule":Calendar.Rule, +  "ZEROSHIFT":({0,0,0,""}) +  ]); +  +  }(); +     class Rule    {    string id;       mapping rules=([]);    -  +  array(string) lines = ({}); +     int amt=0;       void create(string _id) { id=_id; }    -  +  void add_line(string line) +  { +  lines += ({ line }); +  } +     void add(string line)    {    array a= array_sscanf(line, replace("%s %s %s %s %s %s %s %[^\t ]",    " ","%*[ \t]"));       if (sizeof(a)<8) complain("illegal rule line format\n");       if (!(int)a[0] && a[0]!="min")    complain("unknown year %O\n",a[0]);   
pike.git/lib/modules/Calendar.pmod/Timezone.pmod:908:    if (first->s=="?")    foreach (s,Shift d) if (!d->offset) first->s=d->s;       s=({last,@s});       last=Shift( ({"0","",0,"u",    s[-1]->offset,s[-1]->s}) );       return ({s, last});    } +  +  +  program compile() +  { + #ifdef RTTZC_TIMING +  float t1=time(t); + #endif +  +  foreach(lines, string line) add(line); +  +  string c = dump(); +  + #ifdef RTTZC_TIMING +  float td=time(t); +  werror("dump %O: %O\n",rule_name,td-t1); + #endif +  + #ifdef RTTZC_DEBUG +  werror("%s\n",c); + #endif +  +  program p; +  mixed err=catch { p=compile_string(c, 0, compile_handler); }; +  if (err) +  { +  int i=0; +  foreach (c/"\n",string line) write("%2d: %s\n",++i,line); +  error(err);    } -  + #ifdef RTTZC_TIMING +  float t3=time(t); +  werror("compile %O: %O\n",rule_name,t3-td); + #endif +  return rule_cache[id] = p; +  }    -  +  } +     class Zone    {    string id;       array rules=({});    -  void create(string _id) { id=_id; } +  array(string) lines = ({});    -  +  array(string) aliases = ({}); +  +  void create(string _id) { +  id=_id; +  aliases = ({ id }); +  } +  +  void add_alias(string zone_alias) +  { +  aliases += ({ zone_alias }); +  } +  +  void add_line(string line) +  { +  lines += ({ line }); +  } +     void add(string line)    {    array a= array_sscanf(line, replace("%s %s %s %s",    " ","%*[ \t]"));    if (sizeof(a)<4)    complain("parse error\n");       a=({parse_offset(a[0]), // offset    a[1], // rule or added offset    a[2], // string
pike.git/lib/modules/Calendar.pmod/Timezone.pmod:1094:    foreach (rules[..<1],array a)    res+=({a[5]+","});    res+=({"});\n",    sprintf(    "string _sprintf(int t) { return (t=='O')?"    "%O:0; }\n"    "string zoneid=%O;\n","Rule.Timezone("+id+")",id)});       return res*"";    } +  +  object compile() +  { +  string zone_name = id; +  // werror("Compiling zone %O...\n", zone_name); +  + #ifdef RTTZC_TIMING +  float t1=time(t); + #endif +  +  foreach(lines, string line) add(line); +  +  string c=dump(); +  + #ifdef RTTZC_TIMING +  float td=time(t); +  werror("dump %O: %O\n",zone_name,td-t1); +  float td=time(t); + #endif +  + #ifdef RTTZC_DEBUG +  werror("%s\n",c); + #endif +  +  program p; +  mixed err=catch { p=compile_string(c, 0, compile_handler); }; +  if (err) +  { +  int i=0; +  foreach (c/"\n",string line) write("%2d: %s\n",++i,line); +  error(err);    } -  +  object zo=p(); +  if (zo->thezone) zo=zo->thezone;    -  + #ifdef RTTZC_TIMING +  float t3=time(t); +  werror("compile %O: %O\n",zone_name,t3-td); + #endif +  return zo; +  } +  +  } +     string base_path=combine_path(__FILE__,"../tzdata/");    array files=    ({    "africa",    "antarctica",    "asia",    "australasia",    "backward",    "etcetera",    "europe",    "northamerica",    "southamerica",    "pacificnew",    "systemv",    });    -  mapping zone_cache=([]); -  mapping rule_cache=([]); -  string all_rules=0; +  mapping zone_cache; +  mapping rule_cache; +  string all_rules; +  static mapping(string:Zone) zones = ([]); +  static mapping(string:Rule) rules = ([]);       string get_all_rules()    {    return    map(files,    lambda(string fn)    {    return (master()->master_read_file(base_path+fn) ||    (error("Failed to open file %O\n",base_path+fn), "")) - "\r";    })*"\n";    }       class Dummymodule (function(string:mixed) f)    {    mixed `[](string s) { return f(s); }    }    -  object compile_handler = class { -  mapping(string:mixed) get_default_module() { -  return constants; -  } -  -  mapping constants = all_constants() + -  (["TZrules":Dummymodule(find_rule), -  "TZRules":TZRules, -  "TZHistory":TZHistory, -  "Rule":Calendar.Rule, -  "ZEROSHIFT":({0,0,0,""}) -  ]); -  -  }(); -  +    // #define RTTZC_DEBUG   // #define RTTZC_TIMING    -  object find_zone(string s) +  void parse_all_rules()    { - #ifdef RTTZC_DEBUG -  werror("Searching for zone %O\n",s); - #endif -  if (zone_cache[s]) return zone_cache[s]; -  if (s=="") return UNDEFINED; -  +     if (!all_rules) all_rules=get_all_rules(); -  +    #ifdef RTTZC_TIMING -  int t=time(1); +     float t1=time(t);   #endif    -  Zone z=Zone(s); -  int n=0; +  rule_cache = ([]); +  zone_cache = ([]);    - #if constant(Regexp.PCRE.Studied) -  if (has_value(s,"\\") || -  has_value(s,"(") || -  has_value(s,"[")) -  return 0; -  Regexp.PCRE.Studied re=Regexp.PCRE.Studied("[Zz]one[ \t]*"+s+"[ \t]"); - #endif +  mapping(string:string) zone_aliases = ([]);    -  for (;;) -  { - #if constant(Regexp.PCRE.Studied) -  array(int)|int v=re->exec(all_rules,n); -  if (!arrayp(v) || !sizeof(v)) return UNDEFINED; -  n=v[0]; - #else -  n=search(all_rules,s,n); - #endif - #ifdef RTTZC_DEBUG -  werror("hit at: %O\n",n); - #endif -  if (n==-1) -  return UNDEFINED; -  int i=max(n-100,0)-1,j; -  do i=search(all_rules,"\nZone",(j=i)+1); while (i<n && i!=-1); +  Zone current_zone; +  foreach(all_rules/"\n", string line) { +  line = (line/"#")[0]; +  if ((line == "") || (line == " ")) continue;    -  if (j<n && -  sscanf(all_rules[j..j+8000],"\nZone%*[ \t]%[^ \t]%*[ \t]%s\n%s", -  string a,string b,string q)==5 && -  a==s) -  { -  z->add(b); -  foreach (q/"\n",string line) -  { -  if (sscanf(line,"%*[ \t]%[-0-9]%s",a,b)==3 && sizeof(a)) -  z->add(a+b); -  else if (sscanf(line,"%*[ ]#%*s")<2) -  break; // end of zone +  if (has_prefix(line, "Rule")) { +  current_zone = 0; +  +  string rule_name, interval; +  if (sscanf(line, "Rule%*[ \t]%[^ \t]%*[ \t]%s", +  rule_name, interval) == 4) { +  Rule r = rules[rule_name]; +  if (!r) { +  r = rules[rule_name] = Rule(rule_name);    } -  break; +  r->add_line(interval); +  } else { +  werror("Failed to parse directive %O.\n", line);    } -  i=max(n-100,0)-1; -  do i=search(all_rules,"\nLink",(j=i)+1); while (i<n && i!=-1); -  if (j<n && -  sscanf(all_rules[j..j+100],"\nLink%*[ \t]%[^ \t]%*[ \t]%[^ \t\n]", -  string a,string b)==4 && -  b==s) -  return find_zone(a); -  n++; +  } else if (has_prefix(line, "Zone")) { +  string zone_name, zone_info; +  if (sscanf(line, "Zone%*[ \t]%[^ \t]%*[ \t]%s", +  zone_name, zone_info) == 4) { +  // werror("Creating zone %O.\n", zone_name); +  Zone z = current_zone = zones[zone_name] = Zone(zone_name); +  z->add_line(zone_info); +  } else { +  werror("Failed to parse directive %O.\n", line);    } -  +  } else if (has_prefix(line, "Link")) { +  string zone_name, zone_alias; +  if (sscanf(line, "Link%*[ \t]%[^ \t]%*[ \t]%[^ \t]", +  zone_name, zone_alias) == 4) { +  Zone z = zones[zone_name]; +  if (z) { +  z->add_alias(zone_alias); +  zones[zone_alias] = z; +  } else if (zone_cache[zone_name]) { +  zone_cache[zone_alias] = zone_cache[zone_name]; +  } else { +  // werror("Deferred alias: %O ==> %O.\n", zone_alias, zone_name); +  zone_aliases[zone_alias] = zone_name; +  } +  } else { +  werror("Failed to parse directive %O.\n", line); +  } +  } else if (current_zone) { +  string prefix, suffix; +  if ((sscanf(line, "%*[ \t]%[-0-9]%s", prefix, suffix) == 3) && +  sizeof(prefix)) { +  current_zone->add_line(prefix + suffix); +  } +  } else { +  // werror("Skipping line %O.\n", line); +  } +  }   #ifdef RTTZC_TIMING -  float t2=time(t); -  werror("find %O: %O\n",s,t2-t1); - #endif -  -  string c=z->dump(); -  - #ifdef RTTZC_TIMING +     float td=time(t); -  werror("dump %O: %O\n",s,td-t2); -  float td=time(t); +  werror("parsing: %O\n",td-t1);   #endif    - #ifdef RTTZC_DEBUG -  werror("%s\n",c); - #endif -  -  program p; -  mixed err=catch { p=compile_string(c, 0, compile_handler); }; -  if (err) -  { -  int i=0; -  foreach (c/"\n",string line) write("%2d: %s\n",++i,line); -  error(err); +  // Fixup the zone aliases. +  foreach(zone_aliases; string zone_alias; string zone_name) { +  Zone z; +  if ((z = zones[zone_name])) { +  z->add_alias(zone_alias); +  zones[zone_alias] = z; +  } else if (!(zone_cache[zone_alias] = zone_cache[zone_name])) { +  werror("Zone %O is a link to a nonexistant zone %O.\n", +  zone_alias, zone_name);    } -  object zo=p(); -  if (zo->thezone) zo=zo->thezone; -  - #ifdef RTTZC_TIMING -  float t3=time(t); -  werror("compile %O: %O\n",s,t3-td); - #endif -  -  return zone_cache[s]=zo; +     } -  +  }    - // #define RTTZC_TIMING -  -  program find_rule(string s) +  object find_zone(string s)    { -  s=UNFIXID(s); -  if (rule_cache[s]) return rule_cache[s]; +    #ifdef RTTZC_DEBUG -  werror("Searching for rule %O\n",s); +  werror("Searching for zone %O\n",s);   #endif -  -  if (!all_rules) all_rules=get_all_rules(); -  - #ifdef RTTZC_TIMING -  int t=time(1); -  float t1=time(t); - #endif -  -  Rule r=Rule(s); -  int n=0; -  for (;;) -  { -  n=search(all_rules,s,n); - #ifdef RTTZC_DEBUG -  werror("hit at: %O\n",n); - #endif -  if (n==-1) -  return UNDEFINED; -  -  int i=max(n-100,0)-1,j; -  do i=search(all_rules,"\nRule",(j=i)+1); while (i<n && i!=-1); -  -  if (j<n && -  sscanf(all_rules[j..j+8000],"\nRule%*[ \t]%[^ \t]%*[ \t]%s\n%s", -  string a,string b,string q)==5 && a==s) -  { -  r->add(b); - #ifdef RTTZC_TIMING -  float tf=time(t); -  werror("find %O at: %O\n",s,tf-t1); -  float tq=time(t); - #endif -  foreach (q/"\n",string line) -  if (sscanf(line,"Rule%*[ \t]%[^ \t]%*[ \t]%s",a,b)==4 && -  a==s) -  r->add(b); -  else if (sscanf(line,"%*[ ]#%*s")<2) -  break; // end of zone - #ifdef RTTZC_TIMING -  float tf=time(t); -  werror("load %O: %O\n",s,tf-tq); - #endif -  break; +  if (!zone_cache) parse_all_rules(); +  object ret = zone_cache[s]; +  if (ret) return ret; +  Zone z; +  if (!(z = zones[s])) return UNDEFINED; +  ret = z->compile(); +  foreach(z->aliases, string zone_alias) { +  zone_cache[zone_alias] = ret; +  m_delete(zones, zone_alias);    } -  n++; +  m_delete(zones, s); +  return ret;    } -  string c=r->dump(); +     - #ifdef RTTZC_DEBUG -  werror("%s\n",c); - #endif - #ifdef RTTZC_TIMING -  float t2=time(t); -  werror("find %O: %O\n",s,t2-t1); -  float t2=time(t); - #endif -  -  program p=compile_string(c, 0, compile_handler); -  - #ifdef RTTZC_TIMING -  float t3=time(t); -  werror("compile %O: %O\n",s,t3-t2); - #endif -  -  return rule_cache[s]=p; +  program find_rule(string s) +  { +  if (!rule_cache) parse_all_rules(); +  s = UNFIXID(s); +  program ret = rule_cache[s]; +  if (ret) return ret; +  Rule r; +  if (!(r = rules[s])) return UNDEFINED; +  ret = rule_cache[s] = r->compile(); +  m_delete(rules, s); +  return ret;    }    -  +     int main(int ac,array(string) am)    {    map(am[1..],find_zone);    return 0;    }      // ----------------------------------------------------------------   // Base class for daylight savings and war time rules   // ----------------------------------------------------------------