10a9064fbSMasahiro Yamada /*
20a9064fbSMasahiro Yamada * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2005
30a9064fbSMasahiro Yamada *
40a9064fbSMasahiro Yamada * Released under the terms of the GNU GPL v2.0
50a9064fbSMasahiro Yamada */
60a9064fbSMasahiro Yamada
70a9064fbSMasahiro Yamada #include <stdlib.h>
80a9064fbSMasahiro Yamada #include <string.h>
90a9064fbSMasahiro Yamada
100a9064fbSMasahiro Yamada #include "lkc.h"
110a9064fbSMasahiro Yamada
escape(const char * text,char * bf,int len)120a9064fbSMasahiro Yamada static char *escape(const char* text, char *bf, int len)
130a9064fbSMasahiro Yamada {
140a9064fbSMasahiro Yamada char *bfp = bf;
150a9064fbSMasahiro Yamada int multiline = strchr(text, '\n') != NULL;
160a9064fbSMasahiro Yamada int eol = 0;
170a9064fbSMasahiro Yamada int textlen = strlen(text);
180a9064fbSMasahiro Yamada
190a9064fbSMasahiro Yamada if ((textlen > 0) && (text[textlen-1] == '\n'))
200a9064fbSMasahiro Yamada eol = 1;
210a9064fbSMasahiro Yamada
220a9064fbSMasahiro Yamada *bfp++ = '"';
230a9064fbSMasahiro Yamada --len;
240a9064fbSMasahiro Yamada
250a9064fbSMasahiro Yamada if (multiline) {
260a9064fbSMasahiro Yamada *bfp++ = '"';
270a9064fbSMasahiro Yamada *bfp++ = '\n';
280a9064fbSMasahiro Yamada *bfp++ = '"';
290a9064fbSMasahiro Yamada len -= 3;
300a9064fbSMasahiro Yamada }
310a9064fbSMasahiro Yamada
320a9064fbSMasahiro Yamada while (*text != '\0' && len > 1) {
330a9064fbSMasahiro Yamada if (*text == '"')
340a9064fbSMasahiro Yamada *bfp++ = '\\';
350a9064fbSMasahiro Yamada else if (*text == '\n') {
360a9064fbSMasahiro Yamada *bfp++ = '\\';
370a9064fbSMasahiro Yamada *bfp++ = 'n';
380a9064fbSMasahiro Yamada *bfp++ = '"';
390a9064fbSMasahiro Yamada *bfp++ = '\n';
400a9064fbSMasahiro Yamada *bfp++ = '"';
410a9064fbSMasahiro Yamada len -= 5;
420a9064fbSMasahiro Yamada ++text;
430a9064fbSMasahiro Yamada goto next;
440a9064fbSMasahiro Yamada }
450a9064fbSMasahiro Yamada else if (*text == '\\') {
460a9064fbSMasahiro Yamada *bfp++ = '\\';
470a9064fbSMasahiro Yamada len--;
480a9064fbSMasahiro Yamada }
490a9064fbSMasahiro Yamada *bfp++ = *text++;
500a9064fbSMasahiro Yamada next:
510a9064fbSMasahiro Yamada --len;
520a9064fbSMasahiro Yamada }
530a9064fbSMasahiro Yamada
540a9064fbSMasahiro Yamada if (multiline && eol)
550a9064fbSMasahiro Yamada bfp -= 3;
560a9064fbSMasahiro Yamada
570a9064fbSMasahiro Yamada *bfp++ = '"';
580a9064fbSMasahiro Yamada *bfp = '\0';
590a9064fbSMasahiro Yamada
600a9064fbSMasahiro Yamada return bf;
610a9064fbSMasahiro Yamada }
620a9064fbSMasahiro Yamada
630a9064fbSMasahiro Yamada struct file_line {
640a9064fbSMasahiro Yamada struct file_line *next;
650a9064fbSMasahiro Yamada const char *file;
660a9064fbSMasahiro Yamada int lineno;
670a9064fbSMasahiro Yamada };
680a9064fbSMasahiro Yamada
file_line__new(const char * file,int lineno)690a9064fbSMasahiro Yamada static struct file_line *file_line__new(const char *file, int lineno)
700a9064fbSMasahiro Yamada {
710a9064fbSMasahiro Yamada struct file_line *self = malloc(sizeof(*self));
720a9064fbSMasahiro Yamada
730a9064fbSMasahiro Yamada if (self == NULL)
740a9064fbSMasahiro Yamada goto out;
750a9064fbSMasahiro Yamada
760a9064fbSMasahiro Yamada self->file = file;
770a9064fbSMasahiro Yamada self->lineno = lineno;
780a9064fbSMasahiro Yamada self->next = NULL;
790a9064fbSMasahiro Yamada out:
800a9064fbSMasahiro Yamada return self;
810a9064fbSMasahiro Yamada }
820a9064fbSMasahiro Yamada
830a9064fbSMasahiro Yamada struct message {
840a9064fbSMasahiro Yamada const char *msg;
850a9064fbSMasahiro Yamada const char *option;
860a9064fbSMasahiro Yamada struct message *next;
870a9064fbSMasahiro Yamada struct file_line *files;
880a9064fbSMasahiro Yamada };
890a9064fbSMasahiro Yamada
900a9064fbSMasahiro Yamada static struct message *message__list;
910a9064fbSMasahiro Yamada
message__new(const char * msg,char * option,const char * file,int lineno)920a9064fbSMasahiro Yamada static struct message *message__new(const char *msg, char *option,
930a9064fbSMasahiro Yamada const char *file, int lineno)
940a9064fbSMasahiro Yamada {
950a9064fbSMasahiro Yamada struct message *self = malloc(sizeof(*self));
960a9064fbSMasahiro Yamada
970a9064fbSMasahiro Yamada if (self == NULL)
980a9064fbSMasahiro Yamada goto out;
990a9064fbSMasahiro Yamada
1000a9064fbSMasahiro Yamada self->files = file_line__new(file, lineno);
1010a9064fbSMasahiro Yamada if (self->files == NULL)
1020a9064fbSMasahiro Yamada goto out_fail;
1030a9064fbSMasahiro Yamada
104*e91610daSEugeniu Rosca self->msg = xstrdup(msg);
1050a9064fbSMasahiro Yamada if (self->msg == NULL)
1060a9064fbSMasahiro Yamada goto out_fail_msg;
1070a9064fbSMasahiro Yamada
1080a9064fbSMasahiro Yamada self->option = option;
1090a9064fbSMasahiro Yamada self->next = NULL;
1100a9064fbSMasahiro Yamada out:
1110a9064fbSMasahiro Yamada return self;
1120a9064fbSMasahiro Yamada out_fail_msg:
1130a9064fbSMasahiro Yamada free(self->files);
1140a9064fbSMasahiro Yamada out_fail:
1150a9064fbSMasahiro Yamada free(self);
1160a9064fbSMasahiro Yamada self = NULL;
1170a9064fbSMasahiro Yamada goto out;
1180a9064fbSMasahiro Yamada }
1190a9064fbSMasahiro Yamada
mesage__find(const char * msg)1200a9064fbSMasahiro Yamada static struct message *mesage__find(const char *msg)
1210a9064fbSMasahiro Yamada {
1220a9064fbSMasahiro Yamada struct message *m = message__list;
1230a9064fbSMasahiro Yamada
1240a9064fbSMasahiro Yamada while (m != NULL) {
1250a9064fbSMasahiro Yamada if (strcmp(m->msg, msg) == 0)
1260a9064fbSMasahiro Yamada break;
1270a9064fbSMasahiro Yamada m = m->next;
1280a9064fbSMasahiro Yamada }
1290a9064fbSMasahiro Yamada
1300a9064fbSMasahiro Yamada return m;
1310a9064fbSMasahiro Yamada }
1320a9064fbSMasahiro Yamada
message__add_file_line(struct message * self,const char * file,int lineno)1330a9064fbSMasahiro Yamada static int message__add_file_line(struct message *self, const char *file,
1340a9064fbSMasahiro Yamada int lineno)
1350a9064fbSMasahiro Yamada {
1360a9064fbSMasahiro Yamada int rc = -1;
1370a9064fbSMasahiro Yamada struct file_line *fl = file_line__new(file, lineno);
1380a9064fbSMasahiro Yamada
1390a9064fbSMasahiro Yamada if (fl == NULL)
1400a9064fbSMasahiro Yamada goto out;
1410a9064fbSMasahiro Yamada
1420a9064fbSMasahiro Yamada fl->next = self->files;
1430a9064fbSMasahiro Yamada self->files = fl;
1440a9064fbSMasahiro Yamada rc = 0;
1450a9064fbSMasahiro Yamada out:
1460a9064fbSMasahiro Yamada return rc;
1470a9064fbSMasahiro Yamada }
1480a9064fbSMasahiro Yamada
message__add(const char * msg,char * option,const char * file,int lineno)1490a9064fbSMasahiro Yamada static int message__add(const char *msg, char *option, const char *file,
1500a9064fbSMasahiro Yamada int lineno)
1510a9064fbSMasahiro Yamada {
1520a9064fbSMasahiro Yamada int rc = 0;
1530a9064fbSMasahiro Yamada char bf[16384];
1540a9064fbSMasahiro Yamada char *escaped = escape(msg, bf, sizeof(bf));
1550a9064fbSMasahiro Yamada struct message *m = mesage__find(escaped);
1560a9064fbSMasahiro Yamada
1570a9064fbSMasahiro Yamada if (m != NULL)
1580a9064fbSMasahiro Yamada rc = message__add_file_line(m, file, lineno);
1590a9064fbSMasahiro Yamada else {
1600a9064fbSMasahiro Yamada m = message__new(escaped, option, file, lineno);
1610a9064fbSMasahiro Yamada
1620a9064fbSMasahiro Yamada if (m != NULL) {
1630a9064fbSMasahiro Yamada m->next = message__list;
1640a9064fbSMasahiro Yamada message__list = m;
1650a9064fbSMasahiro Yamada } else
1660a9064fbSMasahiro Yamada rc = -1;
1670a9064fbSMasahiro Yamada }
1680a9064fbSMasahiro Yamada return rc;
1690a9064fbSMasahiro Yamada }
1700a9064fbSMasahiro Yamada
menu_build_message_list(struct menu * menu)1710a9064fbSMasahiro Yamada static void menu_build_message_list(struct menu *menu)
1720a9064fbSMasahiro Yamada {
1730a9064fbSMasahiro Yamada struct menu *child;
1740a9064fbSMasahiro Yamada
1750a9064fbSMasahiro Yamada message__add(menu_get_prompt(menu), NULL,
1760a9064fbSMasahiro Yamada menu->file == NULL ? "Root Menu" : menu->file->name,
1770a9064fbSMasahiro Yamada menu->lineno);
1780a9064fbSMasahiro Yamada
1790a9064fbSMasahiro Yamada if (menu->sym != NULL && menu_has_help(menu))
1800a9064fbSMasahiro Yamada message__add(menu_get_help(menu), menu->sym->name,
1810a9064fbSMasahiro Yamada menu->file == NULL ? "Root Menu" : menu->file->name,
1820a9064fbSMasahiro Yamada menu->lineno);
1830a9064fbSMasahiro Yamada
1840a9064fbSMasahiro Yamada for (child = menu->list; child != NULL; child = child->next)
1850a9064fbSMasahiro Yamada if (child->prompt != NULL)
1860a9064fbSMasahiro Yamada menu_build_message_list(child);
1870a9064fbSMasahiro Yamada }
1880a9064fbSMasahiro Yamada
message__print_file_lineno(struct message * self)1890a9064fbSMasahiro Yamada static void message__print_file_lineno(struct message *self)
1900a9064fbSMasahiro Yamada {
1910a9064fbSMasahiro Yamada struct file_line *fl = self->files;
1920a9064fbSMasahiro Yamada
1930a9064fbSMasahiro Yamada putchar('\n');
1940a9064fbSMasahiro Yamada if (self->option != NULL)
1950a9064fbSMasahiro Yamada printf("# %s:00000\n", self->option);
1960a9064fbSMasahiro Yamada
1970a9064fbSMasahiro Yamada printf("#: %s:%d", fl->file, fl->lineno);
1980a9064fbSMasahiro Yamada fl = fl->next;
1990a9064fbSMasahiro Yamada
2000a9064fbSMasahiro Yamada while (fl != NULL) {
2010a9064fbSMasahiro Yamada printf(", %s:%d", fl->file, fl->lineno);
2020a9064fbSMasahiro Yamada fl = fl->next;
2030a9064fbSMasahiro Yamada }
2040a9064fbSMasahiro Yamada
2050a9064fbSMasahiro Yamada putchar('\n');
2060a9064fbSMasahiro Yamada }
2070a9064fbSMasahiro Yamada
message__print_gettext_msgid_msgstr(struct message * self)2080a9064fbSMasahiro Yamada static void message__print_gettext_msgid_msgstr(struct message *self)
2090a9064fbSMasahiro Yamada {
2100a9064fbSMasahiro Yamada message__print_file_lineno(self);
2110a9064fbSMasahiro Yamada
2120a9064fbSMasahiro Yamada printf("msgid %s\n"
2130a9064fbSMasahiro Yamada "msgstr \"\"\n", self->msg);
2140a9064fbSMasahiro Yamada }
2150a9064fbSMasahiro Yamada
menu__xgettext(void)2160a9064fbSMasahiro Yamada static void menu__xgettext(void)
2170a9064fbSMasahiro Yamada {
2180a9064fbSMasahiro Yamada struct message *m = message__list;
2190a9064fbSMasahiro Yamada
2200a9064fbSMasahiro Yamada while (m != NULL) {
2210a9064fbSMasahiro Yamada /* skip empty lines ("") */
2220a9064fbSMasahiro Yamada if (strlen(m->msg) > sizeof("\"\""))
2230a9064fbSMasahiro Yamada message__print_gettext_msgid_msgstr(m);
2240a9064fbSMasahiro Yamada m = m->next;
2250a9064fbSMasahiro Yamada }
2260a9064fbSMasahiro Yamada }
2270a9064fbSMasahiro Yamada
main(int ac,char ** av)2280a9064fbSMasahiro Yamada int main(int ac, char **av)
2290a9064fbSMasahiro Yamada {
2300a9064fbSMasahiro Yamada conf_parse(av[1]);
2310a9064fbSMasahiro Yamada
2320a9064fbSMasahiro Yamada menu_build_message_list(menu_get_root_menu(NULL));
2330a9064fbSMasahiro Yamada menu__xgettext();
2340a9064fbSMasahiro Yamada return 0;
2350a9064fbSMasahiro Yamada }
236