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

version» Context lines:

pike.git/lib/modules/Calendar.pmod/mkrules.pike:3:   // ftp://elsie.nci.nih.gov/pub/   // (timezone mailing list: tz@elsie.nci.nih.gov)   //   // source datafile are usually found somewhere around zic(8),   // if they exist in the system.   //   // Most systems only have compiled files, just like pike,   // and zic(8) is the usual compiler.      // pike mkrules.pike ../data/{africa,antarctica,asia,australasia,backward,etcetera,europe,northamerica,pacificnew,southamerica,systemv} - // $Id: mkrules.pike,v 1.6 2000/11/08 22:38:41 hubbe Exp $ +       #pike __REAL_VERSION__      object cal=Calendar.ISO->set_timezone("UTC");   function Year=cal->Year;   object nleapy=Year(1999);      object tzrules; // needed to make timezones, compiled below      mapping rules=([]);   mapping zones=([]);   mapping links=([]);   array arules=({});   array azones=({});    -  + mapping(string:mapping(int:array(string))) abbr2zones = ([ +  "DFT":([ 0x7fffffff:({ "Europe/Oslo", "Europe/Paris" }), ]), +  "NFT":([ 0x7fffffff:({ "Europe/Oslo", "Europe/Paris" }), ]), + ]); +    #define FIXED(D) (yjd+((D)-1))   #define FIX_L(D) (yjd+leap+((D)-1))   #define LDAY(D,W) (yjd+((D)-1)-( (yjd+((D)+(8-W)-1)) % 7))   #define LDAYL(D,W) (yjd+((D)-1)+leap-( (yjd+leap+((D)+(8-W)-1)) % 7))      #define FIXID(id) replace(id,"/-+"/1,"__p"/1)    -  + void add_abbr(string abbr, string zone, int until) + { +  mapping(int:array(string)) zones = abbr2zones[abbr]; +  if (!zones) abbr2zones[abbr] = zones = ([]); +  zones[until] += ({ zone }); + } +    int parse_offset(string t)   {    int h,m,s;    string res;       if (t=="0") return 0;       res="";    if (sscanf(t,"-%d:%d:%d%s",h,m,s,res)&&res=="")    return -(h*3600+m*60+s);
pike.git/lib/modules/Calendar.pmod/mkrules.pike:83:    string s;    string comment;       void create(array a)    {    switch (sizeof(a))    {    case 5:    dayrule=think_day(a[0],a[1]);    comment=a[0]+" "+a[1]; -  [time,timetype]=parse_tod(a[2]); +  // NB: The Morocco rule for 2011-07-31 has 0 as AT, +  // while all others have 0:00. +  [time,timetype] = parse_tod(a[2]) || ({ 0, "" });    switch (timetype)    {    case "": timetype="w"; break;    case "s": case "u": case "w": break;    default: complain("unknown time of day type %O\n",timetype);    }    offset=parse_offset(a[3]);    s=(a[4]=="-")?"":a[4];    break;    case 6:    [dayrule,comment,time,timetype,offset,s]=a;    break;    default:    error("illegal size of a\n");    }    }    -  string _sprintf(int t) +  protected string _sprintf(int t)    { -  return (t=='O')? +  return t=='O' &&    sprintf("Shift(%s,%d%s,%+d,%O)", -  dayrule,time,timetype,offset,s): -  0; +  dayrule,time,timetype,offset,s);    }       int `==(Shift other)    {    return ( dayrule==other->dayrule &&    time==other->time &&    timetype==other->timetype &&    offset==other->offset &&    s==other->s );    }
pike.git/lib/modules/Calendar.pmod/mkrules.pike:182:       return "LDAYL("+(nleapy->month(mon)->day(d)->year_day())+    ","+wd+")";    }    else    complain("unknown rule method %O\n",rule);    }       Shift|array ``+(array|Shift s)    { -  if (!s) return this_object(); +  if (!s) return this;    if (!arrayp(s)) s=({s}); -  return s+({this_object()}); +  return s+({this});    }       int ldayl_is_fix_l(int d1,int wd,int d2,int yn1,int yn2)    {    object y1=Year(yn1);    object y2=Year(yn2);    int yjd,leap;       yjd=y1->julian_day();    leap=y1->leap_year();
pike.git/lib/modules/Calendar.pmod/mkrules.pike:208:    leap=y2->leap_year();    d2=FIX_L(d2);       return d1==d2;    }       Shift try_promote(Shift t,int y0,int y1)    {   // this is year y0   // t is year y1 -  if (t==this_object()) return t; // same! +  if (t==this) return t; // same!    if (t->time!=time ||    t->timetype!=timetype ||    t->offset!=offset ||    t->s!=s) return 0; // no chance       int a,b,c;    if (sscanf(dayrule,"LDAYL(%d,%d)",a,b)==2 &&    sscanf(t->dayrule,"FIX_L(%d)",c)==1)    if (ldayl_is_fix_l(a,b,c,y0,y1)) -  return this_object(); // ldayl +  return this; // ldayl    else    return 0; // no    if (sscanf(t->dayrule,"LDAYL(%d,%d)",a,b)==2 &&    sscanf(dayrule,"FIX_L(%d)",c)==1)    if (ldayl_is_fix_l(a,b,c,y1,y0))    return t; // ldayl    else    return 0; // no       return 0;
pike.git/lib/modules/Calendar.pmod/mkrules.pike:257:    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:"");    }   }    - class Rule + class MyRule (string id)   { -  string id; -  +     mapping rules=([]);    -  +  multiset(string) symbols = (<>); +     int amt=0;    -  void create(string _id) { id=_id; } -  +     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");    -  +  a[7] = (a[7]/" #")[0]; +  if (a[7] == "-") a[7] = ""; +  symbols[a[7]] = 1; +     if (!(int)a[0] && a[0]!="min")    complain("unknown year %O\n",a[0]);      // ---      #define INF_YEAR 2050   #define NUL_YEAR 1850       int y1=(int)a[0] || NUL_YEAR;    int y2;
pike.git/lib/modules/Calendar.pmod/mkrules.pike:325:       if (!r2[NUL_YEAR]) r2[NUL_YEAR]=({last});       for (int y=min(@indices(rules));y<=INF_YEAR; y++)    [r2[y],last]=mkperiods(rules[y],last,first);       res+=("class "+    FIXID(id)+"\n"    "{\n"    " inherit TZRules;\n" -  " static array(array(string|int)) jd_year_periods(int jd)\n" +  " protected array(array(string|int)) jd_year_periods(int jd)\n"    " {\n"    " [int y,int yjd,int leap]=gregorian_yjd(jd);\n"    " switch (y)\n"    " {\n");       string s="",t;       int mn=min(@indices(rules-(<NUL_YEAR>)));       for (int y=INF_YEAR;sizeof(r2);y--)
pike.git/lib/modules/Calendar.pmod/mkrules.pike:390:    int lastoffset=0;    string res=" "*12+"return ({";    foreach (z,Shift s)    {    res+=s->dump(lastoffset,my)+("\n"+" "*21);    lastoffset=s->offset;    }    array resa=res/"\n";    resa[-2]=replace(resa[-2],", ","});");    -  t+=resa[..sizeof(resa)-2]*"\n"+"\n"; +  t+=resa[..<1]*"\n"+"\n";    s=t+s;    }    res+=(s+    " }\n"    " }\n"    "}\n\n");       return res;    }   
pike.git/lib/modules/Calendar.pmod/mkrules.pike:443:       s=({last,@s});       last=Shift( ({"0","",0,"u",    s[-1]->offset,s[-1]->s}) );       return ({s, last});    }   }    - class Zone + class Zone (string id)   { -  string id; -  +     array rules=({});    -  void create(string _id) { id=_id; } -  +     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    a[3],    0, 0, "tz", 0}); // until    a[5]=rule_shift(a);    a[4]=clone_rule(a);    -  +  if (sizeof(a[2])) { +  int until = (a[5] == "forever")?0x7fffffff:(int)a[5]; +  foreach(a[2]/"/", string fmt) { +  MyRule rule = global::rules[a[1]]; +  if (rule) { +  foreach(indices(rule->symbols), string sym) { +  if ((sizeof(sym) > 2) && (fmt != "%s")) continue; +  add_abbr(sprintf(fmt, sym), id, until); +  } +  } else if (a[1] == "Romania") { +  // Kludge for forward reference in tzdata2012c/europe +  // for Europe/Chisinau to the Romania rule. +  foreach(({ "", "S" }), string sym) { +  add_abbr(sprintf(fmt, sym), id, until); +  } +  } else { +  add_abbr(fmt, id, until); +  } +  } +  } +     rules+=({a});    }       string clone_rule(array a)    {    int h,m,s,roff=-17;    if (a[1]=="-") roff=0;    else if (sscanf(a[1],"-%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;    else if (sscanf(a[1],"%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;    else if (sscanf(a[1],"-%d:%d",h,m)==2) roff=h*3600+m*60;    else if (sscanf(a[1],"%d:%d",h,m)==2) roff=h*3600+m*60;       if (roff==-17) // based on DST rule    return sprintf(    "TZrules.%s(%d,%O)",    FIXID(a[1]),-a[0],a[2]);    else // simple timezone    return sprintf( -  "Ruleset.Timezone(%d,%O)", +  "Rule.Timezone(%d,%O)",    -(roff+a[0]),a[2]);    }       string rule_shift(array a)    {    if (a[3]=="" || a[3][0]=='#') return "forever";       string in=a[3];    sscanf(in,"until %s",in);    sscanf(in,"%s#",in);
pike.git/lib/modules/Calendar.pmod/mkrules.pike:567:    string res="";       if (!sizeof(rules))    {    res+=("// skipped %O due to errors\n",id);    return res;    }       if (sizeof(rules)==1) // simple zone    { -  res+=("Ruleset.Timezone "+cid+"="+ +  res+=("Rule.Timezone "+cid+"="+    rules[0][4]+";\n");    return res;    }       mapping rname=([]);    int n=1;       foreach (rules,array a)    if (rname[a[4]]) a[6]=rname[a[4]];    else a[6]=rname[a[4]]="tz"+n++;       res+=("class "+cid+"\n"    "{\n"    " inherit TZHistory;\n" -  " Ruleset.Timezone "+ +  " Rule.Timezone "+    sort(values(rname))*","+";\n" -  " Ruleset.Timezone whatrule(int ux)\n" +  " Rule.Timezone whatrule(int ux)\n"    " {\n"    );       foreach (rules,array a)    {    if (!a[5]) a[5]=rule_shift(a);       string s="";    sscanf(a[3],"%s#%*[ \t]%s",a[3],s);    a[3]="from "+reverse(array_sscanf(reverse(a[3]),"%*[ \t]%s")[0]);
pike.git/lib/modules/Calendar.pmod/mkrules.pike:637:    int n=0;    werror("reading %O...\n",file);    string s=Stdio.read_bytes(file),t;    if (!s)    {    werror("%s:-: Failed to open file: %s\n",file,strerror(errno()));    return;    }       Zone lastz; -  Rule lastr; +  MyRule lastr;       foreach (s/"\n",string line)    {    n++;    mixed err=catch    {    if (line[..0]!="#")    if (sscanf(line,"Zone%*[ \t]%[^ \t]%*[ \t]%s",s,t)==4)    {    if (zones[s]) lastz=zones[s]->add(t);    else (lastz=zones[s]=Zone(s))->add(t),azones+=({lastz});    }    else if (sscanf(line,"Rule%*[ \t]%[^ \t]%*[ \t]%s",s,t)==4)    {    if (rules[s]) rules[s]->add(t); -  else (lastr=rules[s]=Rule(s))->add(t),arules+=({lastr}); +  else (lastr=rules[s]=MyRule(s))->add(t),arules+=({lastr});    lastz=0;    }    else if (sscanf(line,"Link%*[ \t]%[^ \t]%*[ \t]%[^ \t]",s,t)==4)    {    // link t to s    if (links[s]) links[s]+=({t});    else links[s]=({t});    } -  else if (sscanf(line,"%*[ \t]%[-0-9]%s",s,t)==3 && strlen(s)) +  else if (sscanf(line,"%*[ \t]%[-0-9]%s",s,t)==3 && sizeof(s))    {    if (!lastz) complain("implicit zone line w/o zone\n");    lastz->add(s+t);    }    else if ((t="",sscanf(line,"%[ \t]",t),t==line))    ; -  else if (sscanf(line,"%*[ \t]#%s",t,s)==2) +  else if (sscanf(line,"%*[ \t]#%s",t)==2)    ;    else    complain("unknown keyword %O...\n",line[..10]);    };    if (err)    if (stringp(err))    werror("%s:%d: %s",file,n,err);    else    throw(err);    }   }      int main(int ac,array(string) am)   { -  if (sizeof(am)<1) +  array(string) files = am[1..]; +  if (!sizeof(files))    { -  werror("USAGE: %s datafile [datafile ...]\n",am[0]); -  return 1; +  werror("defaulting to reading zonefiles from %s...", +  combine_path(__FILE__, "../tzdata")); +  files = get_dir(combine_path(__FILE__, "../tzdata")); +  files = map(sort(files), +  lambda(string fname) { +  if ((< ".gitignore", "Makefile", "README", +  "factory", "leapseconds", >)[fname] || +  has_prefix(fname, "solar") || +  has_suffix(fname, ".awk") || +  has_suffix(fname, ".list") || +  has_suffix(fname, ".sh") || +  has_suffix(fname, ".tab")) return 0; +  return combine_path(__FILE__, "../tzdata", fname); +  }) - ({ 0 });    } -  map(am[1..],collect_rules); +  map(files, collect_rules);       write("thinking...\n");       string t=TZrules_base;    -  foreach (arules,Rule r) +  foreach (arules,MyRule r)    t+=r->dump();       tzrules=compile_string(t)();       mv("TZrules.pmod","TZrules.pmod~"); -  werror("writing TZrules.pmod (%d bytes)...",strlen(t)); +  werror("writing TZrules.pmod (%d bytes)...",sizeof(t));    Stdio.File("TZrules.pmod","wtc")->write(t);    werror("\n");       t="// ----------------------------------------------------------------\n"    "// Timezones\n"    "//\n"    "// NOTE: this file is generated by mkrules.pike;\n"    "// please do not edit manually /Mirar\n"    "// ----------------------------------------------------------------\n"    "\n"
pike.git/lib/modules/Calendar.pmod/mkrules.pike:725:    "// Timezones\n"    "// "+"-"*70+"\n\n");       mixed err=catch {    foreach (azones,Zone z)    if (sizeof(z->rules)==1)    {    t+=z->dump();    if (links[z->id])    foreach(links[z->id],string s) -  t+="Ruleset.Timezone "+FIXID(s)+"="+ +  t+="Rule.Timezone "+FIXID(s)+"="+    FIXID(z->id)+";\n";    }    };    if (err) if (stringp(err)) error(err); else throw(err);       t+=("\n"    "// "+"-"*70+"\n"    "// Timezones with an attitude\n"    "// "+"-"*70+"\n"    "\n");
pike.git/lib/modules/Calendar.pmod/mkrules.pike:754:    t+="constant "+FIXID(s)+"="+    FIXID(z->id)+";\n";    t+="\n";    }    };    if (err) if (stringp(err)) error(err); else throw(err);       t+=("\n"    "// "+"-"*70+"\n");    -  mv("TZs.pike","TZs.pike~"); -  werror("writing TZs.h (%d bytes)...",strlen(t)); +  mv("TZs.h","TZs.h~"); +  werror("writing TZs.h (%d bytes)...",sizeof(t));    Stdio.File("TZs.h","wtc")->write(t);    werror("\n");       mapping zs=([]);    foreach (azones,Zone z)    if (sscanf(z->id,"%s/%s",string s,string t)==2)    zs[s]=(zs[s]||({}))+({t});    -  t="// ----------------------------------------------------------------\n" -  "// Timezone names\n" -  "//\n" -  "// NOTE: this file is generated by mkrules.pike;\n" -  "// please do not edit manually /Mirar\n" -  "// ----------------------------------------------------------------\n" -  "\n" -  "mapping _module_value=\n" +  // Read and parse the original TZnames.pmod file. +  string orig_names = Stdio.read_bytes("TZnames.pmod"); +  array(string) fragments = orig_names/" zones="; +  if (sizeof(fragments) == 1) fragments = orig_names/" zones ="; +  if (sizeof(fragments) > 2) +  fragments = ({ fragments[0], fragments[1..] * " zones =" }); +  fragments[1] = (fragments[1]/"]);\n\n")[1..]*"]);\n\n"; +  +  t = fragments[0] + " zones =\n"    "([\n"; -  foreach (indices(zs)-({"SystemV","Etc"}),string co) -  t+=(replace( -  sprintf(" %-13s({%-=63s\n", +  +  multiset(string) zone_names = (multiset)indices(zs); +  +  zone_names->SystemV = 0; +  zone_names->Etc = 0; +  +  // Historical ordering... +  foreach (({"America", "Pacific", "Antarctica", "Atlantic", "Indian", +  "Europe", "Africa", "Asia", "Australia" }), string co) { +  t += +  sprintf(" %-13s({%-=60s\n",    sprintf("%O:",co),    map(zs[co],lambda(string s) { return sprintf("%O",s); }) -  *", "+"}),"),({", ",", "}),",,"/1)); -  t+="]);\n\n"; +  *", "+"}),"); +  zone_names[co] = 0; +  } +  // Take care of any remaining zones (probably none). +  foreach (sort(indices(zone_names)),string co) { +  t += +  sprintf(" %-13s({%-=60s\n", +  sprintf("%O:",co), +  map(zs[co],lambda(string s) { return sprintf("%O",s); }) +  *", "+"}),"); +  } +  t += "]);\n\n" + +  fragments[1];    -  mv("TZnames.pike","TZnames.pike~"); -  werror("writing TZnames.pmod (%d bytes)...",strlen(t)); +  // Update the abbreviation table as well. +  fragments = t/" abbr2zones="; +  if (sizeof(fragments) == 1) fragments = t/" abbr2zones ="; +  if (sizeof(fragments) > 2) +  fragments = ({ fragments[0], fragments[1..] * " abbr2zones =" }); +  fragments[1] = (fragments[1]/"]);\n\n")[1..]*"]);\n\n"; +  +  t = fragments[0] + " abbr2zones =\n" +  "([\n"; +  +  foreach(sort(indices(abbr2zones)), string abbr) { +  string line = sprintf(" %q: ({", abbr); +  +  mapping(int:array(string)) info = abbr2zones[abbr]; +  array(string) zones = ({}); +  array(int) until = ({}); +  foreach(info; int us; array(string) zs) { +  zones += zs; +  until += allocate(sizeof(zs), -us); +  } +  // Sort so that the most recent use comes first, +  // and secondarily on the zone name. +  sort(zones, until); +  sort(until, zones); +  foreach(Array.uniq(zones); int i; string zone) { +  string seg = sprintf("%s%q", i?", ":"", zone); +  if (sizeof(line) + sizeof(seg) < 77) { +  line += seg; +  continue; +  } +  t += line + ",\n"; +  line = sprintf(" %q", zone); +  } +  t += line + "}),\n"; +  } +  +  t += "]);\n\n" + +  fragments[1]; +  +  // Cleanup white-space at end of line. +  string t2 = t; +  while ((t = replace(t2, +  ({ " \n", +  " \n", +  " \n", +  " \n", +  " \n", +  " \n", +  " \n", +  " \n", }), ({ "\n" })*8)) != t2) { +  t2 = t; +  } +  +  mv("TZnames.pmod","TZnames.pmod~"); +  werror("writing TZnames.pmod (%d bytes)...",sizeof(t));    Stdio.File("TZnames.pmod","wtc")->write(t);    werror("\n");       return 0;   }         string TZrules_base=   #"// ----------------------------------------------------------------   // Daylight savings and war time rules   //   // NOTE: this file is generated by mkrules.pike;   // please do not edit manually /Mirar   // ----------------------------------------------------------------      // ----------------------------------------------------------------   // all rules are based on the gregorian calendar, so   // this is the gregorian rule:   // ----------------------------------------------------------------    - static array gregorian_yjd(int jd) + protected array gregorian_yjd(int jd)   {    int d=jd-1721426;       int century=(4*d+3)/146097;    int century_jd=(century*146097)/4;    int century_day=d-century_jd;    int century_year=(100*century_day+75)/36525;       int y=century*100+century_year+1;   
pike.git/lib/modules/Calendar.pmod/mkrules.pike:830:   }      // ----------------------------------------------------------------   // Base \"Timezone with rules\" class   // ----------------------------------------------------------------      class TZRules   {    constant is_timezone=1;    constant is_dst_timezone=1; -  static int offset_to_utc; +  protected int offset_to_utc;    string name;    -  static function(string:string) tzformat; -  static array names; +  protected function(string:string) tzformat; +  protected array names;    -  static void create(int offset,string _name) +  protected void create(int offset,string _name)    {    offset_to_utc=offset;    name=_name; -  if (search(name,\"/\")!=-1) +  if (has_value(name, \"/\"))    {    names=name/\"/\";    tzformat=lambda(string s)    {    if (s==\"\") return names[0]; else return names[1];    };    }    else    tzformat=lambda(string s) { return sprintf(name,s); };    }      // the Rule:   // which julian day does dst start and end this year? -  static array(array(string|int)) jd_year_periods(int jd); +  protected array(array(string|int)) jd_year_periods(int jd);      // is (midnight) this julian day dst?    array tz_jd(int jd)    {    array(array(string|int)) a=jd_year_periods(jd);       int i=0,n=sizeof(a)-1;    while (i<n)    {    array b=a[i+1];
pike.git/lib/modules/Calendar.pmod/mkrules.pike:892:    array b=a[i+1];    if (jd<b[0]-1) break;    if (jd<b[0]+1 &&    ux<(b[0]-2440588)*86400+b[1]) break;    i++;    }       return ({offset_to_utc-a[i][2],tzformat(a[i][3])});    }    -  string _sprintf(int t) { return (t=='O')?\"Timezone(\"+name+\")\":0; } +  protected string _sprintf(int t) +  { +  return t=='O' && \"Timezone(\"+name+\")\"; +  }       int raw_utc_offset() { return offset_to_utc; }   }      // ----------------------------------------------------------------------   // DST Rules   // ----------------------------------------------------------------------      // useful macros   #define FIXED(D) (yjd+((D)-1))   #define FIX_L(D) (yjd+leap+((D)-1))   #define LDAY(D,W) (yjd+((D)-1)-( (yjd+((D)+(8-W)-1)) % 7))   #define LDAYL(D,W) (yjd+((D)-1)+leap-( (yjd+leap+((D)+(8-W)-1)) % 7))   #define UO offset_to_utc      // ----------------------------------------------------------------------   ";