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