⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfls.c

📁 OXCC is a multipass, interpreting C compiler with several language extensions. It generates an Archi
💻 C
📖 第 1 页 / 共 5 页
字号:
            len += 4;
      }
    }
    else
      len += 1;
  }

  if (indicator_style != none)
  {
    if (filetype == S_IFREG)
    {
      if (indicator_style == all
        && (f->stats.st_mode & (S_IEXEC | S_IEXEC >> 3 | S_IEXEC >> 6)))
        len += 1;
    }
    else if (filetype & S_IFDIR
#ifdef S_IFLNK
         || filetype == S_IFLNK
#endif
#ifdef S_IFIFO
         || filetype == S_IFIFO
#endif
#ifdef S_IFSOCK
         || filetype == S_IFSOCK
#endif
      ) len += 1;
  }
#ifdef PCDOS
  if(format == many_per_line)
  {
    if(filetype == S_IFDIR)
    {
      len += 2;
      if(indicator_style != none) --len;
    }
  }
#endif
  return len;
}

void
print_many_per_line ()

{
  int filesno;      /* Index into files. */
  int row;      /* Current row. */
  int max_name_length;    /* Length of longest file name + frills. */
  int name_length;    /* Length of each file name + frills. */
  int pos;      /* Current character column. */
  int cols;     /* Number of files across. */
  int rows;     /* Maximum number of files down. */

  /* Compute the maximum file name length.  */
  max_name_length = 0;
  for (filesno = 0; filesno < files_index; filesno++)
  {
    name_length = length_of_file_name_and_frills (files + filesno);
    if (name_length > max_name_length)
      max_name_length = name_length;
  }

  /* Allow at least two spaces between names.  */
  max_name_length += 2;

  /* Calculate the maximum number of columns that will fit. */
  cols = line_length / max_name_length;
  if (cols == 0)
    cols = 1;
  /* Calculate the number of rows that will be in each column except possibly
     for a short column on the right. */
  rows = files_index / cols + (files_index % cols != 0);
  /* Recalculate columns based on rows. */
  cols = files_index / rows + (files_index % rows != 0);

  for (row = 0; row < rows; row++)
  {
    filesno = row;
    pos = 0;
      /* Print the next row.  */
    while (1)
    {
      print_file_name_and_frills (files + filesno);
      name_length = length_of_file_name_and_frills (files + filesno);

      filesno += rows;
      if (filesno >= files_index)
        break;

      indent (pos + name_length, pos + max_name_length);
      pos += max_name_length;
    }
    putchar ('\n');
  }
}

void
print_horizontal ()

{
  int filesno;
  int max_name_length;
  int name_length;
  int cols;
  int pos;

  /* Compute the maximum file name length.  */
  max_name_length = 0;
  for (filesno = 0; filesno < files_index; filesno++)
  {
    name_length = length_of_file_name_and_frills (files + filesno);
    if (name_length > max_name_length)
      max_name_length = name_length;
  }

  /* Allow two spaces between names.  */
  max_name_length += 2;

  cols = line_length / max_name_length;
  if (cols == 0)
    cols = 1;

  pos = 0;
  name_length = 0;

  for (filesno = 0; filesno < files_index; filesno++)
  {
    if (filesno != 0)
    {
      if (filesno % cols == 0)
      {
        putchar ('\n');
        pos = 0;
      }
      else
      {
        indent (pos + name_length, pos + max_name_length);
        pos += max_name_length;
      }
    }

    print_file_name_and_frills (files + filesno);

    name_length = length_of_file_name_and_frills (files + filesno);
  }
  putchar ('\n');
}

void
print_with_commas ()

{
  int filesno;
  int pos, old_pos;

  pos = 0;

  for (filesno = 0; filesno < files_index; filesno++)
  {
    old_pos = pos;

    pos += length_of_file_name_and_frills (files + filesno);
    if (filesno + 1 < files_index)
      pos += 2;   /* For the comma and space */

    if (old_pos != 0 && pos >= line_length)
    {
      putchar ('\n');
      pos -= old_pos;
    }

    print_file_name_and_frills (files + filesno);
    if (filesno + 1 < files_index)
    {
      putchar (',');
      putchar (' ');
    }
  }
  putchar ('\n');
}

#ifndef PCDOS
struct userid
{
  unsigned short uid;
  char *name;
  struct userid *next;
};

struct userid *user_alist;

/* Translate `uid' to a login name, with cache.  */

char *
getuser (uid)
     unsigned short uid;

{
  register struct userid *tail;
  struct passwd *pwent;
  char usernum_string[20];

  for (tail = user_alist; tail; tail = tail->next)
    if (tail->uid == uid)
      return tail->name;

  pwent = getpwuid (uid);
  tail = (struct userid *) xmalloc (sizeof (struct userid));
  tail->uid = uid;
  tail->next = user_alist;
  if (pwent == NULL)
  {
    sprintf (usernum_string, "%u", (unsigned short) uid);
    tail->name = copystring (usernum_string);
  }
  else
    tail->name = copystring (pwent->pw_name);
  user_alist = tail;
  return tail->name;
}

/* We use the same struct as for userids.  */
struct userid *group_alist;

/* Translate `gid' to a group name, with cache.  */

char *
getgroup (gid)
     unsigned short gid;

{
  register struct userid *tail;
  struct group *grent;
  char groupnum_string[20];

  for (tail = group_alist; tail; tail = tail->next)
    if (tail->uid == gid)
      return tail->name;

  grent = getgrgid (gid);
  tail = (struct userid *) xmalloc (sizeof (struct userid));
  tail->uid = gid;
  tail->next = group_alist;
  if (grent == NULL)
  {
    sprintf (groupnum_string, "%u", (unsigned int) gid);
    tail->name = copystring (groupnum_string);
  }
  else
    tail->name = copystring (grent->gr_name);
  group_alist = tail;
  return tail->name;
}
#endif
/* Assuming cursor is at position `from', indent up to position `to'.  */

void
indent (from, to)
     int from, to;

{
  while (from < to)
  {
    if (to / tabsize > from / tabsize)
    {
      putchar ('\t');
      from += tabsize - from % tabsize;
    }
    else
    {
      putchar (' ');
      from++;
    }
  }
}

/* Low level subroutines of general use,
   not specifically related to the task of listing a directory.  */

char *
xrealloc (obj, size)
void *obj;
int size;

{
  char *val = realloc (obj, size);

  if (!val)
    error (1, 0, "virtual memory exhausted");

  return val;
}

char *
xmalloc (size)
     int size;

{
  char *val = malloc (size);

  if (!val)
    error (1, 0, "virtual memory exhausted");

  return val;
}

/* Return a newly allocated copy of `string'. */

char *
copystring (string)
     char *string;

{
  return strcpy ((char *) xmalloc (strlen (string) + 1), string);
}

/* Put `dirname/name' into `dest', handling `.' and `/' properly. */

void
attach (dest, dirname, name)
     char *dest, *dirname, *name;

{
  char *dirnamep = dirname;

  /* Copy dirname if it is not ".". */
  if (dirname[0] != '.' || dirname[1] != 0)
  {
    while (*dirnamep)
      *dest++ = *dirnamep++;
      /* Add '/' if `dirname' doesn't already end with it. */
    if (dirnamep > dirname && (dirnamep[-1] != '/'
#ifdef PCDOS
          && dirnamep[-1] != ':'
#endif
          ))
      *dest++ = '/';
  }
  while (*name)
    *dest++ = *name++;
  *dest = 0;
}

/* Check for a globbing pattern in an explicit argument, the shell may
  have passed it along, always for PCDOS. */

int
if_pattern(name)
register char *name;

{
  register char ch;
  while (ch = *name++)
    if (ch == '*' || ch == '?' || ch == '[')
      return 1;
  return 0;
}
#ifdef PCDOS
void lose_backslashes(char *path)

{
  while(*path)
  {
    if(*path == '\\') *path = '/';
    ++path;
  }
}
#endif

void
usage ()

{
  fprintf (stdout, "\
Usage: ls [-abdgiklnpqrstxABCFNQRSUX1] [path...]\n");
  fprintf (stdout, "\n\
  Switch-------------------Meaning\n\
  a, +all                  List all files.\n\
  b, +escape               Quote nongraphic characters.\n\
  d, +directory            List directory name, not contents.\n\
  g,                       Ignored for Unix compatibility.\n\
  i, +inode                Print index number of each file.\n\
  k, +kilobytes            Print file sizes in kilobyte blocks.\n\
  l, +format=long          Print in long format.\n\
  m, +format=commas        List files horizontally, separated by commas.\n\
  p                        Put '/' after each directory, if not multi-col.\n\
  r, +reverse              Sort in reverse order.\n\
  s, +size                 Print the size of each file in blocks allocated.\n\
  t, +sort=time            Sort directory contents by timestamp.\n\
  x, +format=across        Multi-column, sorted horizontally.\n\
  A, +almost-all           List all files except for '.' and '..'.\n\
  B, +ignore-backups       Do not list files that end with '~'.\n\
  C, +format=vertical      Multi-column, sorted vertically.\n\
  F, +classify             Tag the file type of each file.\n\
  N, +literal              Do not quote file names.\n\
  Q, +quote-name           Enclose file names in double quotes.\n\
  R, +recursive            List the contents of directories recursively.\n\
  S, +sort=size            Sort directory contents by file size.\n\
  U, +sort=none            Do not sort directory contents.\n\
  X, +sort=extension       Sort directory contents by file extension.\n\
  1, +format=single-column List one file per line.\n\
  w, +width cols           Assume screen width to be 'cols' wide.\n\
  T. +tabsize cols         Assume that each tabstop is 'cols' wide.\n\
  I, +ignore pattern       Do not list files that match 'pattern'.\n");

  exit (1);
}
/* Getopt for GNU.
   Copyright (C) 1987, 1989, 1990 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 1, 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, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#ifdef __STDC__
#define CONST const
#else
#define CONST
#endif

/* This version of `getopt' appears to the caller like standard Unix `getopt'
   but it behaves differently for the user, since it allows the user
   to intersperse the options with the other arguments.

   As `getopt' works, it permutes the elements of `argv' so that,
   when it is done, all the options precede everything else.  Thus
   all application programs are extended to handle flexible argument order.

   Setting the environment variable _POSIX_OPTION_ORDER disables permutation.
   Then the behavior is completely standard.

   GNU application programs can use a third alternative mode in which
   they can distinguish the relative order of options and other arguments.  */


/* For communication from `getopt' to the caller.
   When `getopt' finds an option that takes an argument,
   the argument value is returned here.
   Also, when `ordering' is RETURN_IN_ORDER,
   each non-option ARGV-element is returned here.  */

char *optarg = 0;

/* Index in ARGV of the next element to be scanned.
   This is used for communication to and from the caller
   and for communication between successive calls to `getopt'.

   On entry to `getopt', zero means this is the first call; initialize.

   When `getopt' returns EOF, this is the index of the first of the
   non-option elements that the caller should itself scan.

   Otherwise, `optind' communicates from one call to the next
   how much of ARGV has been scanned so far.  */

int optind = 0;

/* The next char to be scanned in the option-element
   in which the last option character we returned was found.
   This allows us to pick up the scan where we left off.

   If this is zero, or a null string, it means resume the scan
   by advancing to the next ARGV-element.  */

static char *nextchar;

/* Callers store zero here to inhibit the error message
   for unrecognized options.  */

int opterr = 1;

/* Describe how to deal with options that follow non-option ARGV-elements.

   If the caller did not specify anything,
   the default is REQUIRE_ORDER if the environment variable
   _POSIX_OPTION_ORDER is defined, PERMUTE otherwise.

   REQUIRE_ORDER means don't recognize them as options;
   stop option processing when the first non-option is seen.
   This is what Unix does.
   This mode of operation is selected by either setting the environment
   variable _POSIX_OPTION_ORDER, or using `+' as the first character
   of the list of option characters.

   PERMUTE is the default.  We permute the contents of ARGV as we scan,
   so that eventually all the non-options are at the end.  This allows options
   to be given in any order, even with programs that were not written to
   expect this.

   RETURN_IN_ORDER is an option available to programs that were written
   to expect options and other ARGV-elements in any order and that care about
   the ordering of the two.  We describe each non-option ARGV-element
   as if it were the argument of an option with character code 1.
   Using `-' as the first character of the list of option characters
   selects this mode of operation.

   The special argument `--' forces an end of option-scanning regardless
   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */

static enum
{
  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;

/* Describe the long-named options requested by the application.
   _GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an
   element containing a name which is zero.
   The field `has_arg' is 1 if the option takes an argument,
   2 if it takes an optional argument.  */


CONST struct option *_getopt_long_options;

int _getopt_long_only = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -