/* basename -- strip directory and suffix from file names                       This is the basename utility
   Copyright (C) 1990-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
                                                                                
#include <config.h>                                                             Provides system specific information
#include <getopt.h>                                                             ...!includes auto-comment...
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "basename"                                                 Line 27
                                                                                
#define AUTHORS proper_name ("David MacKenzie")                                 Line 29
                                                                                
static struct option const longopts[] =                                         Line 31
{                                                                               
  {"multiple", no_argument, NULL, 'a'},                                         Line 33
  {"suffix", required_argument, NULL, 's'},                                     Line 34
  {"zero", no_argument, NULL, 'z'},                                             Line 35
  {GETOPT_HELP_OPTION_DECL},                                                    Line 36
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 37
  {NULL, 0, NULL, 0}                                                            Line 38
};                                                                              Block 1
                                                                                
void                                                                            Line 41
usage (int status)                                                              Line 42
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 44
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 46
    {                                                                           
      printf (_("\                                                              Line 48
Usage: %s NAME [SUFFIX]\n\                                                      Line 49
  or:  %s OPTION... NAME...\n\                                                  Line 50
"),                                                                             Line 51
              program_name, program_name);                                      Line 52
      fputs (_("\                                                               Line 53
Print NAME with any leading directory components removed.\n\                    Line 54
If specified, also remove a trailing SUFFIX.\n\                                 Line 55
"), stdout);                                                                    Line 56
                                                                                
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      fputs (_("\                                                               Line 60
  -a, --multiple       support multiple arguments and treat each as a NAME\n\   Line 61
  -s, --suffix=SUFFIX  remove a trailing SUFFIX; implies -a\n\                  Line 62
  -z, --zero           end each output line with NUL, not newline\n\            Line 63
"), stdout);                                                                    Line 64
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 65
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 66
      printf (_("\                                                              Line 67
\n\                                                                             
Examples:\n\                                                                    Line 69
  %s /usr/bin/sort          -> \"sort\"\n\                                      Line 70
  %s include/stdio.h .h     -> \"stdio\"\n\                                     Provides standard I/O capability
  %s -s .h include/stdio.h  -> \"stdio\"\n\                                     Provides standard I/O capability
  %s -a any/str1 any/str2   -> \"str1\" followed by \"str2\"\n\                 Line 73
"),                                                                             Line 74
              program_name, program_name, program_name, program_name);          Line 75
      emit_ancillary_info (PROGRAM_NAME);                                       Line 76
    }                                                                           
  exit (status);                                                                Line 78
}                                                                               Block 2
                                                                                
/* Remove SUFFIX from the end of NAME if it is there, unless NAME               
   consists entirely of SUFFIX.  */                                             
                                                                                
static void                                                                     Line 84
remove_suffix (char *name, const char *suffix)                                  Line 85
{                                                                               
  char *np;                                                                     Line 87
  const char *sp;                                                               Line 88
                                                                                
  np = name + strlen (name);                                                    Line 90
  sp = suffix + strlen (suffix);                                                Line 91
                                                                                
  while (np > name && sp > suffix)                                              Line 93
    if (*--np != *--sp)                                                         Line 94
      return;                                                                   Line 95
  if (np > name)                                                                Line 96
    *np = '\0';                                                                 Line 97
}                                                                               Block 3
                                                                                
/* Perform the basename operation on STRING.  If SUFFIX is non-NULL, remove     
   the trailing SUFFIX.  Finally, output the result string.  */                 
                                                                                
static void                                                                     Line 103
perform_basename (const char *string, const char *suffix, bool use_nuls)        Line 104
{                                                                               
  char *name = base_name (string);                                              Line 106
  strip_trailing_slashes (name);                                                Line 107
                                                                                
  /* Per POSIX, 'basename // /' must return '//' on platforms with              
     distinct //.  On platforms with drive letters, this generalizes            Line 110
     to making 'basename c: :' return 'c:'.  This rule is captured by           Line 111
     skipping suffix stripping if base_name returned an absolute path           Line 112
     or a drive letter (only possible if name is a file-system                  Line 113
     root).  */                                                                 
  if (suffix && IS_RELATIVE_FILE_NAME (name) && ! FILE_SYSTEM_PREFIX_LEN (name))Line 115
    remove_suffix (name, suffix);                                               Line 116
                                                                                
  fputs (name, stdout);                                                         Line 118
  putchar (use_nuls ? '\0' : '\n');                                             Line 119
  free (name);                                                                  Line 120
}                                                                               Block 4
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 124
{                                                                               
  bool multiple_names = false;                                                  Line 126
  bool use_nuls = false;                                                        Line 127
  const char *suffix = NULL;                                                    Line 128
                                                                                
  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)
                                                                                
  while (true)                                                                  Line 138
    {                                                                           
      int c = getopt_long (argc, argv, "+as:z", longopts, NULL);                Line 140
                                                                                
      if (c == -1)                                                              Line 142
        break;                                                                  Line 143
                                                                                
      switch (c)                                                                Line 145
        {                                                                       
        case 's':                                                               Line 147
          suffix = optarg;                                                      Line 148
          /* -s implies -a, so...  */                                           
          FALLTHROUGH;                                                          Line 150
                                                                                
        case 'a':                                                               Line 152
          multiple_names = true;                                                Line 153
          break;                                                                Line 154
                                                                                
        case 'z':                                                               Line 156
          use_nuls = true;                                                      Line 157
          break;                                                                Line 158
                                                                                
        case_GETOPT_HELP_CHAR;                                                  Line 160
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 161
                                                                                
        default:                                                                Line 163
          usage (EXIT_FAILURE);                                                 Line 164
        }                                                                       
    }                                                                           
                                                                                
  if (argc < optind + 1)                                                        Line 168
    {                                                                           
      error (0, 0, _("missing operand"));                                       Line 170
      usage (EXIT_FAILURE);                                                     Line 171
    }                                                                           
                                                                                
  if (!multiple_names && optind + 2 < argc)                                     Line 174
    {                                                                           
      error (0, 0, _("extra operand %s"), quote (argv[optind + 2]));            Line 176
      usage (EXIT_FAILURE);                                                     Line 177
    }                                                                           
                                                                                
  if (multiple_names)                                                           Line 180
    {                                                                           
      for (; optind < argc; optind++)                                           Line 182
        perform_basename (argv[optind], suffix, use_nuls);                      Line 183
    }                                                                           
  else                                                                          Line 185
    perform_basename (argv[optind],                                             Line 186
                      optind + 2 == argc ? argv[optind + 1] : NULL, use_nuls);  Line 187
                                                                                
  return EXIT_SUCCESS;                                                          Line 189
}                                                                               Block 5