Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / 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                 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         char*            file;
67         int              lineno;
68 };
69
70 static struct file_line *file_line__new(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
93 static struct message *message__new(const char *msg, char *option, char *file, int lineno)
94 {
95         struct message *self = malloc(sizeof(*self));
96
97         if (self == NULL)
98                 goto out;
99
100         self->files = file_line__new(file, lineno);
101         if (self->files == NULL)
102                 goto out_fail;
103
104         self->msg = strdup(msg);
105         if (self->msg == NULL)
106                 goto out_fail_msg;
107
108         self->option = option;
109         self->next = NULL;
110 out:
111         return self;
112 out_fail_msg:
113         free(self->files);
114 out_fail:
115         free(self);
116         self = NULL;
117         goto out;
118 }
119
120 static struct message *mesage__find(const char *msg)
121 {
122         struct message *m = message__list;
123
124         while (m != NULL) {
125                 if (strcmp(m->msg, msg) == 0)
126                         break;
127                 m = m->next;
128         }
129
130         return m;
131 }
132
133 static int message__add_file_line(struct message *self, char *file, int lineno)
134 {
135         int rc = -1;
136         struct file_line *fl = file_line__new(file, lineno);
137
138         if (fl == NULL)
139                 goto out;
140
141         fl->next    = self->files;
142         self->files = fl;
143         rc = 0;
144 out:
145         return rc;
146 }
147
148 static int message__add(const char *msg, char *option, char *file, int lineno)
149 {
150         int rc = 0;
151         char bf[16384];
152         char *escaped = escape(msg, bf, sizeof(bf));
153         struct message *m = mesage__find(escaped);
154
155         if (m != NULL)
156                 rc = message__add_file_line(m, file, lineno);
157         else {
158                 m = message__new(escaped, option, file, lineno);
159
160                 if (m != NULL) {
161                         m->next       = message__list;
162                         message__list = m;
163                 } else
164                         rc = -1;
165         }
166         return rc;
167 }
168
169 static void menu_build_message_list(struct menu *menu)
170 {
171         struct menu *child;
172
173         message__add(menu_get_prompt(menu), NULL,
174                      menu->file == NULL ? "Root Menu" : menu->file->name,
175                      menu->lineno);
176
177         if (menu->sym != NULL && menu_has_help(menu))
178                 message__add(menu_get_help(menu), menu->sym->name,
179                              menu->file == NULL ? "Root Menu" : menu->file->name,
180                              menu->lineno);
181
182         for (child = menu->list; child != NULL; child = child->next)
183                 if (child->prompt != NULL)
184                         menu_build_message_list(child);
185 }
186
187 static void message__print_file_lineno(struct message *self)
188 {
189         struct file_line *fl = self->files;
190
191         putchar('\n');
192         if (self->option != NULL)
193                 printf("# %s:00000\n", self->option);
194
195         printf("#: %s:%d", fl->file, fl->lineno);
196         fl = fl->next;
197
198         while (fl != NULL) {
199                 printf(", %s:%d", fl->file, fl->lineno);
200                 fl = fl->next;
201         }
202
203         putchar('\n');
204 }
205
206 static void message__print_gettext_msgid_msgstr(struct message *self)
207 {
208         message__print_file_lineno(self);
209
210         printf("msgid %s\n"
211                "msgstr \"\"\n", self->msg);
212 }
213
214 static void menu__xgettext(void)
215 {
216         struct message *m = message__list;
217
218         while (m != NULL) {
219                 /* skip empty lines ("") */
220                 if (strlen(m->msg) > sizeof("\"\""))
221                         message__print_gettext_msgid_msgstr(m);
222                 m = m->next;
223         }
224 }
225
226 int main(int ac, char **av)
227 {
228         conf_parse(av[1]);
229
230         menu_build_message_list(menu_get_root_menu(NULL));
231         menu__xgettext();
232         return 0;
233 }