/* expand - convert tabs to spaces                                              This is the expand utility
   Copyright (C) 1989-2018 Free Software Foundation, Inc.                       
                                                                                
   This program is free software: you can redistribute it and/or modify         
   it under the terms of the GNU General Public License as published by         
   the Free Software Foundation, either version 3 of the License, or            
   (at your option) any later version.                                          
                                                                                
   This program is distributed in the hope that it will be useful,              
   but WITHOUT ANY WARRANTY; without even the implied warranty of               
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
   GNU General Public License for more details.                                 
                                                                                
   You should have received a copy of the GNU General Public License            
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */   The GNUv3 license
                                                                                
/* By default, convert all tabs to spaces.                                      
   Preserves backspace characters in the output; they decrement the             
   column count for tab calculations.                                           
   The default action is equivalent to -8.                                      
                                                                                
   Options:                                                                     
   --tabs=tab1[,tab2[,...]]                                                     
   -t tab1[,tab2[,...]]                                                         
   -tab1[,tab2[,...]] If only one tab stop is given, set the tabs tab1          
                        columns apart instead of the default 8.  Otherwise,     
                        set the tabs at columns tab1, tab2, etc. (numbered from 
                        0); replace any tabs beyond the tab stops given with    
                        single spaces.                                          
   --initial                                                                    
   -i   Only convert initial tabs on each line to spaces.                       
                                                                                
   David MacKenzie <djm@gnu.ai.mit.edu> */                                      
                                                                                
#include <config.h>                                                             Provides system specific information
                                                                                
#include <stdio.h>                                                              Provides standard I/O capability
#include <getopt.h>                                                             ...!includes auto-comment...
#include <sys/types.h>                                                          Provides system data types
#include "system.h"                                                             ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "xstrndup.h"                                                           ...!includes auto-comment...
                                                                                
#include "expand-common.h"                                                      ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "expand"                                                   Line 47
                                                                                
#define AUTHORS proper_name ("David MacKenzie")                                 Line 49
                                                                                
static char const shortopts[] = "it:0::1::2::3::4::5::6::7::8::9::";            Line 51
                                                                                
static struct option const longopts[] =                                         Line 53
{                                                                               
  {"tabs", required_argument, NULL, 't'},                                       Line 55
  {"initial", no_argument, NULL, 'i'},                                          Line 56
  {GETOPT_HELP_OPTION_DECL},                                                    Line 57
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 58
  {NULL, 0, NULL, 0}                                                            Line 59
};                                                                              Block 1
                                                                                
void                                                                            Line 62
usage (int status)                                                              Line 63
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 65
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 67
    {                                                                           
      printf (_("\                                                              Line 69
Usage: %s [OPTION]... [FILE]...\n\                                              Line 70
"),                                                                             Line 71
              program_name);                                                    Line 72
      fputs (_("\                                                               Line 73
Convert tabs in each FILE to spaces, writing to standard output.\n\             Line 74
"), stdout);                                                                    Line 75
                                                                                
      emit_stdin_note ();                                                       ...!common auto-comment...
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      fputs (_("\                                                               Line 80
  -i, --initial    do not convert tabs after non blanks\n\                      Line 81
  -t, --tabs=N     have tabs N characters apart, not 8\n\                       Line 82
"), stdout);                                                                    Line 83
      emit_tab_list_info ();                                                    Line 84
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 85
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 86
      emit_ancillary_info (PROGRAM_NAME);                                       Line 87
    }                                                                           
  exit (status);                                                                Line 89
}                                                                               Block 2
                                                                                
                                                                                
/* Change tabs to spaces, writing to stdout.                                    
   Read each file in 'file_list', in order.  */                                 
                                                                                
static void                                                                     Line 96
expand (void)                                                                   Line 97
{                                                                               
  /* Input stream.  */                                                          
  FILE *fp = next_file (NULL);                                                  Line 100
                                                                                
  if (!fp)                                                                      Line 102
    return;                                                                     Line 103
                                                                                
  while (true)                                                                  Line 105
    {                                                                           
      /* Input character, or EOF.  */                                           
      int c;                                                                    Line 108
                                                                                
      /* If true, perform translations.  */                                     
      bool convert = true;                                                      Line 111
                                                                                
                                                                                
      /* The following variables have valid values only when CONVERT            
         is true:  */                                                           
                                                                                
      /* Column of next input character.  */                                    
      uintmax_t column = 0;                                                     Line 118
                                                                                
      /* Index in TAB_LIST of next tab stop to examine.  */                     
      size_t tab_index = 0;                                                     Line 121
                                                                                
                                                                                
      /* Convert a line of text.  */                                            
                                                                                
      do                                                                        
        {                                                                       
          while ((c = getc (fp)) < 0 && (fp = next_file (fp)))                  Line 128
            continue;                                                           Line 129
                                                                                
          if (convert)                                                          Line 131
            {                                                                   
              if (c == '\t')                                                    Line 133
                {                                                               
                  /* Column the next input tab stop is on.  */                  
                  uintmax_t next_tab_column;                                    Line 136
                  bool last_tab IF_LINT (=0);                                   Line 137
                                                                                
                  next_tab_column = get_next_tab_column (column, &tab_index,    Line 139
                                                         &last_tab);            Line 140
                                                                                
                  if (last_tab)                                                 Line 142
                    next_tab_column = column + 1;                               Line 143
                                                                                
                  if (next_tab_column < column)                                 Line 145
                    die (EXIT_FAILURE, 0, _("input line is too long"));         Line 146
                                                                                
                  while (++column < next_tab_column)                            Line 148
                    if (putchar (' ') < 0)                                      Line 149
                      die (EXIT_FAILURE, errno, _("write error"));              Line 150
                                                                                
                  c = ' ';                                                      Line 152
                }                                                               
              else if (c == '\b')                                               Line 154
                {                                                               
                  /* Go back one column, and force recalculation of the         
                     next tab stop.  */                                         
                  column -= !!column;                                           Line 158
                  tab_index -= !!tab_index;                                     Line 159
                }                                                               
              else                                                              Line 161
                {                                                               
                  column++;                                                     Line 163
                  if (!column)                                                  Line 164
                    die (EXIT_FAILURE, 0, _("input line is too long"));         Line 165
                }                                                               
                                                                                
              convert &= convert_entire_line || !! isblank (c);                 Line 168
            }                                                                   
                                                                                
          if (c < 0)                                                            Line 171
            return;                                                             Line 172
                                                                                
          if (putchar (c) < 0)                                                  Line 174
            die (EXIT_FAILURE, errno, _("write error"));                        Line 175
        }                                                                       
      while (c != '\n');                                                        Line 177
    }                                                                           
}                                                                               
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 182
{                                                                               
  int c;                                                                        Line 184
                                                                                
  initialize_main (&argc, &argv);                                               VMS-specific entry point handling wildcard expansion
  set_program_name (argv[0]);                                                   Retains program name and discards path
  setlocale (LC_ALL, "");                                                       Sets up internationalization (i18n)
  bindtextdomain (PACKAGE, LOCALEDIR);                                          Assigns i18n directorySets text domain for _() [gettext()] function
  textdomain (PACKAGE);                                                         Sets text domain for _() [gettext()] function
                                                                                
  atexit (close_stdout);                                                        Close stdout on exit (see gnulib)
  convert_entire_line = true;                                                   Line 193
                                                                                
  while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)       Line 195
    {                                                                           
      switch (c)                                                                Line 197
        {                                                                       
        case 'i':                                                               Line 199
          convert_entire_line = false;                                          Line 200
          break;                                                                Line 201
                                                                                
        case 't':                                                               Line 203
          parse_tab_stops (optarg);                                             Line 204
          break;                                                                Line 205
                                                                                
        case '0': case '1': case '2': case '3': case '4':                       Line 207
        case '5': case '6': case '7': case '8': case '9':                       Line 208
          if (optarg)                                                           Line 209
            parse_tab_stops (optarg - 1);                                       Line 210
          else                                                                  Line 211
            {                                                                   
              char tab_stop[2];                                                 Line 213
              tab_stop[0] = c;                                                  Line 214
              tab_stop[1] = '\0';                                               Line 215
              parse_tab_stops (tab_stop);                                       Line 216
            }                                                                   
          break;                                                                Line 218
                                                                                
        case_GETOPT_HELP_CHAR;                                                  Line 220
                                                                                
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 222
                                                                                
        default:                                                                Line 224
          usage (EXIT_FAILURE);                                                 Line 225
        }                                                                       
    }                                                                           
                                                                                
  finalize_tab_stops ();                                                        Line 229
                                                                                
  set_file_list ( (optind < argc) ? &argv[optind] : NULL);                      Line 231
                                                                                
  expand ();                                                                    Line 233
                                                                                
  cleanup_file_list_stdin ();                                                   Line 235
                                                                                
  return exit_status;                                                           Line 237
}                                                                               Block 4