diff --git a/lib/7.0/modules/Calendar.pmod/Austrian.pmod b/lib/7.0/modules/Calendar.pmod/Austrian.pmod new file mode 100644 index 0000000000000000000000000000000000000000..216139e91bcd13c9dab722b6ca239bc9e29f965c --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Austrian.pmod @@ -0,0 +1,36 @@ +// by Martin Baehr <mbaehr@email.archlab.tuwien.ac.at> + +inherit Calendar.ISO:ISO; + +void create() +{ + month_names= + ({"jänner","feber","märz","april","mai","juni","juli","august", + "september","oktober","november","dezember"}); + + week_day_names= + ({"montag","dienstag","mittwoch","donnerstag", + "freitag","samstag","sonntag"}); +} + +class Week +{ + inherit ISO::Week; + + string name() + { + return "w"+(string)this->number(); + } +} + +class Year +{ + inherit ISO::Year; + + string name() + { + if (this->number()<=0) + return (string)(1-this->number())+" v. Chr."; + return (string)this->number(); + } +} diff --git a/lib/7.0/modules/Calendar.pmod/Gregorian.pmod b/lib/7.0/modules/Calendar.pmod/Gregorian.pmod new file mode 100644 index 0000000000000000000000000000000000000000..f74a7e731b52f75027b88730d77bc23e9c39797a --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Gregorian.pmod @@ -0,0 +1,1543 @@ +// by Mirar + +//! module Calendar +//! submodule Gregorian +//! time units: +//! <ref>Year</ref>, <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> +//! +//! class + +array(string) month_names= + ({"January","February","March","April","May","June","July","August", + "September","October","November","December"}); + +array(string) week_day_names= + ({"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}); + +/* calculated on need */ + +mapping week_day_mapping,month_mapping; + +class _TimeUnit +{ + inherit Calendar._TimeUnit; + + program vYear=function_object(object_program(this_object()))->Year; + program vDay=function_object(object_program(this_object()))->Day; + program vMonth=function_object(object_program(this_object()))->Month; + program vWeek=function_object(object_program(this_object()))->Week; + program vHour=function_object(object_program(this_object()))->Hour; + program vMinute=function_object(object_program(this_object()))->Minute; + program vSecond=function_object(object_program(this_object()))->Second; +} + +//== Year ==================================================================== + +class Year +{ +//! class Year +//! A <ref>Calendar.time_unit</ref>. +//! +//! Lesser units: <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> +//! Greater units: none +//! +//! + inherit _TimeUnit; + +//-- variables ------------------------------------------------------ + + int y; + + array days_per_month; + array month_start_day; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "year"; + } + + array(string) lesser() + { + return ({"month","week","day"}); + } + + array(string) greater() + { + return ({}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + object yp=vDay()->year(); + y=yp->y; + } + else + y=arg[0]; + + int l=this->leap(); + days_per_month= + ({-17, 31,28+l,31,30,31,30,31,31,30,31,30,31}); + + month_start_day=allocate(sizeof(days_per_month)); + + for (int i=1,l=0; i<sizeof(days_per_month); i++) + month_start_day[i]=l,l+=days_per_month[i]; + } + + int `<(object x) + { + return y<(int)x; + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + (int)x==y; + } + + int hash() { return y*113; } + + int `>(object x) + { + return y>(int)x; + } + + object next() + { + return vYear(y+1); + } + + object prev() + { + return vYear(y-1); + } + + object `+(int n) + { + return vYear(y+n); + } + + int|object `-(int|object n) + { + if (objectp(n) && object_program(n)==vYear) return y-n->y; + return this+-n; + } + +//-- nonstandard methods -------------------------------------------- + + int julian_day(int d) // jd%7 gives weekday, mon=0, sun=6 + { + int a; + a = (y-1)/100; + return 1721426 + d - a + (a/4) + (36525*(y-1))/100; + } + + int leap() + { + if (!(y%400)) return 1; + if (!(y%100)) return 0; + return !(y%4); + } + + int leap_day() + { + return 31+24-1; // 24 Feb + } + + int number_of_weeks() + { + int j=julian_day(0)%7; + + // years that starts on a thursday has 53 weeks + if (j==3) return 53; + // leap years that starts on a wednesday has 53 weeks + if (j==2 && this->leap()) return 53; + // other years has 52 weeks + return 52; + } + + int number_of_days() + { + return 365+this->leap(); + } + + int number() + { + return y; + } + + string name() + { + if (y>0) return (string)y+" AD"; + else return (string)(-y+1)+" BC"; + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object month(object|string|int n) + { + if (objectp(n)) + if (object_program(n)==vMonth) + n=n->number(); + + if (stringp(n)) + { + if (!month_mapping) + { + month_mapping= + mkmapping(Array.map(month_names, lower_case)+ + Array.map(month_names, + lambda(string s) + { return lower_case(s[0..2]); } ), + (indices(allocate(13))[1..]) * 2); + } + n=month_mapping[lower_case(n)]; + if (!n) return 0; + } + + if (n<0) + return vMonth(y,13+n); + else + return vMonth(y,n||1); + } + + array(mixed) months() + { + return month_names; + } + + object week(object|int n) + { + if (objectp(n)) + if (object_program(n)==vWeek) + { + n=n->number(); + if (n>number_of_weeks()) return 0; /* no such week */ + } + + if (n<0) + return vWeek(y,this->number_of_weeks()+n+1); + else + return vWeek(y,n||1); + } + + array(mixed) weeks() + { + return indices(allocate(this->number_of_weeks()+1))[1..]; + } + + object day(object|int n) + { + if (objectp(n)) + if (object_program(n)==vDay) + { + object o=n->year(); + n=n->year_day(); + if (o->leap() && n==o->leap_day()) + if (!this->leap()) return 0; + else n=this->leap_day(); + else + { + if (o->leap() && n>o->leap_day()) n--; + if (this->leap() && n>=this->leap_day()) n++; + } + if (n>=number_of_days()) return 0; /* no such day */ + } + else return 0; /* illegal object */ + + if (n<0) + return vDay(y,this->number_of_days()+n); + else + return vDay(y,n); + } + + array(mixed) days() + { + return indices(allocate(this->number_of_days())); + } + +//-- more ----------------------------------------------------------- + + // none +}; + + +// + +//== Month =================================================================== + +class Month +{ + inherit _TimeUnit; +//-- variables ------------------------------------------------------ + + int y; + int m; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "month"; + } + + array(string) lesser() + { + return ({"day"}); + } + + array(string) greater() + { + return ({"year"}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + object mp=vDay()->month(); + y=mp->y; + m=mp->m; + } + else + { + y=arg[0]; + m=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && m<x->m) || (y<x->y)); + } + + int `==(object x) + { + return + objectp(x) && + object_program(x)==object_program(this) && + x->y==y && x->m==m; + } + + int hash() { return y*4721+m; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && m>x->m) || (y>x->y)); + } + + object `+(int n) + { + int m2=m; + int y2=y; + m2+=n; + while (m2>12) { y2++; m2-=12; } + while (m2<1) { y2--; m2+=12; } + return vMonth(y2,m2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vMonth) + return m-n->m+(y-n->y)*12; + return this+(-n); + } + +//-- internal ------------------------------------------------------- + + int yday() + { + return this->year()->month_start_day[m]; + } + +//-- nonstandard methods -------------------------------------------- + + int number_of_days() + { + return this->year()->days_per_month[m]; + } + + int number() + { + return m; + } + + string name() + { + return month_names[this->number()-1]; + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object day(int|object n) + { + if (objectp(n)) + if (object_program(n)==vDay) + { + n=n->month_day(); + if (n>number_of_days()) return 0; /* no such day */ + } + + if (n<0) + return vDay(y,yday()+this->number_of_days()+n); + else + return vDay(y,yday()+(n||1)-1); + } + + array(mixed) days() + { + return indices(allocate(this->number_of_days()+1))[1..]; + } + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } +}; + + +// +//== Week ==================================================================== + +class Week +{ + inherit _TimeUnit; +//-- variables ------------------------------------------------------ + + int y; + int w; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "week"; + } + + array(string) lesser() + { + return ({"day"}); + } + + array(string) greater() + { + return ({"year"}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + object wp=vDay()->week(); + y=wp->y; + w=wp->w; + } + else + { + y=arg[0]; + w=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && w<x->w) || (y<x->y)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->y==y && x->w==w; + } + + int hash() { return y*811+w; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && w>x->w) || (y>x->y)); + } + + object `+(int n) + { + int y2=y,nd; + int w2=w; + w2+=n; + + if (w2>0) + { + nd=vYear(y)->number_of_weeks(); + while (w2>nd) + { + w2-=nd; + y2++; + nd=vYear(y2)->number_of_weeks(); + } + } + else + while (w2<1) + { + y2--; + w2+=vYear(y2)->number_of_weeks(); + } + return vWeek(y2,w2); + } + + int|object `-(int|object n) + { + if (object_program(n)==vWeek && objectp(n)) + return (this->day(1)-n->day(1))/7; + return this+(-n); + } + +//-- internal ------------------------------------------------------- + + int yday() + { + return + ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7] + +7*(w-1); + } + +//-- nonstandard methods -------------------------------------------- + + int number_of_days() + { + return 7; + } + + int number() + { + return w; + } + + string name() + { + return "w"+(string)this->number(); + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object day(int|string|object n) + { + if (stringp(n)) + { + if (!week_day_mapping) + week_day_mapping= + mkmapping(Array.map(week_day_names,lower_case), + ({1,2,3,4,5,6,0})); + n=week_day_mapping[n]; + } + else if (objectp(n)) + if (object_program(n)==vDay) + n=n->week_day(); + else return 0; + + if (n<0) n=7+n; + n+=this->yday()-1; + if (n<0) return vYear(y-1)->day(n); + if (n>=this->year()->number_of_days()) + return vYear(y+1)->day(n-this->year()->number_of_days()); + return vDay(y,n); + } + + array(mixed) days() + { + return ({0,1,2,3,4,5,6}); + } + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } +}; + +// +//== Day ===================================================================== + +class Day +{ + inherit _TimeUnit; + +//-- variables ------------------------------------------------------ + + int y; + int d; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "day"; + } + + array(string) greater() + { + return ({"year","month","week"}); + } + + array(string) lesser() + { + return ({"hour"}); + } + + void create(int|object ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + y=1900+t->year; + d=t->yday; + } + else if (sizeof(arg)==1) + { + int jd; + + if (objectp(arg[0])) + jd=(int)((arg[0]->julian_day||arg[0]->julian_day_f)()); + else + jd=arg[0]; + + object yo; + y=(int)(jd/365.2425)-4712; + yo=vYear(y); + while (yo->julian_day(0)>jd) yo--; + write("y="+yo->number()+" yd="+yo->julian_day(0)+" nod="+yo->number_of_days()+"\n"); + while (jd-yo->julian_day(0)>=yo->number_of_days()) + { + yo++; + write("y="+yo->number()+" yd="+yo->julian_day(0)+" nod="+yo->number_of_days()+"\n"); + + } + y=yo->number(); + write("y="+y+"\n"); + d=jd-vYear(y)->julian_day(0); + write("d="+d+"\n"); + } + else + { + y=arg[0]; + d=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && d<x->d) || (y<x->y)) || + (julian_day()<x->julian_day()); + } + + int `==(object x) + { + return + (object_program(x)==object_program(this) && + x->y==y && x->d==d) || + (x->julian_day() == julian_day()); + } + + int hash() { return y*3203+d; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && d>x->d) || (y>x->y)) || + (julian_day()>x->julian_day()); + } + + object `+(int n) + { + int y2=y,nd; + int d2=d; + d2+=n; + + if (d2>0) + { + nd=vYear(y)->number_of_days(); + while (d2>=nd) + { + d2-=nd; + y2++; + nd=vYear(y2)->number_of_days(); + } + } + else + while (d2<0) + { + y2--; + d2+=vYear(y2)->number_of_days(); + } + return vDay(y2,d2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vDay) + return (this->julian_day()-n->julian_day()); + + return this+(-n); + } + +//-- nonstandard methods -------------------------------------------- + + int julian_day() + { + return vYear(y)->julian_day(d); + } + + int year_day() + { + return d; + } + + int month_day() + { + int d=year_day(); + int pj=0; + foreach (this->year()->month_start_day,int j) + if (d<j) return d-pj+1; + else pj=j; + return d-pj+1; + } + + int week_day() + { + return (julian_day()+1)%7; + } + + string week_day_name() + { + return week_day_names[(this->week_day()+6)%7]; + } + + int number_of_hours() + { + return 24; + } + + string dateofyear() + { + return sprintf("%d %s %s",this->month_day(), + this->month()->name(),this->year()->name()); + } + +//-- less ----------------------------------------------------------- + + object hour(int|object n) + { + if (objectp(n)) + if (object_program(n)==vHour) + n=n->number(); + else return 0; + + if (n<0) n=this->number_of_hours()+n; + if (n<0) return (this-1)->hour(n); + if (n>=this->number_of_hours()) + return (this+1)->hour(n-this->number_of_hours()); + + return vHour(this,n); + } + + array(mixed) hours() + { + return indices(allocate(this->number_of_hours())); + } + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } + + object month() + { + int d=year_day(); + array a=year()->month_start_day; + for (int i=2; i<sizeof(a); i++) + if (d<a[i]) return vMonth(y,i-1); + return vMonth(y,12); + } + + object week() + { + int n; + object ye=this->year(); + n=(-({-1,-2,-3,-4,2,1,0})[this->year()->julian_day(0)%7]+d)/7+1; + if (n>ye->number_of_weeks()) + return ye->next()->week(1); + else if (n<=0) + return ye->prev()->week(-1); + return vWeek(y,n); + } +}; + + +// +//== Hour ==================================================================== + +class Hour +{ + inherit _TimeUnit; + +//-- variables ------------------------------------------------------ + + object d; + int h; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "hour"; + } + + array(string) greater() + { + return ({"day"}); + } + + array(string) lesser() + { + return ({"minute"}); + } + + void create(int|object ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + d=vDay(); + h=t->hour; + } + else + { + if (!objectp(arg[0])) + throw( ({"Calendar...Day(): illegal argument 1\n", + backtrace()}) ); + d=arg[0]; + h=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->d==d && h<x->h) || (d<x->d)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->d==d && x->h==h; + } + + int hash() { return d->__hash()*31957+h; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->d==d && h>x->h) || (d>x->d)); + } + + object `+(int n) + { + object d2=d; + int nh; + int h2=h; + h2+=n; + + // FIXME some magic about DS hour skip/insert hours not counted twice + + // maybe fix some better way to do `+, too + if (h2>0) + { + nh=d->number_of_hours(); + while (h2>=nh) + { + h2-=nh; + d2++; + nh=d2->number_of_hours(); + } + } + else + { + while (h2<0) + { + d2--; + h2+=d2->number_of_hours(); + } + } + + return vHour(d2,h2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vHour) + { + if (n->d==d) return h-n->h; + if (n->d!=d) + { + int x=(d-n->d)*24; // good try + object nh=n+x; + int haz=100; // we don't guess _that_ wrong (1200 hours...) + if (nh->d<d) + while (nh->d<d && !--haz) { nh+=12; x+=12; } + else if (nh->d>d) + while (nh->d>d && !--haz) { nh-=12; x-=12; } + return h-n->h+x; + } + } + + return this+(-n); + } + +//-- nonstandard methods -------------------------------------------- + + int number() + { + return h; + } + + string name() + { + // some magic about DS here + return (string)this->number(); + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + + int number_of_minutes() + { + return 60; + } + +//-- less ----------------------------------------------------------- + + object minute(int|object n) + { + if (objectp(n)) + if (object_program(n)==vMinute) + n=n->number(); + else return 0; + + if (n<0) n=this->number_of_minutes()+n; + if (n<0) return (this-1)->minute(n); + if (n>=this->number_of_minutes()) + return (this+1)->minute(n-this->number_of_minutes()); + + return vMinute(this,n); + } + + array(mixed) minutes() + { + return indices(allocate(this->number_of_minutes())); + } + +//-- more ----------------------------------------------------------- + + object day() + { + return d; + } +}; + + +// +//== Minute =================================================================== + +class Minute +{ + inherit _TimeUnit; + +//-- variables ------------------------------------------------------ + + object h; + int m; + +//-- standard methods ----------------------------------------------- + + string is() + { + return "minute"; + } + + array(string) greater() + { + return ({"hour"}); + } + + array(string) lesser() + { + return ({"second"}); + } + + void create(int|object ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + h=vHour(); + m=t->min; + } + else + { + if (!objectp(arg[0])) + throw( ({"Calendar...Minute(): illegal argument 1\n", + backtrace()}) ); + h=arg[0]; + m=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->h==h && m<x->m) || (h<x->h)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->h==h && x->m==m; + } + + int __hash() { return h->__hash()*101+m; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->h==h && m>x->m) || (h>x->h)); + } + + object `+(int n) + { + object h2=h; + int nm; + int m2=m; + m2+=n; + + // FIXME some magic about HS minute skip/insert minutes not counteh twice + + if (m2>0) + { + // 60 minutes in an hour... + nm=h->number_of_minutes(); + int x=m2/nm; + h2+=x; + m2-=x*nm; + while (m2>=nm) + { + m2-=nm; + h2++; + nm=h2->number_of_minutes(); + } + } + else + { + nm=h->number_of_minutes(); + int x=m2/nm; + h2+=x; + m2-=x*nm; + while (m2<0) + { + h2--; + m2+=h2->number_of_minutes(); + } + } + + return vMinute(h2,m2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vMinute) + { + if (n->h==h) return m-n->m; + if (n->h!=h) + { + int x=(h-n->h)*60; // good try + object nm=n+x; + int haz=100; // we won't guess _that_ wrong (6000 minutes...) + if (nm->h<h) + while (nm->h<h && !--haz) { nm+=30; x+=30; } + else if (nm->h>h) + while (nm->h>h && !--haz) { nm-=30; x-=30; } + return m-n->m+x; + } + } + + return this+(-n); + } + +//-- nonstandard methods -------------------------------------------- + + int number() + { + return m; + } + + string name() + { + // some magic about HS here + return (string)this->number(); + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + + int number_of_seconds() + { + return 60; + } + + string timeofday() + { + return sprintf("%s:%02s",h->name(),name()); + } + + string timeofyear() + { + return sprintf("%s %s:%02s",h->day()->dateofyear(),h->name(),name()); + } + +//-- less ----------------------------------------------------------- + + object second(int|object n) + { + if (objectp(n)) + if (object_program(n)==vSecond) + n=n->number(); + else return 0; + + if (n<0) n=this->number_of_seconds()+n; + if (n<0) return (this-1)->second(n); + if (n>=this->number_of_seconds()) + return (this+1)->second(n-this->number_of_seconds()); + + return vSecond(this,n); + } + + array(mixed) seconds() + { + return indices(allocate(this->number_of_seconds())); + } + +//-- more ----------------------------------------------------------- + + object hour() + { + return h; + } +}; + + +// +//== Second =================================================================== + +class Second +{ + inherit _TimeUnit; + +//-- variables ------------------------------------------------------ + + object m; + int s; + +//-- standarm setsoms ----------------------------------------------- + + string is() + { + return "second"; + } + + array(string) greater() + { + return ({"minute","hour","day","month","year"}); + } + + array(string) lesser() + { + return ({}); + } + + void create(int|object ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + m=vMinute(); + s=t->sec; + } + else if (sizeof(arg)==1) + { + mapping t=localtime(arg[0]); + m=Year(1900+t->year)->month(1+t->mon)->day(t->mday)-> + hour(t->hour)->minute(t->min); + s=t->sec; + } + else + { + if (!objectp(arg[0])) + throw( ({"Calendar...Second(): illegal argument 1\n", + backtrace()}) ); + m=arg[0]; + s=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->m==m && s<x->s) || (m<x->m)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->m==m && x->s==s; + } + + int __hash() { return m->__hash()*101+s; } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->m==m && s>x->s) || (m>x->m)); + } + + object `+(int n) + { + object m2=m; + int ns; + int s2=s; + s2+=n; + + // FIXSE sose sagic about MS second skip/insert seconds not countem twice + + if (s2>0) + { + // 60 seconds in a minute... wrong if leapseconds!! beware + ns=m->number_of_seconds(); + int x=s2/ns; + m2+=x; + s2-=x*ns; + while (s2>=ns) + { + s2-=ns; + m2++; + ns=m2->number_of_seconds(); + } + } + else + { + ns=m->number_of_seconds(); + int x=s2/ns; + m2+=x; + s2-=x*ns; + while (s2<0) + { + m2--; + s2+=m2->number_of_seconds(); + } + } + + return vSecond(m2,s2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vSecond) + { + if (n->m==m) return s-n->s; + if (n->m!=m) + { + int x=(m-n->m)*60; // good try + object ns=n+x; + int maz=100; // we won't guess _that_ wrong (6000 seconds...) + if (ns->m<m) + while (ns->m<m && !--maz) { ns+=30; x+=30; } + else if (ns->m>m) + while (ns->m>m && !--maz) { ns-=30; x-=30; } + return s-n->s+x; + } + } + + return this+(-n); + } + +//-- nonstandard methods -------------------------------------------- + + int number() + { + return s; + } + + string name() + { + // some magic about MS here + return (string)this->number(); + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->nase(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + + string timeofday() + { + return sprintf("%s:%02s",m->timeofday(),name()); + } + + string timeofyear() + { + return sprintf("%s:%02s",m->timeofyear(),name()); + } + +//-- greater -------------------------------------------------------- + + object minute() + { + return m; + } + + object hour() + { + return minute()->hour(); + } + + object day() + { + return minute()->hour()->day(); + } + + object month() + { + return minute()->hour()->day()->month(); + } + + object year() + { + return minute()->hour()->day()->month()->year(); + } + +}; + +//-- parse functions ----------------------------------------------- + +//! method object parse(string fmt,string arg) +//! parse a date, create relevant object +//! fmt is in the format "abc%xdef..." +//! where abc and def is matched, and %x is +//! one of those time units: +//! %Y absolute year +//! %y year (70-99 is 1970-1999, 0-69 is 2000-2069) +//! %M month (number, name or short name) (needs %y) +//! %W week (needs %y) +//! %D date (needs %y, %m) +//! %a day (needs %y) +//! %e weekday (needs %y, %w) +//! %h hour (needs %d, %D or %W) +//! %m minute (needs %h) +//! %s second (needs %s) + +object parse(string fmt,string arg) +{ + string nfmt; + nfmt=replace(fmt, + ({"%Y","%y","%M","%W","%D","%a","%e","%h","%m","%s"}), + ({"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s"})); + array q=Array.map(replace(fmt,"%%","")/"%", + lambda(string s){ return s[..0];})-({""}); + array res=Array.map(array_sscanf(arg,nfmt), + lambda(string s) + { + if (s[0]>='0' && s[0]<='9') + return array_sscanf(s,"%d")[0]; + else + return s; + }); + + if (sizeof(res)<sizeof(q)) + return 0; // parse error + + mapping m=mkmapping(q,res); + + if (!zero_type(m->Y)) m->year=Year(m->Y); + else if (!zero_type(m->y)) + { + if (m->y<70) m->y+=2000; + else if (m->y<100) m->y+=1900; + m->year=Year(m->y); + } + else m->year=Year(); + + object low=m->year; + + if (m->M) + { + m->month=low=m->year->month(m->M); + if(!m->month) + return 0; // Unknown month + } + if (m->W) + m->week=low=m->year->week(m->W); + + if (m->D) + m->day=low=(m->month||Month())->day(m->D); + else if (!zero_type(m->a)) + m->day=low=m->year->day(m->a); + else if (!zero_type(m->e)) + m->day=low=(m->week||Week())->day(m->e); + + if (!zero_type(m->h)) + low=m->hour=(m->day||Day())->hour(m->h); + if (!zero_type(m->m)) + low=m->minute=(m->hour||Hour())->minute(m->m); + if (!zero_type(m->s)) + low=m->second=(m->minute||Minute())->second(m->s); + + return low; +} + +//-- auxillary functions------------------------------------------------ + +//! +//! function datetime(int|void unix_time) +//! Replacement for localtime. +//! +//! function datetime_name(int|void unix_time) +//! Replacement for ctime. +//! +//! function datetime_short_name(int|void unix_time) +//! Replacement for ctime. +//! + + +// Sane replacement for localtime(). +mapping(string:int) datetime(int|void unix_time,int|void skip_extra) +{ + mapping t = localtime(unix_time || time()); + return + ([ "year":t->year+1900, + "month":t->mon+1, + "day":t->mday, + "hour":t->hour, + "minute":t->min, + "second":t->sec, + "yearday":t->yday, + "timezone":t->timezone, + "DST":t->isdst // Dayligt-saving time. + ]) | + // calculate week and week day + (skip_extra + ?([]) + :(["week":(int)Week(), + "weekday":Day()->week_day()])); +} + +// Sane replacement for ctime(). +string datetime_name(int|void unix_time) +{ + mapping t = datetime(unix_time); + return sprintf("%04d-%02d-%02d (%s) -W%02d-%d (%s) %02d:%02d:%02d", + t->year, t->month, t->day, + month_names[t->month-1][..2], + t->week, t->weekday, + week_day_names[t->weekday-1][..2], + t->hour, t->minute, t->second); +} + +// Sane replacement for ctime(). +string datetime_short_name(int|void unix_time) +{ + mapping t = datetime(unix_time,1); + return sprintf("%04d-%02d-%02d %02d:%02d:%02d", + t->year, t->month, t->day, + t->hour, t->minute, t->second); +} diff --git a/lib/7.0/modules/Calendar.pmod/ISO.pmod b/lib/7.0/modules/Calendar.pmod/ISO.pmod new file mode 100644 index 0000000000000000000000000000000000000000..214f6a709b30af38922540416953b0a83cceab53 --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/ISO.pmod @@ -0,0 +1,247 @@ +// IS-8601, international standard + +inherit Calendar.Gregorian:Gregorian; + +class Year +{ + inherit Gregorian::Year; + + int leap_day() + { + if (y>1999) return 31+29-1; // 29 Feb + return 31+24-1; // 24 Feb + } + + string name() + { + return (string)y; + } +} + +class Month +{ + inherit Gregorian::Month; + + string iso_name() + { + return sprintf("%04d-%02d", + (int)this->year(), + (int)this); + } + + string iso_short_name() + { + return name()-"-"; + } +} + +class Week +{ + inherit Gregorian::Week; + + int yday() + { + return + ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7] + +7*(w-1); + } + + array(mixed) days() + { + return ({1,2,3,4,5,6,7}); + } + + string iso_name() + { + return sprintf("%04d-W%02d", + (int)this->year(), + (int)this); + } + + string iso_short_name() + { + return name()-"-"; + } + + object day(int|string|object n) + { + if (stringp(n)) + { + if (!week_day_mapping) + week_day_mapping= + mkmapping(Array.map(week_day_names,lower_case), + ({1,2,3,4,5,6,7})); + n=week_day_mapping[n]; + } + else if (objectp(n)) + if (object_program(n)==vDay) + n=n->week_day(); + else return 0; + + if (n<0) n=8+n; + else if (!n) n=1; + n+=this->yday()-1; + if (n<0) return vYear(y-1)->day(n); + if (n>=this->year()->number_of_days()) + return vYear(y+1)->day(n-this->year()->number_of_days()); + return vDay(y,n); + } +} + +class Day +{ + inherit Gregorian::Day; + + int week_day() + { + return julian_day()%7+1; + } + + string week_day_name() + { +// werror("week_days: %O\n",week_day_names); + return week_day_names[(this->week_day()+6)%7]; + } + + string iso_name() + { + return sprintf("%04d-%02d-%02d", + (int)this->year(), + (int)this->month(), + (int)this->month_day()); + } + + string iso_short_name() + { + return iso_name()-"-"; + } + + string iso_name_by_week() + { + return sprintf("%04d-W%02d-%d", + (int)this->year(), + (int)this->week(), + (int)this->week_day()); + } + + string iso_name_by_yearday() + { + return sprintf("%04d-%03d", + (int)this->year(), + (int)this->year_day()); + } + + string iso_short_name_by_yearday() + { + return iso_name_by_yearday()-"-"; + } + + object week() + { + int n; + object ye=this->year(); + n=(-({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7]+d)/7+1; + if (n>ye->number_of_weeks()) + return ye->next()->week(1); + else if (n<=0) + return ye->prev()->week(-1); + return vWeek(y,n); + } +} + +static private class _Day +{ + // FIXME: Kludge because the day object does not exist in + // Minute and Second. This function will be shadowed in Hour. + object day() + { + return this_object()->hour()->day(); + } +} + +static private class Name +{ + object this = this_object(); + + string iso_name() + { + return this->day()->iso_name()+this->_iso_name(); + } + + string iso_short_name() + { + return this->day()->iso_short_name()+this->_iso_short_name(); + } + + string iso_name_by_week() + { + return this->day()->iso_name_by_week()+this->_iso_name(); + } + + string iso_name_by_yearday() + { + return this->day()->iso_name_by_yearday()+this->_iso_name(); + } + + string iso_short_name_by_yearday() + { + return this->day()->iso_short_name_by_yearday()+this->_iso_short_name(); + } +} + +class Hour +{ + inherit Gregorian::Hour; + inherit Name; + + string _iso_name() + { + return sprintf("T%02d", + (int)this); + } + + string _iso_short_name() + { + return _iso_name(); + } +} + +class Minute +{ + inherit _Day; + inherit Gregorian::Minute; + inherit Name; + + string _iso_name() + { + return sprintf("T%02d:%02d", + (int)this->hour(), + (int)this); + } + + string _iso_short_name() + { + return _iso_name()-":"; + } +} + +class Second +{ + inherit _Day; + inherit Gregorian::Second; + inherit Name; + + string _iso_name() + { + return sprintf("T%02d:%02d:%02d", + (int)this->hour(), + (int)this->minute(), + (int)this); + } + + string _iso_short_name() + { + return _iso_name()-":"; + } +} + diff --git a/lib/7.0/modules/Calendar.pmod/Julian.pmod b/lib/7.0/modules/Calendar.pmod/Julian.pmod new file mode 100644 index 0000000000000000000000000000000000000000..7c03a20b858cc0e31f5795e7de6f5f34fd9b1a64 --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Julian.pmod @@ -0,0 +1,35 @@ +inherit Calendar.Gregorian; + +class Year +{ + inherit Calendar.Gregorian.Year; + + int julian_day(int d) // jd%7 gives weekday, mon=0, sun=6 + { + return 1721424 + d + (36525*(y-1))/100; + } + + int leap() + { + return !(y%4); + } + +} + +class Day +{ + inherit Calendar.Gregorian.Day; + + void create(int ... arg) + { + if (!sizeof(arg)) + { + int jd = Calendar.Gregorian.Day()->julian_day()-1721424; + y = jd*100/36525+1; + d = jd-(y-1)*36525/100; + } + else + ::create(@arg); + } + +} diff --git a/lib/7.0/modules/Calendar.pmod/Orthodox.pmod b/lib/7.0/modules/Calendar.pmod/Orthodox.pmod new file mode 100644 index 0000000000000000000000000000000000000000..faa7de36e9f5f085cd08301914476fcda1d0969c --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Orthodox.pmod @@ -0,0 +1,25 @@ +// by Mirar + +inherit Calendar.Gregorian : christ; + +class Year +{ + inherit Calendar.Gregorian.Year; + + int leap() // tack, hubbe... :-) + { + switch(y%900) + { + case 0: + case 100: + case 300: + case 400: + case 500: + case 700: + case 800: return 0; + case 200: + case 600: return 1; + default: return !(y%4); + } + } +}; diff --git a/lib/7.0/modules/Calendar.pmod/Stardate.pmod b/lib/7.0/modules/Calendar.pmod/Stardate.pmod new file mode 100644 index 0000000000000000000000000000000000000000..a91e964fca62279d71949e5522cb65a7fa45aa73 --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Stardate.pmod @@ -0,0 +1,106 @@ +//! submodule Stardate +//! time unit: TNGDate + +//! class TNGDate +//! implements ST:TNG stardates +//! can be used as create argument to Day + +class TNGDate +{ + inherit Calendar._TimeUnit; + + // 40759.5 2363-10-05 2584405 + // 47391.2 2370-05-23 2586827 + + // 50893.5 2373-11-23 2588107 + + // 6631.7 ---------- 2422 + // 10134.0 ---------- 3702 + // 1000.0 ---------- 365.2425 + // 0.0 - - 2569519 +#define TNGSTARPERJULIAN (1000.0/365.2425) + +//-- variables ------------------------------------------------------ + + float jd; + float tics; + +//-- standard methods ----------------------------------------------- + + void create(int|float|object ... day) + { + float jd; + if (!sizeof(day)) + day=({Calendar.Gregorian.Second()}); + else if (floatp(day[0])) + { + from_stardate(day[0]); + return; + } + if (!intp(day[0])) + { + object o=day[0]; + + if (o->julian_day || o->julian_day_f) + jd=(float)(o->julian_day_f||o->julian_day)(); + else // dig + if (o->day) // larger + { + o=o->day(0); + if (o->julian_day_f) + jd=o->julian_day_f(); + else if (o->julian_day) + jd=(float)o->julian_day(); + else + ; // error, like + } + else // smaller + { + float z=1.0; + while (sizeof(o->greater())) + { + string name=o->is(); + o=o[o->greater()[0]](); + z*=o["number_of_"+name+"s"](); + if (o->julian_day_f || o->julian_day) + { + jd=(o->julian_day||o->julian_day_f)()/z; + break; + } + } + } + } + else + jd=(float)day[0]; + from_julian_day(jd); + } + + static void from_stardate(float f) + { + tics=f; + jd=f/TNGSTARPERJULIAN+2569518.5; + } + + static void from_julian_day(float f) + { + jd=f; + tics=(f-2569518.5)*TNGSTARPERJULIAN; + } + +//-- nonstandard methods -------------------------------------------- + + float number() + { + return tics; + } + + int julian_day() + { + return (int)jd; + } + + float julian_day_f() + { + return jd; + } +} diff --git a/lib/7.0/modules/Calendar.pmod/Swedish.pmod b/lib/7.0/modules/Calendar.pmod/Swedish.pmod new file mode 100644 index 0000000000000000000000000000000000000000..861bd0a7f8fb3c7690cf34fc7407f1c5452d66c2 --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/Swedish.pmod @@ -0,0 +1,238 @@ +// by Mirar + +inherit Calendar.ISO:ISO; + +void create() +{ + month_names= + ({"januari","februari","mars","april","maj","juni","juli","augusti", + "september","oktober","november","december"}); + + week_day_names= + ({"måndag","tisdag","onsdag","torsdag", + "fredag","lördag","söndag"}); +} + +class Week +{ + inherit ISO::Week; + + string name() + { + return "v"+(string)this->number(); + } +} + +class Year +{ + inherit ISO::Year; + + array(array(string)) _namedays; + mapping(string:int) _nameday_lookup; + + string name() + { + if (this->number()<=0) + return (string)(1-this->number())+" fk"; + return (string)this->number(); + } + + array(array(string)) namedays() + { + if (_namedays) return _namedays; + + array(array(string)) a; + + // insert test for year here + if (!(a=namedays_cache[this->leap()+" "+this->leap_day()])) + { + // insert test for year here + a=namedays_1993; + + if (this->leap()) + { + a=a[..this->leap_day()-1]+ + Array.map(allocate(this->leap()), + lambda(int x) { return ({}); })+ + a[this->leap_day()..]; + } + + namedays_cache[this->leap()+" "+this->leap_day()]=a; + } + + return _namedays=a; + } + + object nameday(string name) + { + if (!_nameday_lookup + && !(_nameday_lookup= + namedays_lookup_cache[this->leap()+" "+this->leap_day()])) + { + mapping m=([]); + int i; + foreach (this->namedays(),array a) + { + foreach (a,string name) m[lower_case(name)]=i; + i++; + } + _nameday_lookup = + namedays_lookup_cache[this->leap()+" "+this->leap_day()] = m; + } + + if (zero_type(_nameday_lookup[lower_case(name)])) return 0; + return this->day(_nameday_lookup[lower_case(name)]); + } +} + +class Day +{ + inherit ISO::Day; + + array(string) names() + { + return this->year()->namedays()[this->year_day()]; + } +} + +// --- namnsdagar, data ------------------------------------------------- + +mapping namedays_cache=([]); +mapping namedays_lookup_cache=([]); + +/** + +Name database from alma-1.0, +http://www.lysator.liu.se/~tab/alma-1.0.tar.gz + +Permission to use from Kent Engström, 1998-01-28 + + **/ + + +array(array(string)) namedays_1993= +({ ({}), ({"Svea","Sverker"}), ({"Alfred","Alfrida"}), + ({"Rut","Ritva"}), ({"Hanna","Hannele"}), ({"Baltsar","Kasper"}), + ({"August","Augusta"}), ({"Erland","Erhard"}), ({"Gunnar","Gunder"}), + ({"Sigurd","Sigmund"}), ({"Hugo","Hagar"}), ({"Frideborg","Fridolf"}), + ({"Knut"}), ({"Felix","Felicia"}), ({"Laura","Liv"}), + ({"Hjalmar","Hervor"}), ({"Anton","Tony"}), ({"Hilda","Hildur"}), + ({"Henrik","Henry"}), ({"Fabian","Sebastian"}), ({"Agnes","Agneta"}), + ({"Vincent","Veine"}), ({"Emilia","Emilie"}), ({"Erika","Eira"}), + ({"Paul","Pål"}), ({"Bodil","Boel"}), ({"Göte","Göta"}), + ({"Karl","Karla"}), ({"Valter","Vilma"}), ({"Gunhild","Gunilla"}), + ({"Ivar","Joar"}), ({"Max","Magda"}), ({"Marja","Mia"}), + ({"Disa","Hjördis"}), ({"Ansgar","Anselm"}), ({"Lisa","Elise"}), + ({"Dorotea","Dora"}), ({"Rikard","Dick"}), ({"Berta","Berthold"}), + ({"Fanny","Betty"}), ({"Egon","Egil"}), ({"Yngve","Ingolf"}), + ({"Evelina","Evy"}), ({"Agne","Agnar"}), ({"Valentin","Tina"}), + ({"Sigfrid","Sigbritt"}), ({"Julia","Jill"}), + ({"Alexandra","Sandra"}), ({"Frida","Fritz"}), ({"Gabriella","Ella"}), + ({"Rasmus","Ruben"}), ({"Hilding","Hulda"}), ({"Marina","Marlene"}), + ({"Torsten","Torun"}), ({"Mattias","Mats"}), ({"Sigvard","Sivert"}), + ({"Torgny","Torkel"}), ({"Lage","Laila"}), ({"Maria","Maja"}), + ({"Albin","Inez"}), ({"Ernst","Erna"}), ({"Gunborg","Gunvor"}), + ({"Adrian","Ada"}), ({"Tora","Tor"}), ({"Ebba","Ebbe"}), + ({"Isidor","Doris"}), ({"Siv","Saga"}), ({"Torbjörn","Ambjörn"}), + ({"Edla","Ethel"}), ({"Edvin","Elon"}), ({"Viktoria","Viktor"}), + ({"Greger","Iris"}), ({"Matilda","Maud"}), ({"Kristofer","Christel"}), + ({"Herbert","Gilbert"}), ({"Gertrud","Görel"}), ({"Edvard","Eddie"}), + ({"Josef","Josefina"}), ({"Joakim","Kim"}), ({"Bengt","Benny"}), + ({"Viking","Vilgot"}), ({"Gerda","Gert"}), ({"Gabriel","Rafael"}), + ({"Mary","Marion"}), ({"Emanuel","Manne"}), ({"Ralf","Raymond"}), + ({"Elma","Elmer"}), ({"Jonas","Jens"}), ({"Holger","Reidar"}), + ({"Ester","Estrid"}), ({"Harald","Halvar"}), ({"Gunnel","Gun"}), + ({"Ferdinand","Florence"}), ({"Irene","Irja"}), ({"Nanna","Nanny"}), + ({"Vilhelm","Willy"}), ({"Irma","Mimmi"}), ({"Vanja","Ronja"}), + ({"Otto","Ottilia"}), ({"Ingvar","Ingvor"}), ({"Ulf","Ylva"}), + ({"Julius","Gillis"}), ({"Artur","Douglas"}), ({"Tiburtius","Tim"}), + ({"Olivia","Oliver"}), ({"Patrik","Patricia"}), ({"Elias","Elis"}), + ({"Valdemar","Volmar"}), ({"Olaus","Ola"}), ({"Amalia","Amelie"}), + ({"Annika","Anneli"}), ({"Allan","Alida"}), ({"Georg","Göran"}), + ({"Vega","Viveka"}), ({"Markus","Mark"}), ({"Teresia","Terese"}), + ({"Engelbrekt","Enok"}), ({"Ture Tyko"}), ({"Kennet","Kent"}), + ({"Mariana","Marianne"}), ({"Valborg","Maj"}), ({"Filip","Filippa"}), + ({"John","Jack"}), ({"Monika","Mona"}), ({"Vivianne","Vivan"}), + ({"Marit","Rita"}), ({"Lilian","Lilly"}), ({"Åke","Ove"}), + ({"Jonatan","Gideon"}), ({"Elvira","Elvy"}), ({"Märta","Märit"}), + ({"Charlotta","Lotta"}), ({"Linnea","Nina"}), ({"Lillemor","Lill"}), + ({"Sofia","Sonja"}), ({"Hilma","Hilmer"}), ({"Nore","Nora"}), + ({"Erik","Jerker"}), ({"Majken","Majvor"}), ({"Karolina","Lina"}), + ({"Konstantin","Conny"}), ({"Henning","Hemming"}), + ({"Desiree","Renee"}), ({"Ivan","Yvonne"}), ({"Urban","Ursula"}), + ({"Vilhelmina","Helmy"}), ({"Blenda","Beda"}), + ({"Ingeborg","Borghild"}), ({"Jean","Jeanette"}), + ({"Fritiof","Frej"}), ({"Isabella","Isa"}), ({"Rune","Runa"}), + ({"Rutger","Roger"}), ({"Ingemar","Gudmar"}), + ({"Solveig","Solbritt"}), ({"Bo","Boris"}), ({"Gustav","Gösta"}), + ({"Robert","Robin"}), ({"Eivor","Elaine"}), ({"Petra","Petronella"}), + ({"Kerstin","Karsten"}), ({"Bertil","Berit"}), ({"Eskil","Esbjörn"}), + ({"Aina","Eila"}), ({"Håkan","Heidi"}), ({"Margit","Mait"}), + ({"Axel","Axelina"}), ({"Torborg","Torvald"}), ({"Björn","Bjarne"}), + ({"Germund","Jerry"}), ({"Linda","Linn"}), ({"Alf","Alva"}), + ({"Paulina","Paula"}), ({"Adolf","Adela"}), ({"Johan","Jan"}), + ({"David","Salomon"}), ({"Gunni","Jim"}), ({"Selma","Herta"}), + ({"Leo","Leopold"}), ({"Petrus","Peter"}), ({"Elof","Leif"}), + ({"Aron","Mirjam"}), ({"Rosa","Rosita"}), ({"Aurora","Adina"}), + ({"Ulrika","Ulla"}), ({"Melker","Agaton"}), ({"Ronald","Ronny"}), + ({"Klas","Kaj"}), ({"Kjell","Tjelvar"}), ({"Jörgen","Örjan"}), + ({"Anund","Gunda"}), ({"Eleonora","Ellinor"}), ({"Herman","Hermine"}), + ({"Joel","Judit"}), ({"Folke","Odd"}), ({"Ragnhild","Ragnvald"}), + ({"Reinhold","Reine"}), ({"Alexis","Alice"}), ({"Fredrik","Fred"}), + ({"Sara","Sally"}), ({"Margareta","Greta"}), ({"Johanna","Jane"}), + ({"Magdalena","Madeleine"}), ({"Emma","Emmy"}), + ({"Kristina","Stina"}), ({"Jakob","James"}), ({"Jesper","Jessika"}), + ({"Marta","Moa"}), ({"Botvid","Seved"}), ({"Olof","Olle"}), + ({"Algot","Margot"}), ({"Elin","Elna"}), ({"Per","Pernilla"}), + ({"Karin","Kajsa"}), ({"Tage","Tanja"}), ({"Arne","Arnold"}), + ({"Ulrik","Alrik"}), ({"Sixten","Sölve"}), ({"Dennis","Donald"}), + ({"Silvia","Sylvia"}), ({"Roland","Roine"}), ({"Lars","Lorentz"}), + ({"Susanna","Sanna"}), ({"Klara","Clary"}), ({"Hillevi","Gullvi"}), + ({"William","Bill"}), ({"Stella","Stellan"}), ({"Brynolf","Sigyn"}), + ({"Verner","Veronika"}), ({"Helena","Lena"}), ({"Magnus","Måns"}), + ({"Bernhard","Bernt"}), ({"Jon","Jonna"}), ({"Henrietta","Henny"}), + ({"Signe","Signhild"}), ({"Bartolomeus","Bert"}), + ({"Lovisa","Louise"}), ({"Östen","Ejvind"}), ({"Rolf","Rudolf"}), + ({"Gurli","Gull"}), ({"Hans","Hampus"}), ({"Albert","Albertina"}), + ({"Arvid","Vidar"}), ({"Samuel","Sam"}), ({"Justus","Justina"}), + ({"Alfhild","Alfons"}), ({"Gisela","Glenn"}), ({"Harry","Harriet"}), + ({"Sakarias","Esaias"}), ({"Regina","Roy"}), ({"Alma","Ally"}), + ({"Anita","Anja"}), ({"Tord","Tove"}), ({"Dagny","Daniela"}), + ({"Tyra","Åsa"}), ({"Sture","Styrbjörn"}), ({"Ida","Ellida"}), + ({"Sigrid","Siri"}), ({"Dag","Daga"}), ({"Hildegard","Magnhild"}), + ({"Alvar","Orvar"}), ({"Fredrika","Carita"}), ({"Agda","Agata"}), + ({"Ellen","Elly"}), ({"Maurits","Morgan"}), ({"Tekla","Tea"}), + ({"Gerhard","Gert"}), ({"Kåre","Tryggve"}), ({"Einar","Enar"}), + ({"Dagmar","Rigmor"}), ({"Lennart","Leonard"}), + ({"Mikael","Mikaela"}), ({"Helge","Helny"}), ({"Ragnar","Ragna"}), + ({"Ludvig","Louis"}), ({"Evald","Osvald"}), ({"Frans","Frank"}), + ({"Bror","Bruno"}), ({"Jenny","Jennifer"}), ({"Birgitta","Britta"}), + ({"Nils","Nelly"}), ({"Ingrid","Inger"}), ({"Helmer","Hadar"}), + ({"Erling","Jarl"}), ({"Valfrid","Ernfrid"}), ({"Birgit","Britt"}), + ({"Manfred","Helfrid"}), ({"Hedvig","Hedda"}), ({"Fingal","Finn"}), + ({"Antonia","Annette"}), ({"Lukas","Matteus"}), ({"Tore","Torleif"}), + ({"Sibylla","Camilla"}), ({"Birger","Börje"}), ({"Marika","Marita"}), + ({"Sören","Severin"}), ({"Evert","Eilert"}), ({"Inga","Ingvald"}), + ({"Amanda","My"}), ({"Sabina","Ina"}), ({"Simon","Simone"}), + ({"Viola","Vivi"}), ({"Elsa","Elsie"}), ({"Edit","Edgar"}), + ({"Andre","Andrea"}), ({"Tobias","Toini"}), ({"Hubert","Diana"}), + ({"Uno","Unn"}), ({"Eugen","Eugenia"}), ({"Gustav Adolf"}), + ({"Ingegerd","Ingela"}), ({"Vendela","Vanda"}), ({"Teodor","Ted"}), + ({"Martin","Martina"}), ({"Mårten"}), ({"Konrad","Kurt"}), + ({"Kristian","Krister"}), ({"Emil","Mildred"}), ({"Katja","Nadja"}), + ({"Edmund","Gudmund"}), ({"Naemi","Nancy"}), ({"Pierre","Percy"}), + ({"Elisabet","Lisbeth"}), ({"Pontus","Pia"}), ({"Helga","Olga"}), + ({"Cecilia","Cornelia"}), ({"Klemens","Clarence"}), + ({"Gudrun","Runar"}), ({"Katarina","Carina"}), ({"Linus","Love"}), + ({"Astrid","Asta"}), ({"Malte","Malkolm"}), ({"Sune","Synnöve"}), + ({"Anders","Andreas"}), ({"Oskar","Ossian"}), ({"Beata","Beatrice"}), + ({"Lydia","Carola"}), ({"Barbro","Barbara"}), ({"Sven","Svante"}), + ({"Nikolaus","Niklas"}), ({"Angelika","Angela"}), + ({"Virginia","Vera"}), ({"Anna","Annie"}), ({"Malin","Malena"}), + ({"Daniel","Dan"}), ({"Alexander","Alex"}), ({"Lucia"}), + ({"Sten","Stig"}), ({"Gottfrid","Gotthard"}), ({"Assar","Astor"}), + ({"Inge","Ingemund"}), ({"Abraham","Efraim"}), ({"Isak","Rebecka"}), + ({"Israel","Moses"}), ({"Tomas","Tom"}), ({"Natanael","Natalia"}), + ({"Adam"}), ({"Eva"}), ({}), ({"Stefan","Staffan"}), + ({"Johannes","Hannes"}), ({"Abel","Set"}), ({"Gunlög","Åslög"}), + ({"Sylvester"}), }); diff --git a/lib/7.0/modules/Calendar.pmod/module.pmod b/lib/7.0/modules/Calendar.pmod/module.pmod new file mode 100644 index 0000000000000000000000000000000000000000..302ac793ecb0d90c75c69a52141294345dfc2cc0 --- /dev/null +++ b/lib/7.0/modules/Calendar.pmod/module.pmod @@ -0,0 +1,167 @@ + +//! module Calendar +//! +//! This module implements calendar calculations, and base classes +//! for time units. +//! +//! class time_unit +//! +//! method array(string) lesser() +//! Gives a list of methods to get lesser (shorter) time units. +//! ie, for a month, this gives back <tt>({"day"})</tt> +//! and the method <tt>day(mixed n)</tt> gives back that +//! day object. The method <tt>days()</tt> gives back a +//! list of possible argument values to the method <tt>day</tt>. +//! Concurrently, <tt>Array.map(o->days(),o->day)</tt> gives +//! a list of day objects in the object <tt>o</tt>. +//! +//! +//! Ie:<pre> +//! array(string) lesser() - gives back a list of possible xxx's. +//! object xxxs() - gives back a list of possible n's. +//! object xxx(mixed n) - gives back xxx n +//! object xxx(object(Xxx) o) - gives back the corresponing xxx +//! </pre> +//! +//! The list of n's (as returned from xxxs) are always in order. +//! +//! There are two n's with special meaning, 0 and -1. +//! 0 always gives the first xxx, equal to +//! my_obj->xxx(my_obj->xxxs()[0]), and -1 gives the last, +//! equal to my_obj->xxx(my_obj->xxxs()[-1]). +//! +//! To get all xxxs in the object, do something like +//! <tt>Array.map(my_obj->xxxs(),my_obj->xxx)</tt>. +//! +//! xxx(object) may return zero, if there was no correspondning xxx. +//! +//! method array(string) greater() +//! Gives a list of methods to get greater (longer) time units +//! from this object. For a month, this gives back <tt>({"year"})</tt>, +//! thus the method <tt>month->year()</tt> gives the year object. +//! +//! method object next() +//! method object prev() +//! method object `+(int n) +//! method object `-(int n) +//! method object `-(object x) +//! next and prev gives the logical next and previous object. +//! The <tt>+</tt> operator gives that logical relative object, +//! ie <tt>my_day+14</tt> gives 14 days ahead. +//! <tt>-</tt> works the same way, but can also take an object +//! of the same type and give the difference as an integer. + +#define error(X) throw(({(X),backtrace()})) + +class _TimeUnit +{ + object this=this_object(); + + array(string) greater() { return ({}); } + array(string) lesser() { return ({}); } + + int `<(object x) { error("'< undefined\n"); } + int `>(object x) { error("'> undefined\n"); } + int `==(object x) { error("'== undefined\n"); } + + object `+(int n) { error("`+ undefined\n"); } + object|int `-(int n) { error("`- undefined\n"); } + + object next() { return this+1; } + object prev() { return this+(-1); } +} + + + + + +string print_month(void|object month,void|mapping options) +{ + object w; + object today; + string res=""; + + if (!month) // resolv thing here is to avoid compile-time resolve + month=master()->resolv("Calendar")["Gregorian"]["Month"](); + + options=(["mark_today":1, + "week_space":3, + "weeks":1, + "days":1, + "title":1, + "notes":([])]) | (options || ([])); + options=(["date_space":(options->mark_today?3:2)])|options; + + + today=function_object(object_program(month))->Day(); + + w=month->day(1)->week(); + + res=""; + if (options->weeks) res+=" "+" "*options->week_space; + if (options->title) + res+=sprintf("%|*s\n", + (1+options->date_space)*sizeof(w->days())-1, + intp(options->title) + ?(String.capitalize(month->name()+" ") + +month->year()->name()) + :options->title); + + if (options->days) + { + if (options->weeks) res+=" "+" "*options->week_space; + foreach (Array.map(w->days(),w->day)->week_day_name(),string n) + res+=sprintf("%*s ",options->date_space,n[0..options->date_space-1]); + res+="\n"; + } + + string daynotes=""; + + if (sizeof(Array.filter( + Array.map(month->days(),month->day), + lambda(object d) { return !!options->notes[d]; }))) + daynotes="\n%-|"+options->date_space+"s"; + + do + { + array a; + array b; + object d; + string format=""; + + a=Array.map(Array.map(w->days(),w->day), + lambda(object d) + { if (d->month()!=month) return 0; else return d; }); + + if (options->weeks) + res+=sprintf("%*s ",options->week_space,w->name()); + foreach (a,d) + if (d) + if (!options->mark_today || d!=today) + res+=sprintf("%* |d ", + options->date_space, + d->month_day()); + else + res+=sprintf(">%* |d<", + options->date_space-1, + d->month_day()); + else res+=" "+" "*options->date_space; + + if (options->notes[w]) + res+=sprintf("%-=*s", + options->week_note_column_width, + options->notes[w]); + + res+="\n"; + + if (daynotes) + { + + } + + w++; + } + while (w->day(0)->month()==month); + + return res; +} diff --git a/lib/7.0/modules/Stdio.pmod/module.pmod b/lib/7.0/modules/Stdio.pmod/module.pmod new file mode 100644 index 0000000000000000000000000000000000000000..812b20f4972791b22ec34496d5f5862d69e030f6 --- /dev/null +++ b/lib/7.0/modules/Stdio.pmod/module.pmod @@ -0,0 +1,15 @@ +#pike 7.1 + +class File +{ + inherit Stdio.File: F; + array(int) stat() { return (array) F::stat(); } +} + +class FILE +{ + inherit Stdio.FILE : F; + + array(int) stat() { return (array) F::stat(); } +} + diff --git a/src/builtin_functions.c b/src/builtin_functions.c index bf01d916e552435c9023416772d8459e8003dc35..f3389e1601b98bec378f39683d4d9097c42ab73d 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.311 2000/09/07 11:35:17 grubba Exp $"); +RCSID("$Id: builtin_functions.c,v 1.312 2000/09/26 00:17:44 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -2425,23 +2425,35 @@ PMOD_EXPORT void f_replace(INT32 args) PMOD_EXPORT void f_compile(INT32 args) { struct program *p; + struct object *o; + int major=-1; + int minor=-1; - if(args < 1) - SIMPLE_TOO_FEW_ARGS_ERROR("compile", 1); - if(Pike_sp[-args].type != T_STRING) - SIMPLE_BAD_ARG_ERROR("compile", 1, "string"); + check_all_args("compile",args, + BIT_STRING, + BIT_VOID | BIT_INT | BIT_OBJECT, + BIT_VOID | BIT_INT, + BIT_VOID | BIT_INT, + 0); - if ((args > 1) && (Pike_sp[1-args].type != T_OBJECT) && - (Pike_sp[1-args].type != T_INT)) { - SIMPLE_BAD_ARG_ERROR("compile", 2, "object"); - } + o=0; + if (args > 1) + if(Pike_sp[1-args].type == T_OBJECT) + o=Pike_sp[1-args].u.object; - if ((args > 1) && (Pike_sp[1-args].type == T_OBJECT)) { - p = compile(Pike_sp[-args].u.string, Pike_sp[1-args].u.object); - } else { - p = compile(Pike_sp[-args].u.string, NULL); + if(args == 3) + SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); + + if(args > 3) + { + major=sp[2-args].u.integer; + minor=sp[3-args].u.integer; } + + + p = compile(Pike_sp[-args].u.string, o, major, minor); + #ifdef PIKE_DEBUG if(!(p->flags & PROGRAM_FINISHED)) fatal("Got unfinished program from internal compile().\n"); @@ -5777,7 +5789,7 @@ void init_builtin_efuns(void) ADD_EFUN("combine_path",f_combine_path,tFuncV(tNone,tStr,tStr),0); /* function(string,object|void,mixed...:program) */ - ADD_EFUN("compile", f_compile, tFuncV(tStr tOr(tObj, tVoid),tMix,tPrg), + ADD_EFUN("compile", f_compile, tFuncV(tStr tOr(tObj, tVoid) tOr(tInt, tVoid) tOr(tInt, tVoid) ,tMix,tPrg), OPT_EXTERNAL_DEPEND); /* function(1=mixed:1) */ diff --git a/src/compilation.h b/src/compilation.h index 3f26f59e0057207b2d485e1cfd8fcf3aa433bdb3..f3498238b7ca66444398997f22524d4e434e4536 100644 --- a/src/compilation.h +++ b/src/compilation.h @@ -1,5 +1,5 @@ /* - * $Id: compilation.h,v 1.20 2000/08/24 04:04:40 hubbe Exp $ + * $Id: compilation.h,v 1.21 2000/09/26 00:17:45 hubbe Exp $ * * Compilator state push / pop operator construction file * @@ -141,6 +141,8 @@ STACKMEMBER(unsigned char *,type_stackp,type_stack) STACKMEMBER(unsigned char **,pike_type_mark_stackp,pike_type_mark_stack) ZMEMBER(INT32,parent_identifier,0) + IMEMBER(int, compat_major, PIKE_MAJOR_VERSION) + IMEMBER(int, compat_minor, PIKE_MINOR_VERSION) SEND #undef PCODE diff --git a/src/cpp.c b/src/cpp.c index cd0a410d2569feff0833d9f3cf91a6a5c560d96a..605667de961ca4e7f671b9b0666ba684f86286b5 100644 --- a/src/cpp.c +++ b/src/cpp.c @@ -5,7 +5,7 @@ \*/ /* - * $Id: cpp.c,v 1.75 2000/09/04 22:33:19 grubba Exp $ + * $Id: cpp.c,v 1.76 2000/09/26 00:17:45 hubbe Exp $ */ #include "global.h" #include "stralloc.h" @@ -101,6 +101,9 @@ struct cpp struct pike_string *current_file; struct string_builder buf; struct object *handler; + struct object *compat_handler; + int compat_major; + int compat_minor; }; struct define *defined_macro =0; @@ -130,6 +133,36 @@ void cpp_error(struct cpp *this,char *err) } } +void cpp_change_compat(struct cpp *this, int major, int minor) +{ + if(this->compat_major == major && + this->compat_minor == minor) return; + + if(this->compat_handler) + { + free_object(this->compat_handler); + this->compat_handler=0; + } + if((major == PIKE_MAJOR_VERSION && + minor == PIKE_MINOR_VERSION) || major < 0) + { + this->compat_major=PIKE_MAJOR_VERSION; + this->compat_minor=PIKE_MINOR_VERSION; + return; /* Our work here is done */ + } + + push_int(major); + push_int(minor); + SAFE_APPLY_MASTER("get_compilation_handler",2); + if(sp[-1].type == T_OBJECT) + { + this->compat_handler=sp[-1].u.object; + sp--; + } + this->compat_major=major; + this->compat_minor=minor; +} + /* devours one reference to 'name'! */ static struct define *alloc_empty_define(struct pike_string *name, ptrdiff_t parts) @@ -1018,8 +1051,21 @@ static void check_constant(struct cpp *this, push_svalue(sv); res=1; }else if(get_master()) { + int i; ref_push_string(this->current_file); - SAFE_APPLY_MASTER("resolv",2); + + if(this->handler && (i=find_identifier("resolv",this->handler->prog))!=-1) + { + safe_apply_low(this->handler, i, 2); + } + if(this->compat_handler && (i=find_identifier("resolv",this->compat_handler->prog))!=-1) + { + safe_apply_low(this->compat_handler, i, 2); + } + else + { + SAFE_APPLY_MASTER("resolv", 2); + } res=(throw_value.type!=T_STRING) && (!(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED)); @@ -1030,6 +1076,8 @@ static void check_constant(struct cpp *this, /* Handle contant(.foo) */ push_text("."); ref_push_string(this->current_file); + + /* FIXME: use this->compat_handler */ if (this->handler && this->handler->prog) { ref_push_object(this->handler); SAFE_APPLY_MASTER("handle_import", 3); @@ -1104,8 +1152,10 @@ static int do_safe_index_call(struct pike_string *s) return res; } + /* string cpp(string data, string|void current_file, - * int|string|void charset, object|void handler) + * int|string|void charset, object|void handler, + * void|int compat_major, void|int compat_minor); */ void f_cpp(INT32 args) { @@ -1115,6 +1165,7 @@ void f_cpp(INT32 args) struct cpp this; int auto_convert = 0; struct pike_string *charset = NULL; + #ifdef PIKE_DEBUG ONERROR tmp; #endif /* PIKE_DEBUG */ @@ -1130,9 +1181,17 @@ void f_cpp(INT32 args) add_ref(data); this.handler = NULL; + this.compat_handler = NULL; if(args>1) { + if(args > 5) + { + if(sp[4-args].type != T_INT) + error("Bad argument 5 to cpp()\n"); + if(sp[5-args].type != T_INT) + error("Bad argument 6 to cpp()\n"); + } if(sp[1-args].type != T_STRING) { free_string(data); error("Bad argument 2 to cpp()\n"); @@ -1189,6 +1248,9 @@ void f_cpp(INT32 args) this.current_line=1; this.compile_errors=0; this.defines=0; + this.compat_major=PIKE_MAJOR_VERSION; + this.compat_minor=PIKE_MINOR_VERSION; + do_magic_define(&this,"__LINE__",insert_current_line); do_magic_define(&this,"__FILE__",insert_current_file_as_string); do_magic_define(&this,"__DATE__",insert_current_date_as_string); @@ -1238,6 +1300,12 @@ void f_cpp(INT32 args) SET_ONERROR(tmp, fatal_on_error, "Preprocessor exited with longjump!\n"); #endif /* PIKE_DEBUG */ + if(args > 5) + { + cpp_change_compat(&this, sp[4-args].u.integer, sp[5-args].u.integer); + } + + low_cpp(&this, data->str, data->len, data->size_shift, 0, auto_convert, charset); @@ -1248,6 +1316,12 @@ void f_cpp(INT32 args) if(this.defines) free_hashtable(this.defines, free_one_define); + if(this.compat_handler) + { + free_object(this.compat_handler); + this.compat_handler=0; + } + free_string(this.current_file); free_string(data); @@ -1274,8 +1348,12 @@ void init_cpp() /* function(string, string|void, int|string|void, object|void:string) */ - ADD_EFUN("cpp", f_cpp, tFunc(tStr tOr(tStr,tVoid) tOr(tInt,tOr(tStr,tVoid)) - tOr(tObj,tVoid), tStr), OPT_EXTERNAL_DEPEND); + ADD_EFUN("cpp", f_cpp, tFunc(tStr tOr(tStr,tVoid) + tOr(tInt,tOr(tStr,tVoid)) + tOr(tObj,tVoid) + tOr(tInt,tVoid) + tOr(tInt,tVoid) + , tStr), OPT_EXTERNAL_DEPEND); } diff --git a/src/language.yacc b/src/language.yacc index bf4ab7f46801d43d7a7fbd1d5f9279848b6f16db..26481381a9ae41ce729b5ce262ae6434d4d7c042 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -110,7 +110,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.212 2000/09/20 13:22:51 grubba Exp $"); +RCSID("$Id: language.yacc,v 1.213 2000/09/26 00:17:45 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -2467,7 +2467,7 @@ m_expr_list2: assoc_pair | m_expr_list2 ',' error ; -assoc_pair: expr0 expected_colon expr1 { $$=mknode(F_ARG_LIST,$1,$3); } +assoc_pair: expr0 expected_colon expr0 { $$=mknode(F_ARG_LIST,$1,$3); } | expr0 expected_colon error { free_node($1); $$=0; } ; @@ -2866,16 +2866,13 @@ low_idents: TOK_IDENTIFIER } | TOK_PREDEF TOK_COLON_COLON TOK_IDENTIFIER { - struct svalue tmp; node *tmp2; - tmp.type=T_MAPPING; -#ifdef __CHECKER__ - tmp.subtype=0; -#endif /* __CHECKER__ */ + extern dynamic_buffer used_modules; + if(Pike_compiler->last_identifier) free_string(Pike_compiler->last_identifier); copy_shared_string(Pike_compiler->last_identifier, $3->u.sval.u.string); - tmp.u.mapping=get_builtin_constants(); - tmp2=mkconstantsvaluenode(&tmp); + + tmp2=mkconstantsvaluenode((struct svalue *) used_modules.s.str ); $$=index_node(tmp2, "predef", $3->u.sval.u.string); if(!$$->name) add_ref( $$->name=$3->u.sval.u.string ); @@ -3016,11 +3013,20 @@ typeof: TOK_TYPEOF '(' expr0 ')' node *tmp; /* FIXME: Why build the node at all? */ - + /* Because the optimizer cannot optimize the root node of the + * tree properly -Hubbe + */ tmp=mknode(F_COMMA_EXPR, $3, 0); s=(tmp && CAR(tmp) && CAR(tmp)->type ? CAR(tmp)->type : mixed_type_string); - $$ = mktypenode(s); + if(TEST_COMPAT(7,0)) + { + s=describe_type(s); + $$ = mkstrnode(s); + free_string(s); + }else{ + $$ = mktypenode(s); + } free_node(tmp); } | TOK_TYPEOF '(' error ')' { $$=0; yyerrok; } @@ -3311,7 +3317,8 @@ int low_add_local_name(struct compiler_frame *frame, struct pike_string *type, node *def) { - if (str->len) { + + if (str->len && !TEST_COMPAT(7,0)) { int tmp=islocal(str); if(tmp >= frame->last_block_level) { diff --git a/src/lexer.h b/src/lexer.h index dfd4ea23d8e156a3177df2ccb57096981a680595..bcab17c2c5337377706f07a057a9003e38dcb4fa 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -1,5 +1,5 @@ /* - * $Id: lexer.h,v 1.20 2000/08/07 12:13:37 grubba Exp $ + * $Id: lexer.h,v 1.21 2000/09/26 00:17:46 hubbe Exp $ * * Lexical analyzer template. * Based on lex.c 1.62 @@ -370,17 +370,38 @@ static int low_yylex(YYSTYPE *yylval) } break; } + if(ISWORD("pike")) + { + int minor; + int major; + SKIPSPACE(); + READBUF(C!='\n' && C!='.'); + major=lex_atoi(buf); + if(!GOBBLE('.')) + { + yyerror("Missing '.' in #pike directive."); + minor=0; + }else{ + READBUF(C!='\n' && C!='.'); + minor=lex_atoi(buf); + if(GOBBLE('.')) + yyerror("Build numbers not supported in #pike directive."); + + READBUF(C!='\n'); + change_compiler_compatibility(major, minor); + } + break; + } badhash: /* FIXME: This doesn't look all that safe... * buf isn't NUL-terminated, and it won't work on wide strings. * /grubba 1999-02-20 */ - if (strlen(buf) < 1024) { - my_yyerror("Unknown preprocessor directive #%s.",buf); - } else { - my_yyerror("Unknown preprocessor directive."); + if (strlen(buf) >= 256) { + buf[256]=0; } + my_yyerror("Unknown preprocessor directive #%s.",buf); SKIPUPTO('\n'); continue; } diff --git a/src/preprocessor.h b/src/preprocessor.h index 51a40976996f1f20df060dc7ed0454be1d0da3ee..5b566e1bc1fa1f0baaf2eff083feefc75d8e2a71 100644 --- a/src/preprocessor.h +++ b/src/preprocessor.h @@ -1,5 +1,5 @@ /* - * $Id: preprocessor.h,v 1.33 2000/08/15 19:37:10 lange Exp $ + * $Id: preprocessor.h,v 1.34 2000/09/26 00:17:46 hubbe Exp $ * * Preprocessor template. * Based on cpp.c 1.45 @@ -1303,8 +1303,13 @@ static ptrdiff_t lower_cpp(struct cpp *this, if(OUTP()) { struct pike_string *new_file; - - SAFE_APPLY_MASTER("handle_include",3); + + if(this->compat_handler) + { + safe_apply(this->compat_handler,"handle_include",3); + }else{ + SAFE_APPLY_MASTER("handle_include",3); + } if(Pike_sp[-1].type != PIKE_T_STRING) { @@ -1319,7 +1324,12 @@ static ptrdiff_t lower_cpp(struct cpp *this, assign_svalue_no_free(Pike_sp,Pike_sp-1); Pike_sp++; - SAFE_APPLY_MASTER("read_include",1); + if(this->compat_handler) + { + safe_apply(this->compat_handler,"read_include",1); + }else{ + SAFE_APPLY_MASTER("read_include",1); + } if(Pike_sp[-1].type != PIKE_T_STRING) { @@ -1991,8 +2001,35 @@ static ptrdiff_t lower_cpp(struct cpp *this, } if(WGOBBLE2(pike_)) { - /* FIXME */ - FIND_EOL(); + + if(OUTP()) + { + int major, minor; + ptrdiff_t tmp; + PCHARP ptr; + + STRCAT("#pike", 5); + tmp= this->buf.s->len; + pos += lower_cpp(this, data+pos, len-pos, + CPP_END_AT_NEWLINE | CPP_DO_IF, + auto_convert, charset); + + ptr=MKPCHARP(this->buf.s->str, this->buf.s->size_shift); + INC_PCHARP(ptr, tmp); + + major=STRTOL_PCHARP(ptr, &ptr, 10); + if(INDEX_PCHARP(ptr,0) == '.') + { + INC_PCHARP(ptr, 1); + minor=STRTOL_PCHARP(ptr, &ptr, 10); + cpp_change_compat(this, major, minor); + }else{ + cpp_error(this, "Missing '.' in #pike."); + this->compat_minor=0; + } + } + else + FIND_EOL(); break; } } diff --git a/src/program.c b/src/program.c index 6977f09c86206854b0ae2860d8fe7458988ea2e5..ef94f2c0b456f1182ab4c2bf5d9f0fafeb4fcb4c 100644 --- a/src/program.c +++ b/src/program.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: program.c,v 1.272 2000/09/14 19:58:44 mast Exp $"); +RCSID("$Id: program.c,v 1.273 2000/09/26 00:17:47 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -32,6 +32,7 @@ RCSID("$Id: program.c,v 1.272 2000/09/14 19:58:44 mast Exp $"); #include "security.h" #include "pike_types.h" #include "opcodes.h" +#include "version.h" #include <errno.h> #include <fcntl.h> @@ -158,6 +159,7 @@ struct program *first_program = 0; static int current_program_id=0x10000; struct object *error_handler=0; +struct object *compat_handler=0; struct program *gc_internal_program = 0; static struct program *gc_mark_program_pos = 0; @@ -408,7 +410,13 @@ struct node_s *find_module_identifier(struct pike_string *ident, if(error_handler && (i=find_identifier("resolv",error_handler->prog))!=-1) { safe_apply_low(error_handler, i, 2); - }else{ + } + if(compat_handler && (i=find_identifier("resolv",compat_handler->prog))!=-1) + { + safe_apply_low(compat_handler, i, 2); + } + else + { SAFE_APPLY_MASTER("resolv", 2); } @@ -3281,7 +3289,8 @@ void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))) } struct program *compile(struct pike_string *prog, - struct object *handler) + struct object *handler,/* error handler */ + int major, int minor) { #ifdef PIKE_DEBUG ONERROR tmp; @@ -3291,6 +3300,7 @@ struct program *compile(struct pike_string *prog, int save_depth=compilation_depth; int saved_threads_disabled; struct object *saved_handler = error_handler; + struct object *saved_compat_handler = compat_handler; dynamic_buffer used_modules_save = used_modules; INT32 num_used_modules_save = Pike_compiler->num_used_modules; extern void yyparse(void); @@ -3301,10 +3311,10 @@ struct program *compile(struct pike_string *prog, (long)th_self(),compilation_depth)); error_handler = handler; + compat_handler=0; if(error_handler) { - /* FIXME: support '#Pike 0.6' here */ apply(error_handler,"get_default_module",0); if(IS_ZERO(Pike_sp-1)) { @@ -3369,9 +3379,14 @@ struct program *compile(struct pike_string *prog, /* start_line_numbering(); */ + Pike_compiler->compat_major=PIKE_MAJOR_VERSION; + Pike_compiler->compat_minor=PIKE_MINOR_VERSION; Pike_compiler->compiler_pass=1; lex.pos=prog->str; + if(major>=0) + change_compiler_compatibility(major, minor); + CDFPRINTF((stderr, "compile(): First pass\n")); yyparse(); /* Parse da program */ @@ -3397,6 +3412,9 @@ struct program *compile(struct pike_string *prog, CDFPRINTF((stderr, "compile(): Second pass\n")); + if(major>=0) + change_compiler_compatibility(major, minor); + yyparse(); /* Parse da program again */ p=end_program(); @@ -3436,6 +3454,7 @@ struct program *compile(struct pike_string *prog, used_modules = used_modules_save; Pike_compiler->num_used_modules = num_used_modules_save ; error_handler = saved_handler; + compat_handler = saved_compat_handler; #ifdef PIKE_DEBUG if (resolve_cache) fatal("resolve_cache not freed at end of compilation.\n"); #endif @@ -4400,3 +4419,64 @@ PMOD_EXPORT void *parent_storage(int depth) return loc.o->storage + loc.inherit->storage_offset; } + + + +PMOD_EXPORT void change_compiler_compatibility(int major, int minor) +{ + if(major == Pike_compiler->compat_major && + minor == Pike_compiler->compat_minor) + return; + + if(major == PIKE_MAJOR_VERSION && minor == PIKE_MINOR_VERSION) + { + push_int(0); /* optimization */ + }else{ + push_int(major); + push_int(minor); + SAFE_APPLY_MASTER("get_compilation_handler",2); + } + + if(compat_handler) + { + free_object(compat_handler); + compat_handler=0; + } + + if(sp[-1].type == T_OBJECT) + { + compat_handler=sp[-1].u.object; + sp--; + + apply(compat_handler,"get_default_module",0); + + if(sp[-1].type == T_INT) + { + pop_stack(); + ref_push_mapping(get_builtin_constants()); + } + }else{ + pop_stack(); + ref_push_mapping(get_builtin_constants()); + } + + + if(Pike_compiler->num_used_modules) + { + free_svalue( (struct svalue *)used_modules.s.str ); + ((struct svalue *)used_modules.s.str)[0]=sp[-1]; + sp--; + if(Pike_compiler->module_index_cache) + { + free_mapping(Pike_compiler->module_index_cache); + Pike_compiler->module_index_cache=0; + } + }else{ + use_module(sp-1); + pop_stack(); + } + + Pike_compiler->compat_major=major; + Pike_compiler->compat_minor=minor; + +} diff --git a/src/program.h b/src/program.h index eed7cb4676cdc0fdc93701805ad98a19800a19fc..f95139308ab025142aee3b546d421a035e0b828b 100644 --- a/src/program.h +++ b/src/program.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: program.h,v 1.110 2000/08/31 12:28:06 grubba Exp $ + * $Id: program.h,v 1.111 2000/09/26 00:17:47 hubbe Exp $ */ #ifndef PROGRAM_H #define PROGRAM_H @@ -461,7 +461,9 @@ void store_linenumber(INT32 current_line, struct pike_string *current_file); char *get_line(unsigned char *pc,struct program *prog,INT32 *linep); void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))); struct program *compile(struct pike_string *prog, - struct object *handler); + struct object *handler, + int major, + int minor); int pike_add_function2(char *name, void (*cfun)(INT32), char *type, unsigned INT8 flags, unsigned INT16 opt_flags); @@ -501,6 +503,7 @@ int implements(struct program *a, struct program *b); int is_compatible(struct program *a, struct program *b); int yyexplain_not_implements(struct program *a, struct program *b, int flags); void *parent_storage(int depth); +PMOD_EXPORT void change_compiler_compatibility(int major, int minor); /* Prototypes end here */ #define ADD_FUNCTION(NAME, FUNC, TYPE, FLAGS) \ @@ -576,6 +579,12 @@ void *parent_storage(int depth); #define Pike_new_program Pike_compiler->new_program +/* Return true if compat version is equal or greater to MAJOR.MINOR */ +#define TEST_COMPAT(MAJOR,MINOR) \ + (Pike_compiler->compat_major < (MAJOR) || \ + (Pike_compiler->compat_major == (MAJOR) && \ + Pike_compiler->compat_minor <= (MINOR))) + #endif /* PROGRAM_H */ /* Kludge... */ diff --git a/src/testsuite.in b/src/testsuite.in index 4e151e534369f295546b44ed4193e28dcb7d90b2..6705871b2cae0117642402aba51206543408582b 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -test_true([["$Id: testsuite.in,v 1.332 2000/09/23 21:11:47 mast Exp $"]]); +test_true([["$Id: testsuite.in,v 1.333 2000/09/26 00:17:48 hubbe Exp $"]]); cond([[all_constants()->_verify_internals]], [[ @@ -3403,7 +3403,9 @@ test_true(object_program(this_object())) // testing ! test_equal(!"",0) test_equal(!this_object(),0) -test_equal(!Simulate.this_function(),0) +test_equal( +#pike 7.0 +!Simulate.this_function(),0) // testing == test_true(1==1) @@ -3411,7 +3413,9 @@ test_true(!(1==2)) test_true(""=="") test_true(!(""=="foo")) test_true(this_object()==this_object()) -test_true(Simulate.this_function()==a) +test_true( +#pike 7.0 +Simulate.this_function()==a) test_true(2.0==2.0) test_true(({})==({})) @@ -4556,7 +4560,9 @@ return 1; // #include // FIXME add test for #include -test_compile_any([[#include <simulate.h> +test_compile_any([[ +#pike 7.0 +#include <simulate.h> ]]) // #error @@ -4958,7 +4964,9 @@ test_eq(function_object(a),this_object()) test_eq(function_name(function_object),0) // - get_function (actually in simulate.pike) -test_eq(a,Simulate.get_function(this_object(),"a")) +test_eq(a, +#pike 7.0 +Simulate.get_function(this_object(),"a")) test_eq(a,this_object()->a) // - hash