Constness and global namespace patrol.
[pspp-builds.git] / src / language / lexer / lexer.c
index ec8c45103bc9378fa88df355fa18a5c173c07ea0..452eb7e7beee0ca91471022b42ecf3cd8c05d9ea 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
 #include <language/command.h>
 #include <libpspp/message.h>
 #include <language/line-buffer.h>
@@ -34,6 +35,8 @@
 #include <data/settings.h>
 #include <libpspp/str.h>
 
+#include "size_max.h"
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
 */
 
 \f
-/* Global variables. */
-
-extern const char *keywords[T_N_KEYWORDS + 1];
-
-
 /* Current token. */
 int token;
 
@@ -66,11 +64,11 @@ struct string tokstr;
 /* Pointer to next token in getl_buf. */
 static char *prog;
 
-/* Nonzero only if this line ends with a terminal dot. */
-static int dot;
+/* True only if this line ends with a terminal dot. */
+static bool dot;
 
-/* Nonzero only if the last token returned was T_STOP. */
-static int eof;
+/* True only if the last token returned was T_STOP. */
+static bool eof;
 
 /* If nonzero, next token returned by lex_get().
    Used only in exceptional circumstances. */
@@ -89,7 +87,6 @@ enum string_type
     HEX_STRING          /* Hexadecimal digits. */
   };
 
-static void convert_numeric_string_to_char_string (enum string_type);
 static int parse_string (enum string_type);
 
 #if DUMP_TOKENS
@@ -102,8 +99,8 @@ static void dump_token (void);
 void
 lex_init (void)
 {
-  ds_init (&tokstr, 64);
-  ds_init (&put_tokstr, 64);
+  ds_init_empty (&tokstr);
+  ds_init_empty (&put_tokstr);
   if (!lex_get_line ())
     eof = true;
 }
@@ -125,8 +122,8 @@ restore_token (void)
 {
   assert (put_token != 0);
   token = put_token;
-  ds_replace (&tokstr, ds_c_str (&put_tokstr));
-  str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
+  ds_assign_string (&tokstr, &put_tokstr);
+  str_copy_trunc (tokid, sizeof tokid, ds_cstr (&tokstr));
   tokval = put_tokval;
   put_token = 0;
 }
@@ -137,7 +134,7 @@ static void
 save_token (void) 
 {
   put_token = token;
-  ds_replace (&put_tokstr, ds_c_str (&tokstr));
+  ds_assign_string (&put_tokstr, &tokstr);
   put_tokval = tokval;
 }
 
@@ -184,7 +181,7 @@ lex_get (void)
            }
          else if (!lex_get_line ())
            {
-             eof = 1;
+             eof = true;
              token = T_STOP;
 #if DUMP_TOKENS
              dump_token ();
@@ -223,7 +220,7 @@ lex_get (void)
               negative numbers into two tokens. */
            if (*prog == '-')
              {
-               ds_putc (&tokstr, *prog++);
+               ds_put_char (&tokstr, *prog++);
                while (isspace ((unsigned char) *prog))
                  prog++;
 
@@ -239,32 +236,32 @@ lex_get (void)
                 
            /* Parse the number, copying it into tokstr. */
            while (isdigit ((unsigned char) *prog))
-             ds_putc (&tokstr, *prog++);
+             ds_put_char (&tokstr, *prog++);
            if (*prog == '.')
              {
-               ds_putc (&tokstr, *prog++);
+               ds_put_char (&tokstr, *prog++);
                while (isdigit ((unsigned char) *prog))
-                 ds_putc (&tokstr, *prog++);
+                 ds_put_char (&tokstr, *prog++);
              }
            if (*prog == 'e' || *prog == 'E')
              {
-               ds_putc (&tokstr, *prog++);
+               ds_put_char (&tokstr, *prog++);
                if (*prog == '+' || *prog == '-')
-                 ds_putc (&tokstr, *prog++);
+                 ds_put_char (&tokstr, *prog++);
                while (isdigit ((unsigned char) *prog))
-                 ds_putc (&tokstr, *prog++);
+                 ds_put_char (&tokstr, *prog++);
              }
 
            /* Parse as floating point. */
-           tokval = strtod (ds_c_str (&tokstr), &tail);
+           tokval = strtod (ds_cstr (&tokstr), &tail);
            if (*tail)
              {
                msg (SE, _("%s does not form a valid number."),
-                    ds_c_str (&tokstr));
+                    ds_cstr (&tokstr));
                tokval = 0.0;
 
                ds_clear (&tokstr);
-               ds_putc (&tokstr, '0');
+               ds_put_char (&tokstr, '0');
              }
 
            break;
@@ -386,9 +383,9 @@ parse_id (void)
   const char *start = prog;
   prog = lex_skip_identifier (start);
 
-  ds_concat (&tokstr, start, prog - start);
-  str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
-  return lex_id_to_token (ds_c_str (&tokstr), ds_length (&tokstr));
+  ds_put_substring (&tokstr, ss_buffer (start, prog - start));
+  str_copy_trunc (tokid, sizeof tokid, ds_cstr (&tokstr));
+  return lex_id_to_token (ds_cstr (&tokstr), ds_length (&tokstr));
 }
 
 /* Reports an error to the effect that subcommand SBC may only be
@@ -449,7 +446,7 @@ lex_end_of_command (void)
   if (token != '.')
     {
       lex_error (_("expecting end of command"));
-      return CMD_TRAILING_GARBAGE;
+      return CMD_FAILURE;
     }
   else
     return CMD_SUCCESS;
@@ -495,48 +492,48 @@ lex_integer (void)
 \f  
 /* Token matching functions. */
 
-/* If TOK is the current token, skips it and returns nonzero.
-   Otherwise, returns zero. */
-int
+/* If TOK is the current token, skips it and returns true
+   Otherwise, returns false. */
+bool
 lex_match (int t)
 {
   if (token == t)
     {
       lex_get ();
-      return 1;
+      return true;
     }
   else
-    return 0;
+    return false;
 }
 
 /* If the current token is the identifier S, skips it and returns
-   nonzero.  The identifier may be abbreviated to its first three
+   true.  The identifier may be abbreviated to its first three
    letters.
-   Otherwise, returns zero. */
-int
+   Otherwise, returns false. */
+bool
 lex_match_id (const char *s)
 {
   if (token == T_ID && lex_id_match (s, tokid))
     {
       lex_get ();
-      return 1;
+      return true;
     }
   else
-    return 0;
+    return false;
 }
 
-/* If the current token is integer N, skips it and returns nonzero.
-   Otherwise, returns zero. */
-int
+/* If the current token is integer N, skips it and returns true.
+   Otherwise, returns false. */
+bool
 lex_match_int (int x)
 {
   if (lex_is_integer () && lex_integer () == x)
     {
       lex_get ();
-      return 1;
+      return true;
     }
   else
-    return 0;
+    return false;
 }
 \f
 /* Forced matches. */
@@ -544,91 +541,91 @@ lex_match_int (int x)
 /* If this token is identifier S, fetches the next token and returns
    nonzero.
    Otherwise, reports an error and returns zero. */
-int
+bool
 lex_force_match_id (const char *s)
 {
   if (token == T_ID && lex_id_match (s, tokid))
     {
       lex_get ();
-      return 1;
+      return true;
     }
   else
     {
       lex_error (_("expecting `%s'"), s);
-      return 0;
+      return false;
     }
 }
 
 /* If the current token is T, skips the token.  Otherwise, reports an
-   error and returns from the current function with return value 0. */
-int
+   error and returns from the current function with return value false. */
+bool
 lex_force_match (int t)
 {
   if (token == t)
     {
       lex_get ();
-      return 1;
+      return true;
     }
   else
     {
       lex_error (_("expecting `%s'"), lex_token_name (t));
-      return 0;
+      return false;
     }
 }
 
-/* If this token is a string, does nothing and returns nonzero.
-   Otherwise, reports an error and returns zero. */
-int
+/* If this token is a string, does nothing and returns true.
+   Otherwise, reports an error and returns false. */
+bool
 lex_force_string (void)
 {
   if (token == T_STRING)
-    return 1;
+    return true;
   else
     {
       lex_error (_("expecting string"));
-      return 0;
+      return false;
     }
 }
 
-/* If this token is an integer, does nothing and returns nonzero.
-   Otherwise, reports an error and returns zero. */
-int
+/* If this token is an integer, does nothing and returns true.
+   Otherwise, reports an error and returns false. */
+bool
 lex_force_int (void)
 {
   if (lex_is_integer ())
-    return 1;
+    return true;
   else
     {
       lex_error (_("expecting integer"));
-      return 0;
+      return false;
     }
 }
        
-/* If this token is a number, does nothing and returns nonzero.
-   Otherwise, reports an error and returns zero. */
-int
+/* If this token is a number, does nothing and returns true.
+   Otherwise, reports an error and returns false. */
+bool
 lex_force_num (void)
 {
   if (lex_is_number ())
-    return 1;
+    return true;
   else
     {
       lex_error (_("expecting number"));
-      return 0;
+      return false;
     }
 }
        
-/* If this token is an identifier, does nothing and returns nonzero.
-   Otherwise, reports an error and returns zero. */
-int
+/* If this token is an identifier, does nothing and returns true.
+   Otherwise, reports an error and returns false. */
+bool
 lex_force_id (void)
 {
   if (token == T_ID)
-    return 1;
+    return true;
   else
     {
       lex_error (_("expecting identifier"));
-      return 0;
+      return false;
     }
 }
 /* Weird token functions. */
@@ -693,8 +690,8 @@ lex_put_back_id (const char *id)
   assert (lex_id_to_token (id, strlen (id)) == T_ID);
   save_token ();
   token = T_ID;
-  ds_replace (&tokstr, id);
-  str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr));
+  ds_assign_cstr (&tokstr, id);
+  str_copy_trunc (tokid, sizeof tokid, ds_cstr (&tokstr));
 }
 \f
 /* Weird line processing functions. */
@@ -703,7 +700,7 @@ lex_put_back_id (const char *id)
 const char *
 lex_entire_line (void)
 {
-  return ds_c_str (&getl_buf);
+  return ds_cstr (&getl_buf);
 }
 
 /* As lex_entire_line(), but only returns the part of the current line
@@ -724,7 +721,8 @@ void
 lex_discard_line (void)
 {
   prog = ds_end (&getl_buf);
-  dot = put_token = 0;
+  dot = false;
+  put_token = 0;
 }
 
 /* Sets the current position in the current line to P, which must be
@@ -734,6 +732,25 @@ lex_set_prog (char *p)
 {
   prog = p;
 }
+
+/* Discards the rest of the current command.
+   When we're reading commands from a file, we skip tokens until
+   a terminal dot or EOF.
+   When we're reading commands interactively from the user,
+   that's just discarding the current line, because presumably
+   the user doesn't want to finish typing a command that will be
+   ignored anyway. */
+void
+lex_discard_rest_of_command (void) 
+{
+  if (!getl_is_interactive ())
+    {
+      while (token != T_STOP && token != '.')
+       lex_get ();
+    }
+  else 
+    lex_discard_line (); 
+}
 \f
 /* Weird line reading functions. */
 
@@ -748,7 +765,7 @@ strip_comments (struct string *string)
 
   in_comment = false;
   quote = EOF;
-  for (cp = ds_c_str (string); *cp; )
+  for (cp = ds_cstr (string); *cp; )
     {
       /* If we're not in a comment, check for quote marks. */
       if (!in_comment)
@@ -798,7 +815,7 @@ lex_get_line (void)
     return false;
 
   strip_comments (line);
-  ds_rtrim_spaces (line);
+  ds_rtrim (line, ss_cstr (CC_SPACES));
   
   /* Check for and remove terminal dot. */
   dot = (ds_chomp (line, get_endcmd ())
@@ -816,7 +833,7 @@ lex_get_line (void)
        put_token = '.';
     }
 
-  prog = ds_c_str (line);
+  prog = ds_cstr (line);
 
   return true;
 }
@@ -837,7 +854,7 @@ lex_token_name (int token)
       return t;
     }
 
-  return _("<ERROR>");
+  NOT_REACHED ();
 }
 
 /* Returns an ASCII representation of the current token as a
@@ -852,7 +869,7 @@ lex_token_representation (void)
     case T_ID:
     case T_POS_NUM:
     case T_NEG_NUM:
-      return xstrdup (ds_c_str (&tokstr));
+      return ds_xstrdup (&tokstr);
       break;
 
     case T_STRING:
@@ -860,7 +877,7 @@ lex_token_representation (void)
        int hexstring = 0;
        char *sp, *dp;
 
-       for (sp = ds_c_str (&tokstr); sp < ds_end (&tokstr); sp++)
+       for (sp = ds_cstr (&tokstr); sp < ds_end (&tokstr); sp++)
          if (!isprint ((unsigned char) *sp))
            {
              hexstring = 1;
@@ -875,14 +892,14 @@ lex_token_representation (void)
        *dp++ = '\'';
 
        if (!hexstring)
-         for (sp = ds_c_str (&tokstr); *sp; )
+         for (sp = ds_cstr (&tokstr); *sp; )
            {
              if (*sp == '\'')
                *dp++ = '\'';
              *dp++ = (unsigned char) *sp++;
            }
        else
-         for (sp = ds_c_str (&tokstr); sp < ds_end (&tokstr); sp++)
+         for (sp = ds_cstr (&tokstr); sp < ds_end (&tokstr); sp++)
            {
              *dp++ = (((unsigned char) *sp) >> 4)["0123456789ABCDEF"];
              *dp++ = (((unsigned char) *sp) & 15)["0123456789ABCDEF"];
@@ -914,7 +931,7 @@ lex_token_representation (void)
        }
     }
        
-  assert (0);
+  NOT_REACHED ();
 }
 \f
 /* Really weird functions. */
@@ -930,7 +947,7 @@ lex_negative_to_dash (void)
     {
       token = T_POS_NUM;
       tokval = -tokval;
-      ds_replace (&tokstr, ds_c_str (&tokstr) + 1);
+      ds_assign_substring (&tokstr, ds_substr (&tokstr, 1, SIZE_MAX));
       save_token ();
       token = '-';
     }
@@ -940,7 +957,7 @@ lex_negative_to_dash (void)
 void
 lex_reset_eof (void)
 {
-  eof = 0;
+  eof = false;
 }
 
 /* Skip a COMMENT command. */
@@ -952,7 +969,7 @@ lex_skip_comment (void)
       if (!lex_get_line ()) 
         {
           put_token = T_STOP;
-          eof = 1;
+          eof = true;
           return;
         }
       
@@ -998,7 +1015,7 @@ convert_numeric_string_to_char_string (enum string_type type)
       chars_per_byte = 2;
       break;
     default:
-      abort ();
+      NOT_REACHED ();
     }
   
   byte_cnt = ds_length (&tokstr) / chars_per_byte;
@@ -1007,7 +1024,7 @@ convert_numeric_string_to_char_string (enum string_type type)
               "multiple of %d."),
         base_name, ds_length (&tokstr), chars_per_byte);
 
-  p = ds_c_str (&tokstr);
+  p = ds_cstr (&tokstr);
   for (i = 0; i < byte_cnt; i++)
     {
       int value;
@@ -1037,7 +1054,7 @@ convert_numeric_string_to_char_string (enum string_type type)
          value = value * base + v;
        }
 
-      ds_c_str (&tokstr)[i] = (unsigned char) value;
+      ds_cstr (&tokstr)[i] = (unsigned char) value;
     }
 
   ds_truncate (&tokstr, byte_cnt);
@@ -1076,7 +1093,7 @@ parse_string (enum string_type type)
                break;
            }
 
-         ds_putc (&tokstr, *prog++);
+         ds_put_char (&tokstr, *prog++);
        }
       prog++;
 
@@ -1149,7 +1166,7 @@ finish:
     int warned = 0;
 
     for (i = 0; i < ds_length (&tokstr); i++)
-      if (ds_c_str (&tokstr)[i] == 0)
+      if (ds_cstr (&tokstr)[i] == 0)
        {
          if (!warned)
            {
@@ -1157,7 +1174,7 @@ finish:
                         "characters.  Replacing with spaces."));
              warned = 1;
            }
-         ds_c_str (&tokstr)[i] = ' ';
+         ds_cstr (&tokstr)[i] = ' ';
        }
   }
 
@@ -1191,7 +1208,7 @@ dump_token (void)
       break;
 
     case T_STRING:
-      fprintf (stderr, "STRING\t\"%s\"\n", ds_c_str (&tokstr));
+      fprintf (stderr, "STRING\t\"%s\"\n", ds_cstr (&tokstr));
       break;
 
     case T_STOP: