Pull alexey-fixes into release branch
[linux-2.6] / scripts / kconfig / kxgettext.c
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
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                 *bfp++ = *text++;
47 next:
48                 --len;
49         }
50
51         if (multiline && eol)
52                 bfp -= 3;
53
54         *bfp++ = '"';
55         *bfp = '\0';
56
57         return bf;
58 }
59
60 struct file_line {
61         struct file_line *next;
62         char*            file;
63         int              lineno;
64 };
65
66 static struct file_line *file_line__new(char *file, int lineno)
67 {
68         struct file_line *self = malloc(sizeof(*self));
69
70         if (self == NULL)
71                 goto out;
72
73         self->file   = file;
74         self->lineno = lineno;
75         self->next   = NULL;
76 out:
77         return self;
78 }
79
80 struct message {
81         const char       *msg;
82         const char       *option;
83         struct message   *next;
84         struct file_line *files;
85 };
86
87 static struct message *message__list;
88
89 static struct message *message__new(const char *msg, char *option, char *file, int lineno)
90 {
91         struct message *self = malloc(sizeof(*self));
92
93         if (self == NULL)
94                 goto out;
95
96         self->files = file_line__new(file, lineno);
97         if (self->files == NULL)
98                 goto out_fail;
99
100         self->msg = strdup(msg);
101         if (self->msg == NULL)
102                 goto out_fail_msg;
103
104         self->option = option;
105         self->next = NULL;
106 out:
107         return self;
108 out_fail_msg:
109         free(self->files);
110 out_fail:
111         free(self);
112         self = NULL;
113         goto out;
114 }
115
116 static struct message *mesage__find(const char *msg)
117 {
118         struct message *m = message__list;
119
120         while (m != NULL) {
121                 if (strcmp(m->msg, msg) == 0)
122                         break;
123                 m = m->next;
124         }
125
126         return m;
127 }
128
129 static int message__add_file_line(struct message *self, char *file, int lineno)
130 {
131         int rc = -1;
132         struct file_line *fl = file_line__new(file, lineno);
133
134         if (fl == NULL)
135                 goto out;
136
137         fl->next    = self->files;
138         self->files = fl;
139         rc = 0;
140 out:
141         return rc;
142 }
143
144 static int message__add(const char *msg, char *option, char *file, int lineno)
145 {
146         int rc = 0;
147         char bf[16384];
148         char *escaped = escape(msg, bf, sizeof(bf));
149         struct message *m = mesage__find(escaped);
150
151         if (m != NULL)
152                 rc = message__add_file_line(m, file, lineno);
153         else {
154                 m = message__new(escaped, option, file, lineno);
155
156                 if (m != NULL) {
157                         m->next       = message__list;
158                         message__list = m;
159                 } else
160                         rc = -1;
161         }
162         return rc;
163 }
164
165 void menu_build_message_list(struct menu *menu)
166 {
167         struct menu *child;
168
169         message__add(menu_get_prompt(menu), NULL,
170                      menu->file == NULL ? "Root Menu" : menu->file->name,
171                      menu->lineno);
172
173         if (menu->sym != NULL && menu_has_help(menu))
174                 message__add(menu_get_help(menu), menu->sym->name,
175                              menu->file == NULL ? "Root Menu" : menu->file->name,
176                              menu->lineno);
177
178         for (child = menu->list; child != NULL; child = child->next)
179                 if (child->prompt != NULL)
180                         menu_build_message_list(child);
181 }
182
183 static void message__print_file_lineno(struct message *self)
184 {
185         struct file_line *fl = self->files;
186
187         putchar('\n');
188         if (self->option != NULL)
189                 printf("# %s:00000\n", self->option);
190
191         printf("#: %s:%d", fl->file, fl->lineno);
192         fl = fl->next;
193
194         while (fl != NULL) {
195                 printf(", %s:%d", fl->file, fl->lineno);
196                 fl = fl->next;
197         }
198
199         putchar('\n');
200 }
201
202 static void message__print_gettext_msgid_msgstr(struct message *self)
203 {
204         message__print_file_lineno(self);
205
206         printf("msgid %s\n"
207                "msgstr \"\"\n", self->msg);
208 }
209
210 void menu__xgettext(void)
211 {
212         struct message *m = message__list;
213
214         while (m != NULL) {
215                 /* skip empty lines ("") */
216                 if (strlen(m->msg) > sizeof("\"\""))
217                         message__print_gettext_msgid_msgstr(m);
218                 m = m->next;
219         }
220 }
221
222 int main(int ac, char **av)
223 {
224         conf_parse(av[1]);
225
226         menu_build_message_list(menu_get_root_menu(NULL));
227         menu__xgettext();
228         return 0;
229 }