/* ** This file is in the public domain, so clarified as of ** 2006-07-17 by Arthur David Olson.
*/
/* Enable extensions and modifications for ICU. */ #define ICU
/* Continue executing after link failure. Even if ICU is undefined * (for vanilla zic behavior), ICU_LINKS should be defined, since zic * appears to fail on the 2003 data the first time through during the * linking phase. Running zic twice, with ICU_LINKS defined, causes
* links to be handled correctly. */ #define ICU_LINKS
#define LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
#ifdef ICU /* These constants are embedded in dynamically generated header
* version.h in the standard tzcode distribution. */ staticcharconst PKGVERSION[]="N/A"; staticcharconst TZVERSION[]="N/A"; staticcharconst REPORT_BUGS_TO[]="N/A"; #else #include"version.h" #endif #include"private.h" #include"locale.h" #include"tzfile.h"
/* ** On some ancient hosts, predicates like `isspace(C)' are defined ** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, ** which says they are defined only if C == ((unsigned char) C) || C == EOF. ** Neither the C Standard nor Posix require that `isascii' exist. ** For portability, we check both ancient and modern requirements. ** If isascii is not defined, the isascii check succeeds trivially.
*/ #include"ctype.h" #ifndef isascii #define isascii(x) 1 #endif
zic_t r_loyear; /* for example, 1986 */
zic_t r_hiyear; /* for example, 1986 */ constchar * r_yrtype; int r_lowasnum; int r_hiwasnum;
int r_month; /* 0..11 */
int r_dycode; /* see below */ int r_dayofmonth; int r_wday;
zic_t r_tod; /* time from midnight */ int r_todisstd; /* above is standard time if true */ /* or wall clock time if false */ int r_todisgmt; /* above is GMT if true */ /* or local time if false */
zic_t r_stdoff; /* offset from standard time */ constchar * r_abbrvar; /* variable part of abbreviation */
int r_todo; /* a rule to do (used in outzone) */
zic_t r_temp; /* used in outzone */
};
#ifdef ICU /* Indices into rules[] for final rules. They will occur in pairs, * with finalRules[i] occurring before finalRules[i+1] in the year. * Each zone need only store a start year, a standard offset, and an
* index into finalRules[]. FinalRules[] are aliases into rules[]. */ staticconststruct rule ** finalRules = NULL; staticint finalRulesCount = 0; #endif
staticvoid
associate(void)
{ registerstruct zone * zp; registerstruct rule * rp; registerint base, out; registerint i, j;
if (nrules != 0) {
(void) qsort(rules, nrules, sizeof *rules, rcomp); for (i = 0; i < nrules - 1; ++i) { if (strcmp(rules[i].r_name,
rules[i + 1].r_name) != 0) continue; if (strcmp(rules[i].r_filename,
rules[i + 1].r_filename) == 0) continue;
eat(rules[i].r_filename, rules[i].r_linenum);
warning(_("same rule name in multiple files"));
eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
warning(_("same rule name in multiple files")); for (j = i + 2; j < nrules; ++j) { if (strcmp(rules[i].r_name,
rules[j].r_name) != 0) break; if (strcmp(rules[i].r_filename,
rules[j].r_filename) == 0) continue; if (strcmp(rules[i + 1].r_filename,
rules[j].r_filename) == 0) continue; break;
}
i = j - 1;
}
} for (i = 0; i < nzones; ++i) {
zp = &zones[i];
zp->z_rules = NULL;
zp->z_nrules = 0;
} for (base = 0; base < nrules; base = out) {
rp = &rules[base]; for (out = base + 1; out < nrules; ++out) if (strcmp(rp->r_name, rules[out].r_name) != 0) break; for (i = 0; i < nzones; ++i) {
zp = &zones[i]; if (strcmp(zp->z_rule, rp->r_name) != 0) continue;
zp->z_rules = rp;
zp->z_nrules = out - base;
}
} for (i = 0; i < nzones; ++i) {
zp = &zones[i]; if (zp->z_nrules == 0) { /* ** Maybe we have a local standard time offset.
*/
eat(zp->z_filename, zp->z_linenum);
zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), true); /* ** Note, though, that if there's no rule, ** a '%s' in the format is a bad thing.
*/ if (strchr(zp->z_format, '%') != 0)
error("%s", _("%s in ruleless zone"));
}
} if (errors) exit(EXIT_FAILURE);
}
if (strcmp(fields[nfields], "-") == 0)
fields[nfields] = &nada;
++nfields;
} if (nfields == 0) { /* nothing to do */
} elseif (wantcont) {
wantcont = inzcont(fields, nfields);
} else {
lp = byword(fields[0], line_codes); if (lp == NULL)
error(_("input line of unknown type")); elseswitch ((int) (lp->l_value)) { case LC_RULE:
inrule(fields, nfields);
wantcont = false; break; case LC_ZONE:
wantcont = inzone(fields, nfields); break; case LC_LINK:
inlink(fields, nfields);
wantcont = false; break; case LC_LEAP: if (name != leapsec)
(void) fprintf(stderr,
_("%s: Leap line in non leap seconds file %s\n"),
progname, name); else inleap(fields, nfields);
wantcont = false; break; default: /* "cannot happen" */
(void) fprintf(stderr,
_("%s: panic: Invalid l_value %d\n"),
progname, lp->l_value); exit(EXIT_FAILURE);
}
}
free(fields);
} if (ferror(fp)) {
(void) fprintf(stderr, _("%s: Error reading %s\n"),
progname, filename); exit(EXIT_FAILURE);
} if (fp != stdin && fclose(fp)) { constchar *e = strerror(errno);
(void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
progname, filename, e); exit(EXIT_FAILURE);
} if (wantcont)
error(_("expected continuation line not found"));
}
/* ** Convert a string of one of the forms ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss ** into a number of seconds. ** A null string maps to zero. ** Call error with errstring and return zero on errors.
*/
static zic_t
gethms(constchar *string, constchar *const errstring, constint signable)
{
zic_t hh; int mm, ss, sign;
if (string == NULL || *string == '\0') return 0; if (!signable)
sign = 1; elseif (*string == '-') {
sign = -1;
++string;
} else sign = 1; if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1)
mm = ss = 0; elseif (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2)
ss = 0; elseif (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"),
&hh, &mm, &ss) != 3) {
error("%s", errstring); return 0;
} if (hh < 0 ||
mm < 0 || mm >= MINSPERHOUR ||
ss < 0 || ss > SECSPERMIN) {
error("%s", errstring); return 0;
} if (ZIC_MAX / SECSPERHOUR < hh) {
error(_("time overflow")); return 0;
} if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0)
warning(_("24:00 not handled by pre-1998 versions of zic")); if (noise && (hh > HOURSPERDAY ||
(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
warning(_("values over 24 hours not handled by pre-2007 versions of zic")); return oadd(sign * hh * SECSPERHOUR,
sign * (mm * SECSPERMIN + ss));
}
staticvoid
inlink(registerchar **const fields, constint nfields)
{ struct link l;
if (nfields != LINK_FIELDS) {
error(_("wrong number of fields on Link line")); return;
} if (*fields[LF_FROM] == '\0') {
error(_("blank FROM field on Link line")); return;
} if (*fields[LF_TO] == '\0') {
error(_("blank TO field on Link line")); return;
}
l.l_filename = filename;
l.l_linenum = linenum;
l.l_from = ecpyalloc(fields[LF_FROM]);
l.l_to = ecpyalloc(fields[LF_TO]);
links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
links[nlinks++] = l;
}
if (pass == 1) {
thistimei = timei32;
thistimecnt = timecnt32;
thisleapi = leapi32;
thisleapcnt = leapcnt32;
} else {
thistimei = 0;
thistimecnt = timecnt;
thisleapi = 0;
thisleapcnt = leapcnt;
}
thistimelim = thistimei + thistimecnt;
thisleaplim = thisleapi + thisleapcnt; /* ** Remember that type 0 is reserved.
*/
writetype[0] = false; for (i = 1; i < typecnt; ++i)
writetype[i] = thistimecnt == timecnt; if (thistimecnt == 0) { /* ** No transition times fall in the current ** (32- or 64-bit) window.
*/ if (typecnt != 0)
writetype[typecnt - 1] = true;
} else { for (i = thistimei - 1; i < thistimelim; ++i) if (i >= 0)
writetype[types[i]] = true; /* ** For America/Godthab and Antarctica/Palmer
*/ /* ** Remember that type 0 is reserved.
*/ if (thistimei == 0)
writetype[1] = true;
} #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH /* ** For some pre-2011 systems: if the last-to-be-written ** standard (or daylight) type has an offset different from the ** most recently used offset, ** append an (unused) copy of the most recently used type ** (to help get global "altzone" and "timezone" variables ** set correctly).
*/
{ registerint mrudst, mrustd, hidst, histd, type;
hidst = histd = mrudst = mrustd = -1; for (i = thistimei; i < thistimelim; ++i) if (isdsts[types[i]])
mrudst = types[i]; else mrustd = types[i]; for (i = 0; i < typecnt; ++i) if (writetype[i]) { if (isdsts[i])
hidst = i; else histd = i;
} if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
gmtoffs[hidst] != gmtoffs[mrudst]) {
isdsts[mrudst] = -1;
type = addtype(gmtoffs[mrudst], #ifdef ICU
rawoffs[mrudst], dstoffs[mrudst], #endif
&chars[abbrinds[mrudst]], true,
ttisstds[mrudst],
ttisgmts[mrudst]);
isdsts[mrudst] = true;
writetype[type] = true;
} if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
gmtoffs[histd] != gmtoffs[mrustd]) {
isdsts[mrustd] = -1;
type = addtype(gmtoffs[mrustd], #ifdef ICU
rawoffs[mrudst], dstoffs[mrudst], #endif
&chars[abbrinds[mrustd]], false,
ttisstds[mrustd],
ttisgmts[mrustd]);
isdsts[mrustd] = false;
writetype[type] = true;
}
} #endif/* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
thistypecnt = 0; /* ** Potentially, set type 0 to that of lowest-valued time.
*/ if (thistimei > 0) { for (i = 1; i < typecnt; ++i) if (writetype[i] && !isdsts[i]) break; if (i != types[thistimei - 1]) {
i = types[thistimei - 1];
gmtoffs[0] = gmtoffs[i];
isdsts[0] = isdsts[i];
ttisstds[0] = ttisstds[i];
ttisgmts[0] = ttisgmts[i];
abbrinds[0] = abbrinds[i];
writetype[0] = true;
writetype[i] = false;
}
} for (i = 0; i < typecnt; ++i)
typemap[i] = writetype[i] ? thistypecnt++ : 0; for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
indmap[i] = -1;
thischarcnt = 0; for (i = 0; i < typecnt; ++i) { registerchar * thisabbr;
result[0] = '\0';
zp = zpfirst + zonecount - 1;
stdrp = dstrp = NULL; for (i = 0; i < zp->z_nrules; ++i) {
rp = &zp->z_rules[i]; if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) continue; if (rp->r_yrtype != NULL) continue; if (rp->r_stdoff == 0) { if (stdrp == NULL)
stdrp = rp; elsereturn -1;
} else { if (dstrp == NULL)
dstrp = rp; elsereturn -1;
}
} if (stdrp == NULL && dstrp == NULL) { /* ** There are no rules running through "max". ** Find the latest std rule in stdabbrrp ** and latest rule of any type in stdrp.
*/ registerstruct rule *stdabbrrp = NULL; for (i = 0; i < zp->z_nrules; ++i) {
rp = &zp->z_rules[i]; if (rp->r_stdoff == 0 && rule_cmp(stdabbrrp, rp) < 0)
stdabbrrp = rp; if (rule_cmp(stdrp, rp) < 0)
stdrp = rp;
} /* ** Horrid special case: if year is 2037, ** presume this is a zone handled on a year-by-year basis; ** do not try to apply a rule to the zone.
*/ if (stdrp != NULL && stdrp->r_hiyear == 2037) return YEAR_BY_YEAR_ZONE;
staticvoid
outzone(conststruct zone * const zpfirst, constint zonecount)
{ registerconststruct zone * zp; registerstruct rule * rp; registerint i, j; registerint usestart, useuntil; register zic_t starttime, untiltime; register zic_t gmtoff; register zic_t stdoff; register zic_t year; register zic_t startoff; registerint startttisstd; registerint startttisgmt; registerint type; registerchar * startbuf; registerchar * ab; registerchar * envvar; registerint max_abbr_len; registerint max_envvar_len; registerint prodstic; /* all rules are min to max */ registerint compat; registerint do_extend; registerchar version; #ifdef ICU int finalRuleYear, finalRuleIndex; conststruct rule* finalRule1; conststruct rule* finalRule2; #endif
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
max_envvar_len = 2 * max_abbr_len + 5 * 9;
startbuf = emalloc(max_abbr_len + 1);
ab = emalloc(max_abbr_len + 1);
envvar = emalloc(max_envvar_len + 1);
INITIALIZE(untiltime);
INITIALIZE(starttime); /* ** Now. . .finally. . .generate some useful data!
*/
timecnt = 0;
typecnt = 0;
charcnt = 0;
prodstic = zonecount == 1; /* ** Thanks to Earl Chew ** for noting the need to unconditionally initialize startttisstd.
*/
startttisstd = false;
startttisgmt = false;
min_year = max_year = EPOCH_YEAR; if (leapseen) {
updateminmax(leapminyear);
updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
} /* ** Reserve type 0.
*/
gmtoffs[0] = isdsts[0] = ttisstds[0] = ttisgmts[0] = abbrinds[0] = -1;
typecnt = 1; for (i = 0; i < zonecount; ++i) {
zp = &zpfirst[i]; if (i < zonecount - 1)
updateminmax(zp->z_untilrule.r_loyear); for (j = 0; j < zp->z_nrules; ++j) {
rp = &zp->z_rules[j]; if (rp->r_lowasnum)
updateminmax(rp->r_loyear); if (rp->r_hiwasnum)
updateminmax(rp->r_hiyear); if (rp->r_lowasnum || rp->r_hiwasnum)
prodstic = false;
}
} /* ** Generate lots of data if a rule can't cover all future times.
*/
compat = stringzone(envvar, zpfirst, zonecount);
version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE; #ifdef ICU
do_extend = 0; #endif if (noise) { if (!*envvar)
warning("%s %s",
_("no POSIX environment variable for zone"),
zpfirst->z_name); elseif (compat != 0 && compat != YEAR_BY_YEAR_ZONE) { /* Circa-COMPAT clients, and earlier clients, might not work for this zone when given dates before
1970 or after 2038. */
warning(_("%s: pre-%d clients may mishandle" " distant timestamps"),
zpfirst->z_name, compat);
}
} if (do_extend) { /* ** Search through a couple of extra years past the obvious ** 400, to avoid edge cases. For example, suppose a non-POSIX ** rule applies from 2012 onwards and has transitions in March ** and September, plus some one-off transitions in November ** 2013. If zic looked only at the last 400 years, it would ** set max_year=2413, with the intent that the 400 years 2014 ** through 2413 will be repeated. The last transition listed ** in the tzfile would be in 2413-09, less than 400 years ** after the last one-off transition in 2013-11. Two years ** might be overkill, but with the kind of edge cases ** available we're not sure that one year would suffice.
*/ enum { years_of_observations = YEARSPERREPEAT + 2 };
if (min_year >= ZIC_MIN + years_of_observations)
min_year -= years_of_observations; else min_year = ZIC_MIN; if (max_year <= ZIC_MAX - years_of_observations)
max_year += years_of_observations; else max_year = ZIC_MAX; /* ** Regardless of any of the above, ** for a "proDSTic" zone which specifies that its rules ** always have and always will be in effect, ** we only need one cycle to define the zone.
*/ if (prodstic) {
min_year = 1900;
max_year = min_year + years_of_observations;
}
} /* ** For the benefit of older systems, ** generate data from 1900 through 2037.
*/ if (min_year > 1900)
min_year = 1900; if (max_year < 2037)
max_year = 2037; for (i = 0; i < zonecount; ++i) { /* ** A guess that may well be corrected later.
*/
stdoff = 0;
zp = &zpfirst[i];
usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
useuntil = i < (zonecount - 1); if (useuntil && zp->z_untiltime <= min_time) continue;
gmtoff = zp->z_gmtoff;
eat(zp->z_filename, zp->z_linenum);
*startbuf = '\0';
startoff = zp->z_gmtoff; #ifdef ICU
finalRuleYear = finalRuleIndex = -1;
finalRule1 = finalRule2 = NULL; if (i == (zonecount - 1)) { /* !useuntil */ /* Look for exactly 2 rules that end at 'max' and * note them. Determine max(r_loyear) for the 2 of
* them. */ for (j=0; j<zp->z_nrules; ++j) {
rp = &zp->z_rules[j]; if (rp->r_hiyear == ZIC_MAX) { if (rp->r_loyear > finalRuleYear) {
finalRuleYear = rp->r_loyear;
} if (finalRule1 == NULL) {
finalRule1 = rp;
} elseif (finalRule2 == NULL) {
finalRule2 = rp;
} else {
error("more than two max rules found (ICU)"); exit(EXIT_FAILURE);
}
} elseif (rp->r_hiyear >= finalRuleYear) { /* There might be an overriding non-max rule * to be applied to a specific year after one of * max rule's start year. For example, * * Rule Foo 2010 max ... * Rule Foo 2015 only ... * * In this case, we need to change the start year of
* the final (max) rules to the next year. */
finalRuleYear = rp->r_hiyear + 1;
/* When above adjustment is done, max_year might need * to be adjusted, so the final rule will be properly * evaluated and emitted by the later code block. * * Note: This may push the start year of the final * rules ahead by 1 year unnecessarily. For example, * If there are two rules, non-max rule and max rule * starting in the same year, such as * * Rule Foo 2010 only .... * Rule Foo 2010 max .... * * In this case, the final (max) rule actually starts * in 2010, instead of 2010. We could make this tool * more intelligent to detect such situation. But pushing * final rule start year to 1 year ahead (in the worst case) * will just populate a few extra transitions, and it still * works fine. So for now, we're not trying to put additional * logic to optimize the case.
*/ if (max_year < finalRuleYear) {
max_year = finalRuleYear;
}
}
} if (finalRule1 != NULL) { if (finalRule2 == NULL) {
warning("only one max rule found (ICU)");
finalRuleYear = finalRuleIndex = -1;
finalRule1 = NULL;
} else { if (finalRule1->r_stdoff == finalRule2->r_stdoff) { /* America/Resolute in 2009a uses a pair of rules * which does not change the offset. ICU ignores
* such rules without actual time transitions. */
finalRuleYear = finalRuleIndex = -1;
finalRule1 = finalRule2 = NULL;
} else { /* Swap if necessary so finalRule1 occurs before
* finalRule2 */ if (finalRule1->r_month > finalRule2->r_month) { conststruct rule* t = finalRule1;
finalRule1 = finalRule2;
finalRule2 = t;
} /* Add final rule to our list */
finalRuleIndex = add_icu_final_rules(finalRule1, finalRule2);
}
}
}
} #endif
if (zp->z_nrules == 0) {
stdoff = zp->z_stdoff;
doabbr(startbuf, zp->z_format,
NULL, stdoff != 0, false);
type = addtype(oadd(zp->z_gmtoff, stdoff), #ifdef ICU
zp->z_gmtoff, stdoff, #endif
startbuf, stdoff != 0, startttisstd,
startttisgmt); if (usestart) {
addtt(starttime, type);
usestart = false;
} elseif (stdoff != 0)
addtt(min_time, type);
} elsefor (year = min_year; year <= max_year; ++year) { if (useuntil && year > zp->z_untilrule.r_hiyear) break; /* ** Mark which rules to do in the current year. ** For those to do, calculate rpytime(rp, year);
*/ for (j = 0; j < zp->z_nrules; ++j) {
rp = &zp->z_rules[j];
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
rp->r_todo = year >= rp->r_loyear &&
year <= rp->r_hiyear &&
yearistype(year, rp->r_yrtype); if (rp->r_todo)
rp->r_temp = rpytime(rp, year);
} for ( ; ; ) { registerint k; register zic_t jtime, ktime; register zic_t offset;
INITIALIZE(ktime); if (useuntil) { /* ** Turn untiltime into UT ** assuming the current gmtoff and ** stdoff values.
*/
untiltime = zp->z_untiltime; if (!zp->z_untilrule.r_todisgmt)
untiltime = tadd(untiltime,
-gmtoff); if (!zp->z_untilrule.r_todisstd)
untiltime = tadd(untiltime,
-stdoff);
} /* ** Find the rule (of those to do, if any) ** that takes effect earliest in the year.
*/
k = -1; for (j = 0; j < zp->z_nrules; ++j) {
rp = &zp->z_rules[j]; if (!rp->r_todo) continue;
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
offset = rp->r_todisgmt ? 0 : gmtoff; if (!rp->r_todisstd)
offset = oadd(offset, stdoff);
jtime = rp->r_temp; if (jtime == min_time ||
jtime == max_time) continue;
jtime = tadd(jtime, -offset); if (k < 0 || jtime < ktime) {
k = j;
ktime = jtime;
}
} if (k < 0) break; /* go on to next year */
rp = &zp->z_rules[k];
rp->r_todo = false; if (useuntil && ktime >= untiltime) break;
stdoff = rp->r_stdoff; if (usestart && ktime == starttime)
usestart = false; if (usestart) { if (ktime < starttime) {
startoff = oadd(zp->z_gmtoff,
stdoff);
doabbr(startbuf, zp->z_format,
rp->r_abbrvar,
rp->r_stdoff != 0, false); continue;
} if (*startbuf == '\0' &&
startoff == oadd(zp->z_gmtoff,
stdoff)) {
doabbr(startbuf,
zp->z_format,
rp->r_abbrvar,
rp->r_stdoff !=
0, false);
}
} #ifdef ICU if (year >= finalRuleYear && rp == finalRule1) { /* We want to shift final year 1 year after * the actual final rule takes effect (year + 1), * because the previous type is valid until the first * transition defined by the final rule. Otherwise * we may see unexpected offset shift at the * beginning of the year when the final rule takes * effect. * * Note: This may results some 64bit second transitions * at the very end (year 2038). ICU 4.2 or older releases * cannot handle 64bit second transitions and they are
* dropped from zoneinfo.txt. */
emit_icu_zone(icuFile,
zpfirst->z_name, zp->z_gmtoff,
rp, finalRuleIndex, year + 1); /* only emit this for the first year */
finalRule1 = NULL;
} #endif
eats(zp->z_filename, zp->z_linenum,
rp->r_filename, rp->r_linenum);
doabbr(ab, zp->z_format, rp->r_abbrvar,
rp->r_stdoff != 0, false);
offset = oadd(zp->z_gmtoff, rp->r_stdoff); #ifdef ICU
type = addtype(offset, zp->z_gmtoff, rp->r_stdoff,
ab, rp->r_stdoff != 0,
rp->r_todisstd, rp->r_todisgmt); #else
type = addtype(offset, ab, rp->r_stdoff != 0,
rp->r_todisstd, rp->r_todisgmt); #endif
addtt(ktime, type);
}
} if (usestart) { if (*startbuf == '\0' &&
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.42 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.