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