# # 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. # # Copyright (c) 2018, Joyent, Inc. PROG= expand unexpand SRCS= $(PROG:=.c) include ../Makefile.cmd # workaround two meanings for expand.po POFILES= expand_cmd.po unexpand.po POFILE= expand.po CLOBBERFILES += expand_cmd.c SMOFF += signed .KEEP_STATE: all: $(PROG) install: all $(ROOTPROG) clean: lint: $(LINT.c) expand.c $(LDLIBS) $(LINT.c) unexpand.c $(LDLIBS) $(POFILE): $(POFILES) $(RM) $@; cat $(POFILES) > $@ expand_cmd.c: $(RM) $@; cp expand.c $@ include ../Makefile.targ /* * 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 1989 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ #include #include #include #include #include #include #include #include /* * expand - expand tabs to equivalent spaces */ static int nstops = 0; static int tabstops[100]; static int isClocale; static void getstops(const char *); static void usage(void); int main(argc, argv) int argc; char *argv[]; { static char ibuf[BUFSIZ]; register int c, column; register int n; register int i, j; char *locale; int flag, tflag = 0; int len; int p_col; wchar_t wc; char *p1, *p2; (void) setlocale(LC_ALL, ""); locale = setlocale(LC_CTYPE, NULL); isClocale = (strcmp(locale, "C") == 0); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); /* * First, look for and extract any "-" args then pass * them to getstops(). */ for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--") == 0) break; if (*argv[i] != '-') continue; if (!isdigit(*(argv[i]+1))) continue; getstops(argv[i]+1); tflag++; /* Pull this arg from list */ for (j = i; j < (argc-1); j++) argv[j] = argv[j+1]; argc--; } while ((flag = getopt(argc, argv, "t:")) != EOF) { switch (flag) { case 't': if (tflag) usage(); getstops(optarg); break; default: usage(); break; } } argc -= optind; argv = &argv[optind]; do { if (argc > 0) { if (freopen(argv[0], "r", stdin) == NULL) { perror(argv[0]); exit(1); /* NOTREACHED */ } argc--; argv++; } column = 0; p1 = p2 = ibuf; for (;;) { if (p1 >= p2) { p1 = ibuf; if ((len = fread(p1, 1, BUFSIZ, stdin)) <= 0) break; p2 = p1 + len; } c = *p1++; switch (c) { case '\t': if (nstops == 0) { do { (void) putchar(' '); column++; } while (column & 07); continue; } if (nstops == 1) { do { (void) putchar(' '); column++; } while ( ((column - 1) % tabstops[0]) != (tabstops[0] - 1)); continue; } for (n = 0; n < nstops; n++) if (tabstops[n] > column) break; if (n == nstops) { (void) putchar(' '); column++; continue; } while (column < tabstops[n]) { (void) putchar(' '); column++; } continue; case '\b': if (column) column--; (void) putchar('\b'); continue; default: if (isClocale) { (void) putchar(c); column++; continue; } if (isascii(c)) { (void) putchar(c); column++; continue; } p1--; if ((len = (p2 - p1)) < (unsigned int)MB_CUR_MAX) { for (n = 0; n < len; n++) ibuf[n] = *p1++; p1 = ibuf; p2 = p1 + n; if ((len = fread(p2, 1, BUFSIZ - n, stdin)) > 0) p2 += len; } if ((len = (p2 - p1)) > (unsigned int)MB_CUR_MAX) len = (unsigned int)MB_CUR_MAX; if ((len = mbtowc(&wc, p1, len)) <= 0) { (void) putchar(c); column++; p1++; continue; } if ((p_col = wcwidth(wc)) < 0) p_col = len; p1 += len; (void) putwchar(wc); column += p_col; continue; case '\n': (void) putchar(c); column = 0; continue; } } } while (argc > 0); return (0); /* NOTREACHED */ } static void getstops(const char *cp) { register int i; for (;;) { i = 0; while (*cp >= '0' && *cp <= '9') i = i * 10 + *cp++ - '0'; if (i <= 0 || i > INT_MAX) { (void) fprintf(stderr, gettext( "expand: invalid tablist\n")); usage(); } if (nstops > 0 && i <= tabstops[nstops-1]) { (void) fprintf(stderr, gettext( "expand: tablist must be increasing\n")); usage(); } tabstops[nstops++] = i; if (*cp == 0) break; if (*cp != ',' && *cp != ' ') { (void) fprintf(stderr, gettext( "expand: invalid tablist\n")); usage(); } cp++; } } static void usage(void) { (void) fprintf(stderr, gettext( "usage: expand [-t tablist] [file ...]\n" " expand [-tabstop] [-tab1,tab2,...,tabn] [file ...]\n")); exit(2); /* NOTREACHED */ } /* * 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 1989 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * University Copyright- Copyright (c) 1982, 1986, 1988 * The Regents of the University of California * All Rights Reserved * * University Acknowledgment- Portions of this document are derived from * software developed by the University of California, Berkeley, and its * contributors. */ /* * unexpand - put tabs into a file replacing blanks */ #include #include #include #include #include #include #define INPUT_SIZ LINE_MAX /* POSIX.2 */ #define MAX_TABS 100 /* maximum number of tabstops */ static int nstops = 0; /* total number of tabstops */ static int tabstops[MAX_TABS]; /* the tabstops themselves */ static void tabify(wchar_t *, int); static void getstops(const char *); static void usage(void); int main(argc, argv) int argc; char *argv[]; { int flag; /* option flag read by getopt() */ int all = 0; /* -a flag */ int status = 0; wchar_t input_buf[INPUT_SIZ+1]; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); while ((flag = getopt(argc, argv, "at:")) != EOF) { switch (flag) { case 'a': all++; break; case 't': /* POSIX.2 */ all++; /* -t turns on -a */ getstops(optarg); break; default: usage(); break; } } argc -= optind; argv = &argv[optind]; do { if (argc > 0) { if (freopen(argv[0], "r", stdin) == NULL) { (void) fprintf(stderr, "unexpand: "); perror(argv[0]); status++; } argc--, argv++; } while (fgetws(input_buf, INPUT_SIZ, stdin) != NULL) { input_buf[INPUT_SIZ] = 0; tabify(input_buf, all); } } while (argc > 0); return (status); /* NOTREACHED */ } void tabify(wchar_t *ibuf, int all) { wchar_t *cp; /* current position in ibuf */ int ocol = 0; /* current output column */ int cstop = 0; /* current tabstop */ int spaces = 0; /* spaces to convert to tab */ int p_col; cp = ibuf; for (;;) { switch (*cp) { case ' ': cp++; spaces++; ocol++; if (nstops == 0) { /* default tab = 8 */ if ((ocol & 7) != 0) break; } else if (nstops == 1) { /* tab width */ if ((ocol % tabstops[0]) != 0) break; } else { /* explicit tabstops */ while (cstop < nstops && ocol > tabstops[cstop]) cstop++; if (cstop >= nstops) { (void) putchar(' '); spaces = 0; break; } if (ocol != tabstops[cstop]) break; cstop++; } /* * if we get to this point, we must be at a * tab stop. if spaces, then write out a tab. */ if (spaces > 0) { (void) putchar(((spaces > 1) ? '\t' : ' ')); spaces = 0; } break; case '\b': /* POSIX.2 */ while (spaces-- > 0) (void) putchar(' '); spaces = 0; cp++; (void) putchar('\b'); if (--ocol < 0) ocol = 0; /* just in case */ cstop = 0; break; case '\t': cp++; (void) putchar('\t'); /* adjust ocol to current tabstop */ if (nstops == 0) { ocol = (ocol + 8) & ~07; } else if (nstops == 1) { ocol += ocol % tabstops[0]; } else { if (cstop < nstops && ocol < tabstops[cstop]) ocol = tabstops[cstop++]; else ocol++; } spaces = 0; break; default: while (spaces-- > 0) (void) putchar(' '); spaces = 0; if (*cp == 0 || *cp == '\n' || all == 0) { /* * either end of input line or -a not set */ while (*cp != 0) (void) putwchar(*cp++); return; } (void) putwchar(*cp++); if ((p_col = wcwidth(*cp)) < 0) p_col = 0; ocol += p_col; break; } } } static void getstops(const char *cp) { register int i; for (;;) { i = 0; while (*cp >= '0' && *cp <= '9') i = i * 10 + *cp++ - '0'; if (i <= 0 || i > INT_MAX) { (void) fprintf(stderr, gettext( "unexpand: invalid tablist item\n")); usage(); } if (nstops > 0 && i <= tabstops[nstops-1]) { (void) fprintf(stderr, gettext( "unexpand: tablist must be increasing\n")); usage(); } if (nstops == MAX_TABS) { (void) fprintf(stderr, gettext( "unexpand: number of tabstops limited to %d\n"), MAX_TABS); usage(); } tabstops[nstops++] = i; if (*cp == 0) break; if (*cp != ',' && *cp != ' ') { (void) fprintf(stderr, gettext( "unexpand: invalid tablist separator\n")); usage(); } cp++; } } static void usage(void) { (void) fprintf(stderr, gettext( "usage: unexpand [-a ] [-t tablist] [file ...]\n")); exit(2); /* NOTREACHED */ }