xref: /rk3399_rockchip-uboot/scripts/kconfig/kxgettext.c (revision e82abaeb7f2a0833fccf90460c48b9f2100258f8)
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