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#include "lkc.h"
  11
  12static 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++;
  50next:
  51                --len;
  52        }
  53
  54        if (multiline && eol)
  55                bfp -= 3;
  56
  57        *bfp++ = '"';
  58        *bfp = '\0';
  59
  60        return bf;
  61}
  62
  63struct file_line {
  64        struct file_line *next;
  65        const char *file;
  66        int lineno;
  67};
  68
  69static 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;
  79out:
  80        return self;
  81}
  82
  83struct message {
  84        const char       *msg;
  85        const char       *option;
  86        struct message   *next;
  87        struct file_line *files;
  88};
  89
  90static struct message *message__list;
  91
  92static 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 = 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, 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;
 145out:
 146        return rc;
 147}
 148
 149static 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
 171static 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
 189static 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
 208static 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
 216static 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
 228int 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