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 #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 = xstrdup(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 } 236