Build system overhauled to use Kbuild (XCC)
[akaros.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         const char *file;
67         int lineno;
68 };
69
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
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
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
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
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
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
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
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
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
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 }