@@ -59,66 +59,61 @@ const struct mo_hdr def_hdr = {
5959
6060// pass 0: collect numbers of strings, calculate size and offsets for tables
6161// print header
62- // pass 1: print string table [lengths/offsets]
63- // pass 2: print translation table [lengths/offsets]
64- // pass 3: print strings
65- // pass 4: print translations
62+ // pass 1: create in-memory string tables
6663enum passes {
6764 pass_first = 0 ,
6865 pass_collect_sizes = pass_first ,
6966 pass_second ,
70- pass_print_string_offsets = pass_second ,
71- pass_print_translation_offsets ,
72- pass_print_strings ,
73- pass_print_translations ,
7467 pass_max ,
7568};
7669
70+ struct strtbl {
71+ unsigned len , off ;
72+ };
73+
74+ struct strmap {
75+ struct strtbl str , * trans ;
76+ };
77+
7778struct callbackdata {
7879 enum passes pass ;
7980 unsigned off ;
8081 FILE * out ;
8182 unsigned num [pe_maxstr ];
8283 unsigned len [pe_maxstr ];
84+ struct strmap * strlist ;
85+ struct strtbl * translist ;
86+ char * strbuffer [pe_maxstr ];
87+ unsigned stroff [pe_maxstr ];
88+ unsigned curr [pe_maxstr ];
8389};
8490
91+ static struct callbackdata * cb_for_qsort ;
92+ int strmap_comp (const void * a_ , const void * b_ ) {
93+ const struct strmap * a = a_ , * b = b_ ;
94+ return strcmp (cb_for_qsort -> strbuffer [0 ] + a -> str .off , cb_for_qsort -> strbuffer [0 ] + b -> str .off );
95+ }
96+
8597
8698int process_line_callback (struct po_info * info , void * user ) {
8799 struct callbackdata * d = (struct callbackdata * ) user ;
88100 assert (info -> type == pe_msgid || info -> type == pe_msgstr );
89101 switch (d -> pass ) {
90102 case pass_collect_sizes :
91103 d -> num [info -> type ] += 1 ;
92- d -> len [info -> type ] += info -> textlen ;
93- break ;
94- case pass_print_string_offsets :
95- if (info -> type == pe_msgstr ) break ;
96- write_offsets :
97- // print length of current string
98- fwrite (& info -> textlen , sizeof (unsigned ), 1 , d -> out );
99- // print offset of current string
100- fwrite (& d -> off , sizeof (unsigned ), 1 , d -> out );
101- d -> off += info -> textlen + 1 ;
104+ d -> len [info -> type ] += info -> textlen + 1 ;
102105 break ;
103- case pass_print_translation_offsets :
104- #ifndef DO_NOTHING
105- if (info -> type == pe_msgid ) break ;
106- #else
107- if (info -> type != pe_msgid ) break ;
108- #endif
109- goto write_offsets ;
110- case pass_print_strings :
111- if (info -> type == pe_msgstr ) break ;
112- write_string :
113- fwrite (info -> text , info -> textlen + 1 , 1 , d -> out );
114- break ;
115- case pass_print_translations :
116- #ifndef DO_NOTHING
117- if (info -> type == pe_msgid ) break ;
118- #else
119- if (info -> type != pe_msgid ) break ;
120- #endif
121- goto write_string ;
106+ case pass_second :
107+ memcpy (d -> strbuffer [info -> type ] + d -> stroff [info -> type ], info -> text , info -> textlen + 1 );
108+ if (info -> type == pe_msgid )
109+ d -> strlist [d -> curr [info -> type ]].str = (struct strtbl ){.len = info -> textlen , .off = d -> stroff [info -> type ]};
110+ else {
111+ assert (d -> curr [pe_msgid ] == d -> curr [pe_msgstr ]+ 1 );
112+ d -> translist [d -> curr [info -> type ]] = (struct strtbl ){.len = info -> textlen , .off = d -> stroff [info -> type ]};
113+ d -> strlist [d -> curr [info -> type ]].trans = & d -> translist [d -> curr [info -> type ]];
114+ }
115+ d -> curr [info -> type ]++ ;
116+ d -> stroff [info -> type ]+= info -> textlen + 1 ;
122117 break ;
123118 default :
124119 abort ();
@@ -149,19 +144,17 @@ int process(FILE *in, FILE *out) {
149144 int invalid_file = 0 ;
150145
151146 mohdr .off_tbl_trans = mohdr .off_tbl_org ;
152- for (d .pass = pass_first ; d .pass < pass_max ; d .pass ++ ) {
147+ for (d .pass = pass_first ; d .pass <= pass_second ; d .pass ++ ) {
153148 if (d .pass == pass_second ) {
154149 // start of second pass:
155150 // check that data gathered in first pass is consistent
156- #ifndef DO_NOTHING
157151 if (d .num [pe_msgid ] != d .num [pe_msgstr ]) {
158152 // one should actually abort here,
159153 // but gnu gettext simply writes an empty .mo and returns success.
160154 //abort();
161155 d .num [pe_msgid ] = 0 ;
162156 invalid_file = 1 ;
163157 }
164- #endif
165158
166159 // calculate header fields from len and num arrays
167160 mohdr .numstring = d .num [pe_msgid ];
@@ -172,6 +165,13 @@ int process(FILE *in, FILE *out) {
172165 // set offset startvalue
173166 d .off = mohdr .off_tbl_trans + d .num [pe_msgid ] * (sizeof (unsigned )* 2 );
174167 if (invalid_file ) return 0 ;
168+
169+ d .strlist = malloc (d .num [pe_msgid ] * sizeof (struct strmap ));
170+ d .translist = malloc (d .num [pe_msgstr ] * sizeof (struct strtbl ));
171+ d .strbuffer [pe_msgid ] = malloc (d .len [pe_msgid ]);
172+ d .strbuffer [pe_msgstr ] = malloc (d .len [pe_msgstr ]);
173+ d .stroff [pe_msgid ] = d .stroff [pe_msgstr ] = 0 ;
174+ assert (d .strlist && d .translist && d .strbuffer [0 ] && d .strbuffer [1 ]);
175175 }
176176 poparser_init (p , convbuf , sizeof (convbuf ), process_line_callback , & d );
177177
@@ -183,6 +183,21 @@ int process(FILE *in, FILE *out) {
183183
184184 fseek (in , 0 , SEEK_SET );
185185 }
186+
187+ cb_for_qsort = & d ;
188+ qsort (d .strlist , d .num [pe_msgid ], sizeof (struct strmap ), strmap_comp );
189+ unsigned i ;
190+ for (i = 0 ; i < d .num [0 ]; i ++ ) {
191+ d .strlist [i ].str .off += d .off ;
192+ fwrite (& d .strlist [i ].str , sizeof (struct strtbl ), 1 , d .out );
193+ }
194+ for (i = 0 ; i < d .num [1 ]; i ++ ) {
195+ d .strlist [i ].trans -> off += d .off + d .len [0 ];
196+ fwrite (d .strlist [i ].trans , sizeof (struct strtbl ), 1 , d .out );
197+ }
198+ fwrite (d .strbuffer [0 ], d .len [0 ], 1 , d .out );
199+ fwrite (d .strbuffer [1 ], d .len [1 ], 1 , d .out );
200+
186201 return 0 ;
187202}
188203
0 commit comments