(root)/
util-linux-2.39/
text-utils/
colrm.c
       1  /*
       2   * Copyright (c) 1980 Regents of the University of California.
       3   * All rights reserved.
       4   *
       5   * Redistribution and use in source and binary forms, with or without
       6   * modification, are permitted provided that the following conditions
       7   * are met:
       8   * 1. Redistributions of source code must retain the above copyright
       9   *    notice, this list of conditions and the following disclaimer.
      10   * 2. Redistributions in binary form must reproduce the above copyright
      11   *    notice, this list of conditions and the following disclaimer in the
      12   *    documentation and/or other materials provided with the distribution.
      13   * 3. All advertising materials mentioning features or use of this software
      14   *    must display the following acknowledgement:
      15   *	This product includes software developed by the University of
      16   *	California, Berkeley and its contributors.
      17   * 4. Neither the name of the University nor the names of its contributors
      18   *    may be used to endorse or promote products derived from this software
      19   *    without specific prior written permission.
      20   *
      21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      25   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31   * SUCH DAMAGE.
      32   */
      33  
      34  /*
      35   * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
      36   * 	added Native Language Support
      37   * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
      38   * 	modified to work correctly in multi-byte locales
      39   */
      40  
      41  #include <stdio.h>
      42  #include <stdlib.h>
      43  #include <getopt.h>
      44  #include <unistd.h>
      45  
      46  #include "nls.h"
      47  #include "strutils.h"
      48  #include "c.h"
      49  #include "widechar.h"
      50  #include "closestream.h"
      51  
      52  /*
      53  COLRM removes unwanted columns from a file
      54  	Jeff Schriebman  UC Berkeley 11-74
      55  */
      56  
      57  static void __attribute__((__noreturn__)) usage(void)
      58  {
      59  	FILE *out = stdout;
      60  	fprintf(out, _("\nUsage:\n"
      61  		       " %s [startcol [endcol]]\n"),
      62  		       program_invocation_short_name);
      63  
      64  	fputs(USAGE_SEPARATOR, out);
      65  	fputs(_("Filter out the specified columns.\n"), out);
      66  
      67  	fputs(USAGE_OPTIONS, out);
      68  	printf(USAGE_HELP_OPTIONS(16));
      69  	fprintf(out, _("%s reads from standard input and writes to standard output\n\n"),
      70  		       program_invocation_short_name);
      71  	printf(USAGE_MAN_TAIL("colrm(1)"));
      72  	exit(EXIT_SUCCESS);
      73  }
      74  
      75  static int process_input(unsigned long first, unsigned long last)
      76  {
      77  	unsigned long ct = 0;
      78  	wint_t c;
      79  	unsigned long i;
      80  	int w;
      81  	int padding;
      82  
      83  	for (;;) {
      84  		c = getwc(stdin);
      85  		if (c == WEOF)
      86  			return 0;
      87  		if (c == '\t')
      88  			w = ((ct + 8) & ~7) - ct;
      89  		else if (c == '\b')
      90  			w = (ct ? ct - 1 : 0) - ct;
      91  		else {
      92  			w = wcwidth(c);
      93  			if (w < 0)
      94  				w = 0;
      95  		}
      96  		ct += w;
      97  		if (c == '\n') {
      98  			putwc(c, stdout);
      99  			ct = 0;
     100  			continue;
     101  
     102  		}
     103  		if (!first || ct < first) {
     104  			putwc(c, stdout);
     105  			continue;
     106  		}
     107  		break;
     108  	}
     109  
     110  	for (i = ct - w + 1; i < first; i++)
     111  		putwc(' ', stdout);
     112  
     113  	/* Loop getting rid of characters */
     114  	while (!last || ct < last) {
     115  		c = getwc(stdin);
     116  		if (c == WEOF)
     117  			return 0;
     118  		if (c == '\n') {
     119  			putwc(c, stdout);
     120  			return 1;
     121  		}
     122  		if (c == '\t')
     123  			ct = (ct + 8) & ~7;
     124  		else if (c == '\b')
     125  			ct = ct ? ct - 1 : 0;
     126  		else {
     127  			w = wcwidth(c);
     128  			if (w < 0)
     129  				w = 0;
     130  			ct += w;
     131  		}
     132  	}
     133  
     134  	padding = 0;
     135  
     136  	/* Output last of the line */
     137  	for (;;) {
     138  		c = getwc(stdin);
     139  		if (c == WEOF)
     140  			break;
     141  		if (c == '\n') {
     142  			putwc(c, stdout);
     143  			return 1;
     144  		}
     145  		if (padding == 0 && last < ct) {
     146  			for (i = last; i < ct; i++)
     147  				putwc(' ', stdout);
     148  			padding = 1;
     149  		}
     150  		putwc(c, stdout);
     151  	}
     152  	return 0;
     153  }
     154  
     155  int main(int argc, char **argv)
     156  {
     157  	unsigned long first = 0, last = 0;
     158  	int opt;
     159  
     160  	static const struct option longopts[] = {
     161  		{"version", no_argument, NULL, 'V'},
     162  		{"help",    no_argument, NULL, 'h'},
     163  		{NULL, 0, NULL, 0}
     164  	};
     165  
     166  	setlocale(LC_ALL, "");
     167  	bindtextdomain(PACKAGE, LOCALEDIR);
     168  	textdomain(PACKAGE);
     169  	close_stdout_atexit();
     170  
     171  	while ((opt =
     172  		getopt_long(argc, argv, "Vh", longopts,
     173  			    NULL)) != -1)
     174  		switch (opt) {
     175  		case 'V':
     176  			print_version(EXIT_SUCCESS);
     177  		case 'h':
     178  			usage();
     179  		default:
     180  			errtryhelp(EXIT_FAILURE);
     181  		}
     182  
     183  	if (argc > 1)
     184  		first = strtoul_or_err(*++argv, _("first argument"));
     185  	if (argc > 2)
     186  		last = strtoul_or_err(*++argv, _("second argument"));
     187  
     188  	while (process_input(first, last))
     189  		;
     190  
     191  	fflush(stdout);
     192  	return EXIT_SUCCESS;
     193  }