root/usr/src/cmd/dumpcs/dumpcs.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <locale.h>
#include <wctype.h>
#include <getwidth.h>

#define SCRWID 80
#define LC_NAMELEN 255

#if !defined SS2
#define SS2 0x8e
#endif
#if !defined SS3
#define SS3 0x8f
#endif

static unsigned int cpl;        /* current characters per line */
static unsigned int cplmax;     /* maximum characters per line */
static unsigned char codestr[MB_LEN_MAX + 1];
static char linebuf[SCRWID / 2 * (MB_LEN_MAX + 1)];
static int pinline;             /* any printable to be listed in the line? */
static int omitting;            /* omitting blank lines under no vflag? */
static int vflag = 0;
static int wflag = 0;
static int csprint();
static int prcode();

int
main(ac, av)
int ac;
char *av[];
{
        int c;
        short int eucw[4];
        short int scrw[4];
        int csflag[4];
        int cs;
        int i;
        eucwidth_t eucwidth;
        char *lc_ctype;
        char titlebar[LC_NAMELEN + 14];

        (void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
        (void) textdomain(TEXT_DOMAIN);
        lc_ctype = setlocale(LC_CTYPE, NULL);
        getwidth(&eucwidth);
        eucw[0] = 1;
        eucw[1] = eucwidth._eucw1;
        eucw[2] = eucwidth._eucw2;
        eucw[3] = eucwidth._eucw3;
        scrw[0] = 1;
        scrw[1] = eucwidth._scrw1;
        scrw[2] = eucwidth._scrw2;
        scrw[3] = eucwidth._scrw3;
        for (i = 0; i <= 3; i++)
                csflag[i] = 0;
        for (i = 1; i < ac; i++)
                if (*av[i] != '-')
                        goto usage;
        while ((c = getopt(ac, av, "0123vw")) != -1) {
                switch (c) {
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                                csflag[c - '0'] = 1;
                                break;
                        case 'v':
                                vflag++;
                                break;
                        case 'w':
                                wflag++;
                                break;
                        default:
                        usage:
                                (void) printf(gettext("usage: %s [-0123vw]\n"), av[0]);
                                exit (1);
                }
        }
        if ((csflag[0] + csflag[1] + csflag[2] + csflag[3]) == 0) {
                for (i = 0; i <= 3; i++)
                        csflag[i]++;
        }
        (void) strcpy(titlebar, "");
        for (i = strlen(lc_ctype) + 14; i; i--)
                (void) strcat(titlebar, ":");
        for (cs = 0; cs <= 3; cs++) {
                if (csflag[cs] && eucw[cs] && scrw[cs]) {
                        (void) printf("%s\n", titlebar);
                        (void) printf("LC_CTYPE:%s", lc_ctype);
                        (void) printf(" CS:%d\n", cs);
                        (void) printf("%s", titlebar);
                        (void) csprint(cs, (int) eucw[cs], (int) scrw[cs]);
                        (void) printf("\n");
                }
        }
        return (0);
}

int
csprint(cs, bytes, columns)
int cs, bytes, columns;
{
        int col, i, position;
        int bytelen;
        int minvalue;
        int maxvalue;

        col = SCRWID - bytes * 2 - 1;
        cplmax = 1;
        for (i = columns + 1; i <= col; i *= 2) cplmax *= 2;
        cplmax /= 2;
        bytelen = bytes;
        minvalue = 0x20;
        maxvalue = 0x7f;
        position = 0;
        if (cs > 0) {
                minvalue = 0xa0;
                maxvalue = 0xff;
        }
        if (cs == 2) {
                codestr[position++] = SS2;
                bytelen++;
        }
        if (cs == 3) {
                codestr[position++] = SS3;
                bytelen++;
        }
        codestr[position] = '\0';
        cpl = 0;
        (void) strcpy(linebuf, "");
        (void) prcode(bytelen, position, minvalue, maxvalue, columns);
        if (pinline || vflag) {
                (void) printf("\n%s", linebuf);
        } else if (!omitting) {
                (void) printf("\n*");
        }
        omitting = 0;
        return (0);
}

/*
 * prcode() prints series of len-byte codes, of which each byte can
 * have a code value between min and max, in incremental code order.
 */
int
prcode(len, pos, min, max, col)
int len, pos, min, max, col;
{
        int byte, i, nextpos;
        unsigned long widechar; /* limitting wchar_t width - not good */
        char *prep;
        wchar_t wc;
        int     mbl;

        if (len - pos > 1) {
                for (byte = min; byte <= max; byte++) {
                        codestr[pos] = (unsigned char) byte;
                        nextpos = pos + 1;
                        codestr[nextpos] = '\0';
                        (void) prcode(len, nextpos, min, max, col);
                }
        } else {
                for (byte = min; byte <= max; byte++) {
                        codestr[pos] = (unsigned char) byte;
                        nextpos = pos + 1;
                        codestr[nextpos] = '\0';
                        if (!cpl) {
                                widechar = 0;
                                i = 0;
                                while (codestr[i] != '\0') {
                                        widechar = (widechar << 8) |
                                                (unsigned long) codestr[i++];
                                }
                                if (*linebuf) {
                                        if (pinline || vflag) {
                                                (void) printf("\n%s", linebuf);
                                                omitting = 0;
                                        } else if (!omitting) {
                                                (void) printf("\n*");
                                                omitting++;
                                        }
                                }
                                if (!wflag) {
                                        (void) sprintf(linebuf, "%lx ",
                                            widechar);
                                } else {
                                        (void) mbtowc(&wc, (char *) codestr,
                                            MB_CUR_MAX);
                                        (void) sprintf(linebuf, "%lx ", wc);
                                }
                                pinline = 0;
                        }
                        prep = " ";
                        if ((mbl = mbtowc(&wc, (char *) codestr,
                            MB_CUR_MAX)) < 0)
                                prep = "*";
                        if (mbl == 1) {
                                if (!(isprint(codestr[0]))) prep = "*";
                        } else if (!(iswprint(wc)))
                                prep = "*";
                        if (prep[0] == '*') {
                                (void) strcat(linebuf, prep);
                                for (i = 1; i <= col; i++)
                                        (void) strcat(linebuf, " ");
                        } else {
                                (void) strcat(linebuf, prep);
                                (void) strcat(linebuf, (char *) codestr);
                                pinline = 1;
                        }
                        cpl++;
                        cpl = cpl % cplmax;
                }
        }
        return (0);
}