summaryrefslogtreecommitdiff
path: root/src/msgfmt.c
diff options
context:
space:
mode:
authorxhe <xw897002528@gmail.com>2018-11-28 15:26:53 +0800
committerrofl0r <retnyg@gmx.net>2019-01-16 02:38:18 +0000
commita63618cdb119891c2b7923de87c21125286d7691 (patch)
treec7989d9c8ac55304b502c7397cbcab72866d6cfb /src/msgfmt.c
parent98bd054905c761ae48b1c912a797e45986870d35 (diff)
downloadgettext-tiny-a63618cdb119891c2b7923de87c21125286d7691.tar.gz
complete rewrite of poparser, msgmerge/msgfmt ported
as stated in https://github.com/sabotage-linux/gettext-tiny/issues/39, the old parser is not good enough to handle all the po files. Similiar issues occurred over and over again because our dirty hacks in the project. so, i propose and implement this new parser, which: 1. needs to parse a po file two times. the first time will acquire the maximum width of every entry. the second time will copy the well-prepared contents into struct po_message, and pass it to the callback function. 2. every struct po_message contains all the information of one translation: msgid, msgctxt, msgid_plural, and msgstrs. comments may be added later. the logic of code is quite simple, nothing special need to explain. the special points are: 1. the first time, new parser gives no infomation about what the string is like. neither will the new parser give the exact size(sysdeped), nor you can calculate the exact size on your own. only xxx_len, strlen, sy- sdep in po_message_t is available. xxx_len is the length of the corressponding entry, strlen is almost the same. 2. sysdep present how many cases the string could be expanded to. since you know the length of the original string and the original string is always longer than the converted one, you can get a safe buffer size to work at the second stage. 3. poparser_sysdep(), a function like unescape(), with a bit flag as the third argument. that is, three bits correspond to st_priu32, st_priu64, st_priumax. since there're only up to two cases for every kind of sysdep, you could count from 0 to msg->sysdep-1, and poparser_sysdep will iterate every possible case eventually.
Diffstat (limited to 'src/msgfmt.c')
-rw-r--r--src/msgfmt.c566
1 files changed, 172 insertions, 394 deletions
diff --git a/src/msgfmt.c b/src/msgfmt.c
index c5d43d7..98a9b88 100644
--- a/src/msgfmt.c
+++ b/src/msgfmt.c
@@ -1,28 +1,21 @@
/* msgfmt utility (C) 2012 rofl0r
* released under the MIT license, see LICENSE for details */
+#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <ctype.h>
+#include <limits.h>
#include <assert.h>
#include "poparser.h"
-// in DO_NOTHING mode, we simply write the msgid twice, once for msgid, once for msgstr.
-// TODO: maybe make it write "" instead of echoing the msgid.
-//#define DO_NOTHING
-
-__attribute__((noreturn))
static void syntax(void) {
- fprintf(stdout,
- "Usage: msgfmt [OPTION] filename.po ...\n");
- exit(1);
+ fprintf(stdout, "Usage: msgfmt [OPTION] filename.po ...\n");
}
-__attribute__((noreturn))
static void version(void) {
- fprintf(stdout,
- "msgfmt (GNU gettext-tools compatible) 99.9999.9999\n");
- exit(0);
+ fprintf(stdout, "msgfmt (GNU gettext-tools compatible) 99.9999.9999\n");
}
#define streq(A, B) (!strcmp(A, B))
@@ -56,314 +49,114 @@ const struct mo_hdr def_hdr = {
0,
};
-
-// pass 0: collect numbers of strings, calculate size and offsets for tables
-// print header
-// pass 1: create in-memory string tables
-enum passes {
- pass_first = 0,
- pass_collect_sizes = pass_first,
- pass_second,
- pass_max,
-};
-
struct strtbl {
- unsigned len, off;
+ uint32_t len, off;
};
struct strmap {
- struct strtbl str, *trans;
+ struct strtbl str;
+ struct strtbl trans;
};
struct callbackdata {
- enum passes pass;
- unsigned off;
FILE* out;
- unsigned msgidbuf1_len;
- unsigned msgidbuf2_len;
- unsigned pluralbuf1_len;
- unsigned pluralbuf2_len;
- unsigned ctxtbuf_len;
- unsigned msgstr1_len;
- unsigned msgstr2_len;
- unsigned pluralstr_count;
- unsigned string_maxlen;
- char* msgidbuf1;
- char* msgidbuf2;
- char* pluralbuf1;
- char* pluralbuf2;
- char* msgctxtbuf;
- char* msgstrbuf1;
- char* msgstrbuf2;
- unsigned priv_type;
- unsigned priv_len;
- 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];
+ enum po_stage stage;
+ size_t cnt;
+ size_t len[2];
+ char* buf[2];
+ struct strmap *list;
};
static struct callbackdata *cb_for_qsort;
-int strmap_comp(const void *a_, const void *b_) {
+int strtbl_cmp(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);
+ return strcmp(cb_for_qsort->buf[0] + a->str.off, cb_for_qsort->buf[0] + b->str.off);
}
-enum sysdep_types {
- st_priu32 = 0,
- st_priu64,
- st_priumax,
- st_max
-};
+int process_line_callback(po_message_t msg, void* user) {
+ struct callbackdata *d = (struct callbackdata *) user;
+ struct strtbl *str, *trans;
+ size_t m;
+ int cnt[st_max] = {0};
+ int i, k;
-static const char sysdep_str[][10]={
- [st_priu32] = "\x08<PRIu32>",
- [st_priu64] = "\x08<PRIu64>",
- [st_priumax] = "\x09<PRIuMAX>",
-};
-static const char sysdep_repl[][8]={
- [st_priu32] = "\x02lu\0u",
- [st_priu64] = "\x02lu\0llu",
- [st_priumax] = "\x01ju"
-};
-static const char *get_repl(enum sysdep_types type, unsigned nr) {
- assert(nr < (unsigned)sysdep_repl[type][0]);
- const char* p = sysdep_repl[type]+1;
- while(nr--) p+=strlen(p)+1;
- return p;
-}
-static void replace(char* text, unsigned textlen, const char* what, const char * with) {
- char*p = text;
- size_t la = strlen(what), li=strlen(with);
- assert(la >= li);
- for(p=text;textlen >= la;) {
- if(!memcmp(p,what,la)) {
- memcpy(p, with, li);
- textlen -= la;
- memmove(p+li,p+la,textlen+1);
- p+=li;
- } else {
- p++;
- textlen--;
- }
- }
-}
-static unsigned get_form(enum sysdep_types type, unsigned no, unsigned occurences[st_max]) {
- unsigned i,divisor = 1;
- for(i=type+1;i<st_max;i++) if(occurences[i]) divisor *= sysdep_repl[i][0];
- return (no/divisor)%sysdep_repl[type][0];
-}
-static char** sysdep_transform(const char* text, unsigned textlen, unsigned *len, unsigned *count, int simulate) {
- unsigned occurences[st_max] = {0};
- const char *p=text,*o;
- unsigned i,j, l = textlen;
- while(l && (o=strchr(p, '<'))) {
- l-=o-p;p=o;
- unsigned f = 0;
- for(i=0;i<st_max;i++)
- if(l>=(unsigned)sysdep_str[i][0] && !memcmp(p,sysdep_str[i]+1,sysdep_str[i][0])) {
- occurences[i]++;
- f=1;
- p+=sysdep_str[i][0];
- l-=sysdep_str[i][0];
- break;
- }
- if(!f) p++,l--;
- }
- *count = 1;
- for(i=0;i<st_max;i++) if(occurences[i]) *count *= sysdep_repl[i][0];
- l = textlen * *count;
- for(i=0;i<*count;i++) for(j=0;j<st_max;j++)
- if(occurences[j]) l-= occurences[j] * (sysdep_str[j][0] - strlen(get_repl(j, get_form(j, i, occurences))));
- *len = l+*count-1;
-
- char **out = 0;
- if(!simulate) {
- out = malloc((sizeof(char*)+textlen+1) * *count);
- assert(out);
- char *p = (void*)(out+*count);
- for(i=0;i<*count;i++) {
- out[i]=p;
- memcpy(p, text, textlen+1);
- p+=textlen+1;
- }
- for(i=0;i<*count;i++) for(j=0;j<st_max;j++)
- if(occurences[j])
- replace(out[i], textlen, sysdep_str[j]+1, get_repl(j, get_form(j, i, occurences)));
- }
+ if (msg->flags & PO_FUZZY) return 0;
+ if (msg->strlen[0] == 0) return 0;
- return out;
-}
+ switch(d->stage) {
+ case ps_size:
+ k = 1;
+ for (i=0; i < st_max; i++)
+ if (msg->sysdep[i])
+ k *= msg->sysdep[i];
-static void error(const char* msg) {
- fprintf(stderr, msg);
- exit(1);
-}
+ d->len[0] += (msg->id_len + 1)*k;
-static inline void writemsg(struct callbackdata *d) {
- if(d->msgidbuf1_len != 0) {
- if(!d->strlist[d->curr[pe_msgid]].str.off)
- d->strlist[d->curr[pe_msgid]].str.off=d->stroff[pe_msgid];
+ if (msg->plural_len)
+ d->len[0] += (msg->plural_len + 1)*k;
- if(d->ctxtbuf_len != 0) {
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgctxtbuf, d->ctxtbuf_len);
- d->strlist[d->curr[pe_msgid]].str.len+=d->ctxtbuf_len;
- d->stroff[pe_msgid]+=d->ctxtbuf_len;
- }
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgidbuf1, d->msgidbuf1_len);
- d->stroff[pe_msgid]+=d->msgidbuf1_len;
- d->strlist[d->curr[pe_msgid]].str.len+=d->msgidbuf1_len-1;
- if(d->pluralbuf1_len != 0) {
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->pluralbuf1, d->pluralbuf1_len);
- d->strlist[d->curr[pe_msgid]].str.len+=d->pluralbuf1_len;
- d->stroff[pe_msgid]+=d->pluralbuf1_len;
- }
- d->curr[pe_msgid]++;
- }
- if(d->msgidbuf2_len != 0) {
- if(!d->strlist[d->curr[pe_msgid]].str.off)
- d->strlist[d->curr[pe_msgid]].str.off=d->stroff[pe_msgid];
-
- if(d->ctxtbuf_len != 0) {
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgctxtbuf, d->ctxtbuf_len);
- d->strlist[d->curr[pe_msgid]].str.len+=d->ctxtbuf_len;
- d->stroff[pe_msgid]+=d->ctxtbuf_len;
- }
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgidbuf2, d->msgidbuf2_len);
- d->stroff[pe_msgid]+=d->msgidbuf2_len;
- d->strlist[d->curr[pe_msgid]].str.len+=d->msgidbuf2_len-1;
- if(d->pluralbuf2_len != 0) {
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->pluralbuf2, d->pluralbuf2_len);
- d->strlist[d->curr[pe_msgid]].str.len+=d->pluralbuf2_len;
- d->stroff[pe_msgid]+=d->pluralbuf2_len;
- }
- d->curr[pe_msgid]++;
- }
+ if (msg->ctxt_len)
+ d->len[0] += (msg->ctxt_len + 1)*k;
- d->pluralbuf2_len=d->pluralbuf1_len=d->ctxtbuf_len=d->msgidbuf1_len=d->msgidbuf2_len=0;
-}
+ for (i=0; msg->strlen[i]; i++)
+ d->len[1] += (msg->strlen[i] + 1)*k;
-static inline void writestr(struct callbackdata *d, struct po_info *info) {
- // msgid xx; msgstr ""; is widely happened, it's invalid
-
- // https://github.com/sabotage-linux/gettext-tiny/issues/1
- // no invalid, when empty, check d->num[pe_msgid]
- if(!d->pluralstr_count && d->num[pe_msgid] > 0) {
- d->len[pe_msgid]-=d->msgidbuf1_len;
- d->len[pe_msgid]-=d->msgidbuf2_len;
- d->len[pe_plural]-=d->pluralbuf1_len;
- d->len[pe_plural]-=d->pluralbuf2_len;
- d->len[pe_ctxt]-=d->ctxtbuf_len;
- d->len[pe_msgstr]--;
- d->num[pe_msgid]--;
- d->num[pe_msgstr]--;
- d->pluralbuf2_len=d->pluralbuf1_len=d->ctxtbuf_len=d->msgidbuf1_len=d->msgidbuf2_len=d->msgstr1_len=d->msgstr2_len=d->pluralstr_count=0;
- return;
- }
+ d->cnt += k;
+ break;
+ case ps_parse:
+ for (k=1; k; d->cnt++) {
+ k = 0;
- if(d->pluralstr_count && d->pluralstr_count <= info->nplurals) {
- writemsg(d);
- // plural <= nplurals is allowed
- d->translist[d->curr[pe_msgstr]].len=d->msgstr1_len-1;
- d->translist[d->curr[pe_msgstr]].off=d->stroff[pe_msgstr];
- d->strlist[d->curr[pe_msgstr]].trans = &d->translist[d->curr[pe_msgstr]];
-
- memcpy(d->strbuffer[pe_msgstr] + d->stroff[pe_msgstr], d->msgstrbuf1, d->msgstr1_len);
- d->stroff[pe_msgstr]+=d->msgstr1_len;
- d->curr[pe_msgstr]++;
-
- if(d->msgstr2_len) {
- d->translist[d->curr[pe_msgstr]].len=d->msgstr2_len-1;
- d->translist[d->curr[pe_msgstr]].off=d->stroff[pe_msgstr];
- d->strlist[d->curr[pe_msgstr]].trans = &d->translist[d->curr[pe_msgstr]];
-
- memcpy(d->strbuffer[pe_msgstr] + d->stroff[pe_msgstr], d->msgstrbuf2, d->msgstr2_len);
- d->stroff[pe_msgstr]+=d->msgstr2_len;
- d->curr[pe_msgstr]++;
- }
+ str = &d->list[d->cnt].str;
+ trans = &d->list[d->cnt].trans;
- d->msgstr1_len=d->msgstr2_len=d->pluralstr_count=0;
- }
-}
+ str->off = d->len[0];
+ str->len = 0;
-int process_line_callback(struct po_info* info, void* user) {
- struct callbackdata *d = (struct callbackdata *) user;
- assert(info->type == pe_msgid || info->type == pe_ctxt || info->type == pe_msgstr || info->type == pe_plural);
- char **sysdeps;
- unsigned len, count, i, l;
- switch(d->pass) {
- case pass_collect_sizes:
- sysdep_transform(info->text, info->textlen, &len, &count, 1);
- d->num[info->type] += count;
- if(info->type == pe_msgid && count == 2 && d->priv_type == pe_ctxt) {
- // ctxt meets msgid with sysdeps, multiply num and len to suit it
- d->len[pe_ctxt] += d->priv_len +1;
- d->num[pe_ctxt]++;
+ if (msg->ctxt_len) {
+ m = poparser_sysdep(msg->ctxt, &d->buf[0][d->len[0]], cnt);
+ str->len += m;
+ d->buf[0][d->len[0]+m-1] = 0x4;
+ d->len[0] += m;
+ }
+
+ m = poparser_sysdep(msg->id, &d->buf[0][d->len[0]], cnt);
+ str->len += m;
+ d->len[0] += m;
+
+ if (msg->plural_len) {
+ m = poparser_sysdep(msg->plural, &d->buf[0][d->len[0]], cnt);
+ str->len += m;
+ d->len[0] += m;
}
- if(count != 1 && info->type == pe_ctxt) {
- // except msgid, str, plural, all other types should not have sysdeps
- abort();
+
+ trans->off = d->len[1];
+ trans->len = 0;
+ for (i=0; msg->strlen[i]; i++) {
+ m = poparser_sysdep(msg->str[i], &d->buf[1][d->len[1]], cnt);
+ trans->len += m;
+ d->len[1] += m;
}
- d->priv_type = info->type;
- d->priv_len = len;
- d->len[info->type] += len +1;
-
- if(len+1 > d->string_maxlen)
- d->string_maxlen = len+1;
- break;
- case pass_second:
- sysdeps = sysdep_transform(info->text, info->textlen, &len, &count, 0);
- for(i=0;i<count;i++) {
- l = strlen(sysdeps[i]);
- assert(l+1 <= d->string_maxlen);
- if(info->type == pe_msgid) {
- if(i==0 && d->msgidbuf1_len)
- writestr(d, info);
-
- // just copy, it's written down when writemsg()
- if(i==0) {
- memcpy(d->msgidbuf1, sysdeps[i], l+1);
- d->msgidbuf1_len = l+1;
- } else {
- memcpy(d->msgidbuf2, sysdeps[i], l+1);
- d->msgidbuf2_len = l+1;
- }
- } else if(info->type == pe_plural) {
- if(i==0) {
- memcpy(d->pluralbuf1, sysdeps[i], l+1);
- d->pluralbuf1_len = l+1;
- } else {
- memcpy(d->pluralbuf2, sysdeps[i], l+1);
- d->pluralbuf2_len = l+1;
- }
- } else if(info->type == pe_ctxt) {
- writestr(d, info);
- d->ctxtbuf_len = l+1;
- memcpy(d->msgctxtbuf, sysdeps[i], l);
- d->msgctxtbuf[l] = 0x4;//EOT
- } else {
- // just copy, it's written down when writestr()
- if(l) {
- if(i==0) {
- memcpy(&d->msgstrbuf1[d->msgstr1_len], sysdeps[i], l+1);
- d->msgstr1_len += l+1;
- d->pluralstr_count++;
- } else {
- // sysdeps exist
- memcpy(&d->msgstrbuf2[d->msgstr2_len], sysdeps[i], l+1);
- d->msgstr2_len += l+1;
- }
+ for (i=0; i < st_max; i++) {
+ if (cnt[i] < msg->sysdep[i]) {
+ cnt[i]++;
+
+ // we have a carry
+ if (cnt[i] == msg->sysdep[i]) {
+ cnt[i] = 0;
+ continue;
}
+
+ k = 1;
+ break;
}
}
- free(sysdeps);
- break;
- default:
- abort();
+ }
+
+ break;
+ default:
+ abort();
}
return 0;
}
@@ -371,113 +164,88 @@ int process_line_callback(struct po_info* info, void* user) {
int process(FILE *in, FILE *out) {
struct mo_hdr mohdr = def_hdr;
char line[8192]; char *lp;
+ size_t off, i;
+ enum po_error t;
char convbuf[32768];
struct callbackdata d = {
- .num = {
- [pe_msgid] = 0,
- [pe_msgstr] = 0,
- [pe_plural] = 0,
- [pe_ctxt] = 0,
- },
- .len = {
- [pe_msgid] = 0,
- [pe_msgstr] = 0,
- [pe_plural] = 0,
- [pe_ctxt] = 0,
- },
- .off = 0,
+ .len = {0, 0},
+ .cnt = 0,
.out = out,
- .pass = pass_first,
- .ctxtbuf_len = 0,
- .pluralbuf1_len = 0,
- .pluralbuf2_len = 0,
- .msgidbuf1_len = 0,
- .msgidbuf2_len = 0,
- .msgstr1_len = 0,
- .msgstr2_len = 0,
- .pluralstr_count = 0,
- .string_maxlen = 0,
};
struct po_parser pb, *p = &pb;
mohdr.off_tbl_trans = mohdr.off_tbl_org;
- for(d.pass = pass_first; d.pass <= pass_second; d.pass++) {
- if(d.pass == pass_second) {
- // start of second pass:
- // ensure we dont output when there's no strings at all
- if(d.num[pe_msgid] == 0) {
- return 1;
- }
-
- // check that data gathered in first pass is consistent
- if((d.num[pe_msgstr] < d.num[pe_msgid]) || (d.num[pe_msgstr] > (d.num[pe_msgid] + d.num[pe_plural] * (p->info.nplurals - 1)))) {
- // one should actually abort here,
- // but gnu gettext simply writes an empty .mo and returns success.
- //abort();
- fprintf(stderr, "warning: mismatch of msgid/msgstr count, writing empty .mo file\n");
- d.num[pe_msgid] = 0;
- return 0;
- }
- d.msgidbuf1 = calloc(d.string_maxlen*5+2*d.string_maxlen*p->info.nplurals, 1);
- d.msgidbuf2 = d.msgidbuf1 + d.string_maxlen;
- d.pluralbuf1 = d.msgidbuf2 + d.string_maxlen;
- d.pluralbuf2 = d.pluralbuf1 + d.string_maxlen;
- d.msgctxtbuf = d.pluralbuf2 + d.string_maxlen;
- d.msgstrbuf1 = d.msgctxtbuf + d.string_maxlen;
- d.msgstrbuf2 = d.msgstrbuf1 + d.string_maxlen*p->info.nplurals;
-
- d.strlist = calloc(d.num[pe_msgid] * sizeof(struct strmap), 1);
- d.translist = calloc(d.num[pe_msgstr] * sizeof(struct strtbl), 1);
- d.strbuffer[pe_msgid] = calloc(d.len[pe_msgid]+d.len[pe_plural]+d.len[pe_ctxt], 1);
- d.strbuffer[pe_msgstr] = calloc(d.len[pe_msgstr], 1);
- d.stroff[pe_msgid] = d.stroff[pe_msgstr] = 0;
- assert(d.msgidbuf1 && d.strlist && d.translist && d.strbuffer[pe_msgid] && d.strbuffer[pe_msgstr]);
- }
-
- poparser_init(p, convbuf, sizeof(convbuf), process_line_callback, &d);
+ poparser_init(p, convbuf, sizeof(convbuf), process_line_callback, &d);
+ d.stage = p->stage;
- while((lp = fgets(line, sizeof(line), in))) {
- poparser_feed_line(p, lp, sizeof(line));
- }
- poparser_finish(p);
- if(d.pass == pass_second)
- writestr(&d, &p->info);
-
- if(d.pass == pass_second) {
- // calculate header fields from len and num arrays
- mohdr.numstring = d.num[pe_msgid];
- mohdr.off_tbl_org = sizeof(struct mo_hdr);
- mohdr.off_tbl_trans = mohdr.off_tbl_org + d.num[pe_msgid] * (sizeof(unsigned)*2);
- // set offset startvalue
- d.off = mohdr.off_tbl_trans + d.num[pe_msgid] * (sizeof(unsigned)*2);
+ while((lp = fgets(line, sizeof(line), in))) {
+ if ((t = poparser_feed_line(p, lp, strlen(line))) != po_success)
+ return t;
+ }
+ if ((t = poparser_finish(p)) != po_success)
+ return t;
+
+ if (d.cnt == 0) return -1;
+
+ d.list = (struct strmap*)malloc(sizeof(struct strmap)*d.cnt);
+ d.buf[0] = (char*)malloc(d.len[0]);
+ d.buf[1] = (char*)malloc(d.len[1]);
+ d.len[0] = 0;
+ d.len[1] = 0;
+ d.cnt = 0;
+ d.stage = p->stage;
+
+ fseek(in, 0, SEEK_SET);
+ while ((lp = fgets(line, sizeof(line), in))) {
+ if ((t = poparser_feed_line(p, lp, strlen(line))) != po_success) {
+ free(d.list);
+ free(d.buf[0]);
+ free(d.buf[1]);
+ return t;
}
- fseek(in, 0, SEEK_SET);
+ }
+ if ((t = poparser_finish(p)) != po_success) {
+ free(d.list);
+ free(d.buf[0]);
+ free(d.buf[1]);
+ return t;
}
cb_for_qsort = &d;
- qsort(d.strlist, d.num[pe_msgid], sizeof (struct strmap), strmap_comp);
- unsigned i;
+ qsort(d.list, d.cnt, sizeof(struct strmap), strtbl_cmp);
+ cb_for_qsort = NULL;
// print header
+ mohdr.numstring = d.cnt;
+ mohdr.off_tbl_org = sizeof(struct mo_hdr);
+ mohdr.off_tbl_trans = mohdr.off_tbl_org + d.cnt * sizeof(struct strtbl);
fwrite(&mohdr, sizeof(mohdr), 1, out);
- for(i = 0; i < d.num[pe_msgid]; i++) {
- d.strlist[i].str.off += d.off;
- fwrite(&d.strlist[i].str, sizeof(struct strtbl), 1, d.out);
+
+ off = mohdr.off_tbl_trans + d.cnt * sizeof(struct strtbl);
+ for (i = 0; i < d.cnt; i++) {
+ d.list[i].str.off += off;
+ fwrite(&d.list[i].str, sizeof(struct strtbl), 1, d.out);
}
- for(i = 0; i < d.num[pe_msgid]; i++) {
- d.strlist[i].trans->off += d.off + d.len[pe_msgid] + d.len[pe_plural] + d.len[pe_ctxt];
- fwrite(d.strlist[i].trans, sizeof(struct strtbl), 1, d.out);
+
+ off += d.len[0];
+ for (i = 0; i < d.cnt; i++) {
+ d.list[i].trans.off += off;
+ fwrite(&d.list[i].trans, sizeof(struct strtbl), 1, d.out);
}
- fwrite(d.strbuffer[pe_msgid], d.len[pe_msgid]+d.len[pe_plural]+d.len[pe_ctxt], 1, d.out);
- fwrite(d.strbuffer[pe_msgstr], d.len[pe_msgstr], 1, d.out);
+
+ fwrite(d.buf[0], d.len[0], 1, d.out);
+ fwrite(d.buf[1], d.len[1], 1, d.out);
+
+ free(d.list);
+ free(d.buf[0]);
+ free(d.buf[1]);
return 0;
}
-
void set_file(int out, char* fn, FILE** dest) {
if(streq(fn, "-")) {
if(out) {
@@ -505,11 +273,16 @@ void set_file(int out, char* fn, FILE** dest) {
}
int main(int argc, char**argv) {
- if(argc == 1) syntax();
+ if (argc == 1) {
+ syntax();
+ return 0;
+ }
+
int arg = 1;
FILE *out = NULL;
FILE *in = NULL;
int expect_in_fn = 1;
+ char path[PATH_MAX];
char* locale = NULL;
char* dest = NULL;
#define A argv[arg]
@@ -539,19 +312,20 @@ int main(int argc, char**argv) {
streq(A+2, "statistics") ||
strstarts(A+2, "check-accelerators=") ||
strstarts(A+2, "resource=")
- ) {
- } else if((dest = strstarts(A+2, "locale="))) {
- locale = dest;
- } else if((dest = strstarts(A+2, "output-file="))) {
- set_file(1, dest, &out);
- } else if(streq(A+2, "version")) {
- version();
- } else if(streq(A+2, "help")) {
- syntax();
- } else if (expect_in_fn) {
- set_file(0, A, &in);
- expect_in_fn = 0;
- }
+ ) {
+ } else if((locale = strstarts(A+2, "locale="))) {
+ } else if((dest = strstarts(A+2, "output-file="))) {
+ set_file(1, dest, &out);
+ } else if(streq(A+2, "version")) {
+ version();
+ return 0;
+ } else if(streq(A+2, "help")) {
+ syntax();
+ return 0;
+ } else if (expect_in_fn) {
+ set_file(0, A, &in);
+ expect_in_fn = 0;
+ }
} else if(streq(A + 1, "o")) {
arg++;
dest = A;
@@ -568,8 +342,10 @@ int main(int argc, char**argv) {
) {
} else if (streq(A+1, "V")) {
version();
+ return 0;
} else if (streq(A+1, "h")) {
syntax();
+ return 0;
} else if (streq(A+1, "l")) {
arg++;
locale = A;
@@ -587,14 +363,14 @@ int main(int argc, char**argv) {
}
if (locale != NULL && dest != NULL) {
- int sz = snprintf(NULL, 0, "%s/%s.msg", dest, locale);
- char msg[sz+1];
- snprintf(msg, sizeof(msg), "%s/%s.msg", dest, locale);
- FILE *fp = fopen(msg, "w");
+ snprintf(path, sizeof(path), "%s/%s.msg", dest, locale);
+ FILE *fp = fopen(path, "w");
if (fp) {
fclose(fp);
return 0;
- } else return 1;
+ }
+
+ return -1;
}
if(out == NULL) {
@@ -603,14 +379,16 @@ int main(int argc, char**argv) {
}
if(in == NULL || out == NULL) {
- return 1;
+ return -1;
}
+
int ret = process(in, out);
fflush(in); fflush(out);
+
if(in != stdin) fclose(in);
if(out != stdout) fclose(out);
- if (ret == 1) {
+ if (ret < 0) {
return remove(dest);
}
return ret;