gen_collate.c 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920
  1. /* TODO:
  2. *
  3. * add UNDEFINED at end if not specified
  4. * convert POSITION -> FORWARD,POSITION
  5. *
  6. *
  7. * deal with lowercase in <Uhhhh>
  8. *
  9. * what about reorders that keep the same rule?
  10. *
  11. * remove "unused" collation elements? (probably doesn't save much)
  12. *
  13. * add_rule function ... returns index into rule table after possibly adding custom-indexed rule
  14. * but don't forget about multichar weights... replace with strings of indexes
  15. *
  16. */
  17. #ifndef _GNU_SOURCE
  18. #define _GNU_SOURCE
  19. #endif
  20. #include <stddef.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdint.h>
  25. #include <stdarg.h>
  26. #include <limits.h>
  27. #include <ctype.h>
  28. #include <assert.h>
  29. #include <search.h>
  30. typedef struct {
  31. char *name; /* */
  32. int num_weights; /* */
  33. int ii_shift; /* */
  34. int ti_shift; /* */
  35. int ii_len; /* */
  36. int ti_len; /* */
  37. int max_weight; /* */
  38. int num_col_base; /* */
  39. int max_col_index; /* */
  40. int undefined_idx; /* */
  41. int range_low; /* */
  42. int range_count; /* high - low */
  43. int range_base_weight; /* */
  44. int num_starters; /* */
  45. int range_rule_offset; /* */
  46. int wcs2colidt_offset; /* */
  47. int index2weight_offset; /* */
  48. int index2ruleidx_offset; /* */
  49. int multistart_offset; /* */
  50. } base_locale_t;
  51. #define BASE_LOCALE_LEN 20
  52. static base_locale_t base_locale_array[BASE_LOCALE_LEN];
  53. static size_t base_locale_len;
  54. typedef struct {
  55. char *name; /* */
  56. int base_idx; /* */
  57. int undefined_idx; /* */
  58. int overrides_offset; /* */
  59. int multistart_offset; /* */
  60. } der_locale_t;
  61. #define DER_LOCALE_LEN 300
  62. static der_locale_t der_locale_array[DER_LOCALE_LEN];
  63. static size_t der_locale_len;
  64. #define OVERRIDE_LEN 50000
  65. static uint16_t override_buffer[OVERRIDE_LEN];
  66. static size_t override_len;
  67. #define MULTISTART_LEN 10000
  68. static uint16_t multistart_buffer[MULTISTART_LEN];
  69. static size_t multistart_len;
  70. #define WCS2COLIDT_LEN 200000
  71. static uint16_t wcs2colidt_buffer[WCS2COLIDT_LEN];
  72. static size_t wcs2colidt_len;
  73. #define INDEX2WEIGHT_LEN 200000
  74. static uint16_t index2weight_buffer[INDEX2WEIGHT_LEN];
  75. static size_t index2weight_len;
  76. static uint16_t index2ruleidx_buffer[INDEX2WEIGHT_LEN];
  77. static size_t index2ruleidx_len;
  78. #define WEIGHTSTR_LEN 10000
  79. static uint16_t weightstr_buffer[WEIGHTSTR_LEN];
  80. static size_t weightstr_len;
  81. #define RULETABLE_LEN (1L<<16)
  82. static uint16_t ruletable_buffer[RULETABLE_LEN];
  83. static size_t ruletable_len;
  84. #define RANGE (0x10000UL)
  85. typedef uint16_t tbl_item;
  86. static uint16_t u16_buf[10000];
  87. static int u16_buf_len;
  88. static int u16_starter;
  89. typedef struct {
  90. uint16_t ii_len;
  91. uint16_t ti_len;
  92. uint16_t ut_len;
  93. unsigned char ii_shift;
  94. unsigned char ti_shift;
  95. tbl_item *ii;
  96. tbl_item *ti;
  97. tbl_item *ut;
  98. } table_data;
  99. static size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl);
  100. #define MAX_COLLATION_WEIGHTS 4
  101. #define MAX_FNO 1
  102. #define MAX_FILES (MAX_FNO + 1)
  103. static FILE *fstack[MAX_FILES];
  104. static char *fname[MAX_FILES];
  105. static int lineno[MAX_FILES];
  106. static int fno = -1;
  107. static tbl_item wcs2index[RANGE];
  108. static char linebuf[1024];
  109. static char *pos;
  110. static char *pos_e = NULL;
  111. static char end_of_token = 0; /* slot to save */
  112. #define IN_ORDER 0x01
  113. #define IN_REORDER 0x02
  114. #define IN_REORDER_SECTIONS 0x04
  115. static int order_state;
  116. static int cur_num_weights; /* number of weights in current use */
  117. static char cur_rule[MAX_COLLATION_WEIGHTS];
  118. static int anonsection = 0;
  119. typedef struct ll_item_struct ll_item_t;
  120. struct ll_item_struct {
  121. ll_item_t *next;
  122. ll_item_t *prev;
  123. void *data;
  124. int data_type;
  125. int idx;
  126. };
  127. static ll_item_t *reorder_section_ptr = NULL;
  128. static int superset;
  129. static int superset_order_start_cnt; /* only support one order for now */
  130. static int superset_in_sync;
  131. static ll_item_t *comm_cur_ptr;
  132. static ll_item_t *comm_prev_ptr;
  133. enum {
  134. R_FORWARD = 0x01,
  135. R_POSITION = 0x02,
  136. R_BACKWARD = 0x04 /* must be largest in value */
  137. };
  138. typedef struct {
  139. size_t num_weights;
  140. char rule[MAX_COLLATION_WEIGHTS];
  141. const char *colitem[MAX_COLLATION_WEIGHTS];
  142. } weight_t;
  143. static void *root_weight = NULL;
  144. size_t unique_weights = 0;
  145. typedef struct {
  146. const char *symbol;
  147. weight_t *weight;
  148. } weighted_item_t;
  149. typedef struct {
  150. const char *symbol1;
  151. const char *symbol2;
  152. int length;
  153. weight_t *weight;
  154. } range_item_t;
  155. typedef struct {
  156. const char *name;
  157. ll_item_t *itm_list; /* weighted_item_t list .. circular!!! */
  158. size_t num_items;
  159. size_t num_rules;
  160. char rules[MAX_COLLATION_WEIGHTS];
  161. } section_t;
  162. static section_t *cur_section = NULL;
  163. typedef struct {
  164. const char *symbol;
  165. ll_item_t *node;
  166. } wi_index_t;
  167. typedef struct col_locale_struct col_locale_t;
  168. struct col_locale_struct {
  169. char *name;
  170. void *root_colitem; /* all base and derived, or just derived */
  171. void *root_element;
  172. void *root_scripts;
  173. void *root_wi_index;
  174. void *root_wi_index_reordered;
  175. ll_item_t *section_list;
  176. col_locale_t *base_locale; /* null if this is a base */
  177. void *root_derived_wi;
  178. ll_item_t *derived_list;
  179. void *root_starter_char;
  180. void *root_starter_all;
  181. ll_item_t *undefined_idx;
  182. };
  183. typedef struct {
  184. const char *symbol;
  185. int idx;
  186. } col_index_t;
  187. static void *root_col_locale = NULL;
  188. typedef struct {
  189. const char *keyword;
  190. void (*handler)(void);
  191. } keyword_table_t;
  192. typedef struct {
  193. const char *string;
  194. const char *element; /* NULL if collating symbol */
  195. } colitem_t;
  196. static col_locale_t *cur_base = NULL;
  197. static col_locale_t *cur_derived = NULL;
  198. static col_locale_t *cur_col = NULL;
  199. static void *root_sym = NULL;
  200. static size_t num_sym = 0;
  201. static size_t mem_sym = 0;
  202. static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
  203. static void *xmalloc(size_t n);
  204. static char *xsymdup(const char *s); /* only allocate once... store in a tree */
  205. static void pushfile(char *filename);
  206. static void popfile(void);
  207. static void processfile(void);
  208. static int iscommentchar(int);
  209. static void eatwhitespace(void);
  210. static int next_line(void);
  211. static char *next_token(void);
  212. static void do_unrecognized(void);
  213. static col_locale_t *new_col_locale(char *name);
  214. static ll_item_t *new_ll_item(int data_type, void *data);
  215. static weight_t *register_weight(weight_t *w);
  216. static size_t ll_len(ll_item_t *l);
  217. static size_t ll_count(ll_item_t *l, int mask);
  218. static void add_wi_index(ll_item_t *l);
  219. static size_t tnumnodes(const void *root);
  220. static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl);
  221. static void mark_reordered(const char *sym);
  222. static ll_item_t *find_wi_index_reordered(const char *sym);
  223. static ll_item_t *next_comm_ptr(void);
  224. static ll_item_t *init_comm_ptr(void);
  225. static ll_item_t *find_ll_last(ll_item_t *p);
  226. static void dump_weights(const char *name);
  227. static void finalize_base(void);
  228. static int is_ucode(const char *s);
  229. static int sym_cmp(const void *n1, const void *n2);
  230. static void do_starter_lists(col_locale_t *cl);
  231. static void dump_base_locale(int n);
  232. static void dump_der_locale(int n);
  233. static void dump_collate(FILE *fp);
  234. enum {
  235. DT_SECTION = 0x01,
  236. DT_WEIGHTED = 0x02,
  237. DT_REORDER = 0x04, /* a section to support reorder_after */
  238. DT_COL_LOCALE = 0x08,
  239. DT_RANGE = 0x10,
  240. };
  241. static section_t *new_section(const char *name)
  242. {
  243. section_t *p;
  244. char buf[128];
  245. p = xmalloc(sizeof(section_t));
  246. if (!name) { /* anonymous section */
  247. name = buf;
  248. snprintf(buf, sizeof(buf), "anon%05d", anonsection);
  249. ++anonsection;
  250. } else if (*name != '<') { /* reorder */
  251. name = buf;
  252. snprintf(buf, sizeof(buf), "%s %05d", cur_col->name, anonsection);
  253. ++anonsection;
  254. }
  255. #warning devel code
  256. /* fprintf(stderr, "section %s\n", name); */
  257. p->name = xsymdup(name);
  258. p->itm_list = NULL;
  259. p->num_items = 0;
  260. p->num_rules = 0;
  261. memset(p->rules, 0, MAX_COLLATION_WEIGHTS);
  262. /* cur_num_weights = p->num_rules = 0; */
  263. /* memset(p->rules, 0, MAX_COLLATION_WEIGHTS); */
  264. /* memset(cur_rule, R_FORWARD, 4); */
  265. #warning devel code
  266. if (*p->name == 'a') {
  267. cur_num_weights = p->num_rules = 4;
  268. memset(p->rules, R_FORWARD, 4);
  269. memset(cur_rule, R_FORWARD, 4);
  270. p->rules[3] |= R_POSITION;
  271. cur_rule[3] |= R_POSITION;
  272. }
  273. /* fprintf(stderr, "new section %s -- cur_num_weights = %d\n", p->name, cur_num_weights); */
  274. return p;
  275. }
  276. static void do_order_start(void);
  277. static void do_order_end(void);
  278. static void do_reorder_after(void);
  279. static void do_reorder_end(void);
  280. static void do_reorder_sections_after(void);
  281. static void do_reorder_sections_end(void);
  282. static void do_copy(void);
  283. static void do_colsym(void);
  284. static void do_colele(void);
  285. static void do_script(void);
  286. static void do_range(void);
  287. static col_locale_t *new_col_locale(char *name);
  288. static int colitem_cmp(const void *n1, const void *n2);
  289. static int colelement_cmp(const void *n1, const void *n2);
  290. static void del_colitem(colitem_t *p);
  291. static colitem_t *new_colitem(char *item, char *def);
  292. static void add_colitem(char *item, char *def);
  293. static void add_script(const char *s);
  294. static unsigned int add_rule(weighted_item_t *wi);
  295. static unsigned int add_range_rule(range_item_t *ri);
  296. static const keyword_table_t keyword_table[] = {
  297. { "collating-symbol", do_colsym },
  298. { "collating-element", do_colele },
  299. { "script", do_script },
  300. { "copy", do_copy },
  301. { "order_start", do_order_start },
  302. { "order_end", do_order_end },
  303. { "order-end", do_order_end },
  304. { "reorder-after", do_reorder_after },
  305. { "reorder-end", do_reorder_end },
  306. { "reorder-sections-after", do_reorder_sections_after },
  307. { "reorder-sections-end", do_reorder_sections_end },
  308. { "UCLIBC_RANGE", do_range },
  309. { NULL, do_unrecognized }
  310. };
  311. static void do_unrecognized(void)
  312. {
  313. #if 1
  314. error_msg("warning: unrecognized: %s", pos);
  315. #else
  316. /* fprintf(stderr, "warning: unrecognized initial keyword \"%s\"\n", pos); */
  317. fprintf(stderr, "warning: unrecognized: %s", pos);
  318. if (end_of_token) {
  319. fprintf(stderr, "%c%s", end_of_token, pos_e+1);
  320. }
  321. fprintf(stderr, "\n");
  322. #endif
  323. }
  324. /* typedef struct { */
  325. /* const char *symbol1; */
  326. /* const char *symbol2; */
  327. /* int length; */
  328. /* weight_t *weight; */
  329. /* } range_item_t; */
  330. static void do_range(void)
  331. {
  332. range_item_t *ri;
  333. weight_t w;
  334. int i;
  335. char *s;
  336. char *s1;
  337. char *s2;
  338. const char **ci;
  339. ll_item_t *lli;
  340. assert(!superset);
  341. assert(order_state == IN_ORDER);
  342. s1 = next_token();
  343. if (!s1) {
  344. error_msg("missing start of range");
  345. }
  346. if (!is_ucode(s1)) {
  347. error_msg("start of range is not a ucode: %s", s1);
  348. }
  349. s1 = xsymdup(s1);
  350. s2 = next_token();
  351. if (!s2) {
  352. error_msg("missing end of range");
  353. }
  354. if (!is_ucode(s2)) {
  355. error_msg("end of range is not a ucode: %s", s2);
  356. }
  357. s2 = xsymdup(s2);
  358. ri = (range_item_t *) xmalloc(sizeof(range_item_t));
  359. ri->symbol1 = s1;
  360. ri->symbol2 = s2;
  361. ri->length = strtoul(s2+2, NULL, 16) - strtoul(s1+2, NULL, 16);
  362. if (ri->length <= 0) {
  363. error_msg("illegal range length %d", ri->length);
  364. }
  365. s = next_token();
  366. w.num_weights = cur_num_weights;
  367. for (i=0 ; i < cur_num_weights ; i++) {
  368. w.rule[i] = cur_rule[i];
  369. }
  370. ci = w.colitem + (i-1);
  371. /* now i == cur_num_weights */
  372. #define STR_DITTO "."
  373. while (s && *s && i) {
  374. --i;
  375. if (*s == ';') {
  376. ci[-i] = xsymdup(STR_DITTO);
  377. if (*++s) {
  378. continue;
  379. }
  380. }
  381. if (*s) {
  382. ci[-i] = xsymdup(s);
  383. }
  384. s = next_token();
  385. if (s) {
  386. if (*s == ';') {
  387. ++s;
  388. } else if (i) {
  389. error_msg("missing seperator");
  390. }
  391. }
  392. }
  393. if (s) {
  394. error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s);
  395. }
  396. while (i) { /* missing weights are not an error */
  397. --i;
  398. ci[-i] = xsymdup(STR_DITTO);
  399. }
  400. ri->weight = register_weight(&w);
  401. /* if ((i = is_ucode(t)) != 0) { */
  402. /* assert(!t[i]); */
  403. /* add_colitem(t, NULL); */
  404. /* } */
  405. lli = new_ll_item(DT_RANGE, ri);
  406. if (!cur_section->itm_list) {
  407. /* printf("creating new item list: %s\n", wi->symbol); */
  408. cur_section->itm_list = lli;
  409. lli->prev = lli->next = lli;
  410. ++cur_section->num_items;
  411. } else {
  412. insque(lli, cur_section->itm_list->prev);
  413. /* printf("adding item to list: %d - %s\n", ll_len(cur_section->itm_list), wi->symbol); */
  414. ++cur_section->num_items;
  415. }
  416. /* add_wi_index(lli); */
  417. }
  418. static weighted_item_t *add_weight(char *t)
  419. {
  420. weighted_item_t *wi;
  421. weight_t w;
  422. int i;
  423. char *s;
  424. const char **ci;
  425. t = xsymdup(t);
  426. s = next_token();
  427. w.num_weights = cur_num_weights;
  428. for (i=0 ; i < cur_num_weights ; i++) {
  429. w.rule[i] = cur_rule[i];
  430. }
  431. ci = w.colitem + (i-1);
  432. /* now i == cur_num_weights */
  433. while (s && *s && i) {
  434. --i;
  435. if (*s == ';') {
  436. ci[-i] = xsymdup(STR_DITTO);
  437. if (*++s) {
  438. continue;
  439. }
  440. }
  441. if (*s) {
  442. if (!strcmp(s,t)) {
  443. s = STR_DITTO;
  444. }
  445. ci[-i] = xsymdup(s);
  446. }
  447. s = next_token();
  448. if (s) {
  449. if (*s == ';') {
  450. ++s;
  451. } else if (i) {
  452. error_msg("missing seperator");
  453. }
  454. }
  455. }
  456. if (s) {
  457. error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s);
  458. }
  459. while (i) { /* missing weights are not an error */
  460. --i;
  461. ci[-i] = xsymdup(STR_DITTO);
  462. }
  463. wi = xmalloc(sizeof(weighted_item_t));
  464. wi->symbol = t;
  465. wi->weight = register_weight(&w);
  466. if ((i = is_ucode(t)) != 0) {
  467. assert(!t[i]);
  468. add_colitem(t, NULL);
  469. }
  470. return wi;
  471. }
  472. static void add_superset_weight(char *t)
  473. {
  474. ll_item_t *lli;
  475. weighted_item_t *wi;
  476. if (!comm_cur_ptr
  477. || (strcmp(t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol) != 0)
  478. ) { /* now out of sync */
  479. if (superset_in_sync) { /* need a new section */
  480. superset_in_sync = 0;
  481. cur_section = new_section("R");
  482. cur_num_weights = cur_section->num_rules
  483. = ((section_t *)(cur_base->section_list->data))->num_rules;
  484. memcpy(cur_rule,
  485. ((section_t *)(cur_base->section_list->data))->rules,
  486. MAX_COLLATION_WEIGHTS);
  487. memcpy(cur_section->rules,
  488. ((section_t *)(cur_base->section_list->data))->rules,
  489. MAX_COLLATION_WEIGHTS);
  490. insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list));
  491. assert(comm_prev_ptr);
  492. lli = new_ll_item(DT_REORDER, cur_section);
  493. lli->prev = lli->next = lli;
  494. insque(lli, comm_prev_ptr);
  495. /* fprintf(stderr, " subsection -----------------------\n"); */
  496. }
  497. /* fprintf(stderr, " %s %s\n", t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol); */
  498. wi = add_weight(t);
  499. lli = new_ll_item(DT_WEIGHTED, wi);
  500. mark_reordered(wi->symbol);
  501. /* printf("reorder: %s\n", t); */
  502. if (!cur_section->itm_list) {
  503. cur_section->itm_list = lli;
  504. lli->prev = lli->next = lli;
  505. ++cur_section->num_items;
  506. } else {
  507. insque(lli, cur_section->itm_list->prev);
  508. ++cur_section->num_items;
  509. }
  510. add_wi_index(lli);
  511. } else { /* in sync */
  512. superset_in_sync = 1;
  513. next_comm_ptr();
  514. }
  515. }
  516. static void do_weight(char *t)
  517. {
  518. weighted_item_t *wi;
  519. ll_item_t *lli;
  520. if (superset) {
  521. add_superset_weight(t);
  522. return;
  523. }
  524. switch(order_state) {
  525. case 0:
  526. /* printf("no-order weight: %s\n", t); */
  527. /* break; */
  528. case IN_ORDER:
  529. /* in a section */
  530. /* printf("weight: %s\n", t); */
  531. wi = add_weight(t);
  532. lli = new_ll_item(DT_WEIGHTED, wi);
  533. if (!cur_section->itm_list) {
  534. /* printf("creating new item list: %s\n", wi->symbol); */
  535. cur_section->itm_list = lli;
  536. lli->prev = lli->next = lli;
  537. ++cur_section->num_items;
  538. } else {
  539. insque(lli, cur_section->itm_list->prev);
  540. /* printf("adding item to list: %d - %s\n", ll_len(cur_section->itm_list), wi->symbol); */
  541. ++cur_section->num_items;
  542. }
  543. add_wi_index(lli);
  544. break;
  545. case IN_REORDER:
  546. /* std rule - but in a block with an insert-after pt */
  547. wi = add_weight(t);
  548. lli = new_ll_item(DT_WEIGHTED, wi);
  549. mark_reordered(wi->symbol);
  550. /* printf("reorder: %s\n", t); */
  551. if (!cur_section->itm_list) {
  552. cur_section->itm_list = lli;
  553. lli->prev = lli->next = lli;
  554. ++cur_section->num_items;
  555. } else {
  556. insque(lli, cur_section->itm_list->prev);
  557. ++cur_section->num_items;
  558. }
  559. add_wi_index(lli);
  560. break;
  561. case IN_REORDER_SECTIONS:
  562. t = xsymdup(t);
  563. if (next_token() != NULL) {
  564. error_msg("trailing text in reorder section item: %s", pos);
  565. }
  566. lli = cur_col->section_list;
  567. do {
  568. if (lli->data_type & DT_SECTION) {
  569. if (!strcmp(((section_t *)(lli->data))->name, t)) {
  570. lli->data_type = DT_REORDER;
  571. lli = new_ll_item(DT_REORDER, (section_t *)(lli->data));
  572. insque(lli, reorder_section_ptr);
  573. reorder_section_ptr = lli;
  574. return;
  575. }
  576. }
  577. lli = lli->next;
  578. } while (lli);
  579. error_msg("reorder_sections_after for non-base item currently not supported: %s", t);
  580. /* fprintf(stderr, "reorder_secitons: %s\n", t); */
  581. break;
  582. default:
  583. error_msg("invalid order_state %d", order_state);
  584. }
  585. }
  586. static int col_locale_cmp(const void *n1, const void *n2)
  587. {
  588. return strcmp(((const col_locale_t *) n1)->name, ((const col_locale_t *) n2)->name);
  589. }
  590. static void processfile(void)
  591. {
  592. char *t;
  593. const keyword_table_t *k;
  594. order_state = 0;
  595. #warning devel code
  596. /* cur_num_weights = 0; */
  597. /* cur_num_weights = 4; */
  598. /* memset(cur_rule, R_FORWARD, 4); */
  599. if (cur_col != cur_base) {
  600. cur_col->base_locale = cur_base;
  601. cur_col->undefined_idx = cur_base->undefined_idx;
  602. if (!cur_base->derived_list) {
  603. cur_base->derived_list = new_ll_item(DT_COL_LOCALE, cur_col);
  604. } else {
  605. insque(new_ll_item(DT_COL_LOCALE, cur_col), find_ll_last(cur_base->derived_list));
  606. }
  607. }
  608. if (tfind(cur_col, &root_col_locale, col_locale_cmp)) {
  609. error_msg("attempt to readd locale: %s", cur_col->name);
  610. }
  611. if (!tsearch(cur_col, &root_col_locale, col_locale_cmp)) {
  612. error_msg("OUT OF MEMORY!");
  613. }
  614. if (superset) {
  615. superset_order_start_cnt = 0;
  616. superset_in_sync = 0;
  617. init_comm_ptr();
  618. }
  619. while (next_line()) {
  620. /* printf("%5d:", lineno[fno]); */
  621. /* while ((t = next_token()) != NULL) { */
  622. /* printf(" |%s|", t); */
  623. /* printf("\n"); */
  624. /* } */
  625. t = next_token();
  626. assert(t);
  627. assert(t == pos);
  628. if ((*t == '<') || (!strcmp(t, "UNDEFINED"))) {
  629. do_weight(t);
  630. } else {
  631. for (k = keyword_table ; k->keyword ; k++) {
  632. if (!strcmp(k->keyword, t)) {
  633. break;
  634. }
  635. }
  636. k->handler();
  637. }
  638. }
  639. if (cur_base == cur_col) {
  640. fprintf(stderr, "Base: %15s", cur_col->name);
  641. } else {
  642. #if 1
  643. if (!cur_col->undefined_idx) {
  644. #if 0
  645. if (superset) {
  646. if (superset_order_start_cnt == 1) {
  647. --superset_order_start_cnt; /* ugh.. hack this */
  648. }
  649. }
  650. #endif
  651. /* This is an awful hack to get around the problem of unspecified UNDEFINED
  652. * definitions in the supported locales derived from iso14651_t1. */
  653. if (!strcmp(cur_base->name, "iso14651_t1")) {
  654. fprintf(stderr, "Warning: adding UNDEFINED entry for %s\n", cur_col->name);
  655. strcpy(linebuf, "order_start forward;backward;forward;forward,position\n");
  656. pos_e = NULL;
  657. pos = linebuf;
  658. t = next_token();
  659. assert(t);
  660. assert(t == pos);
  661. do_order_start();
  662. strcpy(linebuf, "UNDEFINED IGNORE;IGNORE;IGNORE\n");
  663. pos_e = NULL;
  664. pos = linebuf;
  665. t = next_token();
  666. assert(t);
  667. assert(t == pos);
  668. do_weight(t);
  669. } else {
  670. error_msg("no definition of UNDEFINED for %s", cur_col->name);
  671. }
  672. }
  673. #endif
  674. fprintf(stderr, " Der: %15s", cur_col->name);
  675. }
  676. {
  677. ll_item_t *p = cur_col->section_list;
  678. fprintf(stderr, "%6u weights", tnumnodes(cur_col->root_wi_index));
  679. if (cur_base) {
  680. fprintf(stderr, " %6u der %6u reor %6u starter - %u new stubs",
  681. tnumnodes(cur_base->root_derived_wi),
  682. tnumnodes(cur_base->root_wi_index_reordered),
  683. tnumnodes(cur_base->root_starter_char),
  684. ll_count(cur_col->section_list, DT_REORDER));
  685. }
  686. fprintf(stderr, "\n");
  687. #if 0
  688. while (p) {
  689. assert(((section_t *)(p->data))->num_items ==
  690. ll_len(((section_t *)(p->data))->itm_list));
  691. if (!p->next &&
  692. ((*((section_t *)(p->data))->name == 'a')
  693. && (((section_t *)(p->data))->num_items == 0))
  694. ) {
  695. break;
  696. }
  697. if (!(p->data_type & DT_REORDER)) {
  698. if ((*((section_t *)(p->data))->name != 'a')
  699. || (((section_t *)(p->data))->num_items > 0)
  700. ) {
  701. fprintf(stderr,
  702. /* "\t%-15s %zu\n", */
  703. "\t%-15s %6u\n",
  704. ((section_t *)(p->data))->name,
  705. ((section_t *)(p->data))->num_items);
  706. }
  707. }
  708. p = p->next;
  709. }
  710. #endif
  711. }
  712. }
  713. static void print_colnode(const void *ptr, VISIT order, int level)
  714. {
  715. const colitem_t *p = *(const colitem_t **) ptr;
  716. if (order == postorder || order == leaf) {
  717. printf("collating item = \"%s\"", p->string);
  718. if (p->element) {
  719. printf(" is %s", p->element);
  720. }
  721. printf("\n");
  722. }
  723. }
  724. static void print_weight_node(const void *ptr, VISIT order, int level)
  725. {
  726. const weight_t *p = *(const weight_t **) ptr;
  727. int i;
  728. if (order == postorder || order == leaf) {
  729. printf("weight: (%d) ", p->num_weights);
  730. for (i = 0 ; i < p->num_weights ; i++) {
  731. if (p->rule[i] & R_FORWARD) {
  732. printf("F");
  733. }
  734. if (p->rule[i] & R_BACKWARD) {
  735. printf("B");
  736. }
  737. if (p->rule[i] & R_POSITION) {
  738. printf("P");
  739. }
  740. printf(",");
  741. }
  742. for (i = 0 ; i < p->num_weights ; i++) {
  743. printf(" %s", p->colitem[i]);
  744. }
  745. printf("\n");
  746. }
  747. }
  748. typedef struct {
  749. const char *der_name;
  750. int base_locale;
  751. } deps_t;
  752. enum {
  753. BASE_iso14651_t1,
  754. BASE_comm,
  755. BASE_cs_CZ,
  756. BASE_ar_SA,
  757. BASE_th_TH,
  758. BASE_ja_JP,
  759. BASE_ko_KR,
  760. BASE_MAX
  761. };
  762. static const char *base_name[] = {
  763. "iso14651_t1",
  764. "comm",
  765. "cs_CZ",
  766. "ar_SA",
  767. "th_TH",
  768. "ja_JP",
  769. "ko_KR"
  770. };
  771. static ll_item_t *locale_list[BASE_MAX];
  772. static void init_locale_list(void)
  773. {
  774. int i;
  775. for (i=0 ; i < BASE_MAX ; i++) {
  776. locale_list[i] = (ll_item_t *) xmalloc(sizeof(ll_item_t));
  777. locale_list[i]->prev = locale_list[i]->next = locale_list[i];
  778. locale_list[i]->data = (void *) base_name[i];
  779. }
  780. }
  781. deps_t deps[] = {
  782. { "af_ZA", BASE_iso14651_t1 },
  783. { "am_ET", BASE_iso14651_t1 },
  784. { "ar_AE", BASE_iso14651_t1 },
  785. { "ar_BH", BASE_iso14651_t1 },
  786. { "ar_DZ", BASE_iso14651_t1 },
  787. { "ar_EG", BASE_iso14651_t1 },
  788. { "ar_IN", BASE_iso14651_t1 },
  789. { "ar_IQ", BASE_iso14651_t1 },
  790. { "ar_JO", BASE_iso14651_t1 },
  791. { "ar_KW", BASE_iso14651_t1 },
  792. { "ar_LB", BASE_iso14651_t1 },
  793. { "ar_LY", BASE_iso14651_t1 },
  794. { "ar_MA", BASE_iso14651_t1 },
  795. { "ar_OM", BASE_iso14651_t1 },
  796. { "ar_QA", BASE_iso14651_t1 },
  797. { "ar_SA", BASE_ar_SA },
  798. { "ar_SD", BASE_iso14651_t1 },
  799. { "ar_SY", BASE_iso14651_t1 },
  800. { "ar_TN", BASE_iso14651_t1 },
  801. { "ar_YE", BASE_iso14651_t1 },
  802. { "az_AZ", BASE_iso14651_t1 },
  803. { "be_BY", BASE_iso14651_t1 },
  804. { "bg_BG", BASE_iso14651_t1 },
  805. { "bn_BD", BASE_iso14651_t1 },
  806. { "bn_IN", BASE_iso14651_t1 },
  807. { "br_FR", BASE_iso14651_t1 },
  808. { "bs_BA", BASE_iso14651_t1 },
  809. { "ca_ES", BASE_comm },
  810. { "cs_CZ", BASE_cs_CZ },
  811. { "cy_GB", BASE_iso14651_t1 },
  812. { "da_DK", BASE_comm },
  813. { "de_AT", BASE_iso14651_t1 },
  814. { "de_BE", BASE_iso14651_t1 },
  815. { "de_CH", BASE_iso14651_t1 },
  816. { "de_DE", BASE_iso14651_t1 },
  817. { "de_LU", BASE_iso14651_t1 },
  818. { "el_GR", BASE_iso14651_t1 },
  819. { "en_AU", BASE_iso14651_t1 },
  820. { "en_BW", BASE_iso14651_t1 },
  821. { "en_CA", BASE_comm },
  822. { "en_DK", BASE_iso14651_t1 },
  823. { "en_GB", BASE_iso14651_t1 },
  824. { "en_HK", BASE_iso14651_t1 },
  825. { "en_IE", BASE_iso14651_t1 },
  826. { "en_IN", BASE_iso14651_t1 },
  827. { "en_NZ", BASE_iso14651_t1 },
  828. { "en_PH", BASE_iso14651_t1 },
  829. { "en_SG", BASE_iso14651_t1 },
  830. { "en_US", BASE_iso14651_t1 },
  831. { "en_ZA", BASE_iso14651_t1 },
  832. { "en_ZW", BASE_iso14651_t1 },
  833. { "eo_EO", BASE_iso14651_t1 },
  834. { "es_AR", BASE_comm },
  835. { "es_BO", BASE_comm },
  836. { "es_CL", BASE_comm },
  837. { "es_CO", BASE_comm },
  838. { "es_CR", BASE_comm },
  839. { "es_DO", BASE_comm },
  840. { "es_EC", BASE_comm },
  841. { "es_ES", BASE_comm },
  842. { "es_GT", BASE_comm },
  843. { "es_HN", BASE_comm },
  844. { "es_MX", BASE_comm },
  845. { "es_NI", BASE_comm },
  846. { "es_PA", BASE_comm },
  847. { "es_PE", BASE_comm },
  848. { "es_PR", BASE_comm },
  849. { "es_PY", BASE_comm },
  850. { "es_SV", BASE_comm },
  851. { "es_US", BASE_comm },
  852. { "es_UY", BASE_comm },
  853. { "es_VE", BASE_comm },
  854. { "et_EE", BASE_comm },
  855. { "eu_ES", BASE_iso14651_t1 },
  856. { "fa_IR", BASE_iso14651_t1 },
  857. { "fi_FI", BASE_comm },
  858. { "fo_FO", BASE_comm },
  859. { "fr_BE", BASE_iso14651_t1 },
  860. { "fr_CA", BASE_comm },
  861. { "fr_CH", BASE_iso14651_t1 },
  862. { "fr_FR", BASE_iso14651_t1 },
  863. { "fr_LU", BASE_iso14651_t1 },
  864. { "ga_IE", BASE_iso14651_t1 },
  865. { "gd_GB", BASE_iso14651_t1 },
  866. { "gl_ES", BASE_comm },
  867. { "gv_GB", BASE_iso14651_t1 },
  868. { "he_IL", BASE_iso14651_t1 },
  869. { "hi_IN", BASE_iso14651_t1 },
  870. { "hr_HR", BASE_comm },
  871. { "hu_HU", BASE_iso14651_t1 },
  872. { "hy_AM", BASE_iso14651_t1 },
  873. { "id_ID", BASE_iso14651_t1 },
  874. { "is_IS", BASE_comm },
  875. { "it_CH", BASE_iso14651_t1 },
  876. { "it_IT", BASE_iso14651_t1 },
  877. { "iw_IL", BASE_iso14651_t1 },
  878. { "ja_JP", BASE_ja_JP },
  879. { "ka_GE", BASE_iso14651_t1 },
  880. { "kl_GL", BASE_comm },
  881. { "ko_KR", BASE_ko_KR },
  882. { "kw_GB", BASE_iso14651_t1 },
  883. { "lt_LT", BASE_comm },
  884. { "lv_LV", BASE_comm },
  885. { "mi_NZ", BASE_iso14651_t1 },
  886. { "mk_MK", BASE_iso14651_t1 },
  887. { "mr_IN", BASE_iso14651_t1 },
  888. { "ms_MY", BASE_iso14651_t1 },
  889. { "mt_MT", BASE_iso14651_t1 },
  890. { "nl_BE", BASE_iso14651_t1 },
  891. { "nl_NL", BASE_iso14651_t1 },
  892. { "nn_NO", BASE_iso14651_t1 },
  893. { "no_NO", BASE_comm },
  894. { "oc_FR", BASE_iso14651_t1 },
  895. { "pl_PL", BASE_comm },
  896. { "pt_BR", BASE_iso14651_t1 },
  897. { "pt_PT", BASE_iso14651_t1 },
  898. { "ro_RO", BASE_iso14651_t1 },
  899. { "ru_RU", BASE_iso14651_t1 },
  900. { "ru_UA", BASE_iso14651_t1 },
  901. { "se_NO", BASE_iso14651_t1 },
  902. { "sk_SK", BASE_cs_CZ },
  903. { "sl_SI", BASE_comm },
  904. { "sq_AL", BASE_iso14651_t1 },
  905. { "sr_YU", BASE_iso14651_t1 },
  906. { "sv_FI", BASE_comm },
  907. { "sv_SE", BASE_iso14651_t1 },
  908. { "ta_IN", BASE_iso14651_t1 },
  909. { "te_IN", BASE_iso14651_t1 },
  910. { "tg_TJ", BASE_iso14651_t1 },
  911. { "th_TH", BASE_th_TH },
  912. { "ti_ER", BASE_iso14651_t1 },
  913. { "ti_ET", BASE_iso14651_t1 },
  914. { "tl_PH", BASE_iso14651_t1 },
  915. { "tr_TR", BASE_comm },
  916. { "tt_RU", BASE_iso14651_t1 },
  917. { "uk_UA", BASE_iso14651_t1 },
  918. { "ur_PK", BASE_iso14651_t1 },
  919. { "uz_UZ", BASE_iso14651_t1 },
  920. { "vi_VN", BASE_iso14651_t1 },
  921. { "wa_BE", BASE_iso14651_t1 },
  922. { "yi_US", BASE_iso14651_t1 },
  923. { "zh_CN", BASE_iso14651_t1 },
  924. { "zh_HK", BASE_iso14651_t1 },
  925. { "zh_SG", BASE_iso14651_t1 },
  926. { "zh_TW", BASE_iso14651_t1 },
  927. };
  928. static int der_count[BASE_MAX];
  929. static const char *new_args[500];
  930. static int new_arg_count;
  931. static int dep_cmp(const void *s1, const void *s2)
  932. {
  933. return strcmp( (const char *) s1, ((const deps_t *) s2)->der_name);
  934. }
  935. static int old_main(int argc, char **argv);
  936. int main(int argc, char **argv)
  937. {
  938. const deps_t *p;
  939. ll_item_t *lli;
  940. int i;
  941. int total;
  942. if (argc < 2) {
  943. return EXIT_FAILURE;
  944. }
  945. init_locale_list();
  946. while (--argc) {
  947. p = (const deps_t *) bsearch(*++argv, deps, sizeof(deps)/sizeof(deps[0]), sizeof(deps[0]), dep_cmp);
  948. if (!p) {
  949. if (!strcmp("C", *argv)) {
  950. printf("ignoring C locale\n");
  951. continue;
  952. } else {
  953. printf("%s not found\n", *argv);
  954. return EXIT_FAILURE;
  955. }
  956. }
  957. i = p->base_locale;
  958. ++der_count[i];
  959. if (!strcmp(base_name[i], *argv)) {
  960. /* same name as base, so skip after count incremented */
  961. continue;
  962. }
  963. /* add it to the list. the main body will catch duplicates */
  964. lli = (ll_item_t *) xmalloc(sizeof(ll_item_t));
  965. lli->prev = lli->next = NULL;
  966. lli->data = (void *) *argv;
  967. insque(lli, locale_list[i]);
  968. }
  969. total = 0;
  970. for (i=0 ; i < BASE_MAX ; i++) {
  971. /* printf("der_count[%2d] = %3d\n", i, der_count[i]); */
  972. total += der_count[i];
  973. }
  974. /* printf("total = %d\n", total); */
  975. new_args[new_arg_count++] = "dummyprogramname";
  976. for (i=0 ; i < BASE_MAX ; i++) {
  977. if (!der_count[i]) {
  978. continue;
  979. }
  980. new_args[new_arg_count++] = (i == BASE_comm) ? "-c" : "-b";
  981. lli = locale_list[i];
  982. do {
  983. new_args[new_arg_count++] = (const char *) (lli->data);
  984. lli = lli->next;
  985. } while (lli != locale_list[i]);
  986. new_args[new_arg_count++] = "-f";
  987. }
  988. /* for (i=0 ; i < new_arg_count ; i++) { */
  989. /* printf("%3d: %s\n", i, new_args[i]); */
  990. /* } */
  991. return old_main(new_arg_count, (char **) new_args);
  992. }
  993. /* usage... prog -b basefile derived {derived} -s single {single} */
  994. static int old_main(int argc, char **argv)
  995. {
  996. int next_is_base = 0;
  997. int next_is_subset = 0;
  998. superset = 0;
  999. while (--argc) {
  1000. ++argv;
  1001. if (**argv == '-') {
  1002. if ((*argv)[1] == 'd') {
  1003. dump_weights((*argv) + 2);
  1004. } else if ((*argv)[1] == 'f') { /* dump all weight rules */
  1005. finalize_base();
  1006. } else if ((*argv)[1] == 'R') { /* dump all weight rules */
  1007. twalk(root_weight, print_weight_node);
  1008. } else if (((*argv)[1] == 'c') && !(*argv)[2]) { /* new common subset */
  1009. cur_base = cur_derived = NULL;
  1010. next_is_subset = 1;
  1011. next_is_base = 1;
  1012. superset = 0;
  1013. } else if (((*argv)[1] == 'b') && !(*argv)[2]) { /* new base locale */
  1014. cur_base = cur_derived = NULL;
  1015. next_is_subset = 0;
  1016. next_is_base = 1;
  1017. superset = 0;
  1018. } else if (((*argv)[1] == 's') && !(*argv)[2]) { /* single locales follow */
  1019. cur_base = cur_derived = NULL;
  1020. next_is_subset = 0;
  1021. next_is_base = 2;
  1022. superset = 0;
  1023. } else {
  1024. error_msg("unrecognized option %s", *argv);
  1025. }
  1026. continue;
  1027. }
  1028. /* new file */
  1029. new_col_locale(*argv); /* automaticly sets cur_col */
  1030. if (next_is_base) {
  1031. cur_base = cur_col;
  1032. } else {
  1033. cur_derived = cur_col;
  1034. }
  1035. pushfile(*argv);
  1036. /* fprintf(stderr, "processing file %s\n", *argv); */
  1037. processfile(); /* this does a popfile */
  1038. /* twalk(cur_col->root_colitem, print_colnode); */
  1039. if (next_is_base == 1) {
  1040. next_is_base = 0;
  1041. }
  1042. if (next_is_subset) {
  1043. next_is_subset = 0;
  1044. superset = 1;
  1045. }
  1046. }
  1047. fprintf(stderr, "success!\n");
  1048. fprintf(stderr,
  1049. /* "num_sym=%zu mem_sym=%zu unique_weights=%zu\n", */
  1050. "num_sym=%u mem_sym=%u unique_weights=%u\n",
  1051. num_sym, mem_sym, unique_weights);
  1052. /* twalk(root_weight, print_weight_node); */
  1053. fprintf(stderr, "num base locales = %d num derived locales = %d\n",
  1054. base_locale_len, der_locale_len);
  1055. fprintf(stderr,
  1056. "override_len = %d multistart_len = %d weightstr_len = %d\n"
  1057. "wcs2colidt_len = %d index2weight_len = %d index2ruleidx_len = %d\n"
  1058. "ruletable_len = %d\n"
  1059. "total size is %d bytes or %d kB\n",
  1060. override_len, multistart_len, weightstr_len,
  1061. wcs2colidt_len, index2weight_len, index2ruleidx_len,
  1062. ruletable_len,
  1063. #warning mult by 2 for rule indecies
  1064. (override_len + multistart_len + weightstr_len
  1065. + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len) * 2,
  1066. (override_len + multistart_len + weightstr_len
  1067. + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len + 511) / 512);
  1068. #if 0
  1069. {
  1070. int i;
  1071. for (i=0 ; i < base_locale_len ; i++) {
  1072. dump_base_locale(i);
  1073. }
  1074. for (i=0 ; i < der_locale_len ; i++) {
  1075. dump_der_locale(i);
  1076. }
  1077. }
  1078. #endif
  1079. {
  1080. FILE *fp = fopen("locale_collate.h", "w");
  1081. if (!fp) {
  1082. error_msg("couldn't open output file!");
  1083. }
  1084. dump_collate(fp);
  1085. if (ferror(fp) || fclose(fp)) {
  1086. error_msg("write error or close error for output file!\n");
  1087. }
  1088. }
  1089. return EXIT_SUCCESS;
  1090. }
  1091. static void error_msg(const char *fmt, ...)
  1092. {
  1093. va_list arg;
  1094. fprintf(stderr, "Error: ");
  1095. if (fno >= 0) {
  1096. fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]);
  1097. }
  1098. va_start(arg, fmt);
  1099. vfprintf(stderr, fmt, arg);
  1100. va_end(arg);
  1101. fprintf(stderr, "\n");
  1102. exit(EXIT_FAILURE);
  1103. }
  1104. static void pushfile(char *filename)
  1105. {
  1106. static char fbuf[PATH_MAX];
  1107. snprintf(fbuf, PATH_MAX, "collation/%s", filename);
  1108. if (fno >= MAX_FNO) {
  1109. error_msg("file stack size exceeded");
  1110. }
  1111. if (!(fstack[++fno] = fopen(fbuf, "r"))) {
  1112. --fno; /* oops */
  1113. error_msg("cannot open file %s", fbuf);
  1114. }
  1115. fname[fno] = xsymdup(filename);
  1116. lineno[fno] = 0;
  1117. }
  1118. static void popfile(void)
  1119. {
  1120. if (fno < 0) {
  1121. error_msg("pop on empty file stack");
  1122. }
  1123. /* free(fname[fno]); */
  1124. fclose(fstack[fno]);
  1125. --fno;
  1126. }
  1127. static void eatwhitespace(void)
  1128. {
  1129. while (isspace(*pos)) {
  1130. ++pos;
  1131. }
  1132. }
  1133. static int iscommentchar(int c)
  1134. {
  1135. return ((c == '#') || (c == '%'));
  1136. }
  1137. static int next_line(void)
  1138. {
  1139. size_t n;
  1140. char *s = linebuf;
  1141. assert(fno >= 0);
  1142. pos_e = NULL;
  1143. do {
  1144. if (fgets(s, sizeof(linebuf), fstack[fno]) != NULL) {
  1145. ++lineno[fno];
  1146. n = strlen(linebuf);
  1147. if ((n == sizeof(linebuf) - 1) && (linebuf[n-1] != '\n')) {
  1148. /* Either line is too long or last line is very long with
  1149. * no trailing newline. But we'll always treat it as an
  1150. * errro. */
  1151. error_msg("line too long?");
  1152. }
  1153. --n;
  1154. /* Be careful... last line doesn't need a newline. */
  1155. if (linebuf[n] == '\n') {
  1156. linebuf[n--] = 0; /* trim trailing newline */
  1157. }
  1158. pos = linebuf;
  1159. eatwhitespace();
  1160. if (*pos && !iscommentchar(*pos)) { /* not empty or comment line */
  1161. return 1; /* got a line */
  1162. }
  1163. } else { /* eof */
  1164. popfile();
  1165. }
  1166. } while (fno >= 0);
  1167. return 0;
  1168. }
  1169. static char *next_token(void)
  1170. {
  1171. char *p;
  1172. #if 0
  1173. if (pos_e == NULL) {
  1174. return NULL
  1175. pos = pos_e;
  1176. *pos = end_of_token;
  1177. end_of_token = 0;
  1178. }
  1179. #else
  1180. if (pos_e != NULL) {
  1181. pos = pos_e;
  1182. *pos = end_of_token;
  1183. end_of_token = 0;
  1184. }
  1185. #endif
  1186. eatwhitespace();
  1187. p = pos;
  1188. if (!*p || iscommentchar(*p)) { /* end of line or start of comment */
  1189. pos = pos_e = NULL;
  1190. *p = 0; /* treat comment as end of line */
  1191. /* fprintf(stdout, "returning NUL token |%s|\n", pos); */
  1192. return NULL;
  1193. #if 1
  1194. } else if (*p == '<') { /* collating symbol, element, or value */
  1195. while (*++p) {
  1196. if ((*p == '/') && p[1]) {
  1197. ++p;
  1198. continue;
  1199. }
  1200. if (*p == '>') {
  1201. pos_e = ++p;
  1202. end_of_token = *p;
  1203. *p = 0;
  1204. /* fprintf(stdout, "returning col token |%s|\n", pos); */
  1205. return pos;
  1206. }
  1207. }
  1208. } else if (*p == '"') { /* collating element value? */
  1209. while (*++p) {
  1210. if (*p == '"') { /* found the end of the quoted string */
  1211. pos_e = ++p;
  1212. end_of_token = *p;
  1213. *p = 0;
  1214. /* fprintf(stdout, "returning quote token |%s|\n", pos); */
  1215. return pos;
  1216. }
  1217. }
  1218. #endif
  1219. } else { /* some kind of keyword */
  1220. while (*++p) {
  1221. if (isspace(*p) || (*p == ';')) {
  1222. break;
  1223. }
  1224. }
  1225. pos_e = p;
  1226. end_of_token = *p;
  1227. *p = 0;
  1228. /* fprintf(stdout, "returning key token |%s|\n", pos); */
  1229. return pos;
  1230. }
  1231. error_msg("illegal token |%s|", pos);
  1232. }
  1233. static void *xmalloc(size_t n)
  1234. {
  1235. void *p;
  1236. if (!(p = malloc(n))) {
  1237. error_msg("OUT OF MEMORY");
  1238. }
  1239. return p;
  1240. }
  1241. static void do_copy(void)
  1242. {
  1243. char *s;
  1244. char *e;
  1245. if ((s = next_token()) != NULL) {
  1246. e = strchr(s + 1, '"');
  1247. if ((*s == '"') && e && (*e == '"') && !e[1]) {
  1248. if (next_token() != NULL) {
  1249. error_msg("illegal trailing text: %s", pos);
  1250. }
  1251. *e = 0;
  1252. ++s;
  1253. if (cur_base && !strcmp(cur_base->name,s)) {
  1254. /* fprintf(stderr, "skipping copy of base file %s\n", s); */
  1255. #warning need to update last in order and position or check
  1256. return;
  1257. }
  1258. /* fprintf(stderr, "full copy of %s\n", s); */
  1259. pushfile(s);
  1260. return;
  1261. }
  1262. }
  1263. error_msg("illegal or missing arg for copy: %s", s);
  1264. }
  1265. static void do_colsym(void)
  1266. {
  1267. char *s;
  1268. char *e;
  1269. if ((s = next_token()) != NULL) {
  1270. e = strrchr(s,'>');
  1271. if ((*s == '<') && e && (*e == '>') && !e[1]) {
  1272. if (next_token() != NULL) {
  1273. error_msg("illegal trailing text: %s", pos);
  1274. }
  1275. e[1] = 0; /* cleanup in case next_token stored something */
  1276. add_colitem(s,NULL);
  1277. return;
  1278. }
  1279. }
  1280. error_msg("illegal or missing arg for collating-symbol: %s", s);
  1281. }
  1282. static void do_colele(void)
  1283. {
  1284. char *s;
  1285. char *e;
  1286. char *s1;
  1287. char *e1;
  1288. int n;
  1289. if ((s = next_token()) != NULL) {
  1290. e = strrchr(s,'>');
  1291. if ((*s == '<') && e && (*e == '>') && !e[1]) {
  1292. if (((s1 = next_token()) == NULL)
  1293. || (strcmp(s1,"from") != 0)
  1294. || ((s1 = next_token()) == NULL)
  1295. || (*s1 != '\"')
  1296. ) {
  1297. error_msg("illegal format for collating-element spec");
  1298. }
  1299. e1 = strchr(s1 + 1, '"');
  1300. if ((*s1 != '"') || !e1 || (*e1 != '"') || (e1[1] != 0)) {
  1301. error_msg("illegal definition for collating-element: %s", s1);
  1302. }
  1303. if (next_token() != NULL) {
  1304. error_msg("illegal trailing text: %s", pos);
  1305. }
  1306. e[1] = 0; /* cleanup in case next_token stored something */
  1307. e1[1] = 0;
  1308. add_colitem(s,s1);
  1309. ++s1;
  1310. if (!(n = is_ucode(s1))) {
  1311. error_msg("starting char must be a <U####> code: %s", s1);
  1312. }
  1313. assert(s1[n] == '<');
  1314. s1[n] = 0;
  1315. s = xsymdup(s1);
  1316. if (!(tsearch(s, &cur_base->root_starter_char, sym_cmp))) {
  1317. error_msg("OUT OF MEMORY");
  1318. }
  1319. return;
  1320. }
  1321. }
  1322. error_msg("illegal or missing arg for collating-element: %s", s);
  1323. }
  1324. static ll_item_t *find_section_list_item(const char *name, col_locale_t *loc)
  1325. {
  1326. ll_item_t *p;
  1327. if (!loc) {
  1328. return NULL;
  1329. }
  1330. p = loc->section_list;
  1331. while (p) {
  1332. #warning devel code
  1333. /* if (!((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER))) { */
  1334. /* fprintf(stderr, "fsli = %d\n", p->data_type); */
  1335. /* } */
  1336. assert((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER));
  1337. if (!strcmp(name, ((section_t *)(p->data))->name)) {
  1338. break;
  1339. }
  1340. p = p->next;
  1341. }
  1342. return p;
  1343. }
  1344. static ll_item_t *find_ll_last(ll_item_t *p)
  1345. {
  1346. assert(p);
  1347. while (p->next) {
  1348. p = p->next;
  1349. }
  1350. return p;
  1351. }
  1352. static void do_script(void)
  1353. {
  1354. char *s;
  1355. char *e;
  1356. if ((s = next_token()) != NULL) {
  1357. e = strrchr(s,'>');
  1358. if ((*s == '<') && e && (*e == '>') && !e[1]) {
  1359. if (next_token() != NULL) {
  1360. error_msg("illegal trailing text: %s", pos);
  1361. }
  1362. e[1] = 0; /* cleanup in case next_token stored something */
  1363. add_script(s);
  1364. return;
  1365. }
  1366. }
  1367. error_msg("illegal or missing arg for script: %s", s);
  1368. }
  1369. static col_locale_t *new_col_locale(char *name)
  1370. {
  1371. ll_item_t *lli;
  1372. ll_item_t *lli2;
  1373. cur_col = (col_locale_t *) xmalloc(sizeof(col_locale_t));
  1374. cur_col->name = name;
  1375. cur_col->root_colitem = NULL;
  1376. cur_col->root_element = NULL;
  1377. cur_col->root_scripts = NULL;
  1378. cur_col->base_locale = NULL;
  1379. if (!superset) {
  1380. /* start with an anonymous section */
  1381. cur_section = new_section(NULL);
  1382. cur_col->section_list = new_ll_item(DT_SECTION, cur_section);
  1383. } else {
  1384. /* start with a reorder section */
  1385. cur_section = new_section("R");
  1386. cur_num_weights = cur_section->num_rules
  1387. = ((section_t *)(cur_base->section_list->data))->num_rules;
  1388. memcpy(cur_rule,
  1389. ((section_t *)(cur_base->section_list->data))->rules,
  1390. MAX_COLLATION_WEIGHTS);
  1391. memcpy(cur_section->rules,
  1392. ((section_t *)(cur_base->section_list->data))->rules,
  1393. MAX_COLLATION_WEIGHTS);
  1394. cur_col->section_list = new_ll_item(DT_REORDER, cur_section);
  1395. assert(cur_base->section_list->next == NULL); /* currently only one section allowed */
  1396. lli = ((section_t *)(cur_base->section_list->data))->itm_list;
  1397. assert(lli);
  1398. lli2 = new_ll_item(DT_REORDER, cur_section);
  1399. lli2->prev = lli2->next = lli2;
  1400. insque(lli2, lli->prev);
  1401. ((section_t *)(cur_base->section_list->data))->itm_list = lli2;
  1402. }
  1403. /* cur_col->section_list = NULL; */
  1404. /* add_script(((section_t *)(cur_col->section_list->data))->name); */
  1405. cur_col->root_wi_index = NULL;
  1406. cur_col->root_wi_index_reordered = NULL;
  1407. cur_col->root_derived_wi = NULL;
  1408. cur_col->derived_list = NULL;
  1409. cur_col->root_starter_char = NULL;
  1410. cur_col->root_starter_all = NULL;
  1411. cur_col->undefined_idx = NULL;
  1412. return cur_col;
  1413. }
  1414. static int colitem_cmp(const void *n1, const void *n2)
  1415. {
  1416. return strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string);
  1417. }
  1418. static int colelement_cmp(const void *n1, const void *n2)
  1419. {
  1420. int r;
  1421. r = strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string);
  1422. if (!r) {
  1423. if (((colitem_t *)n1)->element && ((colitem_t *)n2)->element) {
  1424. r = strcmp(((colitem_t *)n1)->element, ((colitem_t *)n2)->element);
  1425. } else if (((colitem_t *)n1)->element == ((colitem_t *)n2)->element) {
  1426. r = 0; /* both null */
  1427. } else {
  1428. r = (((colitem_t *)n1)->element == NULL) ? -1 : 1;
  1429. }
  1430. }
  1431. return r;
  1432. }
  1433. static void del_colitem(colitem_t *p)
  1434. {
  1435. /* free((void *) p->element); */
  1436. /* free((void *) p->string); */
  1437. free(p);
  1438. }
  1439. static colitem_t *new_colitem(char *item, char *def)
  1440. {
  1441. colitem_t *p;
  1442. p = xmalloc(sizeof(colitem_t));
  1443. p->string = xsymdup(item);
  1444. p->element = (!def) ? def : xsymdup(def);
  1445. return p;
  1446. }
  1447. static void add_colitem(char *item, char *def)
  1448. {
  1449. colitem_t *p;
  1450. #if 0
  1451. printf("adding collation item %s", item);
  1452. if (def) {
  1453. printf(" with definition %s", def);
  1454. }
  1455. printf("\n");
  1456. #endif
  1457. p = new_colitem(item, def);
  1458. #warning devel code
  1459. if (superset) {
  1460. if (tfind(p, &cur_base->root_colitem, colitem_cmp)) {
  1461. /* fprintf(stderr, "skipping superset duplicate collating item \"%s\"\n", p->string); */
  1462. del_colitem(p);
  1463. return;
  1464. /* } else { */
  1465. /* fprintf(stderr, "superset: new collating item \"%s\" = %s\n", p->string, p->element); */
  1466. }
  1467. }
  1468. if (cur_col == cur_derived) {
  1469. if (!tfind(p, &cur_base->root_colitem, colitem_cmp)) {
  1470. /* not in current but could be in base */
  1471. if (!tsearch(p, &cur_base->root_colitem, colitem_cmp)) {
  1472. error_msg("OUT OF MEMORY!");
  1473. }
  1474. } else if (!tfind(p, &cur_base->root_colitem, colelement_cmp)) {
  1475. error_msg("collating element/symbol mismatch: item=%s def=%s", item, def);
  1476. }
  1477. }
  1478. if (!tfind(p, &cur_col->root_colitem, colitem_cmp)) {
  1479. /* not in current but could be in base */
  1480. if (!tsearch(p, &cur_col->root_colitem, colitem_cmp)) {
  1481. error_msg("OUT OF MEMORY!");
  1482. }
  1483. } else if (!tfind(p, &cur_col->root_colitem, colelement_cmp)) {
  1484. error_msg("collating element/symbol mismatch");
  1485. } else { /* already there */
  1486. fprintf(stderr, "duplicate collating item \"%s\"\n", p->string);
  1487. del_colitem(p);
  1488. }
  1489. }
  1490. /* add a script (section) to the current locale */
  1491. static void add_script(const char *s)
  1492. {
  1493. ll_item_t *l;
  1494. /* make sure it isn't in base if working with derived */
  1495. if (cur_base != cur_col) {
  1496. if (find_section_list_item(s, cur_base)) {
  1497. error_msg("attempt to add script %s for derived when already in base", s);
  1498. }
  1499. }
  1500. if (find_section_list_item(s, cur_col)) {
  1501. error_msg("attempt to readd script %s", s);
  1502. }
  1503. l = find_ll_last(cur_col->section_list);
  1504. insque(new_ll_item(DT_SECTION, new_section(s)), l);
  1505. }
  1506. static const char str_forward[] = "forward";
  1507. static const char str_backward[] = "backward";
  1508. static const char str_position[] = "position";
  1509. static void do_order_start(void)
  1510. {
  1511. const char *s;
  1512. char *e;
  1513. ll_item_t *l;
  1514. section_t *sect;
  1515. int rule;
  1516. if (order_state & ~IN_ORDER) {
  1517. error_msg("order_start following reorder{_sections}_after");
  1518. }
  1519. order_state |= IN_ORDER;
  1520. if (superset) {
  1521. if (++superset_order_start_cnt > 1) {
  1522. error_msg("currently only a common order_start is supported in superset");
  1523. }
  1524. return;
  1525. }
  1526. if (!(s = next_token())) {
  1527. s = str_forward; /* if no args */
  1528. }
  1529. if (*s == '<') { /* section (script) */
  1530. e = strrchr(s,'>');
  1531. if ((*s == '<') && e && (*e == '>') && !e[1]) {
  1532. e[1] = 0; /* cleanup in case next_token stored something */
  1533. if (!(l = find_section_list_item(s, cur_col))) {
  1534. error_msg("ref of undefined sections: %s", s);
  1535. }
  1536. sect = (section_t *)(l->data);
  1537. if (sect->num_rules) {
  1538. error_msg("sections already defined: %s", s);
  1539. }
  1540. } else {
  1541. error_msg("illegal section ref: %s", s);
  1542. }
  1543. if (!(s = next_token())) {
  1544. s = str_forward; /* if no args */
  1545. } else if (*s != ';') {
  1546. error_msg("missing seperator!");
  1547. }
  1548. } else { /* need an anonymous section */
  1549. if ((*cur_section->name != '<') && (cur_section->num_items == 0)) { /* already in an empty anonymous section */
  1550. sect = cur_section;
  1551. } else {
  1552. sect = new_section(NULL);
  1553. l = find_ll_last(cur_col->section_list);
  1554. insque(new_ll_item(DT_SECTION, new_section(s)), l);
  1555. }
  1556. sect->num_rules = 0; /* setting this below so nix default */
  1557. }
  1558. cur_section = sect;
  1559. #warning need to add section to weight list?
  1560. /* now do rules */
  1561. do {
  1562. rule = 0;
  1563. if (*s == ';') {
  1564. ++s;
  1565. }
  1566. while (*s) {
  1567. if (!strncmp(str_forward, s, 7)) {
  1568. rule |= R_FORWARD;
  1569. s += 7;
  1570. } else if (!strncmp(str_backward, s, 8)) {
  1571. rule |= R_BACKWARD;
  1572. s += 8;
  1573. } else if (!strncmp(str_position, s, 8)) {
  1574. rule |= R_POSITION;
  1575. s += 8;
  1576. }
  1577. if (*s == ',') {
  1578. ++s;
  1579. continue;
  1580. }
  1581. if (!*s || (*s == ';')) {
  1582. if (sect->num_rules >= MAX_COLLATION_WEIGHTS) {
  1583. error_msg("more than %d weight rules!", MAX_COLLATION_WEIGHTS);
  1584. }
  1585. if (!rule) {
  1586. error_msg("missing weight rule!");
  1587. }
  1588. if ((rule & (R_FORWARD|R_BACKWARD|R_POSITION)) > R_BACKWARD) {
  1589. error_msg("backward paired with forward and/or position!");
  1590. }
  1591. sect->rules[sect->num_rules++] = rule;
  1592. rule = 0;
  1593. continue;
  1594. }
  1595. error_msg("illegal weight rule: %s", s);
  1596. }
  1597. } while ((s = next_token()) != NULL);
  1598. cur_section = sect;
  1599. /* fprintf(stderr, "setting cur_num_weights to %d for %s\n", sect->num_rules, sect->name); */
  1600. cur_num_weights = sect->num_rules;
  1601. memcpy(cur_rule, sect->rules, MAX_COLLATION_WEIGHTS);
  1602. }
  1603. static void do_order_end(void)
  1604. {
  1605. if (!(order_state & IN_ORDER)) {
  1606. error_msg("order_end with no matching order_start");
  1607. }
  1608. order_state &= ~IN_ORDER;
  1609. cur_section = new_section(NULL);
  1610. }
  1611. static void do_reorder_after(void)
  1612. {
  1613. char *t;
  1614. ll_item_t *lli;
  1615. const weight_t *w;
  1616. int save_cur_num_weights;
  1617. char save_cur_rule[MAX_COLLATION_WEIGHTS];
  1618. if (order_state & ~IN_REORDER) {
  1619. error_msg("reorder_after following order_start or reorder_sections_after");
  1620. }
  1621. order_state |= IN_REORDER;
  1622. if (superset) {
  1623. error_msg("currently reorder_after is not supported in supersets");
  1624. }
  1625. #warning have to use rule for current section!!!
  1626. if (!(t = next_token())) {
  1627. error_msg("missing arg for reorder_after");
  1628. }
  1629. t = xsymdup(t);
  1630. if (next_token() != NULL) {
  1631. error_msg("trailing text reorder_after: %s", pos);
  1632. }
  1633. if (cur_col == cur_base) {
  1634. error_msg("sorry.. reorder_after in base locale is not currently supported");
  1635. }
  1636. if (!(lli = find_wi_index(t, cur_base))) {
  1637. error_msg("reorder_after for non-base item currently not supported: %s", t);
  1638. }
  1639. w = ((weighted_item_t *)(lli->data))->weight;
  1640. save_cur_num_weights = cur_num_weights;
  1641. memcpy(save_cur_rule, cur_rule, MAX_COLLATION_WEIGHTS);
  1642. cur_section = new_section("R");
  1643. insque(new_ll_item(DT_REORDER, cur_section), lli);
  1644. #if 0
  1645. {
  1646. ll_item_t *l1;
  1647. ll_item_t *l2;
  1648. ll_item_t *l3;
  1649. l1 = new_ll_item(DT_REORDER, cur_section);
  1650. l2 = find_ll_last(cur_col->section_list);
  1651. insque(l1, l2);
  1652. l3 = find_ll_last(cur_col->section_list);
  1653. fprintf(stderr, "reorder_after %p %p %p %s\n", l1, l2, l3, cur_section->name);
  1654. }
  1655. #else
  1656. insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list));
  1657. #endif
  1658. cur_num_weights = cur_section->num_rules = save_cur_num_weights;
  1659. memcpy(cur_rule, save_cur_rule, MAX_COLLATION_WEIGHTS);
  1660. memcpy(cur_section->rules, save_cur_rule, MAX_COLLATION_WEIGHTS);
  1661. #warning devel code
  1662. /* fprintf(stderr, "reorder -- %s %d\n", ((weighted_item_t *)(lli->data))->symbol, w->num_weights); */
  1663. #warning hack to get around hu_HU reorder-after problem
  1664. /* if (!w->num_weights) { */
  1665. /* } else { */
  1666. /* cur_num_weights = w->num_weights; */
  1667. /* memcpy(cur_rule, w->rule, MAX_COLLATION_WEIGHTS); */
  1668. /* } */
  1669. /* fprintf(stderr, "reorder_after succeeded for %s\n", t); */
  1670. }
  1671. static void do_reorder_end(void)
  1672. {
  1673. if (!(order_state & IN_REORDER)) {
  1674. error_msg("reorder_end with no matching reorder_after");
  1675. }
  1676. order_state &= ~IN_REORDER;
  1677. }
  1678. static void do_reorder_sections_after(void)
  1679. {
  1680. const char *t;
  1681. ll_item_t *lli;
  1682. if (order_state & ~IN_REORDER_SECTIONS) {
  1683. error_msg("reorder_sections_after following order_start or reorder_after");
  1684. }
  1685. order_state |= IN_REORDER_SECTIONS;
  1686. if (superset) {
  1687. error_msg("currently reorder_sections_after is not supported in supersets");
  1688. }
  1689. if (!(t = next_token())) {
  1690. error_msg("missing arg for reorder_sections_after");
  1691. }
  1692. t = xsymdup(t);
  1693. if (next_token() != NULL) {
  1694. error_msg("trailing text reorder_sections_after: %s", pos);
  1695. }
  1696. if (cur_col == cur_base) {
  1697. error_msg("sorry.. reorder_sections_after in base locale is not currently supported");
  1698. }
  1699. lli = cur_base->section_list;
  1700. do {
  1701. /* fprintf(stderr, "hmm -- |%s|%d|\n", ((section_t *)(lli->data))->name, lli->data_type); */
  1702. if (lli->data_type & DT_SECTION) {
  1703. /* fprintf(stderr, "checking |%s|%s|\n", ((section_t *)(lli->data))->name, t); */
  1704. if (!strcmp(((section_t *)(lli->data))->name, t)) {
  1705. reorder_section_ptr = lli;
  1706. return;
  1707. }
  1708. }
  1709. lli = lli->next;
  1710. } while (lli);
  1711. error_msg("reorder_sections_after for non-base item currently not supported: %s", t);
  1712. }
  1713. static void do_reorder_sections_end(void)
  1714. {
  1715. if (!(order_state & IN_REORDER_SECTIONS)) {
  1716. error_msg("reorder_sections_end with no matching reorder_sections_after");
  1717. }
  1718. order_state &= ~IN_REORDER_SECTIONS;
  1719. reorder_section_ptr = NULL;
  1720. }
  1721. static ll_item_t *new_ll_item(int data_type, void *data)
  1722. {
  1723. ll_item_t *p;
  1724. p = xmalloc(sizeof(ll_item_t));
  1725. p->next = p->prev = NULL;
  1726. p->data_type = data_type;
  1727. p->data = data;
  1728. p->idx = INT_MIN;
  1729. return p;
  1730. }
  1731. static int sym_cmp(const void *n1, const void *n2)
  1732. {
  1733. /* fprintf(stderr, "sym_cmp: |%s| |%s|\n", (const char *)n1, (const char *)n2); */
  1734. return strcmp((const char *) n1, (const char *) n2);
  1735. }
  1736. static char *xsymdup(const char *s)
  1737. {
  1738. void *p;
  1739. if (!(p = tfind(s, &root_sym, sym_cmp))) { /* not a currently known symbol */
  1740. if (!(s = strdup(s)) || !(p = tsearch(s, &root_sym, sym_cmp))) {
  1741. error_msg("OUT OF MEMORY!");
  1742. }
  1743. ++num_sym;
  1744. mem_sym += strlen(s) + 1;
  1745. /* fprintf(stderr, "xsymdup: alloc |%s| %p |%s| %p\n", *(char **)p, p, s, s); */
  1746. /* } else { */
  1747. /* fprintf(stderr, "xsymdup: found |%s| %p\n", *(char **)p, p); */
  1748. }
  1749. return *(char **) p;
  1750. }
  1751. static int weight_cmp(const void *n1, const void *n2)
  1752. {
  1753. const weight_t *w1 = (const weight_t *) n1;
  1754. const weight_t *w2 = (const weight_t *) n2;
  1755. int i, r;
  1756. if (w1->num_weights != w2->num_weights) {
  1757. return w1->num_weights - w2->num_weights;
  1758. }
  1759. for (i=0 ; i < w1->num_weights ; i++) {
  1760. if (w1->rule[i] != w2->rule[i]) {
  1761. return w1->rule[i] - w2->rule[i];
  1762. }
  1763. if ((r = strcmp(w1->colitem[i], w2->colitem[i])) != 0) {
  1764. return r;
  1765. }
  1766. }
  1767. return 0;
  1768. }
  1769. static weight_t *register_weight(weight_t *w)
  1770. {
  1771. void *p;
  1772. if (!(p = tfind(w, &root_weight, weight_cmp))) { /* new weight */
  1773. p = xmalloc(sizeof(weight_t));
  1774. memcpy(p, w, sizeof(weight_t));
  1775. if (!(p = tsearch(p, &root_weight, weight_cmp))) {
  1776. error_msg("OUT OF MEMORY!");
  1777. }
  1778. ++unique_weights;
  1779. /* } else { */
  1780. /* fprintf(stderr, "rw: found\n"); */
  1781. }
  1782. return *(weight_t **)p;
  1783. }
  1784. static size_t ll_len(ll_item_t *l)
  1785. {
  1786. size_t n = 0;
  1787. ll_item_t *p = l;
  1788. while (p) {
  1789. ++n;
  1790. p = p->next;
  1791. if (p == l) { /* work for circular too */
  1792. break;
  1793. }
  1794. }
  1795. return n;
  1796. }
  1797. static size_t ll_count(ll_item_t *l, int mask)
  1798. {
  1799. size_t n = 0;
  1800. ll_item_t *p = l;
  1801. while (p) {
  1802. if (p->data_type & mask) {
  1803. ++n;
  1804. }
  1805. p = p->next;
  1806. if (p == l) { /* work for circular too */
  1807. break;
  1808. }
  1809. }
  1810. return n;
  1811. }
  1812. static int wi_index_cmp(const void *n1, const void *n2)
  1813. {
  1814. const char *s1 = ((weighted_item_t *)(((ll_item_t *) n1)->data))->symbol;
  1815. const char *s2 = ((weighted_item_t *)(((ll_item_t *) n2)->data))->symbol;
  1816. return strcmp(s1, s2);
  1817. }
  1818. static void add_wi_index(ll_item_t *l)
  1819. {
  1820. assert(l->data_type == DT_WEIGHTED);
  1821. if (!strcmp(((weighted_item_t *)(l->data))->symbol, "UNDEFINED")) {
  1822. cur_col->undefined_idx = l;
  1823. }
  1824. if (!tfind(l, &cur_col->root_wi_index, wi_index_cmp)) { /* new wi_index */
  1825. if (!tsearch(l, &cur_col->root_wi_index, wi_index_cmp)) {
  1826. error_msg("OUT OF MEMORY!");
  1827. }
  1828. }
  1829. if (cur_base != cur_col) {
  1830. if (!tfind(l, &cur_base->root_wi_index, wi_index_cmp)) {/* not a base val */
  1831. /* printf("derived: %s\n", ((weighted_item_t *)(l->data))->symbol); */
  1832. if (!tfind(l, &cur_base->root_derived_wi, wi_index_cmp)) { /* new derived */
  1833. if (!tsearch(l, &cur_base->root_derived_wi, wi_index_cmp)) {
  1834. error_msg("OUT OF MEMORY!");
  1835. }
  1836. }
  1837. }
  1838. }
  1839. }
  1840. static int final_index;
  1841. static int is_ucode(const char *s)
  1842. {
  1843. if ((s[0] == '<')
  1844. && (s[1] == 'U')
  1845. && isxdigit(s[2])
  1846. && isxdigit(s[3])
  1847. && isxdigit(s[4])
  1848. && isxdigit(s[5])
  1849. && (s[6] == '>')
  1850. ) {
  1851. return 7;
  1852. } else {
  1853. return 0;
  1854. }
  1855. }
  1856. static void add_final_col_index(const char *s)
  1857. {
  1858. ENTRY e;
  1859. e.key = (char *) s;
  1860. e.data = (void *)(final_index);
  1861. if (!hsearch(e, FIND)) { /* not in the table */
  1862. if (!hsearch(e, ENTER)) {
  1863. error_msg("OUT OF MEMORY! (hsearch)");
  1864. }
  1865. #if 0
  1866. {
  1867. int n;
  1868. void *v;
  1869. colitem_t ci;
  1870. colitem_t *p;
  1871. const char *t;
  1872. if (!strcmp(s, "UNDEFINED")) {
  1873. printf("%6d: %s\n", final_index, s);
  1874. } else {
  1875. assert(*s == '<');
  1876. if ((n = is_ucode(s)) != 0) {
  1877. assert(!s[n]);
  1878. printf("%6d: %s\n", final_index, s);
  1879. } else {
  1880. ci.string = (char *) s;
  1881. ci.element = NULL; /* don't care */
  1882. v = tfind(&ci, &cur_base->root_colitem, colitem_cmp);
  1883. if (!v) {
  1884. fprintf(stderr, "%s NOT DEFINED!!!\n", s);
  1885. } else {
  1886. p = *((colitem_t **) v);
  1887. if (p->element != NULL) {
  1888. t = p->element;
  1889. assert(*t == '"');
  1890. ++t;
  1891. n = is_ucode(t);
  1892. assert(n);
  1893. printf("%6d: %.*s | ", final_index, n, t);
  1894. do {
  1895. t += n;
  1896. assert(*t);
  1897. if (*t == '"') {
  1898. assert(!t[1]);
  1899. break;
  1900. }
  1901. n = is_ucode(t);
  1902. assert(n);
  1903. printf("%.*s", n, t);
  1904. } while (1);
  1905. printf(" collating-element %s\n", s);
  1906. } else {
  1907. printf("%6d: %s (collating-symbol)\n", final_index, s);
  1908. }
  1909. }
  1910. }
  1911. }
  1912. }
  1913. #endif
  1914. ++final_index;
  1915. }
  1916. }
  1917. static int final_index_val0(const char *s)
  1918. {
  1919. ENTRY *p;
  1920. ENTRY e;
  1921. e.key = (char *) s;
  1922. if (!(p = hsearch(e, FIND))) { /* not in the table */
  1923. return 0;
  1924. }
  1925. return (int)(p->data);
  1926. }
  1927. static int final_index_val(const char *s)
  1928. {
  1929. ENTRY *p;
  1930. ENTRY e;
  1931. e.key = (char *) s;
  1932. if (!(p = hsearch(e, FIND))) { /* not in the table */
  1933. error_msg("can't find final index: %s", s);
  1934. }
  1935. return (int)(p->data);
  1936. }
  1937. static size_t num_tree_nodes;
  1938. static void count_nodes(const void *ptr, VISIT order, int level)
  1939. {
  1940. if ((order == postorder) || (order == leaf)) {
  1941. ++num_tree_nodes;
  1942. }
  1943. }
  1944. static size_t tnumnodes(const void *root)
  1945. {
  1946. num_tree_nodes = 0;
  1947. twalk(root, count_nodes);
  1948. return num_tree_nodes;
  1949. }
  1950. static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl)
  1951. {
  1952. weighted_item_t w;
  1953. ll_item_t l;
  1954. void *p;
  1955. w.symbol = sym;
  1956. l.data = &w;
  1957. l.data_type = DT_WEIGHTED;
  1958. p = tfind(&l, &cl->root_wi_index, wi_index_cmp);
  1959. if (p) {
  1960. p = *(ll_item_t **)p;
  1961. }
  1962. return (ll_item_t *) p;
  1963. }
  1964. static void mark_reordered(const char *sym)
  1965. {
  1966. ll_item_t *lli;
  1967. lli = find_wi_index(sym, cur_base);
  1968. if (lli) {
  1969. if (!tsearch(lli, &cur_base->root_wi_index_reordered, wi_index_cmp)) {
  1970. error_msg("OUT OF MEMORY!");
  1971. }
  1972. }
  1973. }
  1974. static ll_item_t *find_wi_index_reordered(const char *sym)
  1975. {
  1976. weighted_item_t w;
  1977. ll_item_t l;
  1978. void *p;
  1979. w.symbol = sym;
  1980. l.data = &w;
  1981. l.data_type = DT_WEIGHTED;
  1982. p = tfind(&l, &cur_base->root_wi_index_reordered, wi_index_cmp);
  1983. if (p) {
  1984. p = *(ll_item_t **)p;
  1985. }
  1986. return (ll_item_t *) p;
  1987. }
  1988. static ll_item_t *init_comm_ptr(void)
  1989. {
  1990. assert(cur_base);
  1991. assert(cur_base->section_list);
  1992. /* at the moment, only support one section in comm */
  1993. assert(cur_base->section_list->next == NULL);
  1994. comm_cur_ptr = ((section_t *)(cur_base->section_list->data))->itm_list;
  1995. while (comm_cur_ptr && (comm_cur_ptr->data_type & DT_REORDER)) {
  1996. comm_cur_ptr = comm_cur_ptr->next;
  1997. }
  1998. #warning devel code
  1999. /* { */
  2000. /* ll_item_t *p = comm_cur_ptr; */
  2001. /* fprintf(stderr, "init_comm_ptr\n"); */
  2002. /* while (p != comm_cur_ptr) { */
  2003. /* if (p->data_type & DT_WEIGHTED) { */
  2004. /* fprintf(stderr, "%s", ((weighted_item_t *)p)->symbol); */
  2005. /* } */
  2006. /* p = p->next; */
  2007. /* } */
  2008. /* } */
  2009. assert(comm_cur_ptr);
  2010. /* fprintf(stderr, "init_comm_ptr -- %s %p %p %p %d\n", */
  2011. /* ((weighted_item_t *)(comm_cur_ptr->data))->symbol, */
  2012. /* comm_cur_ptr, comm_cur_ptr->prev, comm_cur_ptr->next, */
  2013. /* ll_len(comm_cur_ptr)); */
  2014. comm_prev_ptr = NULL;
  2015. return comm_cur_ptr;
  2016. }
  2017. static ll_item_t *next_comm_ptr(void)
  2018. {
  2019. /* at the moment, only support one section in comm */
  2020. assert(cur_base->section_list->next == NULL);
  2021. comm_prev_ptr = comm_cur_ptr;
  2022. while (comm_cur_ptr && ((comm_cur_ptr = comm_cur_ptr->next) != NULL)) {
  2023. if (!(comm_cur_ptr->data_type & DT_REORDER)) {
  2024. break;
  2025. }
  2026. }
  2027. return comm_cur_ptr;
  2028. }
  2029. static int dump_count;
  2030. #if 0
  2031. static void dump_section(section_t *s, int mask, col_locale_t *der)
  2032. {
  2033. ll_item_t *lli;
  2034. ll_item_t *lli0;
  2035. weighted_item_t *w;
  2036. weight_t *p;
  2037. int i;
  2038. lli0 = lli = s->itm_list;
  2039. if (!lli0) {
  2040. return;
  2041. }
  2042. do {
  2043. if (!(lli->data_type & mask)) {
  2044. lli = lli->next;
  2045. continue;
  2046. }
  2047. if (lli->data_type & DT_WEIGHTED) {
  2048. ++dump_count;
  2049. w = (weighted_item_t *)(lli->data);
  2050. p = w->weight;
  2051. printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights);
  2052. for (i = 0 ; i < p->num_weights ; i++) {
  2053. if (p->rule[i] & R_FORWARD) {
  2054. printf("F");
  2055. }
  2056. if (p->rule[i] & R_BACKWARD) {
  2057. printf("B");
  2058. }
  2059. if (p->rule[i] & R_POSITION) {
  2060. printf("P");
  2061. }
  2062. printf(",");
  2063. }
  2064. for (i = 0 ; i < p->num_weights ; i++) {
  2065. printf(" %s", p->colitem[i]);
  2066. }
  2067. printf("\n");
  2068. } else if (lli->data_type & (DT_SECTION|DT_REORDER)) {
  2069. if (lli->data_type == DT_REORDER) {
  2070. assert(der);
  2071. if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) {
  2072. lli = lli->next;
  2073. continue;
  2074. }
  2075. }
  2076. if (lli->data_type & DT_SECTION) {
  2077. printf("SECTION -----------------\n");
  2078. } else {
  2079. printf("REORDER -----------------\n");
  2080. }
  2081. dump_section((section_t *)(lli->data), mask, der);
  2082. printf("DONE --------------------\n");
  2083. }
  2084. lli = lli->next;
  2085. } while (lli != lli0);
  2086. }
  2087. #else
  2088. static int in_reorder_section = 0;
  2089. static void dump_section(section_t *s, int mask, col_locale_t *der)
  2090. {
  2091. ll_item_t *lli;
  2092. ll_item_t *lli0;
  2093. weighted_item_t *w;
  2094. weight_t *p;
  2095. int i;
  2096. lli0 = lli = s->itm_list;
  2097. if (!lli0) {
  2098. return;
  2099. }
  2100. do {
  2101. if (!(lli->data_type & mask)) {
  2102. lli = lli->next;
  2103. continue;
  2104. }
  2105. if (lli->data_type & DT_WEIGHTED) {
  2106. ++dump_count;
  2107. w = (weighted_item_t *)(lli->data);
  2108. p = w->weight;
  2109. #if 1
  2110. if (in_reorder_section) {
  2111. printf(" %p", w);
  2112. }
  2113. #else
  2114. printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights);
  2115. for (i = 0 ; i < p->num_weights ; i++) {
  2116. if (p->rule[i] & R_FORWARD) {
  2117. printf("F");
  2118. }
  2119. if (p->rule[i] & R_BACKWARD) {
  2120. printf("B");
  2121. }
  2122. if (p->rule[i] & R_POSITION) {
  2123. printf("P");
  2124. }
  2125. printf(",");
  2126. }
  2127. for (i = 0 ; i < p->num_weights ; i++) {
  2128. printf(" %s", p->colitem[i]);
  2129. }
  2130. printf("\n");
  2131. #endif
  2132. } else if (lli->data_type & (DT_SECTION|DT_REORDER)) {
  2133. if (lli->data_type == DT_REORDER) {
  2134. assert(der);
  2135. if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) {
  2136. lli = lli->next;
  2137. continue;
  2138. }
  2139. }
  2140. if (lli->data_type & DT_SECTION) {
  2141. /* printf("SECTION -----------------\n"); */
  2142. assert(0);
  2143. } else {
  2144. /* printf("REORDER -----------------\n"); */
  2145. in_reorder_section = 1;
  2146. }
  2147. dump_section((section_t *)(lli->data), mask, der);
  2148. /* printf("DONE --------------------\n"); */
  2149. printf("\n");
  2150. in_reorder_section = 0;
  2151. }
  2152. lli = lli->next;
  2153. } while (lli != lli0);
  2154. }
  2155. #endif
  2156. static void dump_weights(const char *name)
  2157. {
  2158. ll_item_t *lli;
  2159. col_locale_t *base;
  2160. col_locale_t *der;
  2161. col_locale_t cl;
  2162. void *p;
  2163. assert(name);
  2164. if (!*name) { /* use last */
  2165. base = cur_base;
  2166. der = cur_derived;
  2167. } else {
  2168. cl.name = (char *) name;
  2169. if (!(p = tfind(&cl, &root_col_locale, col_locale_cmp))) {
  2170. error_msg("unknown locale: %s", name);
  2171. }
  2172. base = *((col_locale_t **) p);
  2173. der = NULL;
  2174. if (base->base_locale) { /* oops... really derived */
  2175. der = base;
  2176. base = der->base_locale;
  2177. }
  2178. }
  2179. dump_count = 0;
  2180. if (base) {
  2181. /* printf("BASE - %s\n", base->name); */
  2182. for (lli = base->section_list ; lli ; lli = lli->next) {
  2183. /* printf("SECTION %s\n", ((section_t *)(lli->data))->name); */
  2184. dump_section((section_t *)(lli->data), ~0, der);
  2185. }
  2186. }
  2187. assert(der != base);
  2188. if (der) {
  2189. /* printf("DERIVED - %s\n", der->name); */
  2190. for (lli = der->section_list ; lli ; lli = lli->next) {
  2191. if (lli->data_type == DT_SECTION) {
  2192. dump_section((section_t *)(lli->data), DT_WEIGHTED, der);
  2193. }
  2194. }
  2195. }
  2196. /* printf("DONE\n"); */
  2197. }
  2198. static void print_starter_node(const void *ptr, VISIT order, int level)
  2199. {
  2200. if (order == postorder || order == leaf) {
  2201. fprintf(stderr, " %s\n", *(const char **) ptr);
  2202. }
  2203. }
  2204. static void finalize_base(void)
  2205. {
  2206. ll_item_t *s;
  2207. ll_item_t *h;
  2208. ll_item_t *lli;
  2209. ll_item_t *h2;
  2210. ll_item_t *l2;
  2211. ll_item_t *cli;
  2212. ll_item_t *rli = NULL;
  2213. weighted_item_t *w;
  2214. weight_t *p;
  2215. int i, n, mr, r, mi;
  2216. col_locale_t *cl;
  2217. void *mm;
  2218. int num_invariant = 0;
  2219. int num_varying = 0;
  2220. int max_weight;
  2221. int index2weight_len_inc = 1;
  2222. assert(cur_base);
  2223. assert(base_locale_len+1 < BASE_LOCALE_LEN);
  2224. base_locale_array[base_locale_len].name = cur_base->name;
  2225. base_locale_array[base_locale_len].num_weights = 1;
  2226. base_locale_array[base_locale_len].index2weight_offset = index2weight_len;
  2227. base_locale_array[base_locale_len].index2ruleidx_offset = index2ruleidx_len;
  2228. if (!strcmp(cur_base->name,"ja_JP") || !strcmp(cur_base->name,"ko_KR")) {
  2229. #warning fix the index2weight check!!
  2230. index2weight_len_inc = 0;
  2231. }
  2232. /* printf("%s -- index2weight_len = %d\n", cur_base->name, index2weight_len); */
  2233. if (!hcreate(30000)) {
  2234. error_msg("OUT OF MEMORY!");
  2235. }
  2236. /* first pass ... set the fixed indexes */
  2237. final_index = i = 1;
  2238. mr = 0;
  2239. for (s = cur_base->section_list ; s ; s = s->next) {
  2240. #if 1
  2241. if (s->data_type & DT_REORDER) { /* a reordered section */
  2242. fprintf(stderr, "pass1: reordered section %s - xxx\n", ((section_t *)(s->data))->name);
  2243. lli = ((section_t *)(s->data))->itm_list;
  2244. r = 0;
  2245. if (lli) {
  2246. /* r = ll_len( ((section_t *)(lli->data))->itm_list ); */
  2247. r = ll_len(lli) + 1;
  2248. }
  2249. if (r > mr) {
  2250. mr = r;
  2251. }
  2252. fprintf(stderr, "pass1: reordered section %s - %d\n", ((section_t *)(s->data))->name, r);
  2253. continue;
  2254. }
  2255. #endif
  2256. h = lli = ((section_t *)(s->data))->itm_list;
  2257. if (!lli) {
  2258. continue;
  2259. }
  2260. do {
  2261. if (lli->data_type & DT_RANGE) {
  2262. i += mr;
  2263. mr = 0;
  2264. #warning check ko_kR and 9
  2265. /* ++i; */
  2266. lli->idx = i;
  2267. assert(!rli);
  2268. rli = lli;
  2269. fprintf(stderr, "range pre = %d after = ", i);
  2270. i += ((range_item_t *)(lli->data))->length + 1;
  2271. #warning check ko_kR and 9
  2272. /* ++i; */
  2273. fprintf(stderr, "%d\n", i);
  2274. if (!index2weight_len_inc) { /* ko_KR hack */
  2275. final_index += ((range_item_t *)(lli->data))->length + 1;
  2276. }
  2277. /* add_final_col_index("RANGE"); */
  2278. } else if (lli->data_type & DT_WEIGHTED) {
  2279. i += mr;
  2280. mr = 0;
  2281. w = (weighted_item_t *)(lli->data);
  2282. if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */
  2283. ++num_varying;
  2284. ++i;
  2285. continue;
  2286. }
  2287. ++num_invariant;
  2288. index2weight_buffer[index2weight_len] = lli->idx = i++;
  2289. index2weight_len += index2weight_len_inc;
  2290. add_final_col_index(w->symbol);
  2291. } else {
  2292. assert(lli->data_type & DT_REORDER);
  2293. r = ll_len( ((section_t *)(lli->data))->itm_list );
  2294. #warning check ko_kR and 9
  2295. if (r > mr) {
  2296. mr = r;
  2297. }
  2298. /* r = 0; */
  2299. }
  2300. } while ((lli = lli->next) != h);
  2301. }
  2302. /* second pass ... set the reordered indexes */
  2303. mi = i + mr;
  2304. mr = i = 0;
  2305. for (s = cur_base->section_list ; s ; s = s->next) {
  2306. h = lli = ((section_t *)(s->data))->itm_list;
  2307. if (!lli) {
  2308. continue;
  2309. }
  2310. do {
  2311. if (lli->data_type & DT_RANGE) {
  2312. i += mr;
  2313. mr = 0;
  2314. i = lli->idx + ((range_item_t *)(lli->data))->length + 1;
  2315. #warning check
  2316. } else if ((lli->data_type & DT_WEIGHTED) && !(s->data_type & DT_REORDER)) {
  2317. i += mr;
  2318. mr = 0;
  2319. w = (weighted_item_t *)(lli->data);
  2320. if (find_wi_index_reordered(w->symbol) /* reordered symbol skipped on first pass */
  2321. #if 0
  2322. || (s->data_type & DT_REORDER) /* or in a reordered section */
  2323. #endif
  2324. ) {
  2325. assert(!(s->data_type & DT_REORDER));
  2326. index2weight_buffer[index2weight_len] = lli->idx = ++i;
  2327. index2weight_len += index2weight_len_inc;
  2328. add_final_col_index(w->symbol);
  2329. /* fprintf(stdout, "%11s: r %6d %6d %s\n", */
  2330. /* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */
  2331. continue;
  2332. }
  2333. i = lli->idx;
  2334. /* fprintf(stdout, "%11s: w %6d %6d %s\n", */
  2335. /* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */
  2336. } else {
  2337. /* fprintf(stderr, "section: %s %d %d\n", ((section_t *)(s->data))->name, */
  2338. /* s->data_type, lli->data_type); */
  2339. /* assert(!(s->data_type & DT_REORDER)); */
  2340. /* assert(lli->data_type & DT_REORDER); */
  2341. #if 1
  2342. if (s->data_type & DT_REORDER) {
  2343. h2 = l2 = lli;
  2344. if (!h2) {
  2345. continue;
  2346. }
  2347. } else {
  2348. assert(s->data_type & DT_SECTION);
  2349. h2 = l2 = ((section_t *)(lli->data))->itm_list;
  2350. if (!h2) {
  2351. continue;
  2352. }
  2353. }
  2354. #else
  2355. h2 = l2 = ((section_t *)(lli->data))->itm_list;
  2356. if (!h2) {
  2357. continue;
  2358. }
  2359. #endif
  2360. r = 0;
  2361. do {
  2362. assert(l2->data_type & DT_WEIGHTED);
  2363. ++r;
  2364. l2->idx = i + r;
  2365. /* fprintf(stdout, "%s: R %6d %s\n", */
  2366. /* ((section_t *)(lli->data))->name, l2->idx, ((weighted_item_t *)(l2->data))->symbol); */
  2367. } while ((l2 = l2->next) != h2);
  2368. if (r > mr) {
  2369. mr = r;
  2370. }
  2371. }
  2372. } while ((lli = lli->next) != h);
  2373. }
  2374. /* finally, walk through all derived locales and set non-reordered section items */
  2375. mr = mi;
  2376. for (cli = cur_base->derived_list ; cli ; cli = cli->next) {
  2377. cl = (col_locale_t *)(cli->data);
  2378. /* fprintf(stderr, "pass3: %d %s\n", cli->data_type, cl->name); */
  2379. /* fprintf(stdout, "pass3: %d %s\n", cli->data_type, cl->name); */
  2380. assert(cli->data_type == DT_COL_LOCALE);
  2381. i = mi;
  2382. for (s = cl->section_list ; s ; s = s->next) {
  2383. /* if (s->data_type & DT_REORDER) { */
  2384. /* continue; */
  2385. /* } */
  2386. h = lli = ((section_t *)(s->data))->itm_list;
  2387. if (!lli) {
  2388. continue;
  2389. }
  2390. do {
  2391. assert(!(lli->data_type & DT_RANGE));
  2392. if (lli->data_type & DT_WEIGHTED) {
  2393. /* fprintf(stderr, " %d %d %s\n", lli->data_type, lli->idx, ((weighted_item_t *)(lli->data))->symbol); */
  2394. add_final_col_index(((weighted_item_t *)(lli->data))->symbol);
  2395. if (s->data_type & DT_REORDER) {
  2396. continue;
  2397. }
  2398. assert(lli->idx == INT_MIN);
  2399. lli->idx = ++i;
  2400. /* fprintf(stdout, "%11s: S %6d %6d %s\n", */
  2401. /* cl->name, lli->idx, */
  2402. /* final_index_val(((weighted_item_t *)(lli->data))->symbol), */
  2403. /* ((weighted_item_t *)(lli->data))->symbol); */
  2404. } else {
  2405. assert(0);
  2406. assert(lli->data_type & DT_SECTION);
  2407. h2 = l2 = ((section_t *)(lli->data))->itm_list;
  2408. if (!h2) {
  2409. continue;
  2410. }
  2411. do {
  2412. assert(l2->data_type & DT_WEIGHTED);
  2413. assert(l2->idx == INT_MIN);
  2414. l2->idx = ++i;
  2415. add_final_col_index(((weighted_item_t *)(l2->data))->symbol);
  2416. } while ((l2 = l2->next) != h2);
  2417. }
  2418. } while ((lli = lli->next) != h);
  2419. }
  2420. if (i > mr) {
  2421. mr = i;
  2422. }
  2423. }
  2424. max_weight = mr;
  2425. assert(num_varying == tnumnodes(cur_base->root_wi_index_reordered));
  2426. /* we can now initialize the wcs2index array */
  2427. {
  2428. ENTRY *p;
  2429. ENTRY e;
  2430. char buf[8];
  2431. static const char xd[] = "0123456789ABCDEF";
  2432. int starter_index = final_index;
  2433. int wcs2index_count = 0;
  2434. strcpy(buf, "<U....>");
  2435. memset(wcs2index, 0, sizeof(wcs2index));
  2436. e.key = (char *) buf;
  2437. for (i=1 ; i <= 0xffff ; i++) {
  2438. buf[5] = xd[ i & 0xf ];
  2439. buf[4] = xd[ (i >> 4) & 0xf ];
  2440. buf[3] = xd[ (i >> 8) & 0xf ];
  2441. buf[2] = xd[ (i >> 12) & 0xf ];
  2442. if ((p = hsearch(e, FIND)) != NULL) {
  2443. ++wcs2index_count;
  2444. if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) {
  2445. wcs2index[i] = ++starter_index;
  2446. /* fprintf(stderr, "wcs2index[ %#06x ] = %d (starter)\n", i, wcs2index[i]); */
  2447. } else {
  2448. wcs2index[i] = (int)(p->data);
  2449. /* fprintf(stderr, "wcs2index[ %#06x ] = %d\n", i, wcs2index[i]); */
  2450. }
  2451. } else {
  2452. if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) {
  2453. error_msg("marked starter but not in hash: %s", buf);
  2454. }
  2455. }
  2456. }
  2457. /* ---------------------------------------------------------------------- */
  2458. {
  2459. int i, n;
  2460. table_data table;
  2461. size_t t, smallest;
  2462. n = 0;
  2463. smallest = SIZE_MAX;
  2464. table.ii = NULL;
  2465. for (i=0 ; i < 14 ; i++) {
  2466. if ((RANGE >> i) < 4) {
  2467. break;
  2468. }
  2469. t = newopt(wcs2index, RANGE, i, &table);
  2470. if (smallest >= t) {
  2471. n = i;
  2472. smallest = t;
  2473. /* } else { */
  2474. /* break; */
  2475. }
  2476. }
  2477. /* printf("smallest = %u for range %#x (%u)\n", smallest, RANGE, RANGE); */
  2478. assert(smallest != SIZE_MAX);
  2479. if (smallest + wcs2colidt_len >= WCS2COLIDT_LEN) {
  2480. error_msg("WCS2COLIDT_LEN too small");
  2481. }
  2482. base_locale_array[base_locale_len].wcs2colidt_offset = wcs2colidt_len;
  2483. table.ii = wcs2colidt_buffer + wcs2colidt_len;
  2484. t = smallest;
  2485. smallest = SIZE_MAX;
  2486. smallest = newopt(wcs2index, RANGE, n, &table);
  2487. assert(t == smallest);
  2488. wcs2colidt_len += smallest;
  2489. /* fprintf(stderr, "smallest = %d wcs2colidt_len = %d\n", smallest, wcs2colidt_len); */
  2490. #if 0
  2491. {
  2492. unsigned int sc, n, i0, i1;
  2493. unsigned int u = 0xe40;
  2494. table_data *tbl = &table;
  2495. #define __LOCALE_DATA_WCctype_TI_MASK ((1 << tbl->ti_shift)-1)
  2496. #define __LOCALE_DATA_WCctype_TI_SHIFT (tbl->ti_shift)
  2497. #define __LOCALE_DATA_WCctype_TI_LEN (tbl->ti_len)
  2498. #define __LOCALE_DATA_WCctype_II_MASK ((1 << tbl->ii_shift)-1)
  2499. #define __LOCALE_DATA_WCctype_II_SHIFT (tbl->ii_shift)
  2500. #define __LOCALE_DATA_WCctype_II_LEN (tbl->ii_len)
  2501. sc = u & __LOCALE_DATA_WCctype_TI_MASK;
  2502. u >>= __LOCALE_DATA_WCctype_TI_SHIFT;
  2503. n = u & __LOCALE_DATA_WCctype_II_MASK;
  2504. u >>= __LOCALE_DATA_WCctype_II_SHIFT;
  2505. i0 = tbl->ii[u];
  2506. fprintf(stderr, "i0 = %d\n", i0);
  2507. i0 <<= __LOCALE_DATA_WCctype_II_SHIFT;
  2508. i1 = tbl->ii[__LOCALE_DATA_WCctype_II_LEN + i0 + n];
  2509. /* i1 = tbl->ti[i0 + n]; */
  2510. fprintf(stderr, "i1 = %d\n", i1);
  2511. i1 <<= __LOCALE_DATA_WCctype_TI_SHIFT;
  2512. /* return *(uint16_t *)(&(tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc])); */
  2513. fprintf(stderr, "i2 = %d\n", __LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc);
  2514. fprintf(stderr, "val = %d\n", tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc]);
  2515. /* return tbl->ut[i1 + sc]; */
  2516. }
  2517. #endif
  2518. base_locale_array[base_locale_len].ii_shift = table.ii_shift;
  2519. base_locale_array[base_locale_len].ti_shift = table.ti_shift;
  2520. base_locale_array[base_locale_len].ii_len = table.ii_len;
  2521. base_locale_array[base_locale_len].ti_len = table.ti_len;
  2522. }
  2523. /* ---------------------------------------------------------------------- */
  2524. base_locale_array[base_locale_len].num_col_base = num_invariant + num_varying;
  2525. base_locale_array[base_locale_len].max_col_index = final_index;
  2526. base_locale_array[base_locale_len].max_weight = max_weight;
  2527. fprintf(stderr, "%s: %6u invariant %6u varying %6u derived %6u total %6u max weight %6u wcs2\n",
  2528. cur_base->name, num_invariant, num_varying,
  2529. tnumnodes(cur_base->root_derived_wi), final_index, max_weight,
  2530. wcs2index_count);
  2531. }
  2532. #if 1
  2533. /* ok, now we need to dump out the base and derived tables... */
  2534. /* don't forget to break up collating elements!!! */
  2535. /* fprintf(stdout, "**************************************************\n"); */
  2536. /* first pass ... set the invariants */
  2537. for (s = cur_base->section_list ; s ; s = s->next) {
  2538. #if 1
  2539. if (s->data_type & DT_REORDER) {
  2540. fprintf(stderr, "1: skipping reordered section %s\n", ((section_t *)(s->data))->name);
  2541. continue;
  2542. }
  2543. #endif
  2544. h = lli = ((section_t *)(s->data))->itm_list;
  2545. if (!lli) {
  2546. continue;
  2547. }
  2548. do {
  2549. if (lli->data_type & DT_WEIGHTED) {
  2550. w = (weighted_item_t *)(lli->data);
  2551. if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */
  2552. continue;
  2553. }
  2554. if (index2weight_len_inc) {
  2555. index2ruleidx_buffer[index2ruleidx_len++] =
  2556. add_rule((weighted_item_t *)(lli->data));
  2557. }
  2558. /* fprintf(stdout, "%11s: w %6d %6d %s\n", */
  2559. /* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */
  2560. }
  2561. } while ((lli = lli->next) != h);
  2562. }
  2563. /* second pass ... set varying */
  2564. for (s = cur_base->section_list ; s ; s = s->next) {
  2565. #if 1
  2566. if (s->data_type & DT_REORDER) {
  2567. fprintf(stderr, "2: skipping reordered section %s\n", ((section_t *)(s->data))->name);
  2568. continue;
  2569. }
  2570. #endif
  2571. h = lli = ((section_t *)(s->data))->itm_list;
  2572. if (!lli) {
  2573. continue;
  2574. }
  2575. do {
  2576. if (lli->data_type & DT_WEIGHTED) {
  2577. w = (weighted_item_t *)(lli->data);
  2578. if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */
  2579. if (index2weight_len_inc) {
  2580. index2ruleidx_buffer[index2ruleidx_len++] =
  2581. add_rule((weighted_item_t *)(lli->data));
  2582. }
  2583. /* fprintf(stdout, "%11s: r %6d %6d %s\n", */
  2584. /* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */
  2585. continue;
  2586. }
  2587. }
  2588. } while ((lli = lli->next) != h);
  2589. }
  2590. do_starter_lists(cur_base);
  2591. /* fprintf(stderr,"updated final_index = %d\n", final_index); */
  2592. if (rli) {
  2593. base_locale_array[base_locale_len].range_low
  2594. = strtoul(((range_item_t *)(rli->data))->symbol1 + 2, NULL, 16);
  2595. base_locale_array[base_locale_len].range_count
  2596. = ((range_item_t *)(rli->data))->length;
  2597. base_locale_array[base_locale_len].range_base_weight = rli->idx;
  2598. base_locale_array[base_locale_len].range_rule_offset = add_range_rule((range_item_t *)(rli->data));
  2599. /* fprintf(stdout, "%11s: %6d %6d %s %s (%d)\n", */
  2600. /* "RANGE", rli->idx, -1, */
  2601. /* ((range_item_t *)(rli->data))->symbol1, */
  2602. /* ((range_item_t *)(rli->data))->symbol2, */
  2603. /* ((range_item_t *)(rli->data))->length); */
  2604. }
  2605. /* fprintf(stdout,"\nDerived\n\n"); */
  2606. /* first, if base name is of the form ll_CC, add a derived locale for it */
  2607. if ((strlen(cur_base->name) == 5)
  2608. && islower(cur_base->name[0])
  2609. && islower(cur_base->name[1])
  2610. && (cur_base->name[2] == '_')
  2611. && isupper(cur_base->name[3])
  2612. && isupper(cur_base->name[4])
  2613. ) {
  2614. fprintf(stderr, "adding special derived for %s\n", cur_base->name);
  2615. /* fprintf(stderr,"updated final_index = %d\n", final_index); */
  2616. assert(der_locale_len+1 < DER_LOCALE_LEN);
  2617. der_locale_array[der_locale_len].name = cur_base->name;
  2618. der_locale_array[der_locale_len].base_idx = base_locale_len;
  2619. u16_buf[0] = 1;
  2620. u16_buf[1] = 0;
  2621. u16_buf_len = 2;
  2622. mm = NULL;
  2623. if ((u16_buf_len > override_len) ||
  2624. !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]),
  2625. u16_buf, u16_buf_len*sizeof(u16_buf[0])))
  2626. ) {
  2627. assert(override_len + u16_buf_len < OVERRIDE_LEN);
  2628. memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0]));
  2629. der_locale_array[der_locale_len].overrides_offset = override_len;
  2630. override_len += u16_buf_len;
  2631. /* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */
  2632. } else if (!(u16_buf_len > override_len)) {
  2633. assert(mm);
  2634. der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer;
  2635. /* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */
  2636. }
  2637. der_locale_array[der_locale_len].multistart_offset
  2638. = base_locale_array[base_locale_len].multistart_offset;
  2639. der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED");
  2640. if (!der_locale_array[der_locale_len].undefined_idx) {
  2641. error_msg("no UNDEFINED definition for %s", cur_base->name);
  2642. }
  2643. ++der_locale_len;
  2644. } else {
  2645. fprintf(stderr, "NOT adding special derived for %s\n", cur_base->name);
  2646. }
  2647. /* now all the derived... */
  2648. for (cli = cur_base->derived_list ; cli ; cli = cli->next) {
  2649. cl = (col_locale_t *)(cli->data);
  2650. assert(cli->data_type == DT_COL_LOCALE);
  2651. assert(der_locale_len+1 < DER_LOCALE_LEN);
  2652. der_locale_array[der_locale_len].name = cl->name;
  2653. der_locale_array[der_locale_len].base_idx = base_locale_len;
  2654. u16_buf_len = 0;
  2655. for (i = 0 ; i < 2 ; i++) {
  2656. if (i) {
  2657. /* fprintf(stdout, " section --- (singles)\n"); */
  2658. u16_buf[u16_buf_len++] = 1; /* single */
  2659. }
  2660. /* we do this in two passes... first all sequences, then all single reorders */
  2661. for (s = cl->section_list ; s ; s = s->next) {
  2662. h = lli = ((section_t *)(s->data))->itm_list;
  2663. if (!lli) {
  2664. continue;
  2665. }
  2666. assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0]));
  2667. if ((!i && (ll_len(h) > 1) ) || (ll_len(h) == i)) {
  2668. if (!i) {
  2669. /* fprintf(stdout, " section ----------------- %d %d\n", i, ll_len(h)); */
  2670. u16_buf[u16_buf_len++] = ll_len(h); /* multi */
  2671. assert(lli->data_type & DT_WEIGHTED);
  2672. #if 0
  2673. u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); /* start index */
  2674. #endif
  2675. u16_buf[u16_buf_len++] = lli->idx; /* start weight */
  2676. }
  2677. do {
  2678. if (lli->data_type & DT_WEIGHTED) {
  2679. /* fprintf(stdout, "%11s: S %6d %6d %s\n", */
  2680. /* cl->name, lli->idx, */
  2681. /* final_index_val(((weighted_item_t *)(lli->data))->symbol), */
  2682. /* ((weighted_item_t *)(lli->data))->symbol); */
  2683. #if 0
  2684. if (i) {
  2685. assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0]));
  2686. u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol);
  2687. assert(u16_buf[u16_buf_len-1]);
  2688. u16_buf[u16_buf_len++] = lli->idx; /* weight */
  2689. }
  2690. #else
  2691. assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0]));
  2692. u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol);
  2693. assert(u16_buf[u16_buf_len-1]);
  2694. if (i) {
  2695. u16_buf[u16_buf_len++] = lli->idx; /* weight */
  2696. }
  2697. #endif
  2698. u16_buf[u16_buf_len++] = add_rule((weighted_item_t *)(lli->data));
  2699. }
  2700. } while ((lli = lli->next) != h);
  2701. }
  2702. }
  2703. }
  2704. u16_buf[u16_buf_len++] = 0;
  2705. mm = NULL;
  2706. if ((u16_buf_len > override_len) ||
  2707. !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]),
  2708. u16_buf, u16_buf_len*sizeof(u16_buf[0])))
  2709. ) {
  2710. assert(override_len + u16_buf_len < OVERRIDE_LEN);
  2711. memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0]));
  2712. der_locale_array[der_locale_len].overrides_offset = override_len;
  2713. override_len += u16_buf_len;
  2714. /* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */
  2715. } else if (!(u16_buf_len > override_len)) {
  2716. assert(mm);
  2717. der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer;
  2718. /* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */
  2719. }
  2720. do_starter_lists(cl);
  2721. der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED");
  2722. #if 0
  2723. assert(der_locale_array[der_locale_len].undefined_idx);
  2724. if (!der_locale_array[der_locale_len].undefined_idx) {
  2725. der_locale_array[der_locale_len].undefined_idx = base_locale_array[base_locale_len].undefined_idx;
  2726. }
  2727. #endif
  2728. if (!der_locale_array[der_locale_len].undefined_idx) {
  2729. error_msg("no UNDEFINED definition for %s", cl->name);
  2730. }
  2731. ++der_locale_len;
  2732. }
  2733. #endif
  2734. #warning handle UNDEFINED idx specially? what if in only some of derived?
  2735. /* base_locale_array[base_locale_len].undefined_idx = final_index_val0("UNDEFINED"); */
  2736. base_locale_array[base_locale_len].undefined_idx = 0;
  2737. hdestroy();
  2738. ++base_locale_len;
  2739. /* if (tnumnodes(cur_base->root_starter_char)) { */
  2740. /* fprintf(stderr, "starter nodes\n"); */
  2741. /* twalk(cur_base->root_starter_char, print_starter_node); */
  2742. /* } */
  2743. }
  2744. static int starter_all_cmp(const void *n1, const void *n2)
  2745. {
  2746. const char *s1 = ((weighted_item_t *) n1)->symbol;
  2747. const char *s2 = ((weighted_item_t *) n2)->symbol;
  2748. colitem_t x;
  2749. colitem_t *p;
  2750. int n;
  2751. /* sort by 1st char ... then inverse for string */
  2752. x.element = NULL;
  2753. if (!is_ucode(s1)) {
  2754. x.string = s1;
  2755. p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
  2756. s1 = (*((colitem_t **) p))->element + 1;
  2757. }
  2758. if (!is_ucode(s2)) {
  2759. x.string = s2;
  2760. p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
  2761. s2 = (*((colitem_t **) p))->element + 1;
  2762. }
  2763. /* <U####>< */
  2764. /* 01234567 */
  2765. assert(is_ucode(s1));
  2766. assert(is_ucode(s2));
  2767. n = strncmp(s1+2, s2+2, 4);
  2768. if (n) {
  2769. return n;
  2770. }
  2771. s1 += 7;
  2772. s2 += 7;
  2773. return strcmp(s2, s1);
  2774. }
  2775. static void print_starter_all_node(const void *ptr, VISIT order, int level)
  2776. {
  2777. const weighted_item_t *w = *(const weighted_item_t **) ptr;
  2778. colitem_t *ci;
  2779. void *p;
  2780. int n;
  2781. colitem_t x;
  2782. if (order == postorder || order == leaf) {
  2783. #if 0
  2784. if ((n = is_ucode(w->symbol)) != 0) {
  2785. printf(" %s\n", w->symbol);
  2786. } else {
  2787. x.string = w->symbol;
  2788. x.element = NULL;
  2789. p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
  2790. assert(p);
  2791. ci = *((colitem_t **) p);
  2792. printf("%s = %s\n", ci->element, w->symbol);
  2793. }
  2794. #else
  2795. printf("%s|", w->symbol);
  2796. /* if ((n = is_ucode(w->symbol)) != 0) { */
  2797. /* printf("\n"); */
  2798. /* } */
  2799. #endif
  2800. }
  2801. }
  2802. static void process_starter_node(const void *ptr, VISIT order, int level)
  2803. {
  2804. const weighted_item_t *w = *(const weighted_item_t **) ptr;
  2805. colitem_t *ci;
  2806. void *p;
  2807. int n;
  2808. colitem_t x;
  2809. const char *s;
  2810. char buf[32];
  2811. /* store index of collation item followed by (unprefixed) nul-terminated string */
  2812. if (order == postorder || order == leaf) {
  2813. if ((n = is_ucode(w->symbol)) != 0) {
  2814. u16_buf[u16_buf_len++] = final_index_val(w->symbol);
  2815. assert(u16_buf[u16_buf_len-1]);
  2816. u16_buf[u16_buf_len++] = 0;
  2817. if (++u16_starter < base_locale_array[base_locale_len].num_starters) {
  2818. u16_buf[u16_starter] = u16_buf_len;
  2819. }
  2820. /* fprintf(stderr, "ucode - %d %d\n", u16_buf[u16_starter-1], u16_buf_len); */
  2821. } else {
  2822. x.string = w->symbol;
  2823. x.element = NULL;
  2824. p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
  2825. assert(p);
  2826. ci = *((colitem_t **) p);
  2827. s = ci->element;
  2828. u16_buf[u16_buf_len++] = final_index_val(w->symbol);
  2829. assert(u16_buf[u16_buf_len-1]);
  2830. assert(*s == '"');
  2831. n = is_ucode(++s);
  2832. /* fprintf(stderr, "s is |%s| with len %d (%d)\n", s, strlen(s), n); */
  2833. assert(n);
  2834. s += n;
  2835. while (*s != '"') {
  2836. n = is_ucode(s);
  2837. assert(n);
  2838. strncpy(buf, s, n+1);
  2839. buf[n] = 0;
  2840. /* fprintf(stderr, "buf is |%s| with len %d (%d)\n", buf, strlen(buf), n); */
  2841. u16_buf[u16_buf_len++] = final_index_val(buf);
  2842. assert(u16_buf[u16_buf_len-1]);
  2843. s += n;
  2844. }
  2845. u16_buf[u16_buf_len++] = 0;
  2846. }
  2847. }
  2848. }
  2849. static void **p_cl_root_starter_all;
  2850. static void complete_starter_node(const void *ptr, VISIT order, int level)
  2851. {
  2852. weighted_item_t w;
  2853. weighted_item_t *p;
  2854. if (order == postorder || order == leaf) {
  2855. w.symbol = *(const char **) ptr;
  2856. w.weight = NULL;
  2857. if (!tfind(&w, p_cl_root_starter_all, starter_all_cmp)) {
  2858. p = xmalloc(sizeof(weighted_item_t));
  2859. p->symbol = w.symbol;
  2860. p->weight = NULL;
  2861. /* fprintf(stderr, "complete_starter_node: %s\n", *(const char **) ptr); */
  2862. if (!tsearch(p, p_cl_root_starter_all, starter_all_cmp)) {
  2863. error_msg("OUT OF MEMORY");
  2864. }
  2865. }
  2866. }
  2867. }
  2868. static void do_starter_lists(col_locale_t *cl)
  2869. {
  2870. ll_item_t *s;
  2871. ll_item_t *h;
  2872. ll_item_t *lli;
  2873. col_locale_t *c;
  2874. colitem_t *ci;
  2875. weighted_item_t *w;
  2876. void *p;
  2877. char buf[32];
  2878. int n;
  2879. colitem_t x;
  2880. void *mm;
  2881. c = cl;
  2882. if (c != cur_base) {
  2883. c = cur_base;
  2884. }
  2885. /* printf("STARTERS %s --------------------\n", cl->name); */
  2886. LOOP:
  2887. for (s = c->section_list ; s ; s = s->next) {
  2888. h = lli = ((section_t *)(s->data))->itm_list;
  2889. if (!lli) {
  2890. continue;
  2891. }
  2892. do {
  2893. if (lli->data_type & DT_WEIGHTED) {
  2894. w = (weighted_item_t *)(lli->data);
  2895. ci = NULL;
  2896. if ((n = is_ucode(w->symbol)) != 0) {
  2897. strcpy(buf, w->symbol);
  2898. } else {
  2899. /* fprintf(stdout, "looking for |%s|\n", w->symbol); */
  2900. x.string = w->symbol;
  2901. x.element = NULL;
  2902. p = tfind(&x, &cur_base->root_colitem, colitem_cmp);
  2903. if (!p) {
  2904. /* fprintf(stderr, "Whoa... processing starters for %s and couldn't find %s\n", */
  2905. /* cl->name, w->symbol); */
  2906. continue;
  2907. }
  2908. ci = *((colitem_t **) p);
  2909. if (!ci->element) { /* just a collating symbol */
  2910. continue;
  2911. }
  2912. assert(ci->element[0] == '"');
  2913. n = is_ucode(ci->element + 1);
  2914. assert(n);
  2915. strncpy(buf, ci->element + 1, n);
  2916. }
  2917. if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) {
  2918. /* fprintf(stdout, "adding from %s: %s", c->name, w->symbol); */
  2919. /* if (ci) { */
  2920. /* fprintf(stdout, " = %s", ci->element); */
  2921. /* } */
  2922. /* fprintf(stdout, "\n"); */
  2923. if (!tsearch(w, &cl->root_starter_all, starter_all_cmp)) {
  2924. error_msg("OUT OF MEMORY");
  2925. }
  2926. }
  2927. }
  2928. } while ((lli = lli->next) != h);
  2929. }
  2930. if (c != cl) {
  2931. c = cl;
  2932. goto LOOP;
  2933. }
  2934. p_cl_root_starter_all = &cl->root_starter_all;
  2935. twalk(cur_base->root_starter_char, complete_starter_node);
  2936. if (cl == cur_base) {
  2937. base_locale_array[base_locale_len].num_starters = tnumnodes(cur_base->root_starter_char);
  2938. }
  2939. #if 0
  2940. printf("\nNow walking tree...\n\n");
  2941. twalk(cl->root_starter_all, print_starter_all_node);
  2942. printf("\n\n");
  2943. #endif
  2944. u16_starter = 0;
  2945. u16_buf[0] = u16_buf_len = base_locale_array[base_locale_len].num_starters;
  2946. twalk(cl->root_starter_all, process_starter_node);
  2947. /* fprintf(stderr, "s=%d n=%d\n", u16_starter, base_locale_array[base_locale_len].num_starters); */
  2948. assert(u16_starter == base_locale_array[base_locale_len].num_starters);
  2949. #if 0
  2950. { int i;
  2951. for (i=0 ; i < u16_buf_len ; i++) {
  2952. fprintf(stderr, "starter %2d: %d - %#06x\n", i, u16_buf[i], u16_buf[i]);
  2953. }}
  2954. #endif
  2955. mm = NULL;
  2956. if (u16_buf_len) {
  2957. /* assert(base_locale_array[base_locale_len].num_starters); */
  2958. if ((u16_buf_len > multistart_len) ||
  2959. !(mm = memmem(multistart_buffer, multistart_len*sizeof(multistart_buffer[0]),
  2960. u16_buf, u16_buf_len*sizeof(u16_buf[0])))
  2961. ) {
  2962. assert(multistart_len + u16_buf_len < MULTISTART_LEN);
  2963. memcpy(multistart_buffer + multistart_len, u16_buf, u16_buf_len*sizeof(u16_buf[0]));
  2964. if (cl == cur_base) {
  2965. base_locale_array[base_locale_len].multistart_offset = multistart_len;
  2966. } else {
  2967. der_locale_array[der_locale_len].multistart_offset = multistart_len;
  2968. }
  2969. multistart_len += u16_buf_len;
  2970. /* fprintf(stderr, "%s: multistart_len = %d u16_buf_len = %d\n", cl->name, multistart_len, u16_buf_len); */
  2971. } else if (!(u16_buf_len > multistart_len)) {
  2972. assert(mm);
  2973. if (cl == cur_base) {
  2974. base_locale_array[base_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer;
  2975. } else {
  2976. der_locale_array[der_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer;
  2977. }
  2978. /* fprintf(stderr, "%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */
  2979. }
  2980. } else {
  2981. assert(!base_locale_array[base_locale_len].num_starters);
  2982. }
  2983. /* printf("u16_buf_len = %d\n", u16_buf_len); */
  2984. /* printf("STARTERS %s DONE ---------------\n", cl->name); */
  2985. }
  2986. /* For sorting the blocks of unsigned chars. */
  2987. static size_t nu_val;
  2988. int nu_memcmp(const void *a, const void *b)
  2989. {
  2990. return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val * sizeof(tbl_item));
  2991. }
  2992. size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl)
  2993. {
  2994. static int recurse = 0;
  2995. tbl_item *ti[RANGE]; /* table index */
  2996. size_t numblocks;
  2997. size_t blocksize;
  2998. size_t uniq;
  2999. size_t i, j;
  3000. size_t smallest, t;
  3001. tbl_item *ii_save;
  3002. int uniqblock[1 << (8*sizeof(tbl_item) - 1)];
  3003. tbl_item uit[RANGE];
  3004. int shift2;
  3005. if (shift > 15) {
  3006. return SIZE_MAX;
  3007. }
  3008. ii_save = NULL;
  3009. blocksize = 1 << shift;
  3010. numblocks = usize >> shift;
  3011. /* init table index */
  3012. for (i=j=0 ; i < numblocks ; i++) {
  3013. ti[i] = ut + j;
  3014. j += blocksize;
  3015. }
  3016. /* sort */
  3017. nu_val = blocksize;
  3018. qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp);
  3019. uniq = 1;
  3020. uit[(ti[0]-ut)/blocksize] = 0;
  3021. for (i=1 ; i < numblocks ; i++) {
  3022. if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) < 0) {
  3023. if (++uniq > (1 << (8*sizeof(tbl_item) - 1))) {
  3024. break;
  3025. }
  3026. uniqblock[uniq - 1] = i;
  3027. }
  3028. #if 1
  3029. else if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) > 0) {
  3030. printf("bad sort %i!\n", i);
  3031. abort();
  3032. }
  3033. #endif
  3034. uit[(ti[i]-ut)/blocksize] = uniq - 1;
  3035. }
  3036. smallest = SIZE_MAX;
  3037. shift2 = -1;
  3038. if (uniq <= (1 << (8*sizeof(tbl_item) - 1))) {
  3039. smallest = numblocks + uniq * blocksize;
  3040. if (!recurse) {
  3041. ++recurse;
  3042. for (j=1 ; j < 14 ; j++) {
  3043. if ((numblocks >> j) < 2) break;
  3044. if (tbl) {
  3045. ii_save = tbl->ii;
  3046. tbl->ii = NULL;
  3047. }
  3048. if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) {
  3049. t += uniq * blocksize;
  3050. }
  3051. if (tbl) {
  3052. tbl->ii = ii_save;
  3053. }
  3054. if (smallest >= t) {
  3055. shift2 = j;
  3056. smallest = t;
  3057. /* if (!tbl->ii) { */
  3058. /* printf("ishift %u tshift %u size %u\n", */
  3059. /* shift2, shift, t); */
  3060. /* } */
  3061. /* } else { */
  3062. /* break; */
  3063. }
  3064. }
  3065. --recurse;
  3066. }
  3067. } else {
  3068. return SIZE_MAX;
  3069. }
  3070. if (tbl->ii) {
  3071. if (recurse) {
  3072. tbl->ii_shift = shift;
  3073. tbl->ii_len = numblocks;
  3074. memcpy(tbl->ii, uit, numblocks*sizeof(tbl_item));
  3075. tbl->ti = tbl->ii + tbl->ii_len;
  3076. tbl->ti_len = uniq * blocksize;
  3077. for (i=0 ; i < uniq ; i++) {
  3078. memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item));
  3079. }
  3080. } else {
  3081. ++recurse;
  3082. /* printf("setting ishift %u tshift %u\n", shift2, shift); */
  3083. newopt(uit, numblocks, shift2, tbl);
  3084. --recurse;
  3085. tbl->ti_shift = shift;
  3086. tbl->ut_len = uniq * blocksize;
  3087. tbl->ut = tbl->ti + tbl->ti_len;
  3088. for (i=0 ; i < uniq ; i++) {
  3089. memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item));
  3090. }
  3091. }
  3092. }
  3093. return smallest;
  3094. }
  3095. static const int rule2val[8] = {
  3096. -1,
  3097. (1 << 14), /* forward */
  3098. (2 << 14), /* position */
  3099. (3 << 14), /* forward,position */
  3100. 0, /* backward */
  3101. -1,
  3102. -1,
  3103. -1,
  3104. };
  3105. static int final_index_val_x(const char *s, const char *sym)
  3106. {
  3107. int r;
  3108. if (!(r = final_index_val0(s))) {
  3109. if (!strcmp(s, "IGNORE")) {
  3110. r = 0;
  3111. } else if (!strcmp(s, "..") || !strcmp(sym, "RANGE")) {
  3112. if (*sym == '.') {
  3113. final_index_val(sym); /* make sure it's known */
  3114. }
  3115. r = 0x3fff;
  3116. } else if (!strcmp(s, ".")) {
  3117. r = 0x3ffe;
  3118. } else {
  3119. error_msg("can't find final index: %s", s);
  3120. }
  3121. }
  3122. return r;
  3123. }
  3124. /* store rule2val in 2 high bits and collation index in lower.
  3125. * for sort strings, store (offset from base) + max colindex as index.
  3126. */
  3127. static unsigned int add_rule(weighted_item_t *wi)
  3128. {
  3129. weight_t *w = wi->weight;
  3130. int i, j, r, n;
  3131. uint16_t rbuf[MAX_COLLATION_WEIGHTS];
  3132. uint16_t ws_buf[32];
  3133. void *mm;
  3134. char buf[32];
  3135. const char *s;
  3136. const char *e;
  3137. for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) {
  3138. rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */
  3139. }
  3140. if (base_locale_array[base_locale_len].num_weights < w->num_weights) {
  3141. base_locale_array[base_locale_len].num_weights = w->num_weights;
  3142. }
  3143. for (i=0 ; i < w->num_weights ; i++) {
  3144. assert(rule2val[(int)(w->rule[i])] >= 0);
  3145. assert(w->colitem[i] && *w->colitem[i]);
  3146. if (*w->colitem[i] == '"') { /* string... */
  3147. s = w->colitem[i] + 1;
  3148. assert(*s == '<');
  3149. n = 0;
  3150. do {
  3151. e = s;
  3152. do {
  3153. if (*e == '/') {
  3154. e += 2;
  3155. continue;
  3156. }
  3157. } while (*e++ != '>');
  3158. assert(((size_t)(e-s) < sizeof(buf)));
  3159. memcpy(buf, s, (size_t)(e-s));
  3160. buf[(size_t)(e-s)] = 0;
  3161. r = final_index_val_x(buf, wi->symbol);
  3162. assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0]));
  3163. ws_buf[n++] = r | rule2val[(int)(w->rule[i])];
  3164. s = e;
  3165. } while (*s != '"');
  3166. ws_buf[n++] = 0; /* terminator */
  3167. mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]),
  3168. ws_buf, n*sizeof(ws_buf[0]));
  3169. if (!mm) {
  3170. assert(weightstr_len + n < WEIGHTSTR_LEN);
  3171. memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0]));
  3172. mm = weightstr_buffer + weightstr_len;
  3173. weightstr_len += n;
  3174. }
  3175. r = (((uint16_t *)(mm)) - weightstr_buffer)
  3176. + base_locale_array[base_locale_len].max_col_index + 2;
  3177. assert(r < (1 << 14));
  3178. rbuf[i] = r | rule2val[(int)(w->rule[i])];
  3179. } else { /* item */
  3180. r = final_index_val_x(w->colitem[i], wi->symbol);
  3181. rbuf[i] = r | rule2val[(int)(w->rule[i])];
  3182. }
  3183. }
  3184. for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) {
  3185. if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) {
  3186. return i/MAX_COLLATION_WEIGHTS;
  3187. }
  3188. }
  3189. memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]));
  3190. ruletable_len += MAX_COLLATION_WEIGHTS;
  3191. return (ruletable_len / MAX_COLLATION_WEIGHTS)-1;
  3192. }
  3193. static unsigned int add_range_rule(range_item_t *ri)
  3194. {
  3195. weight_t *w = ri->weight;
  3196. int i, j, r, n;
  3197. uint16_t rbuf[MAX_COLLATION_WEIGHTS];
  3198. uint16_t ws_buf[32];
  3199. void *mm;
  3200. char buf[32];
  3201. const char *s;
  3202. const char *e;
  3203. for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) {
  3204. rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */
  3205. }
  3206. if (base_locale_array[base_locale_len].num_weights < w->num_weights) {
  3207. base_locale_array[base_locale_len].num_weights = w->num_weights;
  3208. }
  3209. for (i=0 ; i < w->num_weights ; i++) {
  3210. assert(rule2val[(int)(w->rule[i])] >= 0);
  3211. assert(w->colitem[i] && *w->colitem[i]);
  3212. if (*w->colitem[i] == '"') { /* string... */
  3213. s = w->colitem[i] + 1;
  3214. assert(*s == '<');
  3215. n = 0;
  3216. do {
  3217. e = s;
  3218. do {
  3219. if (*e == '/') {
  3220. e += 2;
  3221. continue;
  3222. }
  3223. } while (*e++ != '>');
  3224. assert(((size_t)(e-s) < sizeof(buf)));
  3225. memcpy(buf, s, (size_t)(e-s));
  3226. buf[(size_t)(e-s)] = 0;
  3227. r = final_index_val_x(buf, "RANGE");
  3228. assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0]));
  3229. ws_buf[n++] = r | rule2val[(int)(w->rule[i])];
  3230. s = e;
  3231. } while (*s != '"');
  3232. ws_buf[n++] = 0; /* terminator */
  3233. mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]),
  3234. ws_buf, n*sizeof(ws_buf[0]));
  3235. if (!mm) {
  3236. assert(weightstr_len + n < WEIGHTSTR_LEN);
  3237. memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0]));
  3238. mm = weightstr_buffer + weightstr_len;
  3239. weightstr_len += n;
  3240. }
  3241. r = (((uint16_t *)(mm)) - weightstr_buffer)
  3242. + base_locale_array[base_locale_len].max_col_index + 2;
  3243. assert(r < (1 << 14));
  3244. rbuf[i] = r | rule2val[(int)(w->rule[i])];
  3245. } else { /* item */
  3246. r = final_index_val_x(w->colitem[i], "RANGE");
  3247. rbuf[i] = r | rule2val[(int)(w->rule[i])];
  3248. }
  3249. }
  3250. for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) {
  3251. if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) {
  3252. return i/MAX_COLLATION_WEIGHTS;
  3253. }
  3254. }
  3255. memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]));
  3256. ruletable_len += MAX_COLLATION_WEIGHTS;
  3257. return (ruletable_len / MAX_COLLATION_WEIGHTS)-1;
  3258. }
  3259. #define DUMPn(X) fprintf(stderr, "%10d-%-.20s", base_locale_array[n]. X, #X);
  3260. static void dump_base_locale(int n)
  3261. {
  3262. assert(n < base_locale_len);
  3263. fprintf(stderr, "Base Locale: %s\n", base_locale_array[n].name);
  3264. DUMPn(num_weights);
  3265. DUMPn(ii_shift);
  3266. DUMPn(ti_shift);
  3267. DUMPn(ii_len);
  3268. DUMPn(ti_len);
  3269. DUMPn(max_weight);
  3270. fprintf(stderr, "\n");
  3271. DUMPn(num_col_base);
  3272. DUMPn(max_col_index);
  3273. DUMPn(undefined_idx);
  3274. DUMPn(range_low);
  3275. DUMPn(range_count);
  3276. fprintf(stderr, "\n");
  3277. DUMPn(range_base_weight);
  3278. DUMPn(num_starters);
  3279. fprintf(stderr, "\n");
  3280. DUMPn(range_rule_offset);
  3281. DUMPn(wcs2colidt_offset);
  3282. DUMPn(index2weight_offset);
  3283. fprintf(stderr, "\n");
  3284. DUMPn(index2ruleidx_offset);
  3285. DUMPn(multistart_offset);
  3286. fprintf(stderr, "\n");
  3287. }
  3288. #undef DUMPn
  3289. #define DUMPn(X) fprintf(stderr, "%10d-%s", der_locale_array[n]. X, #X);
  3290. static void dump_der_locale(int n)
  3291. {
  3292. assert(n < der_locale_len);
  3293. fprintf(stderr, "Derived Locale: %s (%.12s)",
  3294. der_locale_array[n].name,
  3295. base_locale_array[der_locale_array[n].base_idx].name);
  3296. DUMPn(base_idx);
  3297. DUMPn(undefined_idx);
  3298. DUMPn(overrides_offset);
  3299. DUMPn(multistart_offset);
  3300. fprintf(stderr, "\n");
  3301. }
  3302. static unsigned long collate_pos;
  3303. static void dump_u16_array(FILE *fp, uint16_t *u, int len, const char *name)
  3304. {
  3305. int i;
  3306. fprintf(fp, "\t/* %8lu %s */\n", collate_pos, name);
  3307. for (i=0 ; i < len ; i++) {
  3308. if (!(i & 7)) {
  3309. fprintf(fp, "\n\t");
  3310. }
  3311. fprintf(fp," %#06x,", (unsigned int)(u[i]));
  3312. }
  3313. fprintf(fp,"\n");
  3314. collate_pos += len;
  3315. }
  3316. #define OUT_U16C(X,N) fprintf(fp,"\t%10d, /* %8lu %s */\n", X, collate_pos++, N);
  3317. static void dump_collate(FILE *fp)
  3318. {
  3319. int n;
  3320. fprintf(fp, "const uint16_t __locale_collate_tbl[] = {\n");
  3321. OUT_U16C(base_locale_len, "numbef of base locales");
  3322. OUT_U16C(der_locale_len, "number of derived locales");
  3323. OUT_U16C(MAX_COLLATION_WEIGHTS, "max collation weights");
  3324. OUT_U16C(index2weight_len, "number of index2{weight|ruleidx} elements");
  3325. OUT_U16C(weightstr_len, "number of weightstr elements");
  3326. OUT_U16C(multistart_len, "number of multistart elements");
  3327. OUT_U16C(override_len, "number of override elements");
  3328. OUT_U16C(ruletable_len, "number of ruletable elements");
  3329. #undef DUMPn
  3330. #define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", base_locale_array[n]. X, collate_pos++, #X);
  3331. for (n=0 ; n < base_locale_len ; n++) {
  3332. unsigned wcs2colidt_offset_low = base_locale_array[n].wcs2colidt_offset & 0xffffU;
  3333. unsigned wcs2colidt_offset_hi = base_locale_array[n].wcs2colidt_offset >> 16;
  3334. fprintf(fp, "\t/* Base Locale %2d: %s */\n", n, base_locale_array[n].name);
  3335. DUMPn(num_weights);
  3336. DUMPn(num_starters);
  3337. DUMPn(ii_shift);
  3338. DUMPn(ti_shift);
  3339. DUMPn(ii_len);
  3340. DUMPn(ti_len);
  3341. DUMPn(max_weight);
  3342. DUMPn(num_col_base);
  3343. DUMPn(max_col_index);
  3344. DUMPn(undefined_idx);
  3345. DUMPn(range_low);
  3346. DUMPn(range_count);
  3347. DUMPn(range_base_weight);
  3348. DUMPn(range_rule_offset);
  3349. DUMPn(index2weight_offset);
  3350. DUMPn(index2ruleidx_offset);
  3351. DUMPn(multistart_offset);
  3352. #undef DUMPn
  3353. #define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", X, collate_pos++, #X);
  3354. DUMPn(wcs2colidt_offset_low);
  3355. DUMPn(wcs2colidt_offset_hi);
  3356. }
  3357. #undef DUMPn
  3358. fprintf(fp, "#define COL_IDX_C %5d\n", 0);
  3359. #define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", der_locale_array[n]. X, collate_pos++, #X);
  3360. for (n=0 ; n < der_locale_len ; n++) {
  3361. fprintf(fp, "#define COL_IDX_%s %5d\n", der_locale_array[n].name, n+1);
  3362. fprintf(fp, "\t/* Derived Locale %4d: %s (%.12s) */\n",
  3363. n, der_locale_array[n].name,
  3364. base_locale_array[der_locale_array[n].base_idx].name);
  3365. DUMPn(base_idx);
  3366. DUMPn(undefined_idx);
  3367. DUMPn(overrides_offset);
  3368. DUMPn(multistart_offset);
  3369. }
  3370. #undef DUMPn
  3371. fprintf(fp, "\n");
  3372. dump_u16_array(fp, index2weight_buffer, index2weight_len, "index2weight");
  3373. dump_u16_array(fp, index2ruleidx_buffer, index2ruleidx_len, "index2ruleidx");
  3374. dump_u16_array(fp, multistart_buffer, multistart_len, "multistart");
  3375. dump_u16_array(fp, override_buffer, override_len, "override");
  3376. dump_u16_array(fp, ruletable_buffer, ruletable_len, "ruletable");
  3377. dump_u16_array(fp, weightstr_buffer, weightstr_len, "weightstr");
  3378. dump_u16_array(fp, wcs2colidt_buffer, wcs2colidt_len, "wcs2colidt");
  3379. fprintf(fp,"}; /* %8lu */\n", collate_pos);
  3380. fprintf(fp,"#define __lc_collate_data_LEN %d\n\n", collate_pos);
  3381. }