scan: New library for high-level PSPP syntax lexical analysis.
[pspp-builds.git] / src / libpspp / getl.c
index dbabde478ed7952b8f69c1e16de8765357ef3504..9db6c3ae56260d3be735efd45588622b4eb2077b 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2009, 2010 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
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#include <stdlib.h>
 #include <config.h>
 
-#include "getl.h"
+#include "libpspp/getl.h"
+
+#include <stdlib.h>
+
+#include "libpspp/ll.h"
+#include "libpspp/str.h"
+#include "libpspp/string-array.h"
 
-#include <libpspp/str.h>
-#include <libpspp/ll.h>
-#include <libpspp/version.h>
-#include <libpspp/alloc.h>
+#include "gl/configmake.h"
+#include "gl/relocatable.h"
+#include "gl/xalloc.h"
 
 struct getl_source
   {
@@ -32,19 +36,22 @@ struct getl_source
     struct ll  ll;   /* Element in the sources list */
 
     struct getl_interface *interface;
+    enum syntax_mode syntax_mode;
+    enum error_mode error_mode;
   };
 
 struct source_stream
   {
     struct ll_list sources ;  /* List of source files. */
-
-    struct string the_include_path;
+    struct string_array include_path;
   };
 
-const char *
-getl_include_path (const struct source_stream *ss)
+char **
+getl_include_path (const struct source_stream *ss_)
 {
-  return ds_cstr (&ss->the_include_path);
+  struct source_stream *ss = CONST_CAST (struct source_stream *, ss_);
+  string_array_terminate_null (&ss->include_path);
+  return ss->include_path.strings;
 }
 
 static struct getl_source *
@@ -54,17 +61,41 @@ current_source (const struct source_stream *ss)
   return ll_data (ll, struct getl_source, ll );
 }
 
+enum syntax_mode
+source_stream_current_syntax_mode (const struct source_stream *ss)
+{
+  struct getl_source *cs = current_source (ss);
+
+  return cs->syntax_mode;
+}
+
+
+
+enum error_mode
+source_stream_current_error_mode (const struct source_stream *ss)
+{
+  struct getl_source *cs = current_source (ss);
+
+  return cs->error_mode;
+}
+
+
+
 /* Initialize getl. */
 struct source_stream *
-create_source_stream (const char *initial_include_path)
+create_source_stream (void)
 {
-  struct source_stream *ss = xzalloc (sizeof (*ss));
+  struct source_stream *ss;
+
+  ss = xzalloc (sizeof (*ss));
   ll_init (&ss->sources);
-#if 0
-  ds_init_cstr (&ss->the_include_path,
-                fn_getenv_default ("STAT_INCLUDE_PATH", include_path));
-#endif
-  ds_init_cstr (&ss->the_include_path, initial_include_path);
+
+  string_array_init (&ss->include_path);
+  string_array_append (&ss->include_path, ".");
+  if (getenv ("HOME") != NULL)
+    string_array_append_nocopy (&ss->include_path,
+                                xasprintf ("%s/.pspp", getenv ("HOME")));
+  string_array_append (&ss->include_path, relocate (PKGDATADIR));
 
   return ss;
 }
@@ -73,33 +104,38 @@ create_source_stream (const char *initial_include_path)
 void
 getl_clear_include_path (struct source_stream *ss)
 {
-  ds_clear (&ss->the_include_path);
+  string_array_clear (&ss->include_path);
 }
 
 /* Add to the include path. */
 void
 getl_add_include_dir (struct source_stream *ss, const char *path)
 {
-  if (ds_length (&ss->the_include_path))
-    ds_put_char (&ss->the_include_path, ':');
-
-  ds_put_cstr (&ss->the_include_path, path);
+  string_array_append (&ss->include_path, path);
 }
 
 /* Appends source S to the list of source files. */
 void
-getl_append_source (struct source_stream *ss, struct getl_interface *i)
+getl_append_source (struct source_stream *ss,
+                   struct getl_interface *i,
+                   enum syntax_mode syntax_mode,
+                   enum error_mode err_mode)
 {
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
 
   s->interface = i ;
+  s->syntax_mode = syntax_mode;
+  s->error_mode = err_mode;
 
-  ll_push_head (&ss->sources, &s->ll);
+  ll_push_tail (&ss->sources, &s->ll);
 }
 
 /* Nests source S within the current source file. */
 void
-getl_include_source (struct source_stream *ss, struct getl_interface *i)
+getl_include_source (struct source_stream *ss,
+                    struct getl_interface *i,
+                    enum syntax_mode syntax_mode,
+                    enum error_mode err_mode)
 {
   struct getl_source *current = current_source (ss);
   struct getl_source *s = xzalloc (sizeof ( struct getl_source ));
@@ -108,6 +144,8 @@ getl_include_source (struct source_stream *ss, struct getl_interface *i)
 
   s->included_from = current ;
   s->includes  = NULL;
+  s->syntax_mode  = syntax_mode;
+  s->error_mode = err_mode;
   current->includes = s;
 
   ll_push_head (&ss->sources, &s->ll);
@@ -174,18 +212,18 @@ getl_source_name (const struct source_stream *ss)
   return s->interface->name (s->interface);
 }
 
-/* Returns the location within the current source, or -1 if there is
-   no current source */
+/* Returns the line number within the current source, or 0 if there is no
+   current source. */
 int
 getl_source_location (const struct source_stream *ss)
 {
   const struct getl_source *s = current_source (ss);
 
   if ( ll_is_empty (&ss->sources) )
-    return -1;
+    return 0;
 
   if ( !s->interface->location )
-    return -1;
+    return 0;
 
   return s->interface->location (s->interface);
 }
@@ -197,7 +235,7 @@ destroy_source_stream (struct source_stream *ss)
 {
   while ( !ll_is_empty (&ss->sources))
     close_source (ss);
-  ds_destroy (&ss->the_include_path);
+  string_array_destroy (&ss->include_path);
 
   free (ss);
 }
@@ -205,10 +243,9 @@ destroy_source_stream (struct source_stream *ss)
 
 /* Reads a single line into LINE.
    Returns true when a line has been read, false at end of input.
-   On success, sets *SYNTAX to the style of the syntax read. */
+*/
 bool
-getl_read_line (struct source_stream *ss, struct string *line,
-               enum getl_syntax *syntax)
+getl_read_line (struct source_stream *ss, struct string *line)
 {
   assert (ss != NULL);
   while (!ll_is_empty (&ss->sources))
@@ -216,12 +253,12 @@ getl_read_line (struct source_stream *ss, struct string *line,
       struct getl_source *s = current_source (ss);
 
       ds_clear (line);
-      if (s->interface->read (s->interface, line, syntax))
+      if (s->interface->read (s->interface, line))
         {
           while (s)
            {
              if (s->interface->filter)
-               s->interface->filter (s->interface, line, *syntax);
+               s->interface->filter (s->interface, line);
              s = s->included_from;
            }