|
|
1.1 root 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: #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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.