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