summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2014-08-13 17:44:15 +0200
committerrofl0r <retnyg@gmx.net>2014-08-13 17:44:15 +0200
commitd99bf44a8025a1b27dfae8b6a245883ba7f0bf4d (patch)
treeb341802c7c07b2f51d10a2007beb4e20ffa1bf70
parentee82b152ce2b4ab74b7ac72d27540f0dd01172e8 (diff)
downloadgettext-tiny-d99bf44a8025a1b27dfae8b6a245883ba7f0bf4d.tar.gz
Revert "msgfmt: sort strings"
This reverts commit ee82b152ce2b4ab74b7ac72d27540f0dd01172e8. 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.
-rw-r--r--src/msgfmt.c95
1 files changed, 40 insertions, 55 deletions
diff --git a/src/msgfmt.c b/src/msgfmt.c
index 530ad48..fed7b6c 100644
--- a/src/msgfmt.c
+++ b/src/msgfmt.c
@@ -59,41 +59,29 @@ const struct mo_hdr def_hdr = {
// pass 0: collect numbers of strings, calculate size and offsets for tables
// print header
-// pass 1: create in-memory string tables
+// pass 1: print string table [lengths/offsets]
+// pass 2: print translation table [lengths/offsets]
+// pass 3: print strings
+// pass 4: print translations
enum passes {
pass_first = 0,
pass_collect_sizes = pass_first,
pass_second,
+ pass_print_string_offsets = pass_second,
+ pass_print_translation_offsets,
+ pass_print_strings,
+ pass_print_translations,
pass_max,
};
-struct strtbl {
- unsigned len, off;
-};
-
-struct strmap {
- struct strtbl str, *trans;
-};
-
struct callbackdata {
enum passes pass;
unsigned off;
FILE* out;
unsigned num[pe_maxstr];
unsigned len[pe_maxstr];
- struct strmap *strlist;
- struct strtbl *translist;
- char *strbuffer[pe_maxstr];
- unsigned stroff[pe_maxstr];
- unsigned curr[pe_maxstr];
};
-static struct callbackdata *cb_for_qsort;
-int strmap_comp(const void *a_, const void *b_) {
- const struct strmap *a = a_, *b = b_;
- return strcmp(cb_for_qsort->strbuffer[0] + a->str.off, cb_for_qsort->strbuffer[0] + b->str.off);
-}
-
int process_line_callback(struct po_info* info, void* user) {
struct callbackdata *d = (struct callbackdata *) user;
@@ -101,19 +89,36 @@ int process_line_callback(struct po_info* info, void* user) {
switch(d->pass) {
case pass_collect_sizes:
d->num[info->type] += 1;
- d->len[info->type] += info->textlen +1;
+ d->len[info->type] += info->textlen;
break;
- case pass_second:
- memcpy(d->strbuffer[info->type] + d->stroff[info->type], info->text, info->textlen+1);
- if(info->type == pe_msgid)
- d->strlist[d->curr[info->type]].str = (struct strtbl){.len=info->textlen, .off=d->stroff[info->type]};
- else {
- assert(d->curr[pe_msgid] == d->curr[pe_msgstr]+1);
- d->translist[d->curr[info->type]] = (struct strtbl){.len=info->textlen, .off=d->stroff[info->type]};
- d->strlist[d->curr[info->type]].trans = &d->translist[d->curr[info->type]];
- }
- d->curr[info->type]++;
- d->stroff[info->type]+=info->textlen+1;
+ case pass_print_string_offsets:
+ if(info->type == pe_msgstr) break;
+ write_offsets:
+ // print length of current string
+ fwrite(&info->textlen, sizeof(unsigned), 1, d->out);
+ // print offset of current string
+ fwrite(&d->off, sizeof(unsigned), 1, d->out);
+ d->off += info->textlen + 1;
+ break;
+ case pass_print_translation_offsets:
+#ifndef DO_NOTHING
+ if(info->type == pe_msgid) break;
+#else
+ if(info->type != pe_msgid) break;
+#endif
+ goto write_offsets;
+ case pass_print_strings:
+ if(info->type == pe_msgstr) break;
+ write_string:
+ fwrite(info->text, info->textlen + 1, 1, d->out);
+ break;
+ case pass_print_translations:
+#ifndef DO_NOTHING
+ if(info->type == pe_msgid) break;
+#else
+ if(info->type != pe_msgid) break;
+#endif
+ goto write_string;
break;
default:
abort();
@@ -144,10 +149,11 @@ int process(FILE *in, FILE *out) {
int invalid_file = 0;
mohdr.off_tbl_trans = mohdr.off_tbl_org;
- for(d.pass = pass_first; d.pass <= pass_second; d.pass++) {
+ for(d.pass = pass_first; d.pass < pass_max; d.pass++) {
if(d.pass == pass_second) {
// start of second pass:
// check that data gathered in first pass is consistent
+#ifndef DO_NOTHING
if(d.num[pe_msgid] != d.num[pe_msgstr]) {
// one should actually abort here,
// but gnu gettext simply writes an empty .mo and returns success.
@@ -155,6 +161,7 @@ int process(FILE *in, FILE *out) {
d.num[pe_msgid] = 0;
invalid_file = 1;
}
+#endif
// calculate header fields from len and num arrays
mohdr.numstring = d.num[pe_msgid];
@@ -165,13 +172,6 @@ int process(FILE *in, FILE *out) {
// set offset startvalue
d.off = mohdr.off_tbl_trans + d.num[pe_msgid] * (sizeof(unsigned)*2);
if(invalid_file) return 0;
-
- d.strlist = malloc(d.num[pe_msgid] * sizeof(struct strmap));
- d.translist = malloc(d.num[pe_msgstr] * sizeof(struct strtbl));
- d.strbuffer[pe_msgid] = malloc(d.len[pe_msgid]);
- d.strbuffer[pe_msgstr] = malloc(d.len[pe_msgstr]);
- d.stroff[pe_msgid] = d.stroff[pe_msgstr] = 0;
- assert(d.strlist && d.translist && d.strbuffer[0] && d.strbuffer[1]);
}
poparser_init(p, convbuf, sizeof(convbuf), process_line_callback, &d);
@@ -183,21 +183,6 @@ int process(FILE *in, FILE *out) {
fseek(in, 0, SEEK_SET);
}
-
- cb_for_qsort = &d;
- qsort(d.strlist, d.num[pe_msgid], sizeof (struct strmap), strmap_comp);
- unsigned i;
- for(i = 0; i < d.num[0]; i++) {
- d.strlist[i].str.off += d.off;
- fwrite(&d.strlist[i].str, sizeof(struct strtbl), 1, d.out);
- }
- for(i = 0; i < d.num[1]; i++) {
- d.strlist[i].trans->off += d.off + d.len[0];
- fwrite(d.strlist[i].trans, sizeof(struct strtbl), 1, d.out);
- }
- fwrite(d.strbuffer[0], d.len[0], 1, d.out);
- fwrite(d.strbuffer[1], d.len[1], 1, d.out);
-
return 0;
}