summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxhe <xw897002528@gmail.com>2017-05-01 12:47:40 +0800
committerxhe <xw897002528@gmail.com>2017-05-06 13:03:23 +0800
commitd1bd158eb7463967ab3dd9a862e14d114523d37b (patch)
tree5e90c92211151f437b3aa33c467652b65e3d9798
parentffa22a010fbbf330c5c8de41077f36415c16d38a (diff)
downloadgettext-tiny-d1bd158eb7463967ab3dd9a862e14d114523d37b.tar.gz
add support for msgctxt
-rw-r--r--src/msgfmt.c251
-rw-r--r--src/poparser.c24
-rw-r--r--src/poparser.h1
3 files changed, 172 insertions, 104 deletions
diff --git a/src/msgfmt.c b/src/msgfmt.c
index 48b9f4c..d92274a 100644
--- a/src/msgfmt.c
+++ b/src/msgfmt.c
@@ -79,6 +79,23 @@ struct callbackdata {
enum passes pass;
unsigned off;
FILE* out;
+ char msgidbuf1[4096];
+ unsigned milen1;
+ char msgidbuf2[4096];
+ unsigned milen2;
+ char pluralbuf1[4096];
+ unsigned pllen1;
+ char pluralbuf2[4096];
+ unsigned pllen2;
+ char msgctxtbuf[4096];
+ unsigned ctxtlen;
+ char msgstrbuf1[4096];
+ unsigned mslen1;
+ char msgstrbuf2[4096];
+ unsigned mslen2;
+ unsigned msc;
+ unsigned priv_type;
+ unsigned priv_len;
unsigned num[pe_maxstr];
unsigned len[pe_maxstr];
struct strmap *strlist;
@@ -101,14 +118,6 @@ enum sysdep_types {
st_max
};
-static char msgidbuf[1024];
-static unsigned idlen[3] = { 0 };
-static char msgstr1[4096];
-static unsigned mslen1=0;
-static char msgstr2[4096];
-static unsigned mslen2=0;
-static unsigned msc=0;
-
static const char sysdep_str[][10]={
[st_priu32] = "\x08<PRIu32>",
[st_priu64] = "\x08<PRIu64>",
@@ -193,124 +202,157 @@ static void error(const char* msg) {
exit(1);
}
-static inline void write_plurals(struct callbackdata *d) {
- d->translist[d->curr[pe_msgstr]].len=mslen1-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], msgstr1, mslen1);
- d->stroff[pe_msgstr]+=mslen1;
- d->curr[pe_msgstr]++;
+static inline void writemsg(struct callbackdata *d) {
+ if(d->milen1 != 0) {
+ if(!d->strlist[d->curr[pe_msgid]].str.off)
+ d->strlist[d->curr[pe_msgid]].str.off=d->stroff[pe_msgid];
- d->translist[d->curr[pe_msgstr]].len=mslen2-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], msgstr2, mslen2);
- d->stroff[pe_msgstr]+=mslen2;
- d->curr[pe_msgstr]++;
+ if(d->ctxtlen != 0) {
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgctxtbuf, d->ctxtlen);
+ d->strlist[d->curr[pe_msgid]].str.len+=d->ctxtlen;
+ d->stroff[pe_msgid]+=d->ctxtlen;
+ }
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgidbuf1, d->milen1);
+ d->stroff[pe_msgid]+=d->milen1;
+ d->strlist[d->curr[pe_msgid]].str.len+=d->milen1-1;
+ if(d->pllen1 != 0) {
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->pluralbuf1, d->pllen1);
+ d->strlist[d->curr[pe_msgid]].str.len+=d->pllen1;
+ d->stroff[pe_msgid]+=d->pllen1;
+ }
+ d->curr[pe_msgid]++;
+ }
+ if(d->milen2 != 0) {
+ if(!d->strlist[d->curr[pe_msgid]].str.off)
+ d->strlist[d->curr[pe_msgid]].str.off=d->stroff[pe_msgid];
+
+ if(d->ctxtlen != 0) {
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgctxtbuf, d->ctxtlen);
+ d->strlist[d->curr[pe_msgid]].str.len+=d->ctxtlen;
+ d->stroff[pe_msgid]+=d->ctxtlen;
+ }
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->msgidbuf2, d->milen2);
+ d->stroff[pe_msgid]+=d->milen2;
+ d->strlist[d->curr[pe_msgid]].str.len+=d->milen2-1;
+ if(d->pllen2 != 0) {
+ memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], d->pluralbuf2, d->pllen2);
+ d->strlist[d->curr[pe_msgid]].str.len+=d->pllen2;
+ d->stroff[pe_msgid]+=d->pllen2;
+ }
+ d->curr[pe_msgid]++;
+ }
- mslen1=mslen2=msc=0;
+ d->pllen2=d->pllen1=d->ctxtlen=d->milen1=d->milen2=0;
}
-static inline void dinvalid(struct callbackdata *d, struct po_info *info) {
- // previous group of msgid/str is invalid
- if(d->curr[pe_msgid] > 1 && d->translist[d->curr[pe_msgstr]-1].len == 0) {
- // set back the buffer len
+static inline void writestr(struct callbackdata *d, struct po_info *info) {
+ // msgid xx; msgstr ""; is widely happened, it's invalid
+ if(d->curr[pe_msgstr]
+ // we do not check the 1st msgid/str
+ && ((d->curr[pe_msgid] - d->curr[pe_msgstr]) == 0)
+ // in case curr[id] - curr[str] = 2(when sysdeps), .len == 0 is always true
+ && d->translist[d->curr[pe_msgstr]-1].len == 0) {
+ // str empty, invalid, set back everything, so they will be overrided
+
d->len[pe_msgid] -= d->strlist[d->curr[pe_msgstr]-1].str.len + 1;
- d->len[pe_msgstr] -= d->translist[d->curr[pe_msgstr]-1].len + 1;
- // set back the offset
+ d->strlist[d->curr[pe_msgstr]-1].str.len=0;
+ d->len[pe_msgstr]--;
d->stroff[pe_msgid] = d->strlist[d->curr[pe_msgstr]-1].str.off;
d->stroff[pe_msgstr] = d->translist[d->curr[pe_msgstr]-1].off;
-
- // kick the invalid out of counts
d->num[pe_msgid]--;
d->curr[pe_msgid]--;
- d->num[pe_msgstr] -= d->translist[d->curr[pe_msgstr]-1].len + 1;
- d->curr[pe_msgstr] -= d->translist[d->curr[pe_msgstr]-1].len + 1;
+ d->num[pe_msgstr]--;
+ d->curr[pe_msgstr]--;
+ d->mslen1=d->mslen2=d->msc=0;
+ return;
+ }
+
+ if(d->msc && d->msc <= info->nplurals) {
+ // plural <= nplurals is allowed
+ d->translist[d->curr[pe_msgstr]].len=d->mslen1-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->mslen1);
+ d->stroff[pe_msgstr]+=d->mslen1;
+ d->curr[pe_msgstr]++;
+
+ if(d->mslen2 != 0) {
+ d->translist[d->curr[pe_msgstr]].len=d->mslen2-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->mslen2);
+ d->stroff[pe_msgstr]+=d->mslen2;
+ d->curr[pe_msgstr]++;
+ }
+
+ d->mslen1=d->mslen2=d->msc=0;
}
- // plural <= nplurals is allowed
- if(msc && msc <= info->nplurals)
- write_plurals(d);
}
int process_line_callback(struct po_info* info, void* user) {
struct callbackdata *d = (struct callbackdata *) user;
- assert(info->type == pe_msgid || info->type == pe_msgstr || info->type == pe_plural);
+ 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(count != 1 && info->type == pe_ctxt) {
+ // except msgid, str, plural, all other types should not have sysdeps
+ abort();
+ }
+
+ d->priv_type = info->type;
+ d->priv_len = len;
d->len[info->type] += len +1;
break;
case pass_second:
sysdeps = sysdep_transform(info->text, info->textlen, &len, &count, 0);
- // we may met %<PRIu32> in plurals
- unsigned pc = d->curr[pe_msgid] - d->curr[pe_msgstr];
- if(pc == 2 && info->type == pe_plural) {
- // extract len and off infomation
- // bakup the content of msgid
- for(unsigned a=pc;a>0;a--) {
- idlen[a-1] = d->strlist[d->curr[pe_msgid]-a].str.len + 1;
- memcpy(&msgidbuf[idlen[a]], d->strbuffer[pe_msgid] + d->strlist[d->curr[pe_msgid]-a].str.off, idlen[a-1]);
-
- }
- // rollback the offset
- d->stroff[pe_msgid]= d->strlist[d->curr[pe_msgid]-pc].str.off;
- }
for(i=0;i<count;i++) {
l = strlen(sysdeps[i]);
if(info->type == pe_msgid) {
- // check for previous group of msgid/str
- dinvalid(d, info);
- d->strlist[d->curr[pe_msgid]].str.len=l;
- d->strlist[d->curr[pe_msgid]].str.off=d->stroff[pe_msgid];
- d->curr[pe_msgid]++;
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], sysdeps[i], l+1);
- d->stroff[pe_msgid]+=l+1;
+ // after str, it's msgid or msgctxt
+ writestr(d, info);
+ // just copy, it's written down when writemsg()
+ if(i==0) {
+ memcpy(d->msgidbuf1, sysdeps[i], l+1);
+ d->milen1 = l+1;
+ } else {
+ memcpy(d->msgidbuf2, sysdeps[i], l+1);
+ d->milen2 = l+1;
+ }
} else if(info->type == pe_plural) {
- if(pc != 2) {
- // should not count on msg_idplural
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], sysdeps[i], l+1);
- d->strlist[d->curr[pe_msgid]-1].str.len+=l+1;
- d->stroff[pe_msgid]+=l+1;
+ if(i==0) {
+ memcpy(d->pluralbuf1, sysdeps[i], l+1);
+ d->pllen1 = l+1;
} else {
- d->strlist[d->curr[pe_msgid]-(count-i)].str.len = idlen[(count-i)-1]-1 + l+1;
- d->strlist[d->curr[pe_msgid]-(count-i)].str.off = d->stroff[pe_msgid];
-
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], &msgidbuf[idlen[(count-i)]], idlen[(count-i)-1]);
- d->stroff[pe_msgid]+=idlen[(count-i)-1];
-
- memcpy(d->strbuffer[pe_msgid] + d->stroff[pe_msgid], sysdeps[i], l+1);
- d->stroff[pe_msgid]+=l+1;
+ memcpy(d->pluralbuf2, sysdeps[i], l+1);
+ d->pllen2 = l+1;
}
+ } else if(info->type == pe_ctxt) {
+ writestr(d, info);
+ d->ctxtlen = l+1;
+ memcpy(d->msgctxtbuf, sysdeps[i], l);
+ d->msgctxtbuf[l] = 0x4;//EOT
} else {
- if(pc == 1) {
- // all one-shot
- d->translist[d->curr[pe_msgstr]].len=l;
- d->translist[d->curr[pe_msgstr]].off=d->stroff[pe_msgstr];
- d->strlist[d->curr[pe_msgstr]].trans = &d->translist[d->curr[pe_msgstr]];
- d->curr[pe_msgstr]++;
- memcpy(d->strbuffer[pe_msgstr] + d->stroff[pe_msgstr], sysdeps[i], l+1);
- d->stroff[pe_msgstr]+=l+1;
- } else if(pc == 0 ) {
- d->translist[d->curr[pe_msgstr]-1].len+=l+1;
- memcpy(d->strbuffer[pe_msgstr] + d->stroff[pe_msgstr], sysdeps[i], l+1);
- d->stroff[pe_msgstr]+=l+1;
+ writemsg(d);
+ // just copy, it's written down when writestr()
+ if(i==0) {
+ memcpy(&d->msgstrbuf1[d->mslen1], sysdeps[i], l+1);
+ d->mslen1 += l+1;
+ d->msc++;
} else {
- if(i==0) {
- memcpy(&msgstr1[mslen1], sysdeps[i], l+1);
- mslen1 += l+1;
- } else {
- memcpy(&msgstr2[mslen2], sysdeps[i], l+1);
- mslen2 += l+1;
- msc++;
- }
- // time to write down
- if(msc == info->nplurals)
- write_plurals(d);
+ // sysdeps exist
+ memcpy(&d->msgstrbuf2[d->mslen2], sysdeps[i], l+1);
+ d->mslen2 += l+1;
}
}
}
@@ -332,15 +374,25 @@ int process(FILE *in, FILE *out) {
[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,
.out = out,
.pass = pass_first,
+ .ctxtlen = 0,
+ .pllen1 = 0,
+ .pllen2 = 0,
+ .milen1 = 0,
+ .milen2 = 0,
+ .mslen1 = 0,
+ .mslen2 = 0,
+ .msc = 0,
};
struct po_parser pb, *p = &pb;
@@ -360,8 +412,8 @@ int process(FILE *in, FILE *out) {
}
d.strlist = calloc(d.num[pe_msgid] * sizeof(struct strmap), 1);
- d.translist = calloc(d.num[pe_msgid] * sizeof(struct strtbl), 1);
- d.strbuffer[pe_msgid] = calloc(d.len[pe_msgid]+d.len[pe_plural], 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.strlist && d.translist && d.strbuffer[pe_msgid] && d.strbuffer[pe_msgstr]);
@@ -373,8 +425,7 @@ int process(FILE *in, FILE *out) {
poparser_feed_line(p, lp, sizeof(line));
}
poparser_finish(p);
- // check for previous group of msgid/str
- dinvalid(&d, &p->info);
+ writestr(&d, &p->info);
if(d.pass == pass_second) {
// calculate header fields from len and num arrays
@@ -398,10 +449,10 @@ int process(FILE *in, FILE *out) {
fwrite(&d.strlist[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.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);
}
- fwrite(d.strbuffer[pe_msgid], d.len[pe_msgid]+d.len[pe_plural], 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);
return 0;
diff --git a/src/poparser.c b/src/poparser.c
index 3e257eb..2d4bcef 100644
--- a/src/poparser.c
+++ b/src/poparser.c
@@ -30,6 +30,8 @@ static enum po_entry get_type_and_start(struct po_info *info, char* lp, char* en
result_type = pe_msgid;
else if ((x = strstarts(y, "id_plural")) && isspace(*x))
result_type = pe_plural;
+ else if ((x = strstarts(y, "ctxt")) && isspace(*x))
+ result_type = pe_ctxt;
else if ((x = strstarts(y, "str")) && (isspace(*x) ||
(x[0] == '[' && (x[1]-0x30) < info->nplurals && x[2] == ']' && (x += 3) && isspace(*x))))
result_type = pe_msgstr;
@@ -121,6 +123,7 @@ int poparser_feed_line(struct po_parser *p, char* line, size_t buflen) {
[pe_str] = {
[pe_str] = la_abort,
[pe_msgid] = la_abort,
+ [pe_ctxt] = la_abort,
[pe_plural] = la_abort,
[pe_msgstr] = la_abort,
[pe_invalid] = la_abort,
@@ -128,13 +131,23 @@ int poparser_feed_line(struct po_parser *p, char* line, size_t buflen) {
[pe_msgid] = {
[pe_str] = la_incr,
[pe_msgid] = la_abort,
+ [pe_ctxt] = la_abort,
[pe_plural] = la_proc,
[pe_msgstr] = la_proc,
[pe_invalid] = la_proc,
},
+ [pe_ctxt] = {
+ [pe_str] = la_incr,
+ [pe_msgid] = la_proc,
+ [pe_ctxt] = la_abort,
+ [pe_plural] = la_abort,
+ [pe_msgstr] = la_abort,
+ [pe_invalid] = la_proc,
+ },
[pe_plural] = {
[pe_str] = la_incr,
[pe_msgid] = la_abort,
+ [pe_ctxt] = la_abort,
[pe_plural] = la_abort,
[pe_msgstr] = la_proc,
[pe_invalid] = la_proc,
@@ -142,14 +155,16 @@ int poparser_feed_line(struct po_parser *p, char* line, size_t buflen) {
[pe_msgstr] = {
[pe_str] = la_incr,
[pe_msgid] = la_proc,
+ [pe_ctxt] = la_abort,
[pe_plural] = la_abort,
[pe_msgstr] = la_proc,
[pe_invalid] = la_proc,
},
[pe_invalid] = {
- [pe_str] = la_nop, // this can happen when we have msgstr[2] "" ... "foo", since we only parse msgstr[0] and [1]
+ [pe_str] = la_abort,
[pe_msgid] = la_incr,
- [pe_plural] = la_abort,
+ [pe_ctxt] = la_incr,
+ [pe_plural] = la_incr,
[pe_msgstr] = la_incr,
[pe_invalid] = la_nop,
},
@@ -159,16 +174,17 @@ int poparser_feed_line(struct po_parser *p, char* line, size_t buflen) {
type = get_type_and_start(&p->info, line, line + buflen, &strstart);
if(fuzzymark) {
+ if(type == pe_ctxt && fuzzymark == 1) fuzzymark--;
if(type == pe_msgid) fuzzymark--;
if(fuzzymark > 0) return 0;
}
switch(action_tbl[p->prev_type][type]) {
case la_incr:
- assert(type == pe_msgid || type == pe_msgstr || type == pe_str || type == pe_plural);
+ assert(type == pe_msgid || type == pe_msgstr || type == pe_str || type == pe_plural || pe_ctxt);
p->curr_len += get_length_and_convert(&p->info, line + strstart, line + buflen, convbuf + p->curr_len, convbuflen - p->curr_len);
break;
case la_proc:
- assert(p->prev_type == pe_msgid || p->prev_type == pe_msgstr || p->prev_type == pe_plural);
+ assert(p->prev_type == pe_msgid || p->prev_type == pe_msgstr || p->prev_type == pe_plural || p->prev_type == pe_ctxt);
p->info.text = convbuf;
p->info.textlen = p->curr_len;
p->info.type = p->prev_type;
diff --git a/src/poparser.h b/src/poparser.h
index 0e2515b..dfe6107 100644
--- a/src/poparser.h
+++ b/src/poparser.h
@@ -5,6 +5,7 @@
enum po_entry {
pe_msgid = 0,
pe_plural,
+ pe_ctxt,
pe_msgstr,
pe_maxstr,
pe_str = pe_maxstr,