summaryrefslogblamecommitdiff
path: root/locale.c
blob: ede426df7fb1c6812f87c3f50fbb4c0ddb3f79d1 (plain) (tree)
1
2
3
4
5
6
7
8

  

                                              
  
                              
  
                                              














                     

                    

























                                                   
                                                               




                                                                         
                  
































                                                                           
                                                          



                            
                                                                    









                                                 






                                              

                                                                      
         



























                                                     
                                                        
         
                                    

                                    

                               











                                             
                                                      










                                                                          
     


                                                




















                                                                                        



                                                                             

                                      




                                       



                                                                                  












                           

                                                                          













                                                                            
/*
 *
 * Copyright (c) 2016  Konstantin Pugin
 * Konstantin Pugin (ria.freelander@gmail.com)
 *
 * Licensed under the LGPL v3.
 *
 * A 'locale' command implementation for musl.
 *
 */

#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <libgen.h>
#include <stdlib.h>
#include <langinfo.h>
#include <unistd.h>
#include <getopt.h>
#include <stdint.h>
#include <dirent.h>
#include <locale.h>
#include <stdbool.h>
#include <libintl.h>
#include "config.h"
#include "categories.h"


/* If set print the name of the category.  */
static bool show_category_name = 0;

/* If set print the name of the item.  */
static bool show_keyword_name = 0;

/* If set print the usage command.  */
static bool show_usage = 0;

/* Print names of all available locales.  */
static bool do_all = 0;

/* Print names of all available character maps.  */
static bool do_charmaps = 0;

static int remaining = 0;

static void usage(char *name)
{
    char *s;

    s = basename(name);
    fprintf(stderr,
            gettext ("Usage: %s [-a | -m] [FORMAT] name...\n\n"
            "\t-a, --all-locales\tWrite names of all available locales\n"
            "\t-m, --charmaps\tWrite names of available charmaps\n"
            "\nFORMAT:\n"
            "\t-c, --category-name\tWrite names of selected categories\n"
            "\t-k, --keyword-name\tWrite names of selected keywords\n"
            ), s);
}

static int argp_parse(int argc, char *argv[])
{
    int c;
    char *progname;
    static const struct option long_options[] = {
        {"all-locales", no_argument, NULL, 'a'},
        {"charmaps", no_argument, NULL, 'm'},
        {"category-name", no_argument, NULL, 'c'},
        {"keyword-name", no_argument, NULL, 'k'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}};
    progname = *argv;
    while ((c = getopt_long(argc, argv, "amckh", long_options, NULL)) >= 0)

        switch (c) {
        case 'a':
            do_all = 1;
            break;
        case 'c':
            show_category_name = 1;
            break;
        case 'm':
            do_charmaps = 1;
            break;
        case 'k':
            show_keyword_name = 1;
            break;
        case 'h':
            show_usage = 1;
            break;
        case '?':
            fprintf(stderr, gettext("Unknown option.\n"));
            usage(progname);
            return 1;

        default:
            fprintf(stderr, gettext("This should never happen!\n"));
            return 1;
        }

    remaining = optind;
    return 0;
}

static void list_locale()
{
    const char *locpath = getenv("MUSL_LOCPATH");
    printf("C\n");
    printf("C.UTF-8\n");
    if(locpath != NULL)
    {
        DIR *dir = opendir(locpath);
        struct dirent *pDir;
        while ((pDir = readdir(dir)) != NULL){
            if (strcmp(pDir->d_name,".") && strcmp(pDir->d_name,".."))
                printf("%s\n",pDir->d_name);
        }
    }
}

static void list_charmaps()
{
    printf("ASCII\n");
    printf("UTF-8\n");
    return;
}

static void print_item (struct cat_item item)
{
    switch (item.type)
    {
    case CAT_TYPE_STRING:
        if (show_keyword_name)
            printf ("%s=\"", item.name);
        fputs (nl_langinfo (item.id) ? : "", stdout);
        if (show_keyword_name)
            putchar ('"');
        putchar ('\n');
        break;
    case CAT_TYPE_STRINGARRAY:
    {
        const char *val;
        if (show_keyword_name)
            printf ("%s=\"", item.name);

        for (int cnt = item.min; cnt <= item.max; cnt++)
        {
            val = nl_langinfo (cnt);
            if (val != NULL)
                fputs (val, stdout);
            if (cnt < item.max)
                putchar (';');
        }
        if (show_keyword_name)
            putchar ('"');
        putchar ('\n');
    }
        break;
  }
}

/* Show the information request for NAME.  */
static void show_info(const char *name)
{
    for (size_t cat_no = 0; cat_no < LC_ALL; cat_no++)
    {
        if (strcmp (name, get_name_for_cat(cat_no)) == 0)
        /* Print the whole category.  */
        {
            if (show_category_name != 0)
                puts (get_name_for_cat(cat_no));
            const struct cat_item* items = get_cat_for_locale_cat(cat_no);
            for(int j = 0; items[j].type != CAT_TYPE_END; j++)
                print_item(items[j]);
            return;
        }
    }
    if (show_category_name != 0)
        puts (get_cat_name_for_item_name(name));
    print_item(get_cat_item_for_name(name));
}

static void show_locale_vars()
{
    const char *lcall = getenv("LC_ALL") ? : "\0";
    const char *lang = getenv("LANG") ? : "";

    /* LANG has to be the first value.  */
    printf("LANG=%s\n", lang);
    for (size_t cat_no = 0; cat_no < LC_ALL; ++cat_no)
    {
        printf("%s=%s\n",get_name_for_cat(cat_no),lcall[0] != '\0' ? lcall
                                                                : lang[0] != '\0' ? lang
                                                                : "POSIX");
    }
    /* The last is the LC_ALL value.  */
    printf("LC_ALL=%s\n", lcall);
}

int main(int argc, char *argv[])
{
    if (setlocale (LC_CTYPE, "") == NULL)
      fprintf (stderr, gettext ("Cannot set LC_CTYPE to default locale"));
    if (setlocale (LC_MESSAGES, "") == NULL)
      fprintf (stderr, gettext ("Cannot set LC_MESSAGES to default locale"));
    bindtextdomain(PACKAGE,LOCALEDIR);
    textdomain(PACKAGE);
    /* Parse and process arguments.  */
    if (argp_parse(argc, argv))
        return 1;

    if (do_all) {
        if (setlocale (LC_COLLATE, "") == NULL)
            fprintf (stderr, gettext ("Cannot set LC_COLLATE to default locale"));
        else
            list_locale();
        exit(EXIT_SUCCESS);
    }

    if (do_charmaps) {
        list_charmaps();
        exit(EXIT_SUCCESS);
    }

    if (show_usage) {
        usage(*argv);
        exit(EXIT_SUCCESS);
    }

    if (setlocale (LC_ALL, "") == NULL)
        fprintf (stderr, gettext ("Cannot set LC_ALL to default locale"));
    /* If no real argument is given we have to print the contents of the
       current locale definition variables. These are LANG and the LC_*.  */
    if (remaining == argc && show_category_name == 0
        && show_keyword_name == 0) {
        show_locale_vars();
        exit(EXIT_SUCCESS);
    }

    /* Process all given names.  */
    while (remaining < argc)
        show_info(argv[remaining++]);

    exit(EXIT_SUCCESS);
}