linux/scripts/kconfig/kxgettext.c
<<
>>
Prefs
   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        const char *file;
  67        int lineno;
  68};
  69
  70static struct file_line *file_line__new(const 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,
  94                                    const char *file, int lineno)
  95{
  96        struct message *self = malloc(sizeof(*self));
  97
  98        if (self == NULL)
  99                goto out;
 100
 101        self->files = file_line__new(file, lineno);
 102        if (self->files == NULL)
 103                goto out_fail;
 104
 105        self->msg = strdup(msg);
 106        if (self->msg == NULL)
 107                goto out_fail_msg;
 108
 109        self->option = option;
 110        self->next = NULL;
 111out:
 112        return self;
 113out_fail_msg:
 114        free(self->files);
 115out_fail:
 116        free(self);
 117        self = NULL;
 118        goto out;
 119}
 120
 121static struct message *mesage__find(const char *msg)
 122{
 123        struct message *m = message__list;
 124
 125        while (m != NULL) {
 126                if (strcmp(m->msg, msg) == 0)
 127                        break;
 128                m = m->next;
 129        }
 130
 131        return m;
 132}
 133
 134static int message__add_file_line(struct message *self, const char *file,
 135                                  int lineno)
 136{
 137        int rc = -1;
 138        struct file_line *fl = file_line__new(file, lineno);
 139
 140        if (fl == NULL)
 141                goto out;
 142
 143        fl->next    = self->files;
 144        self->files = fl;
 145        rc = 0;
 146out:
 147        return rc;
 148}
 149
 150static int message__add(const char *msg, char *option, const char *file,
 151                        int lineno)
 152{
 153        int rc = 0;
 154        char bf[16384];
 155        char *escaped = escape(msg, bf, sizeof(bf));
 156        struct message *m = mesage__find(escaped);
 157
 158        if (m != NULL)
 159                rc = message__add_file_line(m, file, lineno);
 160        else {
 161                m = message__new(escaped, option, file, lineno);
 162
 163                if (m != NULL) {
 164                        m->next       = message__list;
 165                        message__list = m;
 166                } else
 167                        rc = -1;
 168        }
 169        return rc;
 170}
 171
 172static void menu_build_message_list(struct menu *menu)
 173{
 174        struct menu *child;
 175
 176        message__add(menu_get_prompt(menu), NULL,
 177                     menu->file == NULL ? "Root Menu" : menu->file->name,
 178                     menu->lineno);
 179
 180        if (menu->sym != NULL && menu_has_help(menu))
 181                message__add(menu_get_help(menu), menu->sym->name,
 182                             menu->file == NULL ? "Root Menu" : menu->file->name,
 183                             menu->lineno);
 184
 185        for (child = menu->list; child != NULL; child = child->next)
 186                if (child->prompt != NULL)
 187                        menu_build_message_list(child);
 188}
 189
 190static void message__print_file_lineno(struct message *self)
 191{
 192        struct file_line *fl = self->files;
 193
 194        putchar('\n');
 195        if (self->option != NULL)
 196                printf("# %s:00000\n", self->option);
 197
 198        printf("#: %s:%d", fl->file, fl->lineno);
 199        fl = fl->next;
 200
 201        while (fl != NULL) {
 202                printf(", %s:%d", fl->file, fl->lineno);
 203                fl = fl->next;
 204        }
 205
 206        putchar('\n');
 207}
 208
 209static void message__print_gettext_msgid_msgstr(struct message *self)
 210{
 211        message__print_file_lineno(self);
 212
 213        printf("msgid %s\n"
 214               "msgstr \"\"\n", self->msg);
 215}
 216
 217static void menu__xgettext(void)
 218{
 219        struct message *m = message__list;
 220
 221        while (m != NULL) {
 222                /* skip empty lines ("") */
 223                if (strlen(m->msg) > sizeof("\"\""))
 224                        message__print_gettext_msgid_msgstr(m);
 225                m = m->next;
 226        }
 227}
 228
 229int main(int ac, char **av)
 230{
 231        conf_parse(av[1]);
 232
 233        menu_build_message_list(menu_get_root_menu(NULL));
 234        menu__xgettext();
 235        return 0;
 236}
 237