Back: A Loadable Module
Forward: Integrating Dmalloc
FastBack: Integrating Dmalloc
Up: A Complex GNU Autotools Project
FastForward: M4
Top: Autoconf, Automake, and Libtool
Contents: Table of Contents
Index: Index
About: About this document

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)

  int status = SIC_OKAY;
  int i;

  for (i = 1; status == SIC_OKAY && argv[i]; ++i)
    status = source (sic, argv[i]);

  return status;

And the source function from `sic_repl.c':

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;
    result =  evalstream (sic, stream);

  is_interactive = save_interactive;

  return result;

The reason for separating the source function in this way, is that it makes it easy for the startup sequence in main to 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;
