Skip to content

Commit d99bf44

Browse files
committed
Revert "msgfmt: sort strings"
This reverts commit ee82b15. While this now creates valid translation files, it opened the door for a lot of nasty cornercases like plural forms that were elegantly circumvented in the earlier design, but now causing breakage. such breakage was experienced with de.pot from gnu coreutils. development of the "full-featured" msgfmt will eventually continue in the "full" branch and merged into master when it's ready for prime-time.
1 parent ee82b15 commit d99bf44

File tree

1 file changed

+40
-55
lines changed

1 file changed

+40
-55
lines changed

src/msgfmt.c

Lines changed: 40 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -59,61 +59,66 @@ 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: create in-memory string tables
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
6366
enum passes {
6467
pass_first = 0,
6568
pass_collect_sizes = pass_first,
6669
pass_second,
70+
pass_print_string_offsets = pass_second,
71+
pass_print_translation_offsets,
72+
pass_print_strings,
73+
pass_print_translations,
6774
pass_max,
6875
};
6976

70-
struct strtbl {
71-
unsigned len, off;
72-
};
73-
74-
struct strmap {
75-
struct strtbl str, *trans;
76-
};
77-
7877
struct callbackdata {
7978
enum passes pass;
8079
unsigned off;
8180
FILE* out;
8281
unsigned num[pe_maxstr];
8382
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];
8983
};
9084

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-
9785

9886
int process_line_callback(struct po_info* info, void* user) {
9987
struct callbackdata *d = (struct callbackdata *) user;
10088
assert(info->type == pe_msgid || info->type == pe_msgstr);
10189
switch(d->pass) {
10290
case pass_collect_sizes:
10391
d->num[info->type] += 1;
104-
d->len[info->type] += info->textlen +1;
92+
d->len[info->type] += info->textlen;
10593
break;
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;
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;
102+
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;
117122
break;
118123
default:
119124
abort();
@@ -144,17 +149,19 @@ int process(FILE *in, FILE *out) {
144149
int invalid_file = 0;
145150

146151
mohdr.off_tbl_trans = mohdr.off_tbl_org;
147-
for(d.pass = pass_first; d.pass <= pass_second; d.pass++) {
152+
for(d.pass = pass_first; d.pass < pass_max; d.pass++) {
148153
if(d.pass == pass_second) {
149154
// start of second pass:
150155
// check that data gathered in first pass is consistent
156+
#ifndef DO_NOTHING
151157
if(d.num[pe_msgid] != d.num[pe_msgstr]) {
152158
// one should actually abort here,
153159
// but gnu gettext simply writes an empty .mo and returns success.
154160
//abort();
155161
d.num[pe_msgid] = 0;
156162
invalid_file = 1;
157163
}
164+
#endif
158165

159166
// calculate header fields from len and num arrays
160167
mohdr.numstring = d.num[pe_msgid];
@@ -165,13 +172,6 @@ int process(FILE *in, FILE *out) {
165172
// set offset startvalue
166173
d.off = mohdr.off_tbl_trans + d.num[pe_msgid] * (sizeof(unsigned)*2);
167174
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,21 +183,6 @@ 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-
201186
return 0;
202187
}
203188

0 commit comments

Comments
 (0)