kconfig/streamline-config.pl: Simplify backslash line concatination
[pandora-kernel.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 #include "lkc.h"
11
12 static char *escape(const char* text, char *bf, int len)
13 {
14         char *bfp = bf;
15         int multiline = strchr(text, '\n') != NULL;
16         int eol = 0;
17         int textlen = strlen(text);
18
19         if ((textlen > 0) && (text[textlen-1] == '\n'))
20                 eol = 1;
21
22         *bfp++ = '"';
23         --len;
24
25         if (multiline) {
26                 *bfp++ = '"';
27                 *bfp++ = '\n';
28                 *bfp++ = '"';
29                 len -= 3;
30         }
31
32         while (*text != '\0' && len > 1) {
33                 if (*text == '"')
34                         *bfp++ = '\\';
35                 else if (*text == '\n') {
36                         *bfp++ = '\\';
37                         *bfp++ = 'n';
38                         *bfp++ = '"';
39                         *bfp++ = '\n';
40                         *bfp++ = '"';
41                         len -= 5;
42                         ++text;
43                         goto next;
44                 }
45                 else if (*text == '\\') {
46                         *bfp++ = '\\';
47                         len--;
48                 }
49                 *bfp++ = *text++;
50 next:
51                 --len;
52         }
53
54         if (multiline && eol)
55                 bfp -= 3;
56
57         *bfp++ = '"';
58         *bfp = '\0';
59
60         return bf;
61 }
62
63 struct file_line {
64         struct file_line *next;
65         const char *file;
66         int lineno;
67 };
68
69 static struct file_line *file_line__new(const char *file, int lineno)
70 {
71         struct file_line *self = malloc(sizeof(*self));
72
73         if (self == NULL)
74                 goto out;
75
76         self->file   = file;
77         self->lineno = lineno;
78         self->next   = NULL;
79 out:
80         return self;
81 }
82
83 struct message {
84         const char       *msg;
85         const char       *option;
86         struct message   *next;
87         struct file_line *files;
88 };
89
90 static struct message *message__list;
91
92 static struct message *message__new(const char *msg, char *option,
93                                     const 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, const char *file,
134                                   int lineno)
135 {
136         int rc = -1;
137         struct file_line *fl = file_line__new(file, lineno);
138
139         if (fl == NULL)
140                 goto out;
141
142         fl->next    = self->files;
143         self->files = fl;
144         rc = 0;
145 out:
146         return rc;
147 }
148
149 static int message__add(const char *msg, char *option, const char *file,
150                         int lineno)
151 {
152         int rc = 0;
153         char bf[16384];
154         char *escaped = escape(msg, bf, sizeof(bf));
155         struct message *m = mesage__find(escaped);
156
157         if (m != NULL)
158                 rc = message__add_file_line(m, file, lineno);
159         else {
160                 m = message__new(escaped, option, file, lineno);
161
162                 if (m != NULL) {
163                         m->next       = message__list;
164                         message__list = m;
165                 } else
166                         rc = -1;
167         }
168         return rc;
169 }
170
171 static void menu_build_message_list(struct menu *menu)
172 {
173         struct menu *child;
174
175         message__add(menu_get_prompt(menu), NULL,
176                      menu->file == NULL ? "Root Menu" : menu->file->name,
177                      menu->lineno);
178
179         if (menu->sym != NULL && menu_has_help(menu))
180                 message__add(menu_get_help(menu), menu->sym->name,
181                              menu->file == NULL ? "Root Menu" : menu->file->name,
182                              menu->lineno);
183
184         for (child = menu->list; child != NULL; child = child->next)
185                 if (child->prompt != NULL)
186                         menu_build_message_list(child);
187 }
188
189 static void message__print_file_lineno(struct message *self)
190 {
191         struct file_line *fl = self->files;
192
193         putchar('\n');
194         if (self->option != NULL)
195                 printf("# %s:00000\n", self->option);
196
197         printf("#: %s:%d", fl->file, fl->lineno);
198         fl = fl->next;
199
200         while (fl != NULL) {
201                 printf(", %s:%d", fl->file, fl->lineno);
202                 fl = fl->next;
203         }
204
205         putchar('\n');
206 }
207
208 static void message__print_gettext_msgid_msgstr(struct message *self)
209 {
210         message__print_file_lineno(self);
211
212         printf("msgid %s\n"
213                "msgstr \"\"\n", self->msg);
214 }
215
216 static void menu__xgettext(void)
217 {
218         struct message *m = message__list;
219
220         while (m != NULL) {
221                 /* skip empty lines ("") */
222                 if (strlen(m->msg) > sizeof("\"\""))
223                         message__print_gettext_msgid_msgstr(m);
224                 m = m->next;
225         }
226 }
227
228 int main(int ac, char **av)
229 {
230         conf_parse(av[1]);
231
232         menu_build_message_list(menu_get_root_menu(NULL));
233         menu__xgettext();
234         return 0;
235 }