1*0a9064fbSMasahiro Yamada /*
2*0a9064fbSMasahiro Yamada * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
3*0a9064fbSMasahiro Yamada *
4*0a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0
5*0a9064fbSMasahiro Yamada */
6*0a9064fbSMasahiro Yamada
7*0a9064fbSMasahiro Yamada #include <stdlib.h>
8*0a9064fbSMasahiro Yamada #include <string.h>
9*0a9064fbSMasahiro Yamada
10*0a9064fbSMasahiro Yamada #include "lkc.h"
11*0a9064fbSMasahiro Yamada
escape(const char * text,char * bf,int len)12*0a9064fbSMasahiro Yamada static char *escape(const char* text, char *bf, int len)
13*0a9064fbSMasahiro Yamada {
14*0a9064fbSMasahiro Yamada char *bfp = bf;
15*0a9064fbSMasahiro Yamada int multiline = strchr(text, '\n') != NULL;
16*0a9064fbSMasahiro Yamada int eol = 0;
17*0a9064fbSMasahiro Yamada int textlen = strlen(text);
18*0a9064fbSMasahiro Yamada
19*0a9064fbSMasahiro Yamada if ((textlen > 0) && (text[textlen-1] == '\n'))
20*0a9064fbSMasahiro Yamada eol = 1;
21*0a9064fbSMasahiro Yamada
22*0a9064fbSMasahiro Yamada *bfp++ = '"';
23*0a9064fbSMasahiro Yamada --len;
24*0a9064fbSMasahiro Yamada
25*0a9064fbSMasahiro Yamada if (multiline) {
26*0a9064fbSMasahiro Yamada *bfp++ = '"';
27*0a9064fbSMasahiro Yamada *bfp++ = '\n';
28*0a9064fbSMasahiro Yamada *bfp++ = '"';
29*0a9064fbSMasahiro Yamada len -= 3;
30*0a9064fbSMasahiro Yamada }
31*0a9064fbSMasahiro Yamada
32*0a9064fbSMasahiro Yamada while (*text != '\0' && len > 1) {
33*0a9064fbSMasahiro Yamada if (*text == '"')
34*0a9064fbSMasahiro Yamada *bfp++ = '\\';
35*0a9064fbSMasahiro Yamada else if (*text == '\n') {
36*0a9064fbSMasahiro Yamada *bfp++ = '\\';
37*0a9064fbSMasahiro Yamada *bfp++ = 'n';
38*0a9064fbSMasahiro Yamada *bfp++ = '"';
39*0a9064fbSMasahiro Yamada *bfp++ = '\n';
40*0a9064fbSMasahiro Yamada *bfp++ = '"';
41*0a9064fbSMasahiro Yamada len -= 5;
42*0a9064fbSMasahiro Yamada ++text;
43*0a9064fbSMasahiro Yamada goto next;
44*0a9064fbSMasahiro Yamada }
45*0a9064fbSMasahiro Yamada else if (*text == '\\') {
46*0a9064fbSMasahiro Yamada *bfp++ = '\\';
47*0a9064fbSMasahiro Yamada len--;
48*0a9064fbSMasahiro Yamada }
49*0a9064fbSMasahiro Yamada *bfp++ = *text++;
50*0a9064fbSMasahiro Yamada next:
51*0a9064fbSMasahiro Yamada --len;
52*0a9064fbSMasahiro Yamada }
53*0a9064fbSMasahiro Yamada
54*0a9064fbSMasahiro Yamada if (multiline && eol)
55*0a9064fbSMasahiro Yamada bfp -= 3;
56*0a9064fbSMasahiro Yamada
57*0a9064fbSMasahiro Yamada *bfp++ = '"';
58*0a9064fbSMasahiro Yamada *bfp = '\0';
59*0a9064fbSMasahiro Yamada
60*0a9064fbSMasahiro Yamada return bf;
61*0a9064fbSMasahiro Yamada }
62*0a9064fbSMasahiro Yamada
63*0a9064fbSMasahiro Yamada struct file_line {
64*0a9064fbSMasahiro Yamada struct file_line *next;
65*0a9064fbSMasahiro Yamada const char *file;
66*0a9064fbSMasahiro Yamada int lineno;
67*0a9064fbSMasahiro Yamada };
68*0a9064fbSMasahiro Yamada
file_line__new(const char * file,int lineno)69*0a9064fbSMasahiro Yamada static struct file_line *file_line__new(const char *file, int lineno)
70*0a9064fbSMasahiro Yamada {
71*0a9064fbSMasahiro Yamada struct file_line *self = malloc(sizeof(*self));
72*0a9064fbSMasahiro Yamada
73*0a9064fbSMasahiro Yamada if (self == NULL)
74*0a9064fbSMasahiro Yamada goto out;
75*0a9064fbSMasahiro Yamada
76*0a9064fbSMasahiro Yamada self->file = file;
77*0a9064fbSMasahiro Yamada self->lineno = lineno;
78*0a9064fbSMasahiro Yamada self->next = NULL;
79*0a9064fbSMasahiro Yamada out:
80*0a9064fbSMasahiro Yamada return self;
81*0a9064fbSMasahiro Yamada }
82*0a9064fbSMasahiro Yamada
83*0a9064fbSMasahiro Yamada struct message {
84*0a9064fbSMasahiro Yamada const char *msg;
85*0a9064fbSMasahiro Yamada const char *option;
86*0a9064fbSMasahiro Yamada struct message *next;
87*0a9064fbSMasahiro Yamada struct file_line *files;
88*0a9064fbSMasahiro Yamada };
89*0a9064fbSMasahiro Yamada
90*0a9064fbSMasahiro Yamada static struct message *message__list;
91*0a9064fbSMasahiro Yamada
message__new(const char * msg,char * option,const char * file,int lineno)92*0a9064fbSMasahiro Yamada static struct message *message__new(const char *msg, char *option,
93*0a9064fbSMasahiro Yamada const char *file, int lineno)
94*0a9064fbSMasahiro Yamada {
95*0a9064fbSMasahiro Yamada struct message *self = malloc(sizeof(*self));
96*0a9064fbSMasahiro Yamada
97*0a9064fbSMasahiro Yamada if (self == NULL)
98*0a9064fbSMasahiro Yamada goto out;
99*0a9064fbSMasahiro Yamada
100*0a9064fbSMasahiro Yamada self->files = file_line__new(file, lineno);
101*0a9064fbSMasahiro Yamada if (self->files == NULL)
102*0a9064fbSMasahiro Yamada goto out_fail;
103*0a9064fbSMasahiro Yamada
104*0a9064fbSMasahiro Yamada self->msg = strdup(msg);
105*0a9064fbSMasahiro Yamada if (self->msg == NULL)
106*0a9064fbSMasahiro Yamada goto out_fail_msg;
107*0a9064fbSMasahiro Yamada
108*0a9064fbSMasahiro Yamada self->option = option;
109*0a9064fbSMasahiro Yamada self->next = NULL;
110*0a9064fbSMasahiro Yamada out:
111*0a9064fbSMasahiro Yamada return self;
112*0a9064fbSMasahiro Yamada out_fail_msg:
113*0a9064fbSMasahiro Yamada free(self->files);
114*0a9064fbSMasahiro Yamada out_fail:
115*0a9064fbSMasahiro Yamada free(self);
116*0a9064fbSMasahiro Yamada self = NULL;
117*0a9064fbSMasahiro Yamada goto out;
118*0a9064fbSMasahiro Yamada }
119*0a9064fbSMasahiro Yamada
mesage__find(const char * msg)120*0a9064fbSMasahiro Yamada static struct message *mesage__find(const char *msg)
121*0a9064fbSMasahiro Yamada {
122*0a9064fbSMasahiro Yamada struct message *m = message__list;
123*0a9064fbSMasahiro Yamada
124*0a9064fbSMasahiro Yamada while (m != NULL) {
125*0a9064fbSMasahiro Yamada if (strcmp(m->msg, msg) == 0)
126*0a9064fbSMasahiro Yamada break;
127*0a9064fbSMasahiro Yamada m = m->next;
128*0a9064fbSMasahiro Yamada }
129*0a9064fbSMasahiro Yamada
130*0a9064fbSMasahiro Yamada return m;
131*0a9064fbSMasahiro Yamada }
132*0a9064fbSMasahiro Yamada
message__add_file_line(struct message * self,const char * file,int lineno)133*0a9064fbSMasahiro Yamada static int message__add_file_line(struct message *self, const char *file,
134*0a9064fbSMasahiro Yamada int lineno)
135*0a9064fbSMasahiro Yamada {
136*0a9064fbSMasahiro Yamada int rc = -1;
137*0a9064fbSMasahiro Yamada struct file_line *fl = file_line__new(file, lineno);
138*0a9064fbSMasahiro Yamada
139*0a9064fbSMasahiro Yamada if (fl == NULL)
140*0a9064fbSMasahiro Yamada goto out;
141*0a9064fbSMasahiro Yamada
142*0a9064fbSMasahiro Yamada fl->next = self->files;
143*0a9064fbSMasahiro Yamada self->files = fl;
144*0a9064fbSMasahiro Yamada rc = 0;
145*0a9064fbSMasahiro Yamada out:
146*0a9064fbSMasahiro Yamada return rc;
147*0a9064fbSMasahiro Yamada }
148*0a9064fbSMasahiro Yamada
message__add(const char * msg,char * option,const char * file,int lineno)149*0a9064fbSMasahiro Yamada static int message__add(const char *msg, char *option, const char *file,
150*0a9064fbSMasahiro Yamada int lineno)
151*0a9064fbSMasahiro Yamada {
152*0a9064fbSMasahiro Yamada int rc = 0;
153*0a9064fbSMasahiro Yamada char bf[16384];
154*0a9064fbSMasahiro Yamada char *escaped = escape(msg, bf, sizeof(bf));
155*0a9064fbSMasahiro Yamada struct message *m = mesage__find(escaped);
156*0a9064fbSMasahiro Yamada
157*0a9064fbSMasahiro Yamada if (m != NULL)
158*0a9064fbSMasahiro Yamada rc = message__add_file_line(m, file, lineno);
159*0a9064fbSMasahiro Yamada else {
160*0a9064fbSMasahiro Yamada m = message__new(escaped, option, file, lineno);
161*0a9064fbSMasahiro Yamada
162*0a9064fbSMasahiro Yamada if (m != NULL) {
163*0a9064fbSMasahiro Yamada m->next = message__list;
164*0a9064fbSMasahiro Yamada message__list = m;
165*0a9064fbSMasahiro Yamada } else
166*0a9064fbSMasahiro Yamada rc = -1;
167*0a9064fbSMasahiro Yamada }
168*0a9064fbSMasahiro Yamada return rc;
169*0a9064fbSMasahiro Yamada }
170*0a9064fbSMasahiro Yamada
menu_build_message_list(struct menu * menu)171*0a9064fbSMasahiro Yamada static void menu_build_message_list(struct menu *menu)
172*0a9064fbSMasahiro Yamada {
173*0a9064fbSMasahiro Yamada struct menu *child;
174*0a9064fbSMasahiro Yamada
175*0a9064fbSMasahiro Yamada message__add(menu_get_prompt(menu), NULL,
176*0a9064fbSMasahiro Yamada menu->file == NULL ? "Root Menu" : menu->file->name,
177*0a9064fbSMasahiro Yamada menu->lineno);
178*0a9064fbSMasahiro Yamada
179*0a9064fbSMasahiro Yamada if (menu->sym != NULL && menu_has_help(menu))
180*0a9064fbSMasahiro Yamada message__add(menu_get_help(menu), menu->sym->name,
181*0a9064fbSMasahiro Yamada menu->file == NULL ? "Root Menu" : menu->file->name,
182*0a9064fbSMasahiro Yamada menu->lineno);
183*0a9064fbSMasahiro Yamada
184*0a9064fbSMasahiro Yamada for (child = menu->list; child != NULL; child = child->next)
185*0a9064fbSMasahiro Yamada if (child->prompt != NULL)
186*0a9064fbSMasahiro Yamada menu_build_message_list(child);
187*0a9064fbSMasahiro Yamada }
188*0a9064fbSMasahiro Yamada
message__print_file_lineno(struct message * self)189*0a9064fbSMasahiro Yamada static void message__print_file_lineno(struct message *self)
190*0a9064fbSMasahiro Yamada {
191*0a9064fbSMasahiro Yamada struct file_line *fl = self->files;
192*0a9064fbSMasahiro Yamada
193*0a9064fbSMasahiro Yamada putchar('\n');
194*0a9064fbSMasahiro Yamada if (self->option != NULL)
195*0a9064fbSMasahiro Yamada printf("# %s:00000\n", self->option);
196*0a9064fbSMasahiro Yamada
197*0a9064fbSMasahiro Yamada printf("#: %s:%d", fl->file, fl->lineno);
198*0a9064fbSMasahiro Yamada fl = fl->next;
199*0a9064fbSMasahiro Yamada
200*0a9064fbSMasahiro Yamada while (fl != NULL) {
201*0a9064fbSMasahiro Yamada printf(", %s:%d", fl->file, fl->lineno);
202*0a9064fbSMasahiro Yamada fl = fl->next;
203*0a9064fbSMasahiro Yamada }
204*0a9064fbSMasahiro Yamada
205*0a9064fbSMasahiro Yamada putchar('\n');
206*0a9064fbSMasahiro Yamada }
207*0a9064fbSMasahiro Yamada
message__print_gettext_msgid_msgstr(struct message * self)208*0a9064fbSMasahiro Yamada static void message__print_gettext_msgid_msgstr(struct message *self)
209*0a9064fbSMasahiro Yamada {
210*0a9064fbSMasahiro Yamada message__print_file_lineno(self);
211*0a9064fbSMasahiro Yamada
212*0a9064fbSMasahiro Yamada printf("msgid %s\n"
213*0a9064fbSMasahiro Yamada "msgstr \"\"\n", self->msg);
214*0a9064fbSMasahiro Yamada }
215*0a9064fbSMasahiro Yamada
menu__xgettext(void)216*0a9064fbSMasahiro Yamada static void menu__xgettext(void)
217*0a9064fbSMasahiro Yamada {
218*0a9064fbSMasahiro Yamada struct message *m = message__list;
219*0a9064fbSMasahiro Yamada
220*0a9064fbSMasahiro Yamada while (m != NULL) {
221*0a9064fbSMasahiro Yamada /* skip empty lines ("") */
222*0a9064fbSMasahiro Yamada if (strlen(m->msg) > sizeof("\"\""))
223*0a9064fbSMasahiro Yamada message__print_gettext_msgid_msgstr(m);
224*0a9064fbSMasahiro Yamada m = m->next;
225*0a9064fbSMasahiro Yamada }
226*0a9064fbSMasahiro Yamada }
227*0a9064fbSMasahiro Yamada
main(int ac,char ** av)228*0a9064fbSMasahiro Yamada int main(int ac, char **av)
229*0a9064fbSMasahiro Yamada {
230*0a9064fbSMasahiro Yamada conf_parse(av[1]);
231*0a9064fbSMasahiro Yamada
232*0a9064fbSMasahiro Yamada menu_build_message_list(menu_get_root_menu(NULL));
233*0a9064fbSMasahiro Yamada menu__xgettext();
234*0a9064fbSMasahiro Yamada return 0;
235*0a9064fbSMasahiro Yamada }
236