//-------------------------------------------------------------------//

//  Synopsis:   Check R-files for global variable references.

//  Syntax:	lcheck ( FR )

//  Description:

//  lcheck uses the built-in function, fvscope, to look for global
//  variable references from within functions. Global variable
//  references, from within functions are not necessarily
//  bad. However, when writing a library of R-files for widespread
//  usage it is best to avoid references to global variables, other
//  than functions.

//  lcheck takes a single string argument, FR, which is the
//  filename(s) of the R-files to be checked. FR will be expanded by
//  the shell, so shell meta-characters are allowed.

//         lcheck ("*.r");

//  The above will check all the R-files (files with a suffix of `.r')
//  with fvscope, prompting the user for a return between files.

//  Note: Do not execute this function on itself.

//  Dependencies:
//     This file requires AWK, preferrable mawk.

//-------------------------------------------------------------------//

//
// A simple AWK program
//

static (fname_awk)
fname_awk = "/=[ ]*function[ ]*\(*/ { fn = 1; print $1 }"+...
            "END { if (!fn) { printf(\"NO_FUNCTION_NAMES...\\n\"); }}";

static (AWK)
AWK = "mawk";

lcheck = function ( FR )
{
  local (ans, flist, i, fname, str1, str2, str3, str4)

  if (class (FR) != "string") 
  {
    error ("lcheck: requires a string argument");
  }

  str1 = "| ls "+FR;
  str3 = "| "+ AWK + " '/\*/'";

  while (length (ans = getline (str1)))
  {
    for (i in members (ans))
    {
      str2 = "| "+AWK+" '" + fname_awk + "' < "+ans.[i];
      flist = getline (str2);
      if (flist.[1] != "NO_FUNCTION_NAMES...")
      {
	fname = flist.[1];
	printf ("Checking variable scope in: %s\n", fname);
	load (ans.[i]);
	str4 = "fvscope (" + fname + ",\"" + str3 + "\")";
	eval (str4);
	close (str3);
	pause ();
      }
      close (str2);
    }
  }
  close (str1);
};
