/* yes - output a string repeatedly until killed                                This is the yes utility
   Copyright (C) 1991-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
                                                                                
/* David MacKenzie <djm@gnu.ai.mit.edu> */                                      
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
#include <getopt.h>                                                             ...!includes auto-comment...
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
                                                                                
#include "error.h"                                                              ...!includes auto-comment...
#include "full-write.h"                                                         ...!includes auto-comment...
#include "long-options.h"                                                       ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "yes"                                                      Line 31
                                                                                
#define AUTHORS proper_name ("David MacKenzie")                                 Line 33
                                                                                
static struct option const long_options[] =                                     Line 35
{                                                                               
  {NULL, 0, NULL, 0}                                                            Line 37
};                                                                              Block 1
                                                                                
void                                                                            Line 40
usage (int status)                                                              Line 41
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 43
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 45
    {                                                                           
      printf (_("\                                                              Line 47
Usage: %s [STRING]...\n\                                                        Line 48
  or:  %s OPTION\n\                                                             Line 49
"),                                                                             Line 50
              program_name, program_name);                                      Line 51
                                                                                
      fputs (_("\                                                               Line 53
Repeatedly output a line with all specified STRING(s), or 'y'.\n\               Line 54
\n\                                                                             
"), stdout);                                                                    Line 56
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 57
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 58
      emit_ancillary_info (PROGRAM_NAME);                                       Line 59
    }                                                                           
  exit (status);                                                                Line 61
}                                                                               Block 2
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 65
{                                                                               
  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)
                                                                                
  parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,          ...!common auto-comment...
                      usage, AUTHORS, (char const *) NULL);                     Line 76
  if (getopt_long (argc, argv, "+", long_options, NULL) != -1)                  Line 77
    usage (EXIT_FAILURE);                                                       Line 78
                                                                                
  char **operands = argv + optind;                                              Line 80
  char **operand_lim = argv + argc;                                             Line 81
  if (optind == argc)                                                           Line 82
    *operand_lim++ = bad_cast ("y");                                            Line 83
                                                                                
  /* Buffer data locally once, rather than having the                           
     large overhead of stdio buffering each item.  */                           
  size_t bufalloc = 0;                                                          Line 87
  bool reuse_operand_strings = true;                                            Line 88
  for (char **operandp = operands; operandp < operand_lim; operandp++)          Line 89
    {                                                                           
      size_t operand_len = strlen (*operandp);                                  Line 91
      bufalloc += operand_len + 1;                                              Line 92
      if (operandp + 1 < operand_lim                                            Line 93
          && *operandp + operand_len + 1 != operandp[1])                        Line 94
        reuse_operand_strings = false;                                          Line 95
    }                                                                           
                                                                                
  /* Improve performance by using a buffer size greater than BUFSIZ / 2.  */    
  if (bufalloc <= BUFSIZ / 2)                                                   Line 99
    {                                                                           
      bufalloc = BUFSIZ;                                                        Line 101
      reuse_operand_strings = false;                                            Line 102
    }                                                                           
                                                                                
  /* Fill the buffer with one copy of the output.  If possible, reuse           
     the operands strings; this wins when the buffer would be large.  */        
  char *buf = reuse_operand_strings ? *operands : xmalloc (bufalloc);           Line 107
  size_t bufused = 0;                                                           Line 108
  for (char **operandp = operands; operandp < operand_lim; operandp++)          Line 109
    {                                                                           
      size_t operand_len = strlen (*operandp);                                  Line 111
      if (! reuse_operand_strings)                                              Line 112
        memcpy (buf + bufused, *operandp, operand_len);                         Line 113
      bufused += operand_len;                                                   Line 114
      buf[bufused++] = ' ';                                                     Line 115
    }                                                                           
  buf[bufused - 1] = '\n';                                                      Line 117
                                                                                
  /* If a larger buffer was allocated, fill it by repeating the buffer          
     contents.  */                                                              
  size_t copysize = bufused;                                                    Line 121
  for (size_t copies = bufalloc / copysize; --copies; )                         Line 122
    {                                                                           
      memcpy (buf + bufused, buf, copysize);                                    Line 124
      bufused += copysize;                                                      Line 125
    }                                                                           
                                                                                
  /* Repeatedly output the buffer until there is a write error; then fail.  */  
  while (full_write (STDOUT_FILENO, buf, bufused) == bufused)                   Line 129...!syscalls auto-comment...
    continue;                                                                   Line 130
  error (0, errno, _("standard output"));                                       Line 131
  return EXIT_FAILURE;                                                          Line 132
}