busybox/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                *bfp++ = *text++;
  47next:
  48                --len;
  49        }
  50
  51        if (multiline && eol)
  52                bfp -= 3;
  53
  54        *bfp++ = '"';
  55        *bfp = '\0';
  56
  57        return bf;
  58}
  59
  60struct file_line {
  61        struct file_line *next;
  62        char*            file;
  63        int              lineno;
  64};
  65
  66static struct file_line *file_line__new(char *file, int lineno)
  67{
  68        struct file_line *self = malloc(sizeof(*self));
  69
  70        if (self == NULL)
  71                goto out;
  72
  73        self->file   = file;
  74        self->lineno = lineno;
  75        self->next   = NULL;
  76out:
  77        return self;
  78}
  79
  80struct message {
  81        const char       *msg;
  82        const char       *option;
  83        struct message   *next;
  84        struct file_line *files;
  85};
  86
  87static struct message *message__list;
  88
  89static struct message *message__new(const char *msg, char *option, char *file, int lineno)
  90{
  91        struct message *self = malloc(sizeof(*self));
  92
  93        if (self == NULL)
  94                goto out;
  95
  96        self->files = file_line__new(file, lineno);
  97        if (self->files == NULL)
  98                goto out_fail;
  99
 100        self->msg = strdup(msg);
 101        if (self->msg == NULL)
 102                goto out_fail_msg;
 103
 104        self->option = option;
 105        self->next = NULL;
 106out:
 107        return self;
 108out_fail_msg:
 109        free(self->files);
 110out_fail:
 111        free(self);
 112        self = NULL;
 113        goto out;
 114}
 115
 116static struct message *mesage__find(const char *msg)
 117{
 118        struct message *m = message__list;
 119
 120        while (m != NULL) {
 121                if (strcmp(m->msg, msg) == 0)
 122                        break;
 123                m = m->next;
 124        }
 125
 126        return m;
 127}
 128
 129static int message__add_file_line(struct message *self, char *file, int lineno)
 130{
 131        int rc = -1;
 132        struct file_line *fl = file_line__new(file, lineno);
 133
 134        if (fl == NULL)
 135                goto out;
 136
 137        fl->next    = self->files;
 138        self->files = fl;
 139        rc = 0;
 140out:
 141        return rc;
 142}
 143
 144static int message__add(const char *msg, char *option, char *file, int lineno)
 145{
 146        int rc = 0;
 147        char bf[16384];
 148        char *escaped = escape(msg, bf, sizeof(bf));
 149        struct message *m = mesage__find(escaped);
 150
 151        if (m != NULL)
 152                rc = message__add_file_line(m, file, lineno);
 153        else {
 154                m = message__new(escaped, option, file, lineno);
 155
 156                if (m != NULL) {
 157                        m->next       = message__list;
 158                        message__list = m;
 159                } else
 160                        rc = -1;
 161        }
 162        return rc;
 163}
 164
 165void menu_build_message_list(struct menu *menu)
 166{
 167        struct menu *child;
 168
 169        message__add(menu_get_prompt(menu), NULL,
 170                     menu->file == NULL ? "Root Menu" : menu->file->name,
 171                     menu->lineno);
 172
 173        if (menu->sym != NULL && menu->sym->help != NULL)
 174                message__add(menu->sym->help, menu->sym->name,
 175                             menu->file == NULL ? "Root Menu" : menu->file->name,
 176                             menu->lineno);
 177
 178        for (child = menu->list; child != NULL; child = child->next)
 179                if (child->prompt != NULL)
 180                        menu_build_message_list(child);
 181}
 182
 183static void message__print_file_lineno(struct message *self)
 184{
 185        struct file_line *fl = self->files;
 186
 187        putchar('\n');
 188        if (self->option != NULL)
 189                printf("# %s:00000\n", self->option);
 190
 191        printf("#: %s:%d", fl->file, fl->lineno);
 192        fl = fl->next;
 193
 194        while (fl != NULL) {
 195                printf(", %s:%d", fl->file, fl->lineno);
 196                fl = fl->next;
 197        }
 198
 199        putchar('\n');
 200}
 201
 202static void message__print_gettext_msgid_msgstr(struct message *self)
 203{
 204        message__print_file_lineno(self);
 205
 206        printf("msgid %s\n"
 207               "msgstr \"\"\n", self->msg);
 208}
 209
 210void menu__xgettext(void)
 211{
 212        struct message *m = message__list;
 213
 214        while (m != NULL) {
 215                message__print_gettext_msgid_msgstr(m);
 216                m = m->next;
 217        }
 218}
 219
 220int main(int ac, char **av)
 221{
 222        conf_parse(av[1]);
 223
 224        menu_build_message_list(menu_get_root_menu(NULL));
 225        menu__xgettext();
 226        return 0;
 227}
 228