Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
kxgettext.c
Go to the documentation of this file.
1 /*
2  * Arnaldo Carvalho de Melo <[email protected]>, 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 }