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