/
mudtem/
mudtem/area/scripts/
mudtem/bin/
mudtem/log/
mudtem/player/
mudtem/slang/autoconf/
mudtem/slang/doc/
mudtem/slang/doc/OLD/help/
mudtem/slang/doc/internal/
mudtem/slang/doc/text/
mudtem/slang/doc/tm/tools/
mudtem/slang/examples/
mudtem/slang/modules/
mudtem/slang/slsh/
mudtem/slang/slsh/lib/
mudtem/slang/slsh/scripts/
mudtem/slang/src/mkfiles/
mudtem/slang/src/util/
mudtem/src/CVS/
mudtem/src/include/
mudtem/src/include/CVS/
mudtem/src/var/CVS/
#!/usr/bin/env slsh
%_debug_info = 1;
% A simple ls designed primarily for windows.

static variable Months = 
  ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
  "Oct", "Nov", "Dec"];

static variable Six_Months_Ago = _time () - 3600*24*30*6;
   

static define parse_mode (mode, x)
{
   variable m;
   if (mode & 4)
     m = "r";
   else m = "-";

   if (mode & 2)
     m += "w";
   else 
     m += "-";
   
   if (x != "x") m += x;
   else if (mode & 1)
     m += "x";
   else
     m += "-";
   
   return m;
}

static define ls_long (file_list, st_list)
{
   _for (0, length(file_list)-1, 1)
     {
	variable i = ();
	variable file = file_list[i];
	variable st = st_list[i];

	variable size, mode, owner, group, symlink, mtime;
	variable mstring;
	variable tm;

	size = st.st_size;
	mtime = st.st_mtime;
	mode = st.st_mode;
	owner = st.st_uid;
	group = st.st_gid;

	tm = localtime (mtime);
#ifdef WIN32
	if (tm == NULL)
	  mtime = "Jan 01  1980";
	else
#endif
	if (mtime < Six_Months_Ago)
	  mtime = sprintf ("%s %2d  %4d", 
			   Months[tm.tm_mon],
			   tm.tm_mday,
			   1900 + tm.tm_year);
	else
	  mtime = sprintf ("%s %2d %2d:%02d",
			   Months[tm.tm_mon],
			   tm.tm_mday,
			   tm.tm_hour,
			   tm.tm_min);

			   
	symlink = "";
	if (stat_is ("reg", mode))
	  mstring = "-";
	else if (stat_is ("dir", mode))
	  mstring = "d";
	else if (stat_is ("lnk", mode))
	  {
	     %symlink = " -> " + 
	     mstring = "l";
	  }
	else if (stat_is ("chr"))
	  mstring = "c";
	else
	  mstring = "?";
	     
	variable x = "x";
	if (mode & 04000) x = "s";
	mstring += parse_mode (mode shr 6, x);
	x = "x"; if (mode & 02000) x = "g";
	mstring += parse_mode (mode shr 3, x);
	x = "x"; if (mode & 02000) x = "t";
	mstring += parse_mode (mode, x);

	() = fprintf (stdout,
		      "%8s %8S %8S %10S %s %s%s\n",
		      mstring, owner, group, size, mtime, file, symlink);
     }
}

static variable 
  Use_Long_Form = 0,
  Use_atime = 0,
  Sort_By_Time = 0,
  Sort_By_Size = 0,
  Use_a_Option = 0,
  Use_F_Option = 1,
  Use_d_Option = 0;


static define parse_args (args)
{
   variable ch;
   
   foreach (args)
     {
	ch = ();
	switch (ch)
	  { case 'l': Use_Long_Form = 1; }
	  { case 'u': Use_atime = 1; }
	  { case 't': Sort_By_Time = 1; }
	  { case 'S': Sort_By_Size = 1; }
	  { case 'd': Use_d_Option = 1; }
	  { case 'a': Use_a_Option = 1; }
	  { case '-':}		       %  ignore it
	  {
	     () = fprintf (stderr, "Option '%c' not supported.\n", ch);
	  }
     }
}

define ls_short (dirs)
{
   variable max_len;
   variable ncols;
   variable num, num_per_row, num_rows;
   variable stride;

   num = length (dirs);
   max_len = 0;
   foreach (dirs)
     {
	variable dir;
	
	dir = ();
	if (strlen (dir) > max_len)
	  max_len = strlen (dir);
     }

   max_len += 2;
   
   variable format = "%-" + string (max_len) + "s";

   ncols = 80;
   num_per_row = ncols / max_len;
   if (num_per_row == 0)
     num_per_row = 1;

   num_rows = (num + num_per_row - 1) / num_per_row;
   _for (0, num_rows-1, 1)
     {
	variable r = ();
	_for (0, num_per_row-1, 1)
	  {
	     variable c = ();
	     variable i = r + num_rows * c;

	     if (i < num)
	       () = fprintf (stdout, format, dirs[i]);
	  }
	() = fputs ("\n", stdout);
     }
}

static define size_sort (a, b)
{
   b.st_size - a.st_size;
}

static define time_sort (a, b)
{
   b.st_mtime - a.st_mtime;
}

static define is_non_null_fun (a)
{
   a != NULL;
}


define sort_files (dirs, sts)
{
   variable st, i, non_null;
   
   % Some of the sts structs may be NULL.  Get rid of those
   non_null = array_map (Char_Type, &is_non_null_fun, sts);

   i = where (non_null);
   dirs = dirs [i];
   sts = sts [i];

   
   if (Use_atime)
     {
	foreach (sts)
	  {
	     st = ();
	     st.st_mtime = st.st_atime;
	  }
     }
   
   if (Sort_By_Time)
     i = array_sort (sts, &time_sort);
   else if (Sort_By_Size)
     i = array_sort (sts, &size_sort);
   else
     i = array_sort (dirs);
   
   return dirs[i], sts[i];
}

static define isdir_fun (st)
{
   stat_is ("dir", st.st_mode);
}

   
define do_ls (dirs, recurse);
define do_ls (dirs, this_dir, recurse, prune_hidden)
{
   variable i, len, st, sts, dir;

   if (dirs == NULL)
     return;

   len = length(dirs);
   sts = Struct_Type [len];


   _for (0, len-1, 1)
     {
	i = ();
	dir = dirs[i];

	if (prune_hidden)
	  {
	     if ((dir[0] == '.') and (Use_a_Option == 0))
	       continue;
	  }

	st = lstat_file (path_concat (this_dir, dir));
	if (st == NULL)
	  () = fprintf (stderr, "%s: %s: %s\n",
			__argv[0],
			path_concat (this_dir, dir),
			errno_string (errno));
	else
	  sts[i] = st;
     }


   (dirs, sts) =  sort_files (dirs, sts);

   variable isdir = array_map (Char_Type, &isdir_fun, sts);
   variable i_reg = where (isdir == 0);
   variable i_dir = where (isdir);


   if (Use_F_Option)
     dirs[i_dir] = array_map (String_Type, &path_concat, dirs[i_dir], "");


   if ((recurse == 0)
       or Use_d_Option)
     {
	if (Use_Long_Form)
	  ls_long (dirs, sts);
	else
	  ls_short (dirs);
	return;
     }

   if (Use_Long_Form)
     ls_long (dirs[i_reg], sts[i_reg]);
   else
     ls_short (dirs[i_reg]);
	

   if (length(i_dir) == 1)
     {
	dir = dirs[i_dir][0];
	
	do_ls (listdir (dir), dir, 0, 1);
	return;
     }

   foreach (dirs[i_dir])
     {
	dir = ();
	() = fprintf (stdout, "%s:\n", dir);
	do_ls (listdir (dir), dir, 0, 1);
	() = fprintf (stdout, "\n");
     }
}

define main (argc, argv)
{
   variable dirs;

   if (argc == 1)
     return do_ls (listdir("."), ".", 0, 1);
   else if (__argv[1][0] == '-')
     {
	parse_args (__argv[1]);
	if (__argc > 2)
	  dirs = __argv[[2:]];
	else
	  return do_ls (listdir("."), ".", 0, 1);
     }
   else
     dirs = __argv[[1:]];

   do_ls (dirs, ".", 1, 0);
}

   
main (__argc, __argv);