Home | History | Annotate | Download | only in kconfig
      1 /*
      2  * Arnaldo Carvalho de Melo <acme (at) 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