zic.c 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284
  1. /* Compile .zi time zone data into TZif binary files. */
  2. /*
  3. ** This file is in the public domain, so clarified as of
  4. ** 2006-07-17 by Arthur David Olson.
  5. */
  6. #include "version.h"
  7. #include "private.h"
  8. #include "tzfile.h"
  9. #include <fcntl.h>
  10. #include <locale.h>
  11. #include <stdarg.h>
  12. #include <stddef.h>
  13. #include <stdio.h>
  14. #define ZIC_VERSION_PRE_2013 '2'
  15. #define ZIC_VERSION '3'
  16. typedef int_fast64_t zic_t;
  17. #define ZIC_MIN INT_FAST64_MIN
  18. #define ZIC_MAX INT_FAST64_MAX
  19. #define PRIdZIC PRIdFAST64
  20. #define SCNdZIC SCNdFAST64
  21. #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
  22. #define ZIC_MAX_ABBR_LEN_WO_WARN 6
  23. #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
  24. #ifdef HAVE_DIRECT_H
  25. # include <direct.h>
  26. # include <io.h>
  27. # undef mkdir
  28. # define mkdir(name, mode) _mkdir(name)
  29. #endif
  30. #if HAVE_SYS_STAT_H
  31. #include <sys/stat.h>
  32. #endif
  33. #ifdef S_IRUSR
  34. #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
  35. #else
  36. #define MKDIR_UMASK 0755
  37. #endif
  38. /* Port to native MS-Windows and to ancient UNIX. */
  39. #if !defined S_ISDIR && defined S_IFDIR && defined S_IFMT
  40. # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
  41. #endif
  42. #if HAVE_SYS_WAIT_H
  43. #include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
  44. #endif /* HAVE_SYS_WAIT_H */
  45. #ifndef WIFEXITED
  46. #define WIFEXITED(status) (((status) & 0xff) == 0)
  47. #endif /* !defined WIFEXITED */
  48. #ifndef WEXITSTATUS
  49. #define WEXITSTATUS(status) (((status) >> 8) & 0xff)
  50. #endif /* !defined WEXITSTATUS */
  51. /* The maximum ptrdiff_t value, for pre-C99 platforms. */
  52. #ifndef PTRDIFF_MAX
  53. static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
  54. #endif
  55. /* The minimum alignment of a type, for pre-C11 platforms. */
  56. #if __STDC_VERSION__ < 201112
  57. # define _Alignof(type) offsetof(struct { char a; type b; }, b)
  58. #endif
  59. /* The type for line numbers. Use PRIdMAX to format them; formerly
  60. there was also "#define PRIdLINENO PRIdMAX" and formats used
  61. PRIdLINENO, but xgettext cannot grok that. */
  62. typedef intmax_t lineno;
  63. struct rule {
  64. const char * r_filename;
  65. lineno r_linenum;
  66. const char * r_name;
  67. zic_t r_loyear; /* for example, 1986 */
  68. zic_t r_hiyear; /* for example, 1986 */
  69. const char * r_yrtype;
  70. bool r_lowasnum;
  71. bool r_hiwasnum;
  72. int r_month; /* 0..11 */
  73. int r_dycode; /* see below */
  74. int r_dayofmonth;
  75. int r_wday;
  76. zic_t r_tod; /* time from midnight */
  77. bool r_todisstd; /* above is standard time if 1 */
  78. /* or wall clock time if 0 */
  79. bool r_todisgmt; /* above is GMT if 1 */
  80. /* or local time if 0 */
  81. bool r_isdst; /* is this daylight saving time? */
  82. zic_t r_stdoff; /* offset from default time (which is
  83. usually standard time) */
  84. const char * r_abbrvar; /* variable part of abbreviation */
  85. bool r_todo; /* a rule to do (used in outzone) */
  86. zic_t r_temp; /* used in outzone */
  87. };
  88. /*
  89. ** r_dycode r_dayofmonth r_wday
  90. */
  91. #define DC_DOM 0 /* 1..31 */ /* unused */
  92. #define DC_DOWGEQ 1 /* 1..31 */ /* 0..6 (Sun..Sat) */
  93. #define DC_DOWLEQ 2 /* 1..31 */ /* 0..6 (Sun..Sat) */
  94. struct zone {
  95. const char * z_filename;
  96. lineno z_linenum;
  97. const char * z_name;
  98. zic_t z_gmtoff;
  99. char * z_rule;
  100. const char * z_format;
  101. char z_format_specifier;
  102. bool z_isdst;
  103. zic_t z_stdoff;
  104. struct rule * z_rules;
  105. ptrdiff_t z_nrules;
  106. struct rule z_untilrule;
  107. zic_t z_untiltime;
  108. };
  109. #if !HAVE_POSIX_DECLS
  110. extern int getopt(int argc, char * const argv[],
  111. const char * options);
  112. extern int link(const char * fromname, const char * toname);
  113. extern char * optarg;
  114. extern int optind;
  115. #endif
  116. #if ! HAVE_LINK
  117. # define link(from, to) (errno = ENOTSUP, -1)
  118. #endif
  119. #if ! HAVE_SYMLINK
  120. # define readlink(file, buf, size) (errno = ENOTSUP, -1)
  121. # define symlink(from, to) (errno = ENOTSUP, -1)
  122. # define S_ISLNK(m) 0
  123. #endif
  124. #ifndef AT_SYMLINK_FOLLOW
  125. # define linkat(fromdir, from, todir, to, flag) \
  126. (itssymlink(from) ? (errno = ENOTSUP, -1) : link(from, to))
  127. #endif
  128. static void addtt(zic_t starttime, int type);
  129. static int addtype(zic_t, char const *, bool, bool, bool);
  130. static void leapadd(zic_t, bool, int, int);
  131. static void adjleap(void);
  132. static void associate(void);
  133. static void dolink(const char *, const char *, bool);
  134. static char ** getfields(char * buf);
  135. static zic_t gethms(const char * string, const char * errstring);
  136. static zic_t getstdoff(char *, bool *);
  137. static void infile(const char * filename);
  138. static void inleap(char ** fields, int nfields);
  139. static void inlink(char ** fields, int nfields);
  140. static void inrule(char ** fields, int nfields);
  141. static bool inzcont(char ** fields, int nfields);
  142. static bool inzone(char ** fields, int nfields);
  143. static bool inzsub(char **, int, bool);
  144. static bool itsdir(char const *);
  145. static bool itssymlink(char const *);
  146. static bool is_alpha(char a);
  147. static char lowerit(char);
  148. static void mkdirs(char const *, bool);
  149. static void newabbr(const char * abbr);
  150. static zic_t oadd(zic_t t1, zic_t t2);
  151. static void outzone(const struct zone * zp, ptrdiff_t ntzones);
  152. static zic_t rpytime(const struct rule * rp, zic_t wantedy);
  153. static void rulesub(struct rule * rp,
  154. const char * loyearp, const char * hiyearp,
  155. const char * typep, const char * monthp,
  156. const char * dayp, const char * timep);
  157. static zic_t tadd(zic_t t1, zic_t t2);
  158. static bool yearistype(zic_t year, const char * type);
  159. /* Bound on length of what %z can expand to. */
  160. enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
  161. /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
  162. TZif files whose POSIX-TZ-style strings contain '<'; see
  163. QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
  164. workaround will no longer be needed when Qt 5.6.1 and earlier are
  165. obsolete, say in the year 2021. */
  166. #ifndef WORK_AROUND_QTBUG_53071
  167. enum { WORK_AROUND_QTBUG_53071 = true };
  168. #endif
  169. static int charcnt;
  170. static bool errors;
  171. static bool warnings;
  172. static const char * filename;
  173. static int leapcnt;
  174. static bool leapseen;
  175. static zic_t leapminyear;
  176. static zic_t leapmaxyear;
  177. static lineno linenum;
  178. static int max_abbrvar_len = PERCENT_Z_LEN_BOUND;
  179. static int max_format_len;
  180. static zic_t max_year;
  181. static zic_t min_year;
  182. static bool noise;
  183. static const char * rfilename;
  184. static lineno rlinenum;
  185. static const char * progname;
  186. static ptrdiff_t timecnt;
  187. static ptrdiff_t timecnt_alloc;
  188. static int typecnt;
  189. /*
  190. ** Line codes.
  191. */
  192. #define LC_RULE 0
  193. #define LC_ZONE 1
  194. #define LC_LINK 2
  195. #define LC_LEAP 3
  196. /*
  197. ** Which fields are which on a Zone line.
  198. */
  199. #define ZF_NAME 1
  200. #define ZF_GMTOFF 2
  201. #define ZF_RULE 3
  202. #define ZF_FORMAT 4
  203. #define ZF_TILYEAR 5
  204. #define ZF_TILMONTH 6
  205. #define ZF_TILDAY 7
  206. #define ZF_TILTIME 8
  207. #define ZONE_MINFIELDS 5
  208. #define ZONE_MAXFIELDS 9
  209. /*
  210. ** Which fields are which on a Zone continuation line.
  211. */
  212. #define ZFC_GMTOFF 0
  213. #define ZFC_RULE 1
  214. #define ZFC_FORMAT 2
  215. #define ZFC_TILYEAR 3
  216. #define ZFC_TILMONTH 4
  217. #define ZFC_TILDAY 5
  218. #define ZFC_TILTIME 6
  219. #define ZONEC_MINFIELDS 3
  220. #define ZONEC_MAXFIELDS 7
  221. /*
  222. ** Which files are which on a Rule line.
  223. */
  224. #define RF_NAME 1
  225. #define RF_LOYEAR 2
  226. #define RF_HIYEAR 3
  227. #define RF_COMMAND 4
  228. #define RF_MONTH 5
  229. #define RF_DAY 6
  230. #define RF_TOD 7
  231. #define RF_STDOFF 8
  232. #define RF_ABBRVAR 9
  233. #define RULE_FIELDS 10
  234. /*
  235. ** Which fields are which on a Link line.
  236. */
  237. #define LF_FROM 1
  238. #define LF_TO 2
  239. #define LINK_FIELDS 3
  240. /*
  241. ** Which fields are which on a Leap line.
  242. */
  243. #define LP_YEAR 1
  244. #define LP_MONTH 2
  245. #define LP_DAY 3
  246. #define LP_TIME 4
  247. #define LP_CORR 5
  248. #define LP_ROLL 6
  249. #define LEAP_FIELDS 7
  250. /*
  251. ** Year synonyms.
  252. */
  253. #define YR_MINIMUM 0
  254. #define YR_MAXIMUM 1
  255. #define YR_ONLY 2
  256. static struct rule * rules;
  257. static ptrdiff_t nrules; /* number of rules */
  258. static ptrdiff_t nrules_alloc;
  259. static struct zone * zones;
  260. static ptrdiff_t nzones; /* number of zones */
  261. static ptrdiff_t nzones_alloc;
  262. struct link {
  263. const char * l_filename;
  264. lineno l_linenum;
  265. const char * l_from;
  266. const char * l_to;
  267. };
  268. static struct link * links;
  269. static ptrdiff_t nlinks;
  270. static ptrdiff_t nlinks_alloc;
  271. struct lookup {
  272. const char * l_word;
  273. const int l_value;
  274. };
  275. static struct lookup const * byword(const char * string,
  276. const struct lookup * lp);
  277. static struct lookup const zi_line_codes[] = {
  278. { "Rule", LC_RULE },
  279. { "Zone", LC_ZONE },
  280. { "Link", LC_LINK },
  281. { NULL, 0 }
  282. };
  283. static struct lookup const leap_line_codes[] = {
  284. { "Leap", LC_LEAP },
  285. { NULL, 0}
  286. };
  287. static struct lookup const mon_names[] = {
  288. { "January", TM_JANUARY },
  289. { "February", TM_FEBRUARY },
  290. { "March", TM_MARCH },
  291. { "April", TM_APRIL },
  292. { "May", TM_MAY },
  293. { "June", TM_JUNE },
  294. { "July", TM_JULY },
  295. { "August", TM_AUGUST },
  296. { "September", TM_SEPTEMBER },
  297. { "October", TM_OCTOBER },
  298. { "November", TM_NOVEMBER },
  299. { "December", TM_DECEMBER },
  300. { NULL, 0 }
  301. };
  302. static struct lookup const wday_names[] = {
  303. { "Sunday", TM_SUNDAY },
  304. { "Monday", TM_MONDAY },
  305. { "Tuesday", TM_TUESDAY },
  306. { "Wednesday", TM_WEDNESDAY },
  307. { "Thursday", TM_THURSDAY },
  308. { "Friday", TM_FRIDAY },
  309. { "Saturday", TM_SATURDAY },
  310. { NULL, 0 }
  311. };
  312. static struct lookup const lasts[] = {
  313. { "last-Sunday", TM_SUNDAY },
  314. { "last-Monday", TM_MONDAY },
  315. { "last-Tuesday", TM_TUESDAY },
  316. { "last-Wednesday", TM_WEDNESDAY },
  317. { "last-Thursday", TM_THURSDAY },
  318. { "last-Friday", TM_FRIDAY },
  319. { "last-Saturday", TM_SATURDAY },
  320. { NULL, 0 }
  321. };
  322. static struct lookup const begin_years[] = {
  323. { "minimum", YR_MINIMUM },
  324. { "maximum", YR_MAXIMUM },
  325. { NULL, 0 }
  326. };
  327. static struct lookup const end_years[] = {
  328. { "minimum", YR_MINIMUM },
  329. { "maximum", YR_MAXIMUM },
  330. { "only", YR_ONLY },
  331. { NULL, 0 }
  332. };
  333. static struct lookup const leap_types[] = {
  334. { "Rolling", true },
  335. { "Stationary", false },
  336. { NULL, 0 }
  337. };
  338. static const int len_months[2][MONSPERYEAR] = {
  339. { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  340. { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  341. };
  342. static const int len_years[2] = {
  343. DAYSPERNYEAR, DAYSPERLYEAR
  344. };
  345. static struct attype {
  346. zic_t at;
  347. bool dontmerge;
  348. unsigned char type;
  349. } * attypes;
  350. static zic_t gmtoffs[TZ_MAX_TYPES];
  351. static char isdsts[TZ_MAX_TYPES];
  352. static unsigned char abbrinds[TZ_MAX_TYPES];
  353. static bool ttisstds[TZ_MAX_TYPES];
  354. static bool ttisgmts[TZ_MAX_TYPES];
  355. static char chars[TZ_MAX_CHARS];
  356. static zic_t trans[TZ_MAX_LEAPS];
  357. static zic_t corr[TZ_MAX_LEAPS];
  358. static char roll[TZ_MAX_LEAPS];
  359. /*
  360. ** Memory allocation.
  361. */
  362. static _Noreturn void
  363. memory_exhausted(const char *msg)
  364. {
  365. fprintf(stderr, _("%s: Memory exhausted: %s\n"), progname, msg);
  366. exit(EXIT_FAILURE);
  367. }
  368. static ATTRIBUTE_PURE size_t
  369. size_product(size_t nitems, size_t itemsize)
  370. {
  371. if (SIZE_MAX / itemsize < nitems)
  372. memory_exhausted(_("size overflow"));
  373. return nitems * itemsize;
  374. }
  375. static ATTRIBUTE_PURE size_t
  376. align_to(size_t size, size_t alignment)
  377. {
  378. size_t aligned_size = size + alignment - 1;
  379. aligned_size -= aligned_size % alignment;
  380. if (aligned_size < size)
  381. memory_exhausted(_("alignment overflow"));
  382. return aligned_size;
  383. }
  384. #if !HAVE_STRDUP
  385. static char *
  386. strdup(char const *str)
  387. {
  388. char *result = malloc(strlen(str) + 1);
  389. return result ? strcpy(result, str) : result;
  390. }
  391. #endif
  392. static void *
  393. memcheck(void *ptr)
  394. {
  395. if (ptr == NULL)
  396. memory_exhausted(strerror(errno));
  397. return ptr;
  398. }
  399. static void * ATTRIBUTE_MALLOC
  400. emalloc(size_t size)
  401. {
  402. return memcheck(malloc(size));
  403. }
  404. static void *
  405. erealloc(void *ptr, size_t size)
  406. {
  407. return memcheck(realloc(ptr, size));
  408. }
  409. static char * ATTRIBUTE_MALLOC
  410. ecpyalloc (char const *str)
  411. {
  412. return memcheck(strdup(str));
  413. }
  414. static void *
  415. growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
  416. {
  417. if (nitems < *nitems_alloc)
  418. return ptr;
  419. else {
  420. ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
  421. ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
  422. if ((amax - 1) / 3 * 2 < *nitems_alloc)
  423. memory_exhausted(_("integer overflow"));
  424. *nitems_alloc += (*nitems_alloc >> 1) + 1;
  425. return erealloc(ptr, size_product(*nitems_alloc, itemsize));
  426. }
  427. }
  428. /*
  429. ** Error handling.
  430. */
  431. static void
  432. eats(char const *name, lineno num, char const *rname, lineno rnum)
  433. {
  434. filename = name;
  435. linenum = num;
  436. rfilename = rname;
  437. rlinenum = rnum;
  438. }
  439. static void
  440. eat(char const *name, lineno num)
  441. {
  442. eats(name, num, NULL, -1);
  443. }
  444. static void ATTRIBUTE_FORMAT((printf, 1, 0))
  445. verror(const char *const string, va_list args)
  446. {
  447. /*
  448. ** Match the format of "cc" to allow sh users to
  449. ** zic ... 2>&1 | error -t "*" -v
  450. ** on BSD systems.
  451. */
  452. if (filename)
  453. fprintf(stderr, _("\"%s\", line %"PRIdMAX": "), filename, linenum);
  454. vfprintf(stderr, string, args);
  455. if (rfilename != NULL)
  456. fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"),
  457. rfilename, rlinenum);
  458. fprintf(stderr, "\n");
  459. }
  460. static void ATTRIBUTE_FORMAT((printf, 1, 2))
  461. error(const char *const string, ...)
  462. {
  463. va_list args;
  464. va_start(args, string);
  465. verror(string, args);
  466. va_end(args);
  467. errors = true;
  468. }
  469. static void ATTRIBUTE_FORMAT((printf, 1, 2))
  470. warning(const char *const string, ...)
  471. {
  472. va_list args;
  473. fprintf(stderr, _("warning: "));
  474. va_start(args, string);
  475. verror(string, args);
  476. va_end(args);
  477. warnings = true;
  478. }
  479. static void
  480. close_file(FILE *stream, char const *dir, char const *name)
  481. {
  482. char const *e = (ferror(stream) ? _("I/O error")
  483. : fclose(stream) != 0 ? strerror(errno) : NULL);
  484. if (e) {
  485. fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
  486. dir ? dir : "", dir ? "/" : "",
  487. name ? name : "", name ? ": " : "",
  488. e);
  489. exit(EXIT_FAILURE);
  490. }
  491. }
  492. static _Noreturn void
  493. usage(FILE *stream, int status)
  494. {
  495. fprintf(stream,
  496. _("%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n"
  497. "\t[ -l localtime ] [ -p posixrules ] [ -d directory ] \\\n"
  498. "\t[ -t localtime-link ] [ -L leapseconds ] [ filename ... ]\n\n"
  499. "Report bugs to %s.\n"),
  500. progname, progname, REPORT_BUGS_TO);
  501. if (status == EXIT_SUCCESS)
  502. close_file(stream, NULL, NULL);
  503. exit(status);
  504. }
  505. /* Change the working directory to DIR, possibly creating DIR and its
  506. ancestors. After this is done, all files are accessed with names
  507. relative to DIR. */
  508. static void
  509. change_directory (char const *dir)
  510. {
  511. if (chdir(dir) != 0) {
  512. int chdir_errno = errno;
  513. if (chdir_errno == ENOENT) {
  514. mkdirs(dir, false);
  515. chdir_errno = chdir(dir) == 0 ? 0 : errno;
  516. }
  517. if (chdir_errno != 0) {
  518. fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
  519. progname, dir, strerror(chdir_errno));
  520. exit(EXIT_FAILURE);
  521. }
  522. }
  523. }
  524. static const char * psxrules;
  525. static const char * lcltime;
  526. static const char * directory;
  527. static const char * leapsec;
  528. static const char * tzdefault;
  529. static const char * yitcommand;
  530. int
  531. main(int argc, char **argv)
  532. {
  533. register int c, k;
  534. register ptrdiff_t i, j;
  535. #ifdef S_IWGRP
  536. umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
  537. #endif
  538. #if HAVE_GETTEXT
  539. setlocale(LC_ALL, "");
  540. #ifdef TZ_DOMAINDIR
  541. bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
  542. #endif /* defined TEXTDOMAINDIR */
  543. textdomain(TZ_DOMAIN);
  544. #endif /* HAVE_GETTEXT */
  545. progname = argv[0];
  546. if (TYPE_BIT(zic_t) < 64) {
  547. fprintf(stderr, "%s: %s\n", progname,
  548. _("wild compilation-time specification of zic_t"));
  549. return EXIT_FAILURE;
  550. }
  551. for (k = 1; k < argc; k++)
  552. if (strcmp(argv[k], "--version") == 0) {
  553. printf("zic %s%s\n", PKGVERSION, TZVERSION);
  554. close_file(stdout, NULL, NULL);
  555. return EXIT_SUCCESS;
  556. } else if (strcmp(argv[k], "--help") == 0) {
  557. usage(stdout, EXIT_SUCCESS);
  558. }
  559. while ((c = getopt(argc, argv, "d:l:L:p:st:vy:")) != EOF && c != -1)
  560. switch (c) {
  561. default:
  562. usage(stderr, EXIT_FAILURE);
  563. case 'd':
  564. if (directory == NULL)
  565. directory = optarg;
  566. else {
  567. fprintf(stderr,
  568. _("%s: More than one -d option specified\n"),
  569. progname);
  570. return EXIT_FAILURE;
  571. }
  572. break;
  573. case 'l':
  574. if (lcltime == NULL)
  575. lcltime = optarg;
  576. else {
  577. fprintf(stderr,
  578. _("%s: More than one -l option specified\n"),
  579. progname);
  580. return EXIT_FAILURE;
  581. }
  582. break;
  583. case 'p':
  584. if (psxrules == NULL)
  585. psxrules = optarg;
  586. else {
  587. fprintf(stderr,
  588. _("%s: More than one -p option specified\n"),
  589. progname);
  590. return EXIT_FAILURE;
  591. }
  592. break;
  593. case 't':
  594. if (tzdefault != NULL) {
  595. fprintf(stderr,
  596. _("%s: More than one -t option"
  597. " specified\n"),
  598. progname);
  599. return EXIT_FAILURE;
  600. }
  601. tzdefault = optarg;
  602. break;
  603. case 'y':
  604. if (yitcommand == NULL) {
  605. warning(_("-y is obsolescent"));
  606. yitcommand = optarg;
  607. } else {
  608. fprintf(stderr,
  609. _("%s: More than one -y option specified\n"),
  610. progname);
  611. return EXIT_FAILURE;
  612. }
  613. break;
  614. case 'L':
  615. if (leapsec == NULL)
  616. leapsec = optarg;
  617. else {
  618. fprintf(stderr,
  619. _("%s: More than one -L option specified\n"),
  620. progname);
  621. return EXIT_FAILURE;
  622. }
  623. break;
  624. case 'v':
  625. noise = true;
  626. break;
  627. case 's':
  628. warning(_("-s ignored"));
  629. break;
  630. }
  631. if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
  632. usage(stderr, EXIT_FAILURE); /* usage message by request */
  633. if (directory == NULL)
  634. directory = TZDIR;
  635. if (tzdefault == NULL)
  636. tzdefault = TZDEFAULT;
  637. if (yitcommand == NULL)
  638. yitcommand = "yearistype";
  639. if (optind < argc && leapsec != NULL) {
  640. infile(leapsec);
  641. adjleap();
  642. }
  643. for (k = optind; k < argc; k++)
  644. infile(argv[k]);
  645. if (errors)
  646. return EXIT_FAILURE;
  647. associate();
  648. change_directory(directory);
  649. for (i = 0; i < nzones; i = j) {
  650. /*
  651. ** Find the next non-continuation zone entry.
  652. */
  653. for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
  654. continue;
  655. outzone(&zones[i], j - i);
  656. }
  657. /*
  658. ** Make links.
  659. */
  660. for (i = 0; i < nlinks; ++i) {
  661. eat(links[i].l_filename, links[i].l_linenum);
  662. dolink(links[i].l_from, links[i].l_to, false);
  663. if (noise)
  664. for (j = 0; j < nlinks; ++j)
  665. if (strcmp(links[i].l_to,
  666. links[j].l_from) == 0)
  667. warning(_("link to link"));
  668. }
  669. if (lcltime != NULL) {
  670. eat(_("command line"), 1);
  671. dolink(lcltime, tzdefault, true);
  672. }
  673. if (psxrules != NULL) {
  674. eat(_("command line"), 1);
  675. dolink(psxrules, TZDEFRULES, true);
  676. }
  677. if (warnings && (ferror(stderr) || fclose(stderr) != 0))
  678. return EXIT_FAILURE;
  679. return errors ? EXIT_FAILURE : EXIT_SUCCESS;
  680. }
  681. static bool
  682. componentcheck(char const *name, char const *component,
  683. char const *component_end)
  684. {
  685. enum { component_len_max = 14 };
  686. ptrdiff_t component_len = component_end - component;
  687. if (component_len == 0) {
  688. if (!*name)
  689. error (_("empty file name"));
  690. else
  691. error (_(component == name
  692. ? "file name '%s' begins with '/'"
  693. : *component_end
  694. ? "file name '%s' contains '//'"
  695. : "file name '%s' ends with '/'"),
  696. name);
  697. return false;
  698. }
  699. if (0 < component_len && component_len <= 2
  700. && component[0] == '.' && component_end[-1] == '.') {
  701. int len = component_len;
  702. error(_("file name '%s' contains '%.*s' component"),
  703. name, len, component);
  704. return false;
  705. }
  706. if (noise) {
  707. if (0 < component_len && component[0] == '-')
  708. warning(_("file name '%s' component contains leading '-'"),
  709. name);
  710. if (component_len_max < component_len)
  711. warning(_("file name '%s' contains overlength component"
  712. " '%.*s...'"),
  713. name, component_len_max, component);
  714. }
  715. return true;
  716. }
  717. static bool
  718. namecheck(const char *name)
  719. {
  720. register char const *cp;
  721. /* Benign characters in a portable file name. */
  722. static char const benign[] =
  723. "-/_"
  724. "abcdefghijklmnopqrstuvwxyz"
  725. "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  726. /* Non-control chars in the POSIX portable character set,
  727. excluding the benign characters. */
  728. static char const printable_and_not_benign[] =
  729. " !\"#$%&'()*+,.0123456789:;<=>?@[\\]^`{|}~";
  730. register char const *component = name;
  731. for (cp = name; *cp; cp++) {
  732. unsigned char c = *cp;
  733. if (noise && !strchr(benign, c)) {
  734. warning((strchr(printable_and_not_benign, c)
  735. ? _("file name '%s' contains byte '%c'")
  736. : _("file name '%s' contains byte '\\%o'")),
  737. name, c);
  738. }
  739. if (c == '/') {
  740. if (!componentcheck(name, component, cp))
  741. return false;
  742. component = cp + 1;
  743. }
  744. }
  745. return componentcheck(name, component, cp);
  746. }
  747. /* Create symlink contents suitable for symlinking FROM to TO, as a
  748. freshly allocated string. FROM should be a relative file name, and
  749. is relative to the global variable DIRECTORY. TO can be either
  750. relative or absolute. */
  751. static char *
  752. relname(char const *from, char const *to)
  753. {
  754. size_t i, taillen, dotdotetcsize;
  755. size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX;
  756. char const *f = from;
  757. char *result = NULL;
  758. if (*to == '/') {
  759. /* Make F absolute too. */
  760. size_t len = strlen(directory);
  761. bool needslash = len && directory[len - 1] != '/';
  762. linksize = len + needslash + strlen(from) + 1;
  763. f = result = emalloc(linksize);
  764. strcpy(result, directory);
  765. result[len] = '/';
  766. strcpy(result + len + needslash, from);
  767. }
  768. for (i = 0; f[i] && f[i] == to[i]; i++)
  769. if (f[i] == '/')
  770. dir_len = i + 1;
  771. for (; to[i]; i++)
  772. dotdots += to[i] == '/' && to[i - 1] != '/';
  773. taillen = strlen(f + dir_len);
  774. dotdotetcsize = 3 * dotdots + taillen + 1;
  775. if (dotdotetcsize <= linksize) {
  776. if (!result)
  777. result = emalloc(dotdotetcsize);
  778. for (i = 0; i < dotdots; i++)
  779. memcpy(result + 3 * i, "../", 3);
  780. memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
  781. }
  782. return result;
  783. }
  784. /* Hard link FROM to TO, following any symbolic links.
  785. Return 0 if successful, an error number otherwise. */
  786. static int
  787. hardlinkerr(char const *from, char const *to)
  788. {
  789. int r = linkat(AT_FDCWD, from, AT_FDCWD, to, AT_SYMLINK_FOLLOW);
  790. return r == 0 ? 0 : errno;
  791. }
  792. static void
  793. dolink(char const *fromfield, char const *tofield, bool staysymlink)
  794. {
  795. bool todirs_made = false;
  796. int link_errno;
  797. /*
  798. ** We get to be careful here since
  799. ** there's a fair chance of root running us.
  800. */
  801. if (itsdir(fromfield)) {
  802. fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
  803. progname, directory, fromfield, strerror(EPERM));
  804. exit(EXIT_FAILURE);
  805. }
  806. if (staysymlink)
  807. staysymlink = itssymlink(tofield);
  808. if (remove(tofield) == 0)
  809. todirs_made = true;
  810. else if (errno != ENOENT) {
  811. char const *e = strerror(errno);
  812. fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
  813. progname, directory, tofield, e);
  814. exit(EXIT_FAILURE);
  815. }
  816. link_errno = staysymlink ? ENOTSUP : hardlinkerr(fromfield, tofield);
  817. if (link_errno == ENOENT && !todirs_made) {
  818. mkdirs(tofield, true);
  819. todirs_made = true;
  820. link_errno = hardlinkerr(fromfield, tofield);
  821. }
  822. if (link_errno != 0) {
  823. bool absolute = *fromfield == '/';
  824. char *linkalloc = absolute ? NULL : relname(fromfield, tofield);
  825. char const *contents = absolute ? fromfield : linkalloc;
  826. int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
  827. if (!todirs_made
  828. && (symlink_errno == ENOENT || symlink_errno == ENOTSUP)) {
  829. mkdirs(tofield, true);
  830. if (symlink_errno == ENOENT)
  831. symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
  832. }
  833. free(linkalloc);
  834. if (symlink_errno == 0) {
  835. if (link_errno != ENOTSUP)
  836. warning(_("symbolic link used because hard link failed: %s"),
  837. strerror(link_errno));
  838. } else {
  839. FILE *fp, *tp;
  840. int c;
  841. fp = fopen(fromfield, "rb");
  842. if (!fp) {
  843. char const *e = strerror(errno);
  844. fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
  845. progname, directory, fromfield, e);
  846. exit(EXIT_FAILURE);
  847. }
  848. tp = fopen(tofield, "wb");
  849. if (!tp) {
  850. char const *e = strerror(errno);
  851. fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
  852. progname, directory, tofield, e);
  853. exit(EXIT_FAILURE);
  854. }
  855. while ((c = getc(fp)) != EOF)
  856. putc(c, tp);
  857. close_file(fp, directory, fromfield);
  858. close_file(tp, directory, tofield);
  859. if (link_errno != ENOTSUP)
  860. warning(_("copy used because hard link failed: %s"),
  861. strerror(link_errno));
  862. else if (symlink_errno != ENOTSUP)
  863. warning(_("copy used because symbolic link failed: %s"),
  864. strerror(symlink_errno));
  865. }
  866. }
  867. }
  868. #define TIME_T_BITS_IN_FILE 64
  869. static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
  870. static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
  871. /* Return true if NAME is a directory. */
  872. static bool
  873. itsdir(char const *name)
  874. {
  875. struct stat st;
  876. int res = stat(name, &st);
  877. #ifdef S_ISDIR
  878. if (res == 0)
  879. return S_ISDIR(st.st_mode) != 0;
  880. #endif
  881. if (res == 0 || errno == EOVERFLOW) {
  882. size_t n = strlen(name);
  883. char *nameslashdot = emalloc(n + 3);
  884. bool dir;
  885. memcpy(nameslashdot, name, n);
  886. strcpy(&nameslashdot[n], &"/."[! (n && name[n - 1] != '/')]);
  887. dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
  888. free(nameslashdot);
  889. return dir;
  890. }
  891. return false;
  892. }
  893. /* Return true if NAME is a symbolic link. */
  894. static bool
  895. itssymlink(char const *name)
  896. {
  897. char c;
  898. return 0 <= readlink(name, &c, 1);
  899. }
  900. /*
  901. ** Associate sets of rules with zones.
  902. */
  903. /*
  904. ** Sort by rule name.
  905. */
  906. static int
  907. rcomp(const void *cp1, const void *cp2)
  908. {
  909. return strcmp(((const struct rule *) cp1)->r_name,
  910. ((const struct rule *) cp2)->r_name);
  911. }
  912. static void
  913. associate(void)
  914. {
  915. register struct zone * zp;
  916. register struct rule * rp;
  917. register ptrdiff_t i, j, base, out;
  918. if (nrules != 0) {
  919. qsort(rules, nrules, sizeof *rules, rcomp);
  920. for (i = 0; i < nrules - 1; ++i) {
  921. if (strcmp(rules[i].r_name,
  922. rules[i + 1].r_name) != 0)
  923. continue;
  924. if (strcmp(rules[i].r_filename,
  925. rules[i + 1].r_filename) == 0)
  926. continue;
  927. eat(rules[i].r_filename, rules[i].r_linenum);
  928. warning(_("same rule name in multiple files"));
  929. eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
  930. warning(_("same rule name in multiple files"));
  931. for (j = i + 2; j < nrules; ++j) {
  932. if (strcmp(rules[i].r_name,
  933. rules[j].r_name) != 0)
  934. break;
  935. if (strcmp(rules[i].r_filename,
  936. rules[j].r_filename) == 0)
  937. continue;
  938. if (strcmp(rules[i + 1].r_filename,
  939. rules[j].r_filename) == 0)
  940. continue;
  941. break;
  942. }
  943. i = j - 1;
  944. }
  945. }
  946. for (i = 0; i < nzones; ++i) {
  947. zp = &zones[i];
  948. zp->z_rules = NULL;
  949. zp->z_nrules = 0;
  950. }
  951. for (base = 0; base < nrules; base = out) {
  952. rp = &rules[base];
  953. for (out = base + 1; out < nrules; ++out)
  954. if (strcmp(rp->r_name, rules[out].r_name) != 0)
  955. break;
  956. for (i = 0; i < nzones; ++i) {
  957. zp = &zones[i];
  958. if (strcmp(zp->z_rule, rp->r_name) != 0)
  959. continue;
  960. zp->z_rules = rp;
  961. zp->z_nrules = out - base;
  962. }
  963. }
  964. for (i = 0; i < nzones; ++i) {
  965. zp = &zones[i];
  966. if (zp->z_nrules == 0) {
  967. /*
  968. ** Maybe we have a local standard time offset.
  969. */
  970. eat(zp->z_filename, zp->z_linenum);
  971. zp->z_stdoff = getstdoff(zp->z_rule, &zp->z_isdst);
  972. /*
  973. ** Note, though, that if there's no rule,
  974. ** a '%s' in the format is a bad thing.
  975. */
  976. if (zp->z_format_specifier == 's')
  977. error("%s", _("%s in ruleless zone"));
  978. }
  979. }
  980. if (errors)
  981. exit(EXIT_FAILURE);
  982. }
  983. static void
  984. infile(const char *name)
  985. {
  986. register FILE * fp;
  987. register char ** fields;
  988. register char * cp;
  989. register const struct lookup * lp;
  990. register int nfields;
  991. register bool wantcont;
  992. register lineno num;
  993. char buf[BUFSIZ];
  994. if (strcmp(name, "-") == 0) {
  995. name = _("standard input");
  996. fp = stdin;
  997. } else if ((fp = fopen(name, "r")) == NULL) {
  998. const char *e = strerror(errno);
  999. fprintf(stderr, _("%s: Can't open %s: %s\n"),
  1000. progname, name, e);
  1001. exit(EXIT_FAILURE);
  1002. }
  1003. wantcont = false;
  1004. for (num = 1; ; ++num) {
  1005. eat(name, num);
  1006. if (fgets(buf, sizeof buf, fp) != buf)
  1007. break;
  1008. cp = strchr(buf, '\n');
  1009. if (cp == NULL) {
  1010. error(_("line too long"));
  1011. exit(EXIT_FAILURE);
  1012. }
  1013. *cp = '\0';
  1014. fields = getfields(buf);
  1015. nfields = 0;
  1016. while (fields[nfields] != NULL) {
  1017. static char nada;
  1018. if (strcmp(fields[nfields], "-") == 0)
  1019. fields[nfields] = &nada;
  1020. ++nfields;
  1021. }
  1022. if (nfields == 0) {
  1023. /* nothing to do */
  1024. } else if (wantcont) {
  1025. wantcont = inzcont(fields, nfields);
  1026. } else {
  1027. struct lookup const *line_codes
  1028. = name == leapsec ? leap_line_codes : zi_line_codes;
  1029. lp = byword(fields[0], line_codes);
  1030. if (lp == NULL)
  1031. error(_("input line of unknown type"));
  1032. else switch (lp->l_value) {
  1033. case LC_RULE:
  1034. inrule(fields, nfields);
  1035. wantcont = false;
  1036. break;
  1037. case LC_ZONE:
  1038. wantcont = inzone(fields, nfields);
  1039. break;
  1040. case LC_LINK:
  1041. inlink(fields, nfields);
  1042. wantcont = false;
  1043. break;
  1044. case LC_LEAP:
  1045. inleap(fields, nfields);
  1046. wantcont = false;
  1047. break;
  1048. default: /* "cannot happen" */
  1049. fprintf(stderr,
  1050. _("%s: panic: Invalid l_value %d\n"),
  1051. progname, lp->l_value);
  1052. exit(EXIT_FAILURE);
  1053. }
  1054. }
  1055. free(fields);
  1056. }
  1057. close_file(fp, NULL, filename);
  1058. if (wantcont)
  1059. error(_("expected continuation line not found"));
  1060. }
  1061. /*
  1062. ** Convert a string of one of the forms
  1063. ** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
  1064. ** into a number of seconds.
  1065. ** A null string maps to zero.
  1066. ** Call error with errstring and return zero on errors.
  1067. */
  1068. static zic_t
  1069. gethms(char const *string, char const *errstring)
  1070. {
  1071. zic_t hh;
  1072. int sign, mm = 0, ss = 0;
  1073. char hhx, mmx, ssx, xr = '0', xs;
  1074. int tenths = 0;
  1075. bool ok = true;
  1076. if (string == NULL || *string == '\0')
  1077. return 0;
  1078. if (*string == '-') {
  1079. sign = -1;
  1080. ++string;
  1081. } else sign = 1;
  1082. switch (sscanf(string,
  1083. "%"SCNdZIC"%c%d%c%d%c%1d%*[0]%c%*[0123456789]%c",
  1084. &hh, &hhx, &mm, &mmx, &ss, &ssx, &tenths, &xr, &xs)) {
  1085. default: ok = false; break;
  1086. case 8:
  1087. ok = '0' <= xr && xr <= '9';
  1088. /* fallthrough */
  1089. case 7:
  1090. ok &= ssx == '.';
  1091. if (ok && noise)
  1092. warning(_("fractional seconds rejected by"
  1093. " pre-2018 versions of zic"));
  1094. /* fallthrough */
  1095. case 5: ok &= mmx == ':'; /* fallthrough */
  1096. case 3: ok &= hhx == ':'; /* fallthrough */
  1097. case 1: break;
  1098. }
  1099. if (!ok) {
  1100. error("%s", errstring);
  1101. return 0;
  1102. }
  1103. if (hh < 0 ||
  1104. mm < 0 || mm >= MINSPERHOUR ||
  1105. ss < 0 || ss > SECSPERMIN) {
  1106. error("%s", errstring);
  1107. return 0;
  1108. }
  1109. if (ZIC_MAX / SECSPERHOUR < hh) {
  1110. error(_("time overflow"));
  1111. return 0;
  1112. }
  1113. ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
  1114. if (noise && (hh > HOURSPERDAY ||
  1115. (hh == HOURSPERDAY && (mm != 0 || ss != 0))))
  1116. warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
  1117. return oadd(sign * hh * SECSPERHOUR,
  1118. sign * (mm * SECSPERMIN + ss));
  1119. }
  1120. static zic_t
  1121. getstdoff(char *field, bool *isdst)
  1122. {
  1123. int dst = -1;
  1124. zic_t stdoff;
  1125. size_t fieldlen = strlen(field);
  1126. if (fieldlen != 0) {
  1127. char *ep = field + fieldlen - 1;
  1128. switch (*ep) {
  1129. case 'd': dst = 1; *ep = '\0'; break;
  1130. case 's': dst = 0; *ep = '\0'; break;
  1131. }
  1132. }
  1133. stdoff = gethms(field, _("invalid saved time"));
  1134. *isdst = dst < 0 ? stdoff != 0 : dst;
  1135. return stdoff;
  1136. }
  1137. static void
  1138. inrule(char **fields, int nfields)
  1139. {
  1140. static struct rule r;
  1141. if (nfields != RULE_FIELDS) {
  1142. error(_("wrong number of fields on Rule line"));
  1143. return;
  1144. }
  1145. switch (*fields[RF_NAME]) {
  1146. case '\0':
  1147. case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
  1148. case '+': case '-':
  1149. case '0': case '1': case '2': case '3': case '4':
  1150. case '5': case '6': case '7': case '8': case '9':
  1151. error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
  1152. return;
  1153. }
  1154. r.r_filename = filename;
  1155. r.r_linenum = linenum;
  1156. r.r_stdoff = getstdoff(fields[RF_STDOFF], &r.r_isdst);
  1157. rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
  1158. fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
  1159. r.r_name = ecpyalloc(fields[RF_NAME]);
  1160. r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
  1161. if (max_abbrvar_len < strlen(r.r_abbrvar))
  1162. max_abbrvar_len = strlen(r.r_abbrvar);
  1163. rules = growalloc(rules, sizeof *rules, nrules, &nrules_alloc);
  1164. rules[nrules++] = r;
  1165. }
  1166. static bool
  1167. inzone(char **fields, int nfields)
  1168. {
  1169. register ptrdiff_t i;
  1170. if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
  1171. error(_("wrong number of fields on Zone line"));
  1172. return false;
  1173. }
  1174. if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) {
  1175. error(
  1176. _("\"Zone %s\" line and -l option are mutually exclusive"),
  1177. tzdefault);
  1178. return false;
  1179. }
  1180. if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
  1181. error(
  1182. _("\"Zone %s\" line and -p option are mutually exclusive"),
  1183. TZDEFRULES);
  1184. return false;
  1185. }
  1186. for (i = 0; i < nzones; ++i)
  1187. if (zones[i].z_name != NULL &&
  1188. strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
  1189. error(_("duplicate zone name %s"
  1190. " (file \"%s\", line %"PRIdMAX")"),
  1191. fields[ZF_NAME],
  1192. zones[i].z_filename,
  1193. zones[i].z_linenum);
  1194. return false;
  1195. }
  1196. return inzsub(fields, nfields, false);
  1197. }
  1198. static bool
  1199. inzcont(char **fields, int nfields)
  1200. {
  1201. if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
  1202. error(_("wrong number of fields on Zone continuation line"));
  1203. return false;
  1204. }
  1205. return inzsub(fields, nfields, true);
  1206. }
  1207. static bool
  1208. inzsub(char **fields, int nfields, bool iscont)
  1209. {
  1210. register char * cp;
  1211. char * cp1;
  1212. static struct zone z;
  1213. register int i_gmtoff, i_rule, i_format;
  1214. register int i_untilyear, i_untilmonth;
  1215. register int i_untilday, i_untiltime;
  1216. register bool hasuntil;
  1217. if (iscont) {
  1218. i_gmtoff = ZFC_GMTOFF;
  1219. i_rule = ZFC_RULE;
  1220. i_format = ZFC_FORMAT;
  1221. i_untilyear = ZFC_TILYEAR;
  1222. i_untilmonth = ZFC_TILMONTH;
  1223. i_untilday = ZFC_TILDAY;
  1224. i_untiltime = ZFC_TILTIME;
  1225. z.z_name = NULL;
  1226. } else if (!namecheck(fields[ZF_NAME]))
  1227. return false;
  1228. else {
  1229. i_gmtoff = ZF_GMTOFF;
  1230. i_rule = ZF_RULE;
  1231. i_format = ZF_FORMAT;
  1232. i_untilyear = ZF_TILYEAR;
  1233. i_untilmonth = ZF_TILMONTH;
  1234. i_untilday = ZF_TILDAY;
  1235. i_untiltime = ZF_TILTIME;
  1236. z.z_name = ecpyalloc(fields[ZF_NAME]);
  1237. }
  1238. z.z_filename = filename;
  1239. z.z_linenum = linenum;
  1240. z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));
  1241. if ((cp = strchr(fields[i_format], '%')) != 0) {
  1242. if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
  1243. || strchr(fields[i_format], '/')) {
  1244. error(_("invalid abbreviation format"));
  1245. return false;
  1246. }
  1247. }
  1248. z.z_rule = ecpyalloc(fields[i_rule]);
  1249. z.z_format = cp1 = ecpyalloc(fields[i_format]);
  1250. z.z_format_specifier = cp ? *cp : '\0';
  1251. if (z.z_format_specifier == 'z') {
  1252. if (noise)
  1253. warning(_("format '%s' not handled by pre-2015 versions of zic"),
  1254. z.z_format);
  1255. cp1[cp - fields[i_format]] = 's';
  1256. }
  1257. if (max_format_len < strlen(z.z_format))
  1258. max_format_len = strlen(z.z_format);
  1259. hasuntil = nfields > i_untilyear;
  1260. if (hasuntil) {
  1261. z.z_untilrule.r_filename = filename;
  1262. z.z_untilrule.r_linenum = linenum;
  1263. rulesub(&z.z_untilrule,
  1264. fields[i_untilyear],
  1265. "only",
  1266. "",
  1267. (nfields > i_untilmonth) ?
  1268. fields[i_untilmonth] : "Jan",
  1269. (nfields > i_untilday) ? fields[i_untilday] : "1",
  1270. (nfields > i_untiltime) ? fields[i_untiltime] : "0");
  1271. z.z_untiltime = rpytime(&z.z_untilrule,
  1272. z.z_untilrule.r_loyear);
  1273. if (iscont && nzones > 0 &&
  1274. z.z_untiltime > min_time &&
  1275. z.z_untiltime < max_time &&
  1276. zones[nzones - 1].z_untiltime > min_time &&
  1277. zones[nzones - 1].z_untiltime < max_time &&
  1278. zones[nzones - 1].z_untiltime >= z.z_untiltime) {
  1279. error(_(
  1280. "Zone continuation line end time is not after end time of previous line"
  1281. ));
  1282. return false;
  1283. }
  1284. }
  1285. zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
  1286. zones[nzones++] = z;
  1287. /*
  1288. ** If there was an UNTIL field on this line,
  1289. ** there's more information about the zone on the next line.
  1290. */
  1291. return hasuntil;
  1292. }
  1293. static void
  1294. inleap(char **fields, int nfields)
  1295. {
  1296. register const char * cp;
  1297. register const struct lookup * lp;
  1298. register zic_t i, j;
  1299. zic_t year;
  1300. int month, day;
  1301. zic_t dayoff, tod;
  1302. zic_t t;
  1303. char xs;
  1304. if (nfields != LEAP_FIELDS) {
  1305. error(_("wrong number of fields on Leap line"));
  1306. return;
  1307. }
  1308. dayoff = 0;
  1309. cp = fields[LP_YEAR];
  1310. if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) {
  1311. /*
  1312. ** Leapin' Lizards!
  1313. */
  1314. error(_("invalid leaping year"));
  1315. return;
  1316. }
  1317. if (!leapseen || leapmaxyear < year)
  1318. leapmaxyear = year;
  1319. if (!leapseen || leapminyear > year)
  1320. leapminyear = year;
  1321. leapseen = true;
  1322. j = EPOCH_YEAR;
  1323. while (j != year) {
  1324. if (year > j) {
  1325. i = len_years[isleap(j)];
  1326. ++j;
  1327. } else {
  1328. --j;
  1329. i = -len_years[isleap(j)];
  1330. }
  1331. dayoff = oadd(dayoff, i);
  1332. }
  1333. if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
  1334. error(_("invalid month name"));
  1335. return;
  1336. }
  1337. month = lp->l_value;
  1338. j = TM_JANUARY;
  1339. while (j != month) {
  1340. i = len_months[isleap(year)][j];
  1341. dayoff = oadd(dayoff, i);
  1342. ++j;
  1343. }
  1344. cp = fields[LP_DAY];
  1345. if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
  1346. day <= 0 || day > len_months[isleap(year)][month]) {
  1347. error(_("invalid day of month"));
  1348. return;
  1349. }
  1350. dayoff = oadd(dayoff, day - 1);
  1351. if (dayoff < min_time / SECSPERDAY) {
  1352. error(_("time too small"));
  1353. return;
  1354. }
  1355. if (dayoff > max_time / SECSPERDAY) {
  1356. error(_("time too large"));
  1357. return;
  1358. }
  1359. t = dayoff * SECSPERDAY;
  1360. tod = gethms(fields[LP_TIME], _("invalid time of day"));
  1361. cp = fields[LP_CORR];
  1362. {
  1363. register bool positive;
  1364. int count;
  1365. if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
  1366. positive = false;
  1367. count = 1;
  1368. } else if (strcmp(cp, "+") == 0) {
  1369. positive = true;
  1370. count = 1;
  1371. } else {
  1372. error(_("illegal CORRECTION field on Leap line"));
  1373. return;
  1374. }
  1375. if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
  1376. error(_(
  1377. "illegal Rolling/Stationary field on Leap line"
  1378. ));
  1379. return;
  1380. }
  1381. t = tadd(t, tod);
  1382. if (t < 0) {
  1383. error(_("leap second precedes Epoch"));
  1384. return;
  1385. }
  1386. leapadd(t, positive, lp->l_value, count);
  1387. }
  1388. }
  1389. static void
  1390. inlink(char **fields, int nfields)
  1391. {
  1392. struct link l;
  1393. if (nfields != LINK_FIELDS) {
  1394. error(_("wrong number of fields on Link line"));
  1395. return;
  1396. }
  1397. if (*fields[LF_FROM] == '\0') {
  1398. error(_("blank FROM field on Link line"));
  1399. return;
  1400. }
  1401. if (! namecheck(fields[LF_TO]))
  1402. return;
  1403. l.l_filename = filename;
  1404. l.l_linenum = linenum;
  1405. l.l_from = ecpyalloc(fields[LF_FROM]);
  1406. l.l_to = ecpyalloc(fields[LF_TO]);
  1407. links = growalloc(links, sizeof *links, nlinks, &nlinks_alloc);
  1408. links[nlinks++] = l;
  1409. }
  1410. static void
  1411. rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
  1412. const char *typep, const char *monthp, const char *dayp,
  1413. const char *timep)
  1414. {
  1415. register const struct lookup * lp;
  1416. register const char * cp;
  1417. register char * dp;
  1418. register char * ep;
  1419. char xs;
  1420. if ((lp = byword(monthp, mon_names)) == NULL) {
  1421. error(_("invalid month name"));
  1422. return;
  1423. }
  1424. rp->r_month = lp->l_value;
  1425. rp->r_todisstd = false;
  1426. rp->r_todisgmt = false;
  1427. dp = ecpyalloc(timep);
  1428. if (*dp != '\0') {
  1429. ep = dp + strlen(dp) - 1;
  1430. switch (lowerit(*ep)) {
  1431. case 's': /* Standard */
  1432. rp->r_todisstd = true;
  1433. rp->r_todisgmt = false;
  1434. *ep = '\0';
  1435. break;
  1436. case 'w': /* Wall */
  1437. rp->r_todisstd = false;
  1438. rp->r_todisgmt = false;
  1439. *ep = '\0';
  1440. break;
  1441. case 'g': /* Greenwich */
  1442. case 'u': /* Universal */
  1443. case 'z': /* Zulu */
  1444. rp->r_todisstd = true;
  1445. rp->r_todisgmt = true;
  1446. *ep = '\0';
  1447. break;
  1448. }
  1449. }
  1450. rp->r_tod = gethms(dp, _("invalid time of day"));
  1451. free(dp);
  1452. /*
  1453. ** Year work.
  1454. */
  1455. cp = loyearp;
  1456. lp = byword(cp, begin_years);
  1457. rp->r_lowasnum = lp == NULL;
  1458. if (!rp->r_lowasnum) switch (lp->l_value) {
  1459. case YR_MINIMUM:
  1460. rp->r_loyear = ZIC_MIN;
  1461. break;
  1462. case YR_MAXIMUM:
  1463. rp->r_loyear = ZIC_MAX;
  1464. break;
  1465. default: /* "cannot happen" */
  1466. fprintf(stderr,
  1467. _("%s: panic: Invalid l_value %d\n"),
  1468. progname, lp->l_value);
  1469. exit(EXIT_FAILURE);
  1470. } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
  1471. error(_("invalid starting year"));
  1472. return;
  1473. }
  1474. cp = hiyearp;
  1475. lp = byword(cp, end_years);
  1476. rp->r_hiwasnum = lp == NULL;
  1477. if (!rp->r_hiwasnum) switch (lp->l_value) {
  1478. case YR_MINIMUM:
  1479. rp->r_hiyear = ZIC_MIN;
  1480. break;
  1481. case YR_MAXIMUM:
  1482. rp->r_hiyear = ZIC_MAX;
  1483. break;
  1484. case YR_ONLY:
  1485. rp->r_hiyear = rp->r_loyear;
  1486. break;
  1487. default: /* "cannot happen" */
  1488. fprintf(stderr,
  1489. _("%s: panic: Invalid l_value %d\n"),
  1490. progname, lp->l_value);
  1491. exit(EXIT_FAILURE);
  1492. } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) {
  1493. error(_("invalid ending year"));
  1494. return;
  1495. }
  1496. if (rp->r_loyear > rp->r_hiyear) {
  1497. error(_("starting year greater than ending year"));
  1498. return;
  1499. }
  1500. if (*typep == '\0')
  1501. rp->r_yrtype = NULL;
  1502. else {
  1503. if (rp->r_loyear == rp->r_hiyear) {
  1504. error(_("typed single year"));
  1505. return;
  1506. }
  1507. warning(_("year type \"%s\" is obsolete; use \"-\" instead"),
  1508. typep);
  1509. rp->r_yrtype = ecpyalloc(typep);
  1510. }
  1511. /*
  1512. ** Day work.
  1513. ** Accept things such as:
  1514. ** 1
  1515. ** lastSunday
  1516. ** last-Sunday (undocumented; warn about this)
  1517. ** Sun<=20
  1518. ** Sun>=7
  1519. */
  1520. dp = ecpyalloc(dayp);
  1521. if ((lp = byword(dp, lasts)) != NULL) {
  1522. rp->r_dycode = DC_DOWLEQ;
  1523. rp->r_wday = lp->l_value;
  1524. rp->r_dayofmonth = len_months[1][rp->r_month];
  1525. } else {
  1526. if ((ep = strchr(dp, '<')) != 0)
  1527. rp->r_dycode = DC_DOWLEQ;
  1528. else if ((ep = strchr(dp, '>')) != 0)
  1529. rp->r_dycode = DC_DOWGEQ;
  1530. else {
  1531. ep = dp;
  1532. rp->r_dycode = DC_DOM;
  1533. }
  1534. if (rp->r_dycode != DC_DOM) {
  1535. *ep++ = 0;
  1536. if (*ep++ != '=') {
  1537. error(_("invalid day of month"));
  1538. free(dp);
  1539. return;
  1540. }
  1541. if ((lp = byword(dp, wday_names)) == NULL) {
  1542. error(_("invalid weekday name"));
  1543. free(dp);
  1544. return;
  1545. }
  1546. rp->r_wday = lp->l_value;
  1547. }
  1548. if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
  1549. rp->r_dayofmonth <= 0 ||
  1550. (rp->r_dayofmonth > len_months[1][rp->r_month])) {
  1551. error(_("invalid day of month"));
  1552. free(dp);
  1553. return;
  1554. }
  1555. }
  1556. free(dp);
  1557. }
  1558. static void
  1559. convert(const int_fast32_t val, char *const buf)
  1560. {
  1561. register int i;
  1562. register int shift;
  1563. unsigned char *const b = (unsigned char *) buf;
  1564. for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
  1565. b[i] = val >> shift;
  1566. }
  1567. static void
  1568. convert64(const zic_t val, char *const buf)
  1569. {
  1570. register int i;
  1571. register int shift;
  1572. unsigned char *const b = (unsigned char *) buf;
  1573. for (i = 0, shift = 56; i < 8; ++i, shift -= 8)
  1574. b[i] = val >> shift;
  1575. }
  1576. static void
  1577. puttzcode(const int_fast32_t val, FILE *const fp)
  1578. {
  1579. char buf[4];
  1580. convert(val, buf);
  1581. fwrite(buf, sizeof buf, 1, fp);
  1582. }
  1583. static void
  1584. puttzcode64(const zic_t val, FILE *const fp)
  1585. {
  1586. char buf[8];
  1587. convert64(val, buf);
  1588. fwrite(buf, sizeof buf, 1, fp);
  1589. }
  1590. static int
  1591. atcomp(const void *avp, const void *bvp)
  1592. {
  1593. const zic_t a = ((const struct attype *) avp)->at;
  1594. const zic_t b = ((const struct attype *) bvp)->at;
  1595. return (a < b) ? -1 : (a > b);
  1596. }
  1597. static void
  1598. swaptypes(int i, int j)
  1599. {
  1600. { zic_t t = gmtoffs[i]; gmtoffs[i] = gmtoffs[j]; gmtoffs[j] = t; }
  1601. { char t = isdsts[i]; isdsts[i] = isdsts[j]; isdsts[j] = t; }
  1602. { unsigned char t = abbrinds[i]; abbrinds[i] = abbrinds[j];
  1603. abbrinds[j] = t; }
  1604. { bool t = ttisstds[i]; ttisstds[i] = ttisstds[j]; ttisstds[j] = t; }
  1605. { bool t = ttisgmts[i]; ttisgmts[i] = ttisgmts[j]; ttisgmts[j] = t; }
  1606. }
  1607. static void
  1608. writezone(const char *const name, const char *const string, char version,
  1609. int defaulttype)
  1610. {
  1611. register FILE * fp;
  1612. register ptrdiff_t i, j;
  1613. register int leapcnt32, leapi32;
  1614. register ptrdiff_t timecnt32, timei32;
  1615. register int pass;
  1616. static const struct tzhead tzh0;
  1617. static struct tzhead tzh;
  1618. bool dir_checked = false;
  1619. zic_t one = 1;
  1620. zic_t y2038_boundary = one << 31;
  1621. ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
  1622. /* Allocate the ATS and TYPES arrays via a single malloc,
  1623. as this is a bit faster. */
  1624. zic_t *ats = emalloc(align_to(size_product(nats, sizeof *ats + 1),
  1625. _Alignof(zic_t)));
  1626. void *typesptr = ats + nats;
  1627. unsigned char *types = typesptr;
  1628. /*
  1629. ** Sort.
  1630. */
  1631. if (timecnt > 1)
  1632. qsort(attypes, timecnt, sizeof *attypes, atcomp);
  1633. /*
  1634. ** Optimize.
  1635. */
  1636. {
  1637. ptrdiff_t fromi, toi;
  1638. toi = 0;
  1639. fromi = 0;
  1640. for ( ; fromi < timecnt; ++fromi) {
  1641. if (toi != 0 && ((attypes[fromi].at +
  1642. gmtoffs[attypes[toi - 1].type]) <=
  1643. (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
  1644. : attypes[toi - 2].type]))) {
  1645. attypes[toi - 1].type =
  1646. attypes[fromi].type;
  1647. continue;
  1648. }
  1649. if (toi == 0
  1650. || attypes[fromi].dontmerge
  1651. || attypes[toi - 1].type != attypes[fromi].type)
  1652. attypes[toi++] = attypes[fromi];
  1653. }
  1654. timecnt = toi;
  1655. }
  1656. if (noise && timecnt > 1200) {
  1657. if (timecnt > TZ_MAX_TIMES)
  1658. warning(_("reference clients mishandle"
  1659. " more than %d transition times"),
  1660. TZ_MAX_TIMES);
  1661. else
  1662. warning(_("pre-2014 clients may mishandle"
  1663. " more than 1200 transition times"));
  1664. }
  1665. /*
  1666. ** Transfer.
  1667. */
  1668. for (i = 0; i < timecnt; ++i) {
  1669. ats[i] = attypes[i].at;
  1670. types[i] = attypes[i].type;
  1671. }
  1672. /*
  1673. ** Correct for leap seconds.
  1674. */
  1675. for (i = 0; i < timecnt; ++i) {
  1676. j = leapcnt;
  1677. while (--j >= 0)
  1678. if (ats[i] > trans[j] - corr[j]) {
  1679. ats[i] = tadd(ats[i], corr[j]);
  1680. break;
  1681. }
  1682. }
  1683. /* Work around QTBUG-53071 for timestamps less than y2038_boundary - 1,
  1684. by inserting a no-op transition at time y2038_boundary - 1.
  1685. This works only for timestamps before the boundary, which
  1686. should be good enough in practice as QTBUG-53071 should be
  1687. long-dead by 2038. Do this after correcting for leap
  1688. seconds, as the idea is to insert a transition just before
  1689. 32-bit time_t rolls around, and this occurs at a slightly
  1690. different moment if transitions are leap-second corrected. */
  1691. if (WORK_AROUND_QTBUG_53071 && timecnt != 0
  1692. && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<')) {
  1693. ats[timecnt] = y2038_boundary - 1;
  1694. types[timecnt] = types[timecnt - 1];
  1695. timecnt++;
  1696. }
  1697. /*
  1698. ** Figure out 32-bit-limited starts and counts.
  1699. */
  1700. timecnt32 = timecnt;
  1701. timei32 = 0;
  1702. leapcnt32 = leapcnt;
  1703. leapi32 = 0;
  1704. while (0 < timecnt32 && INT32_MAX < ats[timecnt32 - 1])
  1705. --timecnt32;
  1706. while (1 < timecnt32 && ats[timei32] < INT32_MIN
  1707. && ats[timei32 + 1] <= INT32_MIN) {
  1708. /* Discard too-low transitions, except keep any last too-low
  1709. transition if no transition is exactly at INT32_MIN.
  1710. The kept transition will be output as an INT32_MIN
  1711. "transition" appropriate for buggy 32-bit clients that do
  1712. not use time type 0 for timestamps before the first
  1713. transition; see below. */
  1714. --timecnt32;
  1715. ++timei32;
  1716. }
  1717. while (0 < leapcnt32 && INT32_MAX < trans[leapcnt32 - 1])
  1718. --leapcnt32;
  1719. while (0 < leapcnt32 && trans[leapi32] < INT32_MIN) {
  1720. --leapcnt32;
  1721. ++leapi32;
  1722. }
  1723. /*
  1724. ** Remove old file, if any, to snap links.
  1725. */
  1726. if (remove(name) == 0)
  1727. dir_checked = true;
  1728. else if (errno != ENOENT) {
  1729. const char *e = strerror(errno);
  1730. fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
  1731. progname, directory, name, e);
  1732. exit(EXIT_FAILURE);
  1733. }
  1734. fp = fopen(name, "wb");
  1735. if (!fp) {
  1736. int fopen_errno = errno;
  1737. if (fopen_errno == ENOENT && !dir_checked) {
  1738. mkdirs(name, true);
  1739. fp = fopen(name, "wb");
  1740. fopen_errno = errno;
  1741. }
  1742. if (!fp) {
  1743. fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
  1744. progname, directory, name, strerror(fopen_errno));
  1745. exit(EXIT_FAILURE);
  1746. }
  1747. }
  1748. for (pass = 1; pass <= 2; ++pass) {
  1749. register ptrdiff_t thistimei, thistimecnt, thistimelim;
  1750. register int thisleapi, thisleapcnt, thisleaplim;
  1751. int old0;
  1752. char omittype[TZ_MAX_TYPES];
  1753. int typemap[TZ_MAX_TYPES];
  1754. register int thistypecnt;
  1755. char thischars[TZ_MAX_CHARS];
  1756. int thischarcnt;
  1757. bool toomanytimes;
  1758. int indmap[TZ_MAX_CHARS];
  1759. if (pass == 1) {
  1760. thistimei = timei32;
  1761. thistimecnt = timecnt32;
  1762. toomanytimes = thistimecnt >> 31 >> 1 != 0;
  1763. thisleapi = leapi32;
  1764. thisleapcnt = leapcnt32;
  1765. } else {
  1766. thistimei = 0;
  1767. thistimecnt = timecnt;
  1768. toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
  1769. thisleapi = 0;
  1770. thisleapcnt = leapcnt;
  1771. }
  1772. if (toomanytimes)
  1773. error(_("too many transition times"));
  1774. thistimelim = thistimei + thistimecnt;
  1775. thisleaplim = thisleapi + thisleapcnt;
  1776. memset(omittype, true, typecnt);
  1777. omittype[defaulttype] = false;
  1778. for (i = thistimei; i < thistimelim; i++)
  1779. omittype[types[i]] = false;
  1780. /* Reorder types to make DEFAULTTYPE type 0.
  1781. Use TYPEMAP to swap OLD0 and DEFAULTTYPE so that
  1782. DEFAULTTYPE appears as type 0 in the output instead
  1783. of OLD0. TYPEMAP also omits unused types. */
  1784. old0 = strlen(omittype);
  1785. swaptypes(old0, defaulttype);
  1786. #ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
  1787. /*
  1788. ** For some pre-2011 systems: if the last-to-be-written
  1789. ** standard (or daylight) type has an offset different from the
  1790. ** most recently used offset,
  1791. ** append an (unused) copy of the most recently used type
  1792. ** (to help get global "altzone" and "timezone" variables
  1793. ** set correctly).
  1794. */
  1795. {
  1796. register int mrudst, mrustd, hidst, histd, type;
  1797. hidst = histd = mrudst = mrustd = -1;
  1798. for (i = thistimei; i < thistimelim; ++i)
  1799. if (isdsts[types[i]])
  1800. mrudst = types[i];
  1801. else mrustd = types[i];
  1802. for (i = old0; i < typecnt; i++)
  1803. if (!omittype[i]) {
  1804. if (isdsts[i])
  1805. hidst = i;
  1806. else histd = i;
  1807. }
  1808. if (hidst >= 0 && mrudst >= 0 && hidst != mrudst &&
  1809. gmtoffs[hidst] != gmtoffs[mrudst]) {
  1810. isdsts[mrudst] = -1;
  1811. type = addtype(gmtoffs[mrudst],
  1812. &chars[abbrinds[mrudst]],
  1813. true,
  1814. ttisstds[mrudst],
  1815. ttisgmts[mrudst]);
  1816. isdsts[mrudst] = 1;
  1817. omittype[type] = false;
  1818. }
  1819. if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
  1820. gmtoffs[histd] != gmtoffs[mrustd]) {
  1821. isdsts[mrustd] = -1;
  1822. type = addtype(gmtoffs[mrustd],
  1823. &chars[abbrinds[mrustd]],
  1824. false,
  1825. ttisstds[mrustd],
  1826. ttisgmts[mrustd]);
  1827. isdsts[mrustd] = 0;
  1828. omittype[type] = false;
  1829. }
  1830. }
  1831. #endif /* !defined LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
  1832. thistypecnt = 0;
  1833. for (i = old0; i < typecnt; i++)
  1834. if (!omittype[i])
  1835. typemap[i == old0 ? defaulttype
  1836. : i == defaulttype ? old0 : i]
  1837. = thistypecnt++;
  1838. for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
  1839. indmap[i] = -1;
  1840. thischarcnt = 0;
  1841. for (i = old0; i < typecnt; i++) {
  1842. register char * thisabbr;
  1843. if (omittype[i])
  1844. continue;
  1845. if (indmap[abbrinds[i]] >= 0)
  1846. continue;
  1847. thisabbr = &chars[abbrinds[i]];
  1848. for (j = 0; j < thischarcnt; ++j)
  1849. if (strcmp(&thischars[j], thisabbr) == 0)
  1850. break;
  1851. if (j == thischarcnt) {
  1852. strcpy(&thischars[thischarcnt], thisabbr);
  1853. thischarcnt += strlen(thisabbr) + 1;
  1854. }
  1855. indmap[abbrinds[i]] = j;
  1856. }
  1857. #define DO(field) fwrite(tzh.field, sizeof tzh.field, 1, fp)
  1858. tzh = tzh0;
  1859. memcpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic);
  1860. tzh.tzh_version[0] = version;
  1861. convert(thistypecnt, tzh.tzh_ttisgmtcnt);
  1862. convert(thistypecnt, tzh.tzh_ttisstdcnt);
  1863. convert(thisleapcnt, tzh.tzh_leapcnt);
  1864. convert(thistimecnt, tzh.tzh_timecnt);
  1865. convert(thistypecnt, tzh.tzh_typecnt);
  1866. convert(thischarcnt, tzh.tzh_charcnt);
  1867. DO(tzh_magic);
  1868. DO(tzh_version);
  1869. DO(tzh_reserved);
  1870. DO(tzh_ttisgmtcnt);
  1871. DO(tzh_ttisstdcnt);
  1872. DO(tzh_leapcnt);
  1873. DO(tzh_timecnt);
  1874. DO(tzh_typecnt);
  1875. DO(tzh_charcnt);
  1876. #undef DO
  1877. for (i = thistimei; i < thistimelim; ++i)
  1878. if (pass == 1)
  1879. /*
  1880. ** Output an INT32_MIN "transition"
  1881. ** if appropriate; see above.
  1882. */
  1883. puttzcode(((ats[i] < INT32_MIN) ?
  1884. INT32_MIN : ats[i]), fp);
  1885. else puttzcode64(ats[i], fp);
  1886. for (i = thistimei; i < thistimelim; ++i) {
  1887. unsigned char uc;
  1888. uc = typemap[types[i]];
  1889. fwrite(&uc, sizeof uc, 1, fp);
  1890. }
  1891. for (i = old0; i < typecnt; i++)
  1892. if (!omittype[i]) {
  1893. puttzcode(gmtoffs[i], fp);
  1894. putc(isdsts[i], fp);
  1895. putc((unsigned char) indmap[abbrinds[i]], fp);
  1896. }
  1897. if (thischarcnt != 0)
  1898. fwrite(thischars, sizeof thischars[0],
  1899. thischarcnt, fp);
  1900. for (i = thisleapi; i < thisleaplim; ++i) {
  1901. register zic_t todo;
  1902. if (roll[i]) {
  1903. if (timecnt == 0 || trans[i] < ats[0]) {
  1904. j = 0;
  1905. while (isdsts[j])
  1906. if (++j >= typecnt) {
  1907. j = 0;
  1908. break;
  1909. }
  1910. } else {
  1911. j = 1;
  1912. while (j < timecnt &&
  1913. trans[i] >= ats[j])
  1914. ++j;
  1915. j = types[j - 1];
  1916. }
  1917. todo = tadd(trans[i], -gmtoffs[j]);
  1918. } else todo = trans[i];
  1919. if (pass == 1)
  1920. puttzcode(todo, fp);
  1921. else puttzcode64(todo, fp);
  1922. puttzcode(corr[i], fp);
  1923. }
  1924. for (i = old0; i < typecnt; i++)
  1925. if (!omittype[i])
  1926. putc(ttisstds[i], fp);
  1927. for (i = old0; i < typecnt; i++)
  1928. if (!omittype[i])
  1929. putc(ttisgmts[i], fp);
  1930. swaptypes(old0, defaulttype);
  1931. }
  1932. fprintf(fp, "\n%s\n", string);
  1933. close_file(fp, directory, name);
  1934. free(ats);
  1935. }
  1936. static char const *
  1937. abbroffset(char *buf, zic_t offset)
  1938. {
  1939. char sign = '+';
  1940. int seconds, minutes;
  1941. if (offset < 0) {
  1942. offset = -offset;
  1943. sign = '-';
  1944. }
  1945. seconds = offset % SECSPERMIN;
  1946. offset /= SECSPERMIN;
  1947. minutes = offset % MINSPERHOUR;
  1948. offset /= MINSPERHOUR;
  1949. if (100 <= offset) {
  1950. error(_("%%z UT offset magnitude exceeds 99:59:59"));
  1951. return "%z";
  1952. } else {
  1953. char *p = buf;
  1954. *p++ = sign;
  1955. *p++ = '0' + offset / 10;
  1956. *p++ = '0' + offset % 10;
  1957. if (minutes | seconds) {
  1958. *p++ = '0' + minutes / 10;
  1959. *p++ = '0' + minutes % 10;
  1960. if (seconds) {
  1961. *p++ = '0' + seconds / 10;
  1962. *p++ = '0' + seconds % 10;
  1963. }
  1964. }
  1965. *p = '\0';
  1966. return buf;
  1967. }
  1968. }
  1969. static size_t
  1970. doabbr(char *abbr, struct zone const *zp, char const *letters,
  1971. bool isdst, zic_t stdoff, bool doquotes)
  1972. {
  1973. register char * cp;
  1974. register char * slashp;
  1975. register size_t len;
  1976. char const *format = zp->z_format;
  1977. slashp = strchr(format, '/');
  1978. if (slashp == NULL) {
  1979. char letterbuf[PERCENT_Z_LEN_BOUND + 1];
  1980. if (zp->z_format_specifier == 'z')
  1981. letters = abbroffset(letterbuf, zp->z_gmtoff + stdoff);
  1982. else if (!letters)
  1983. letters = "%s";
  1984. sprintf(abbr, format, letters);
  1985. } else if (isdst) {
  1986. strcpy(abbr, slashp + 1);
  1987. } else {
  1988. memcpy(abbr, format, slashp - format);
  1989. abbr[slashp - format] = '\0';
  1990. }
  1991. len = strlen(abbr);
  1992. if (!doquotes)
  1993. return len;
  1994. for (cp = abbr; is_alpha(*cp); cp++)
  1995. continue;
  1996. if (len > 0 && *cp == '\0')
  1997. return len;
  1998. abbr[len + 2] = '\0';
  1999. abbr[len + 1] = '>';
  2000. memmove(abbr + 1, abbr, len);
  2001. abbr[0] = '<';
  2002. return len + 2;
  2003. }
  2004. static void
  2005. updateminmax(const zic_t x)
  2006. {
  2007. if (min_year > x)
  2008. min_year = x;
  2009. if (max_year < x)
  2010. max_year = x;
  2011. }
  2012. static int
  2013. stringoffset(char *result, zic_t offset)
  2014. {
  2015. register int hours;
  2016. register int minutes;
  2017. register int seconds;
  2018. bool negative = offset < 0;
  2019. int len = negative;
  2020. if (negative) {
  2021. offset = -offset;
  2022. result[0] = '-';
  2023. }
  2024. seconds = offset % SECSPERMIN;
  2025. offset /= SECSPERMIN;
  2026. minutes = offset % MINSPERHOUR;
  2027. offset /= MINSPERHOUR;
  2028. hours = offset;
  2029. if (hours >= HOURSPERDAY * DAYSPERWEEK) {
  2030. result[0] = '\0';
  2031. return 0;
  2032. }
  2033. len += sprintf(result + len, "%d", hours);
  2034. if (minutes != 0 || seconds != 0) {
  2035. len += sprintf(result + len, ":%02d", minutes);
  2036. if (seconds != 0)
  2037. len += sprintf(result + len, ":%02d", seconds);
  2038. }
  2039. return len;
  2040. }
  2041. static int
  2042. stringrule(char *result, const struct rule *const rp, const zic_t dstoff,
  2043. const zic_t gmtoff)
  2044. {
  2045. register zic_t tod = rp->r_tod;
  2046. register int compat = 0;
  2047. if (rp->r_dycode == DC_DOM) {
  2048. register int month, total;
  2049. if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY)
  2050. return -1;
  2051. total = 0;
  2052. for (month = 0; month < rp->r_month; ++month)
  2053. total += len_months[0][month];
  2054. /* Omit the "J" in Jan and Feb, as that's shorter. */
  2055. if (rp->r_month <= 1)
  2056. result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
  2057. else
  2058. result += sprintf(result, "J%d", total + rp->r_dayofmonth);
  2059. } else {
  2060. register int week;
  2061. register int wday = rp->r_wday;
  2062. register int wdayoff;
  2063. if (rp->r_dycode == DC_DOWGEQ) {
  2064. wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK;
  2065. if (wdayoff)
  2066. compat = 2013;
  2067. wday -= wdayoff;
  2068. tod += wdayoff * SECSPERDAY;
  2069. week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK;
  2070. } else if (rp->r_dycode == DC_DOWLEQ) {
  2071. if (rp->r_dayofmonth == len_months[1][rp->r_month])
  2072. week = 5;
  2073. else {
  2074. wdayoff = rp->r_dayofmonth % DAYSPERWEEK;
  2075. if (wdayoff)
  2076. compat = 2013;
  2077. wday -= wdayoff;
  2078. tod += wdayoff * SECSPERDAY;
  2079. week = rp->r_dayofmonth / DAYSPERWEEK;
  2080. }
  2081. } else return -1; /* "cannot happen" */
  2082. if (wday < 0)
  2083. wday += DAYSPERWEEK;
  2084. result += sprintf(result, "M%d.%d.%d",
  2085. rp->r_month + 1, week, wday);
  2086. }
  2087. if (rp->r_todisgmt)
  2088. tod += gmtoff;
  2089. if (rp->r_todisstd && !rp->r_isdst)
  2090. tod += dstoff;
  2091. if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
  2092. *result++ = '/';
  2093. if (! stringoffset(result, tod))
  2094. return -1;
  2095. if (tod < 0) {
  2096. if (compat < 2013)
  2097. compat = 2013;
  2098. } else if (SECSPERDAY <= tod) {
  2099. if (compat < 1994)
  2100. compat = 1994;
  2101. }
  2102. }
  2103. return compat;
  2104. }
  2105. static int
  2106. rule_cmp(struct rule const *a, struct rule const *b)
  2107. {
  2108. if (!a)
  2109. return -!!b;
  2110. if (!b)
  2111. return 1;
  2112. if (a->r_hiyear != b->r_hiyear)
  2113. return a->r_hiyear < b->r_hiyear ? -1 : 1;
  2114. if (a->r_month - b->r_month != 0)
  2115. return a->r_month - b->r_month;
  2116. return a->r_dayofmonth - b->r_dayofmonth;
  2117. }
  2118. enum { YEAR_BY_YEAR_ZONE = 1 };
  2119. static int
  2120. stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
  2121. {
  2122. register const struct zone * zp;
  2123. register struct rule * rp;
  2124. register struct rule * stdrp;
  2125. register struct rule * dstrp;
  2126. register ptrdiff_t i;
  2127. register const char * abbrvar;
  2128. register int compat = 0;
  2129. register int c;
  2130. size_t len;
  2131. int offsetlen;
  2132. struct rule stdr, dstr;
  2133. result[0] = '\0';
  2134. zp = zpfirst + zonecount - 1;
  2135. stdrp = dstrp = NULL;
  2136. for (i = 0; i < zp->z_nrules; ++i) {
  2137. rp = &zp->z_rules[i];
  2138. if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX)
  2139. continue;
  2140. if (rp->r_yrtype != NULL)
  2141. continue;
  2142. if (!rp->r_isdst) {
  2143. if (stdrp == NULL)
  2144. stdrp = rp;
  2145. else return -1;
  2146. } else {
  2147. if (dstrp == NULL)
  2148. dstrp = rp;
  2149. else return -1;
  2150. }
  2151. }
  2152. if (stdrp == NULL && dstrp == NULL) {
  2153. /*
  2154. ** There are no rules running through "max".
  2155. ** Find the latest std rule in stdabbrrp
  2156. ** and latest rule of any type in stdrp.
  2157. */
  2158. register struct rule *stdabbrrp = NULL;
  2159. for (i = 0; i < zp->z_nrules; ++i) {
  2160. rp = &zp->z_rules[i];
  2161. if (!rp->r_isdst && rule_cmp(stdabbrrp, rp) < 0)
  2162. stdabbrrp = rp;
  2163. if (rule_cmp(stdrp, rp) < 0)
  2164. stdrp = rp;
  2165. }
  2166. /*
  2167. ** Horrid special case: if year is 2037,
  2168. ** presume this is a zone handled on a year-by-year basis;
  2169. ** do not try to apply a rule to the zone.
  2170. */
  2171. if (stdrp != NULL && stdrp->r_hiyear == 2037)
  2172. return YEAR_BY_YEAR_ZONE;
  2173. if (stdrp != NULL && stdrp->r_isdst) {
  2174. /* Perpetual DST. */
  2175. dstr.r_month = TM_JANUARY;
  2176. dstr.r_dycode = DC_DOM;
  2177. dstr.r_dayofmonth = 1;
  2178. dstr.r_tod = 0;
  2179. dstr.r_todisstd = dstr.r_todisgmt = false;
  2180. dstr.r_isdst = stdrp->r_isdst;
  2181. dstr.r_stdoff = stdrp->r_stdoff;
  2182. dstr.r_abbrvar = stdrp->r_abbrvar;
  2183. stdr.r_month = TM_DECEMBER;
  2184. stdr.r_dycode = DC_DOM;
  2185. stdr.r_dayofmonth = 31;
  2186. stdr.r_tod = SECSPERDAY + stdrp->r_stdoff;
  2187. stdr.r_todisstd = stdr.r_todisgmt = false;
  2188. stdr.r_isdst = false;
  2189. stdr.r_stdoff = 0;
  2190. stdr.r_abbrvar
  2191. = (stdabbrrp ? stdabbrrp->r_abbrvar : "");
  2192. dstrp = &dstr;
  2193. stdrp = &stdr;
  2194. }
  2195. }
  2196. if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_isdst))
  2197. return -1;
  2198. abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
  2199. len = doabbr(result, zp, abbrvar, false, 0, true);
  2200. offsetlen = stringoffset(result + len, -zp->z_gmtoff);
  2201. if (! offsetlen) {
  2202. result[0] = '\0';
  2203. return -1;
  2204. }
  2205. len += offsetlen;
  2206. if (dstrp == NULL)
  2207. return compat;
  2208. len += doabbr(result + len, zp, dstrp->r_abbrvar,
  2209. dstrp->r_isdst, dstrp->r_stdoff, true);
  2210. if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) {
  2211. offsetlen = stringoffset(result + len,
  2212. -(zp->z_gmtoff + dstrp->r_stdoff));
  2213. if (! offsetlen) {
  2214. result[0] = '\0';
  2215. return -1;
  2216. }
  2217. len += offsetlen;
  2218. }
  2219. result[len++] = ',';
  2220. c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
  2221. if (c < 0) {
  2222. result[0] = '\0';
  2223. return -1;
  2224. }
  2225. if (compat < c)
  2226. compat = c;
  2227. len += strlen(result + len);
  2228. result[len++] = ',';
  2229. c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
  2230. if (c < 0) {
  2231. result[0] = '\0';
  2232. return -1;
  2233. }
  2234. if (compat < c)
  2235. compat = c;
  2236. return compat;
  2237. }
  2238. static void
  2239. outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
  2240. {
  2241. register const struct zone * zp;
  2242. register struct rule * rp;
  2243. register ptrdiff_t i, j;
  2244. register bool usestart, useuntil;
  2245. register zic_t starttime, untiltime;
  2246. register zic_t gmtoff;
  2247. register zic_t stdoff;
  2248. register zic_t year;
  2249. register zic_t startoff;
  2250. register bool startttisstd;
  2251. register bool startttisgmt;
  2252. register int type;
  2253. register char * startbuf;
  2254. register char * ab;
  2255. register char * envvar;
  2256. register int max_abbr_len;
  2257. register int max_envvar_len;
  2258. register bool prodstic; /* all rules are min to max */
  2259. register int compat;
  2260. register bool do_extend;
  2261. register char version;
  2262. ptrdiff_t lastatmax = -1;
  2263. zic_t one = 1;
  2264. zic_t y2038_boundary = one << 31;
  2265. zic_t max_year0;
  2266. int defaulttype = -1;
  2267. max_abbr_len = 2 + max_format_len + max_abbrvar_len;
  2268. max_envvar_len = 2 * max_abbr_len + 5 * 9;
  2269. startbuf = emalloc(max_abbr_len + 1);
  2270. ab = emalloc(max_abbr_len + 1);
  2271. envvar = emalloc(max_envvar_len + 1);
  2272. INITIALIZE(untiltime);
  2273. INITIALIZE(starttime);
  2274. /*
  2275. ** Now. . .finally. . .generate some useful data!
  2276. */
  2277. timecnt = 0;
  2278. typecnt = 0;
  2279. charcnt = 0;
  2280. prodstic = zonecount == 1;
  2281. /*
  2282. ** Thanks to Earl Chew
  2283. ** for noting the need to unconditionally initialize startttisstd.
  2284. */
  2285. startttisstd = false;
  2286. startttisgmt = false;
  2287. min_year = max_year = EPOCH_YEAR;
  2288. if (leapseen) {
  2289. updateminmax(leapminyear);
  2290. updateminmax(leapmaxyear + (leapmaxyear < ZIC_MAX));
  2291. }
  2292. for (i = 0; i < zonecount; ++i) {
  2293. zp = &zpfirst[i];
  2294. if (i < zonecount - 1)
  2295. updateminmax(zp->z_untilrule.r_loyear);
  2296. for (j = 0; j < zp->z_nrules; ++j) {
  2297. rp = &zp->z_rules[j];
  2298. if (rp->r_lowasnum)
  2299. updateminmax(rp->r_loyear);
  2300. if (rp->r_hiwasnum)
  2301. updateminmax(rp->r_hiyear);
  2302. if (rp->r_lowasnum || rp->r_hiwasnum)
  2303. prodstic = false;
  2304. }
  2305. }
  2306. /*
  2307. ** Generate lots of data if a rule can't cover all future times.
  2308. */
  2309. compat = stringzone(envvar, zpfirst, zonecount);
  2310. version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION;
  2311. do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE;
  2312. if (noise) {
  2313. if (!*envvar)
  2314. warning("%s %s",
  2315. _("no POSIX environment variable for zone"),
  2316. zpfirst->z_name);
  2317. else if (compat != 0 && compat != YEAR_BY_YEAR_ZONE) {
  2318. /* Circa-COMPAT clients, and earlier clients, might
  2319. not work for this zone when given dates before
  2320. 1970 or after 2038. */
  2321. warning(_("%s: pre-%d clients may mishandle"
  2322. " distant timestamps"),
  2323. zpfirst->z_name, compat);
  2324. }
  2325. }
  2326. if (do_extend) {
  2327. /*
  2328. ** Search through a couple of extra years past the obvious
  2329. ** 400, to avoid edge cases. For example, suppose a non-POSIX
  2330. ** rule applies from 2012 onwards and has transitions in March
  2331. ** and September, plus some one-off transitions in November
  2332. ** 2013. If zic looked only at the last 400 years, it would
  2333. ** set max_year=2413, with the intent that the 400 years 2014
  2334. ** through 2413 will be repeated. The last transition listed
  2335. ** in the tzfile would be in 2413-09, less than 400 years
  2336. ** after the last one-off transition in 2013-11. Two years
  2337. ** might be overkill, but with the kind of edge cases
  2338. ** available we're not sure that one year would suffice.
  2339. */
  2340. enum { years_of_observations = YEARSPERREPEAT + 2 };
  2341. if (min_year >= ZIC_MIN + years_of_observations)
  2342. min_year -= years_of_observations;
  2343. else min_year = ZIC_MIN;
  2344. if (max_year <= ZIC_MAX - years_of_observations)
  2345. max_year += years_of_observations;
  2346. else max_year = ZIC_MAX;
  2347. /*
  2348. ** Regardless of any of the above,
  2349. ** for a "proDSTic" zone which specifies that its rules
  2350. ** always have and always will be in effect,
  2351. ** we only need one cycle to define the zone.
  2352. */
  2353. if (prodstic) {
  2354. min_year = 1900;
  2355. max_year = min_year + years_of_observations;
  2356. }
  2357. }
  2358. /*
  2359. ** For the benefit of older systems,
  2360. ** generate data from 1900 through 2038.
  2361. */
  2362. if (min_year > 1900)
  2363. min_year = 1900;
  2364. max_year0 = max_year;
  2365. if (max_year < 2038)
  2366. max_year = 2038;
  2367. for (i = 0; i < zonecount; ++i) {
  2368. /*
  2369. ** A guess that may well be corrected later.
  2370. */
  2371. stdoff = 0;
  2372. zp = &zpfirst[i];
  2373. usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
  2374. useuntil = i < (zonecount - 1);
  2375. if (useuntil && zp->z_untiltime <= min_time)
  2376. continue;
  2377. gmtoff = zp->z_gmtoff;
  2378. eat(zp->z_filename, zp->z_linenum);
  2379. *startbuf = '\0';
  2380. startoff = zp->z_gmtoff;
  2381. if (zp->z_nrules == 0) {
  2382. stdoff = zp->z_stdoff;
  2383. doabbr(startbuf, zp, NULL, zp->z_isdst, stdoff, false);
  2384. type = addtype(oadd(zp->z_gmtoff, stdoff),
  2385. startbuf, zp->z_isdst, startttisstd,
  2386. startttisgmt);
  2387. if (usestart) {
  2388. addtt(starttime, type);
  2389. usestart = false;
  2390. } else
  2391. defaulttype = type;
  2392. } else for (year = min_year; year <= max_year; ++year) {
  2393. if (useuntil && year > zp->z_untilrule.r_hiyear)
  2394. break;
  2395. /*
  2396. ** Mark which rules to do in the current year.
  2397. ** For those to do, calculate rpytime(rp, year);
  2398. */
  2399. for (j = 0; j < zp->z_nrules; ++j) {
  2400. rp = &zp->z_rules[j];
  2401. eats(zp->z_filename, zp->z_linenum,
  2402. rp->r_filename, rp->r_linenum);
  2403. rp->r_todo = year >= rp->r_loyear &&
  2404. year <= rp->r_hiyear &&
  2405. yearistype(year, rp->r_yrtype);
  2406. if (rp->r_todo) {
  2407. rp->r_temp = rpytime(rp, year);
  2408. rp->r_todo
  2409. = (rp->r_temp < y2038_boundary
  2410. || year <= max_year0);
  2411. }
  2412. }
  2413. for ( ; ; ) {
  2414. register ptrdiff_t k;
  2415. register zic_t jtime, ktime;
  2416. register zic_t offset;
  2417. INITIALIZE(ktime);
  2418. if (useuntil) {
  2419. /*
  2420. ** Turn untiltime into UT
  2421. ** assuming the current gmtoff and
  2422. ** stdoff values.
  2423. */
  2424. untiltime = zp->z_untiltime;
  2425. if (!zp->z_untilrule.r_todisgmt)
  2426. untiltime = tadd(untiltime,
  2427. -gmtoff);
  2428. if (!zp->z_untilrule.r_todisstd)
  2429. untiltime = tadd(untiltime,
  2430. -stdoff);
  2431. }
  2432. /*
  2433. ** Find the rule (of those to do, if any)
  2434. ** that takes effect earliest in the year.
  2435. */
  2436. k = -1;
  2437. for (j = 0; j < zp->z_nrules; ++j) {
  2438. rp = &zp->z_rules[j];
  2439. if (!rp->r_todo)
  2440. continue;
  2441. eats(zp->z_filename, zp->z_linenum,
  2442. rp->r_filename, rp->r_linenum);
  2443. offset = rp->r_todisgmt ? 0 : gmtoff;
  2444. if (!rp->r_todisstd)
  2445. offset = oadd(offset, stdoff);
  2446. jtime = rp->r_temp;
  2447. if (jtime == min_time ||
  2448. jtime == max_time)
  2449. continue;
  2450. jtime = tadd(jtime, -offset);
  2451. if (k < 0 || jtime < ktime) {
  2452. k = j;
  2453. ktime = jtime;
  2454. } else if (jtime == ktime) {
  2455. char const *dup_rules_msg =
  2456. _("two rules for same instant");
  2457. eats(zp->z_filename, zp->z_linenum,
  2458. rp->r_filename, rp->r_linenum);
  2459. warning("%s", dup_rules_msg);
  2460. rp = &zp->z_rules[k];
  2461. eats(zp->z_filename, zp->z_linenum,
  2462. rp->r_filename, rp->r_linenum);
  2463. error("%s", dup_rules_msg);
  2464. }
  2465. }
  2466. if (k < 0)
  2467. break; /* go on to next year */
  2468. rp = &zp->z_rules[k];
  2469. rp->r_todo = false;
  2470. if (useuntil && ktime >= untiltime)
  2471. break;
  2472. stdoff = rp->r_stdoff;
  2473. if (usestart && ktime == starttime)
  2474. usestart = false;
  2475. if (usestart) {
  2476. if (ktime < starttime) {
  2477. startoff = oadd(zp->z_gmtoff,
  2478. stdoff);
  2479. doabbr(startbuf, zp,
  2480. rp->r_abbrvar,
  2481. rp->r_isdst,
  2482. rp->r_stdoff,
  2483. false);
  2484. continue;
  2485. }
  2486. if (*startbuf == '\0' &&
  2487. startoff == oadd(zp->z_gmtoff,
  2488. stdoff)) {
  2489. doabbr(startbuf,
  2490. zp,
  2491. rp->r_abbrvar,
  2492. rp->r_isdst,
  2493. rp->r_stdoff,
  2494. false);
  2495. }
  2496. }
  2497. eats(zp->z_filename, zp->z_linenum,
  2498. rp->r_filename, rp->r_linenum);
  2499. doabbr(ab, zp, rp->r_abbrvar,
  2500. rp->r_isdst, rp->r_stdoff, false);
  2501. offset = oadd(zp->z_gmtoff, rp->r_stdoff);
  2502. type = addtype(offset, ab, rp->r_isdst,
  2503. rp->r_todisstd, rp->r_todisgmt);
  2504. if (defaulttype < 0 && !rp->r_isdst)
  2505. defaulttype = type;
  2506. if (rp->r_hiyear == ZIC_MAX
  2507. && ! (0 <= lastatmax
  2508. && ktime < attypes[lastatmax].at))
  2509. lastatmax = timecnt;
  2510. addtt(ktime, type);
  2511. }
  2512. }
  2513. if (usestart) {
  2514. if (*startbuf == '\0' &&
  2515. zp->z_format != NULL &&
  2516. strchr(zp->z_format, '%') == NULL &&
  2517. strchr(zp->z_format, '/') == NULL)
  2518. strcpy(startbuf, zp->z_format);
  2519. eat(zp->z_filename, zp->z_linenum);
  2520. if (*startbuf == '\0')
  2521. error(_("can't determine time zone abbreviation to use just after until time"));
  2522. else {
  2523. bool isdst = startoff != zp->z_gmtoff;
  2524. type = addtype(startoff, startbuf, isdst,
  2525. startttisstd, startttisgmt);
  2526. if (defaulttype < 0 && !isdst)
  2527. defaulttype = type;
  2528. addtt(starttime, type);
  2529. }
  2530. }
  2531. /*
  2532. ** Now we may get to set starttime for the next zone line.
  2533. */
  2534. if (useuntil) {
  2535. startttisstd = zp->z_untilrule.r_todisstd;
  2536. startttisgmt = zp->z_untilrule.r_todisgmt;
  2537. starttime = zp->z_untiltime;
  2538. if (!startttisstd)
  2539. starttime = tadd(starttime, -stdoff);
  2540. if (!startttisgmt)
  2541. starttime = tadd(starttime, -gmtoff);
  2542. }
  2543. }
  2544. if (defaulttype < 0)
  2545. defaulttype = 0;
  2546. if (0 <= lastatmax)
  2547. attypes[lastatmax].dontmerge = true;
  2548. if (do_extend) {
  2549. /*
  2550. ** If we're extending the explicitly listed observations
  2551. ** for 400 years because we can't fill the POSIX-TZ field,
  2552. ** check whether we actually ended up explicitly listing
  2553. ** observations through that period. If there aren't any
  2554. ** near the end of the 400-year period, add a redundant
  2555. ** one at the end of the final year, to make it clear
  2556. ** that we are claiming to have definite knowledge of
  2557. ** the lack of transitions up to that point.
  2558. */
  2559. struct rule xr;
  2560. struct attype *lastat;
  2561. xr.r_month = TM_JANUARY;
  2562. xr.r_dycode = DC_DOM;
  2563. xr.r_dayofmonth = 1;
  2564. xr.r_tod = 0;
  2565. for (lastat = &attypes[0], i = 1; i < timecnt; i++)
  2566. if (attypes[i].at > lastat->at)
  2567. lastat = &attypes[i];
  2568. if (lastat->at < rpytime(&xr, max_year - 1)) {
  2569. addtt(rpytime(&xr, max_year + 1), lastat->type);
  2570. attypes[timecnt - 1].dontmerge = true;
  2571. }
  2572. }
  2573. writezone(zpfirst->z_name, envvar, version, defaulttype);
  2574. free(startbuf);
  2575. free(ab);
  2576. free(envvar);
  2577. }
  2578. static void
  2579. addtt(zic_t starttime, int type)
  2580. {
  2581. attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
  2582. attypes[timecnt].at = starttime;
  2583. attypes[timecnt].dontmerge = false;
  2584. attypes[timecnt].type = type;
  2585. ++timecnt;
  2586. }
  2587. static int
  2588. addtype(zic_t gmtoff, char const *abbr, bool isdst, bool ttisstd, bool ttisgmt)
  2589. {
  2590. register int i, j;
  2591. /*
  2592. ** See if there's already an entry for this zone type.
  2593. ** If so, just return its index.
  2594. */
  2595. for (i = 0; i < typecnt; ++i) {
  2596. if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
  2597. strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
  2598. ttisstd == ttisstds[i] &&
  2599. ttisgmt == ttisgmts[i])
  2600. return i;
  2601. }
  2602. /*
  2603. ** There isn't one; add a new one, unless there are already too
  2604. ** many.
  2605. */
  2606. if (typecnt >= TZ_MAX_TYPES) {
  2607. error(_("too many local time types"));
  2608. exit(EXIT_FAILURE);
  2609. }
  2610. if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) {
  2611. error(_("UT offset out of range"));
  2612. exit(EXIT_FAILURE);
  2613. }
  2614. gmtoffs[i] = gmtoff;
  2615. isdsts[i] = isdst;
  2616. ttisstds[i] = ttisstd;
  2617. ttisgmts[i] = ttisgmt;
  2618. for (j = 0; j < charcnt; ++j)
  2619. if (strcmp(&chars[j], abbr) == 0)
  2620. break;
  2621. if (j == charcnt)
  2622. newabbr(abbr);
  2623. abbrinds[i] = j;
  2624. ++typecnt;
  2625. return i;
  2626. }
  2627. static void
  2628. leapadd(zic_t t, bool positive, int rolling, int count)
  2629. {
  2630. register int i, j;
  2631. if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
  2632. error(_("too many leap seconds"));
  2633. exit(EXIT_FAILURE);
  2634. }
  2635. for (i = 0; i < leapcnt; ++i)
  2636. if (t <= trans[i])
  2637. break;
  2638. do {
  2639. for (j = leapcnt; j > i; --j) {
  2640. trans[j] = trans[j - 1];
  2641. corr[j] = corr[j - 1];
  2642. roll[j] = roll[j - 1];
  2643. }
  2644. trans[i] = t;
  2645. corr[i] = positive ? 1 : -count;
  2646. roll[i] = rolling;
  2647. ++leapcnt;
  2648. } while (positive && --count != 0);
  2649. }
  2650. static void
  2651. adjleap(void)
  2652. {
  2653. register int i;
  2654. register zic_t last = 0;
  2655. register zic_t prevtrans = 0;
  2656. /*
  2657. ** propagate leap seconds forward
  2658. */
  2659. for (i = 0; i < leapcnt; ++i) {
  2660. if (trans[i] - prevtrans < 28 * SECSPERDAY) {
  2661. error(_("Leap seconds too close together"));
  2662. exit(EXIT_FAILURE);
  2663. }
  2664. prevtrans = trans[i];
  2665. trans[i] = tadd(trans[i], last);
  2666. last = corr[i] += last;
  2667. }
  2668. }
  2669. static char *
  2670. shellquote(char *b, char const *s)
  2671. {
  2672. *b++ = '\'';
  2673. while (*s) {
  2674. if (*s == '\'')
  2675. *b++ = '\'', *b++ = '\\', *b++ = '\'';
  2676. *b++ = *s++;
  2677. }
  2678. *b++ = '\'';
  2679. return b;
  2680. }
  2681. static bool
  2682. yearistype(zic_t year, const char *type)
  2683. {
  2684. char *buf;
  2685. char *b;
  2686. int result;
  2687. if (type == NULL || *type == '\0')
  2688. return true;
  2689. buf = emalloc(1 + 4 * strlen(yitcommand) + 2
  2690. + INT_STRLEN_MAXIMUM(zic_t) + 2 + 4 * strlen(type) + 2);
  2691. b = shellquote(buf, yitcommand);
  2692. *b++ = ' ';
  2693. b += sprintf(b, "%"PRIdZIC, year);
  2694. *b++ = ' ';
  2695. b = shellquote(b, type);
  2696. *b = '\0';
  2697. result = system(buf);
  2698. if (WIFEXITED(result)) {
  2699. int status = WEXITSTATUS(result);
  2700. if (status <= 1) {
  2701. free(buf);
  2702. return status == 0;
  2703. }
  2704. }
  2705. error(_("Wild result from command execution"));
  2706. fprintf(stderr, _("%s: command was '%s', result was %d\n"),
  2707. progname, buf, result);
  2708. exit(EXIT_FAILURE);
  2709. }
  2710. /* Is A a space character in the C locale? */
  2711. static bool
  2712. is_space(char a)
  2713. {
  2714. switch (a) {
  2715. default:
  2716. return false;
  2717. case ' ': case '\f': case '\n': case '\r': case '\t': case '\v':
  2718. return true;
  2719. }
  2720. }
  2721. /* Is A an alphabetic character in the C locale? */
  2722. static bool
  2723. is_alpha(char a)
  2724. {
  2725. switch (a) {
  2726. default:
  2727. return false;
  2728. case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
  2729. case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
  2730. case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
  2731. case 'V': case 'W': case 'X': case 'Y': case 'Z':
  2732. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
  2733. case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
  2734. case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
  2735. case 'v': case 'w': case 'x': case 'y': case 'z':
  2736. return true;
  2737. }
  2738. }
  2739. /* If A is an uppercase character in the C locale, return its lowercase
  2740. counterpart. Otherwise, return A. */
  2741. static char
  2742. lowerit(char a)
  2743. {
  2744. switch (a) {
  2745. default: return a;
  2746. case 'A': return 'a'; case 'B': return 'b'; case 'C': return 'c';
  2747. case 'D': return 'd'; case 'E': return 'e'; case 'F': return 'f';
  2748. case 'G': return 'g'; case 'H': return 'h'; case 'I': return 'i';
  2749. case 'J': return 'j'; case 'K': return 'k'; case 'L': return 'l';
  2750. case 'M': return 'm'; case 'N': return 'n'; case 'O': return 'o';
  2751. case 'P': return 'p'; case 'Q': return 'q'; case 'R': return 'r';
  2752. case 'S': return 's'; case 'T': return 't'; case 'U': return 'u';
  2753. case 'V': return 'v'; case 'W': return 'w'; case 'X': return 'x';
  2754. case 'Y': return 'y'; case 'Z': return 'z';
  2755. }
  2756. }
  2757. /* case-insensitive equality */
  2758. static ATTRIBUTE_PURE bool
  2759. ciequal(register const char *ap, register const char *bp)
  2760. {
  2761. while (lowerit(*ap) == lowerit(*bp++))
  2762. if (*ap++ == '\0')
  2763. return true;
  2764. return false;
  2765. }
  2766. static ATTRIBUTE_PURE bool
  2767. itsabbr(register const char *abbr, register const char *word)
  2768. {
  2769. if (lowerit(*abbr) != lowerit(*word))
  2770. return false;
  2771. ++word;
  2772. while (*++abbr != '\0')
  2773. do {
  2774. if (*word == '\0')
  2775. return false;
  2776. } while (lowerit(*word++) != lowerit(*abbr));
  2777. return true;
  2778. }
  2779. /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */
  2780. static ATTRIBUTE_PURE bool
  2781. ciprefix(char const *abbr, char const *word)
  2782. {
  2783. do
  2784. if (!*abbr)
  2785. return true;
  2786. while (lowerit(*abbr++) == lowerit(*word++));
  2787. return false;
  2788. }
  2789. static const struct lookup *
  2790. byword(const char *word, const struct lookup *table)
  2791. {
  2792. register const struct lookup * foundlp;
  2793. register const struct lookup * lp;
  2794. if (word == NULL || table == NULL)
  2795. return NULL;
  2796. /* If TABLE is LASTS and the word starts with "last" followed
  2797. by a non-'-', skip the "last" and look in WDAY_NAMES instead.
  2798. Warn about any usage of the undocumented prefix "last-". */
  2799. if (table == lasts && ciprefix("last", word) && word[4]) {
  2800. if (word[4] == '-')
  2801. warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
  2802. word, word + 5);
  2803. else {
  2804. word += 4;
  2805. table = wday_names;
  2806. }
  2807. }
  2808. /*
  2809. ** Look for exact match.
  2810. */
  2811. for (lp = table; lp->l_word != NULL; ++lp)
  2812. if (ciequal(word, lp->l_word))
  2813. return lp;
  2814. /*
  2815. ** Look for inexact match.
  2816. */
  2817. foundlp = NULL;
  2818. for (lp = table; lp->l_word != NULL; ++lp)
  2819. if (ciprefix(word, lp->l_word)) {
  2820. if (foundlp == NULL)
  2821. foundlp = lp;
  2822. else return NULL; /* multiple inexact matches */
  2823. }
  2824. /* Warn about any backward-compatibility issue with pre-2017c zic. */
  2825. if (foundlp) {
  2826. bool pre_2017c_match = false;
  2827. for (lp = table; lp->l_word; lp++)
  2828. if (itsabbr(word, lp->l_word)) {
  2829. if (pre_2017c_match) {
  2830. warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
  2831. break;
  2832. }
  2833. pre_2017c_match = true;
  2834. }
  2835. }
  2836. return foundlp;
  2837. }
  2838. static char **
  2839. getfields(register char *cp)
  2840. {
  2841. register char * dp;
  2842. register char ** array;
  2843. register int nsubs;
  2844. if (cp == NULL)
  2845. return NULL;
  2846. array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
  2847. nsubs = 0;
  2848. for ( ; ; ) {
  2849. while (is_space(*cp))
  2850. ++cp;
  2851. if (*cp == '\0' || *cp == '#')
  2852. break;
  2853. array[nsubs++] = dp = cp;
  2854. do {
  2855. if ((*dp = *cp++) != '"')
  2856. ++dp;
  2857. else while ((*dp = *cp++) != '"')
  2858. if (*dp != '\0')
  2859. ++dp;
  2860. else {
  2861. error(_("Odd number of quotation marks"));
  2862. exit(EXIT_FAILURE);
  2863. }
  2864. } while (*cp && *cp != '#' && !is_space(*cp));
  2865. if (is_space(*cp))
  2866. ++cp;
  2867. *dp = '\0';
  2868. }
  2869. array[nsubs] = NULL;
  2870. return array;
  2871. }
  2872. static _Noreturn void
  2873. time_overflow(void)
  2874. {
  2875. error(_("time overflow"));
  2876. exit(EXIT_FAILURE);
  2877. }
  2878. static ATTRIBUTE_PURE zic_t
  2879. oadd(zic_t t1, zic_t t2)
  2880. {
  2881. if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
  2882. time_overflow();
  2883. return t1 + t2;
  2884. }
  2885. static ATTRIBUTE_PURE zic_t
  2886. tadd(zic_t t1, zic_t t2)
  2887. {
  2888. if (t1 < 0) {
  2889. if (t2 < min_time - t1) {
  2890. if (t1 != min_time)
  2891. time_overflow();
  2892. return min_time;
  2893. }
  2894. } else {
  2895. if (max_time - t1 < t2) {
  2896. if (t1 != max_time)
  2897. time_overflow();
  2898. return max_time;
  2899. }
  2900. }
  2901. return t1 + t2;
  2902. }
  2903. /*
  2904. ** Given a rule, and a year, compute the date (in seconds since January 1,
  2905. ** 1970, 00:00 LOCAL time) in that year that the rule refers to.
  2906. */
  2907. static zic_t
  2908. rpytime(const struct rule *rp, zic_t wantedy)
  2909. {
  2910. register int m, i;
  2911. register zic_t dayoff; /* with a nod to Margaret O. */
  2912. register zic_t t, y;
  2913. if (wantedy == ZIC_MIN)
  2914. return min_time;
  2915. if (wantedy == ZIC_MAX)
  2916. return max_time;
  2917. dayoff = 0;
  2918. m = TM_JANUARY;
  2919. y = EPOCH_YEAR;
  2920. if (y < wantedy) {
  2921. wantedy -= y;
  2922. dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
  2923. wantedy %= YEARSPERREPEAT;
  2924. wantedy += y;
  2925. } else if (wantedy < 0) {
  2926. dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
  2927. wantedy %= YEARSPERREPEAT;
  2928. }
  2929. while (wantedy != y) {
  2930. if (wantedy > y) {
  2931. i = len_years[isleap(y)];
  2932. ++y;
  2933. } else {
  2934. --y;
  2935. i = -len_years[isleap(y)];
  2936. }
  2937. dayoff = oadd(dayoff, i);
  2938. }
  2939. while (m != rp->r_month) {
  2940. i = len_months[isleap(y)][m];
  2941. dayoff = oadd(dayoff, i);
  2942. ++m;
  2943. }
  2944. i = rp->r_dayofmonth;
  2945. if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
  2946. if (rp->r_dycode == DC_DOWLEQ)
  2947. --i;
  2948. else {
  2949. error(_("use of 2/29 in non leap-year"));
  2950. exit(EXIT_FAILURE);
  2951. }
  2952. }
  2953. --i;
  2954. dayoff = oadd(dayoff, i);
  2955. if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
  2956. register zic_t wday;
  2957. #define LDAYSPERWEEK ((zic_t) DAYSPERWEEK)
  2958. wday = EPOCH_WDAY;
  2959. /*
  2960. ** Don't trust mod of negative numbers.
  2961. */
  2962. if (dayoff >= 0)
  2963. wday = (wday + dayoff) % LDAYSPERWEEK;
  2964. else {
  2965. wday -= ((-dayoff) % LDAYSPERWEEK);
  2966. if (wday < 0)
  2967. wday += LDAYSPERWEEK;
  2968. }
  2969. while (wday != rp->r_wday)
  2970. if (rp->r_dycode == DC_DOWGEQ) {
  2971. dayoff = oadd(dayoff, 1);
  2972. if (++wday >= LDAYSPERWEEK)
  2973. wday = 0;
  2974. ++i;
  2975. } else {
  2976. dayoff = oadd(dayoff, -1);
  2977. if (--wday < 0)
  2978. wday = LDAYSPERWEEK - 1;
  2979. --i;
  2980. }
  2981. if (i < 0 || i >= len_months[isleap(y)][m]) {
  2982. if (noise)
  2983. warning(_("rule goes past start/end of month; \
  2984. will not work with pre-2004 versions of zic"));
  2985. }
  2986. }
  2987. if (dayoff < min_time / SECSPERDAY)
  2988. return min_time;
  2989. if (dayoff > max_time / SECSPERDAY)
  2990. return max_time;
  2991. t = (zic_t) dayoff * SECSPERDAY;
  2992. return tadd(t, rp->r_tod);
  2993. }
  2994. static void
  2995. newabbr(const char *string)
  2996. {
  2997. register int i;
  2998. if (strcmp(string, GRANDPARENTED) != 0) {
  2999. register const char * cp;
  3000. const char * mp;
  3001. cp = string;
  3002. mp = NULL;
  3003. while (is_alpha(*cp) || ('0' <= *cp && *cp <= '9')
  3004. || *cp == '-' || *cp == '+')
  3005. ++cp;
  3006. if (noise && cp - string < 3)
  3007. mp = _("time zone abbreviation has fewer than 3 characters");
  3008. if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
  3009. mp = _("time zone abbreviation has too many characters");
  3010. if (*cp != '\0')
  3011. mp = _("time zone abbreviation differs from POSIX standard");
  3012. if (mp != NULL)
  3013. warning("%s (%s)", mp, string);
  3014. }
  3015. i = strlen(string) + 1;
  3016. if (charcnt + i > TZ_MAX_CHARS) {
  3017. error(_("too many, or too long, time zone abbreviations"));
  3018. exit(EXIT_FAILURE);
  3019. }
  3020. strcpy(&chars[charcnt], string);
  3021. charcnt += i;
  3022. }
  3023. /* Ensure that the directories of ARGNAME exist, by making any missing
  3024. ones. If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
  3025. do it for ARGNAME too. Exit with failure if there is trouble.
  3026. Do not consider an existing non-directory to be trouble. */
  3027. static void
  3028. mkdirs(char const *argname, bool ancestors)
  3029. {
  3030. register char * name;
  3031. register char * cp;
  3032. cp = name = ecpyalloc(argname);
  3033. /* On MS-Windows systems, do not worry about drive letters or
  3034. backslashes, as this should suffice in practice. Time zone
  3035. names do not use drive letters and backslashes. If the -d
  3036. option of zic does not name an already-existing directory,
  3037. it can use slashes to separate the already-existing
  3038. ancestor prefix from the to-be-created subdirectories. */
  3039. /* Do not mkdir a root directory, as it must exist. */
  3040. while (*cp == '/')
  3041. cp++;
  3042. while (cp && ((cp = strchr(cp, '/')) || !ancestors)) {
  3043. if (cp)
  3044. *cp = '\0';
  3045. /*
  3046. ** Try to create it. It's OK if creation fails because
  3047. ** the directory already exists, perhaps because some
  3048. ** other process just created it. For simplicity do
  3049. ** not check first whether it already exists, as that
  3050. ** is checked anyway if the mkdir fails.
  3051. */
  3052. if (mkdir(name, MKDIR_UMASK) != 0) {
  3053. /* For speed, skip itsdir if errno == EEXIST. Since
  3054. mkdirs is called only after open fails with ENOENT
  3055. on a subfile, EEXIST implies itsdir here. */
  3056. int err = errno;
  3057. if (err != EEXIST && !itsdir(name)) {
  3058. error(_("%s: Can't create directory %s: %s"),
  3059. progname, name, strerror(err));
  3060. exit(EXIT_FAILURE);
  3061. }
  3062. }
  3063. if (cp)
  3064. *cp++ = '/';
  3065. }
  3066. free(name);
  3067. }