|  |  20.3 Interpreting Commands from a File 
For all practical purposes, any interpreter is pretty useless if it only
works interactively.  I have added a `source' built-in command to
`sic_builtin.c' which takes lines of input from a file and
evaluates them using `sic_repl.c' in much the same way as lines
typed at the prompt are evaluated otherwise.  Here is the built-in handler:
 
 |  | 
 /* List of built in functions. */
#define builtin_functions               \
        BUILTIN(exit,           0, 1)   \
        BUILTIN(load,           1, 1)   \
        BUILTIN(source,         1, -1)  \
        BUILTIN(unload,         1, -1)
BUILTIN_DECLARATION (source)
{
  int status = SIC_OKAY;
  int i;
  for (i = 1; status == SIC_OKAY && argv[i]; ++i)
    status = source (sic, argv[i]);
  return status;
}
 | 
 
And the sourcefunction from `sic_repl.c': 
 |  | 
 int
source (Sic *sic, const char *path)
{
  FILE *stream;
  int result = SIC_OKAY;
  int save_interactive = is_interactive;
  SIC_ASSERT (sic && path);
  
  is_interactive = 0;
  if ((stream = fopen (path, "rt")) == NULL)
    {
      sic_result_clear (sic);
      sic_result_append (sic, "cannot source \"", path, "\": ",
                         strerror (errno), NULL);
      result = SIC_ERROR;
    }
  else
    result =  evalstream (sic, stream);
  is_interactive = save_interactive;
  return result;
}
 | 
 
The reason for separating the sourcefunction in this way, is
that it makes it easy for the startup sequence inmainto
evaluate a startup file.  In traditional Unix fashion, the startup file
is named `.sicrc', and is evaluated if it is present in the user's
home directory: 
 |  | 
 static int
evalsicrc (Sic *sic)
{
  int result = SIC_OKAY;
  char *home = getenv ("HOME");
  char *sicrcpath, *separator = "";
  int len;
  if (!home)
    home = "";
  len = strlen (home);
  if (len && home[len -1] != '/')
    separator = "/";
  len += strlen (separator) + strlen (SICRCFILE) + 1;
  sicrcpath = XMALLOC (char, len);
  sprintf (sicrcpath, "%s%s%s", home, separator, SICRCFILE);
  if (access (sicrcpath, R_OK) == 0)
    result = source (sic, sicrcpath);
  return result;
}
 | 
 
 |