X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flexer.c;h=cc2f8ca8e54e35407569b3a26bcb62923846fbee;hb=65e4b2dda3939a9c35913a79b7e79c3120713a6c;hp=f676375e9409ac4478ec8bf5e5c333277a90a888;hpb=4848cff524922cc77ed21662406807471e96a68e;p=pspp diff --git a/src/lexer.c b/src/lexer.c index f676375e94..cc2f8ca8e5 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "lexer.h" @@ -29,11 +29,15 @@ #include "alloc.h" #include "command.h" #include "error.h" -#include "getline.h" +#include "getl.h" #include "magic.h" #include "settings.h" #include "str.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + /* #define DUMP_TOKENS 1 */ @@ -41,6 +45,9 @@ /* Global variables. */ +extern const char *keywords[T_N_KEYWORDS + 1]; + + /* Current token. */ int token; @@ -48,23 +55,14 @@ int token; double tokval; /* T_ID: the identifier. */ -char tokid[9]; +char tokid[LONG_NAME_LEN + 1]; /* T_ID, T_STRING: token string value. - For T_ID, this is not truncated to 8 characters as is tokid. */ + For T_ID, this is not truncated as is tokid. */ struct string tokstr; /* Static variables. */ -/* Table of keywords. */ -static const char *keywords[T_N_KEYWORDS + 1] = - { - "AND", "OR", "NOT", - "EQ", "GE", "GT", "LE", "LT", "NE", - "ALL", "BY", "TO", "WITH", - NULL, - }; - /* Pointer to next token in getl_buf. */ static char *prog; @@ -81,7 +79,6 @@ static struct string put_tokstr; static double put_tokval; static void unexpected_eof (void); -static inline int check_id (const char *id, size_t len); static void convert_numeric_string_to_char_string (int type); static int parse_string (int type); @@ -95,6 +92,7 @@ static void dump_token (void); void lex_init (void) { + ds_init (&tokstr, 64); ds_init (&put_tokstr, 64); if (!lex_get_line ()) unexpected_eof (); @@ -103,7 +101,8 @@ lex_init (void) void lex_done (void) { - ds_destroy(&put_tokstr); + ds_destroy (&put_tokstr); + ds_destroy (&tokstr); } @@ -117,8 +116,7 @@ restore_token (void) assert (put_token != 0); token = put_token; ds_replace (&tokstr, ds_c_str (&put_tokstr)); - strncpy (tokid, ds_c_str (&put_tokstr), 8); - tokid[8] = 0; + str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr)); tokval = put_tokval; put_token = 0; } @@ -355,15 +353,15 @@ lex_get (void) } /* Copy id to tokstr. */ - ds_putc (&tokstr, toupper ((unsigned char) *prog++)); + ds_putc (&tokstr, *prog++); while (CHAR_IS_IDN (*prog)) - ds_putc (&tokstr, toupper ((unsigned char) *prog++)); + ds_putc (&tokstr, *prog++); - /* Copy tokstr to tokid, truncating it to 8 characters. */ - strncpy (tokid, ds_c_str (&tokstr), 8); - tokid[8] = 0; + /* Copy tokstr to tokid, possibly truncating it.*/ + str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr)); - token = check_id (ds_c_str (&tokstr), ds_length (&tokstr)); + /* Determine token type. */ + token = lex_id_to_token (ds_c_str (&tokstr), ds_length (&tokstr)); break; default: @@ -382,17 +380,40 @@ lex_get (void) #endif } +/* Reports an error to the effect that subcommand SBC may only be + specified once. */ +void +lex_sbc_only_once (const char *sbc) +{ + msg (SE, _("Subcommand %s may only be specified once."), sbc); +} + +/* Reports an error to the effect that subcommand SBC is + missing. */ +void +lex_sbc_missing (const char *sbc) +{ + lex_error (_("missing required subcommand %s"), sbc); +} + /* Prints a syntax error message containing the current token and given message MESSAGE (if non-null). */ void lex_error (const char *message, ...) { char *token_rep; + char where[128]; token_rep = lex_token_representation (); - if (token_rep[0] == 0) - msg (SE, _("Syntax error at end of file.")); - else if (message) + if (token == T_STOP) + strcpy (where, "end of file"); + else if (token == '.') + strcpy (where, "end of command"); + else + snprintf (where, sizeof where, "`%s'", token_rep); + free (token_rep); + + if (message) { char buf[1024]; va_list args; @@ -401,12 +422,10 @@ lex_error (const char *message, ...) vsnprintf (buf, 1024, message, args); va_end (args); - msg (SE, _("Syntax error %s at `%s'."), buf, token_rep); + msg (SE, _("Syntax error %s at %s."), buf, where); } else - msg (SE, _("Syntax error at `%s'."), token_rep); - - free (token_rep); + msg (SE, _("Syntax error at %s."), where); } /* Checks that we're at end of command. @@ -480,7 +499,8 @@ lex_match (int t) } /* If the current token is the identifier S, skips it and returns - nonzero. + nonzero. The identifier may be abbreviated to its first three + letters. Otherwise, returns zero. */ int lex_match_id (const char *s) @@ -540,7 +560,7 @@ lex_force_match (int t) } else { - lex_error (_("expecting %s"), lex_token_name (t)); + lex_error (_("expecting `%s'"), lex_token_name (t)); return 0; } } @@ -600,43 +620,6 @@ lex_force_id (void) return 0; } } - -/* Comparing identifiers. */ - -/* Keywords match if one of the following is true: KW and TOK are - identical (barring differences in case), or TOK is at least 3 - characters long and those characters are identical to KW. KW_LEN - is the length of KW, TOK_LEN is the length of TOK. */ -int -lex_id_match_len (const char *kw, size_t kw_len, - const char *tok, size_t tok_len) -{ - size_t i = 0; - - assert (kw && tok); - for (;;) - { - if (i == kw_len && i == tok_len) - return 1; - else if (i == tok_len) - return i >= 3; - else if (i == kw_len) - return 0; - else if (toupper ((unsigned char) kw[i]) - != toupper ((unsigned char) tok[i])) - return 0; - - i++; - } -} - -/* Same as lex_id_match_len() minus the need to pass in the lengths. */ -int -lex_id_match (const char *kw, const char *tok) -{ - return lex_id_match_len (kw, strlen (kw), tok, strlen (tok)); -} - /* Weird token functions. */ /* Returns the first character of the next token, except that if the @@ -695,11 +678,11 @@ lex_put_back (int t) void 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); - strncpy (tokid, ds_c_str (&tokstr), 8); - tokid[8] = 0; + str_copy_trunc (tokid, sizeof tokid, ds_c_str (&tokstr)); } /* Weird line processing functions. */ @@ -770,7 +753,7 @@ lex_preprocess_line (void) int quote; /* Remove C-style comments begun by slash-star and terminated by - star-slash or newline. */ + star-slash or newline. */ quote = comment = 0; for (cp = ds_c_str (&getl_buf); *cp; ) { @@ -820,12 +803,12 @@ lex_preprocess_line (void) len--; /* Check for and remove terminal dot. */ - if (len > 0 && s[len - 1] == get_endcmd() ) + if (len > 0 && s[len - 1] == get_endcmd ()) { dot = 1; len--; } - else if (len == 0 && get_nullline() ) + else if (len == 0 && get_nulline ()) dot = 1; else dot = 0; @@ -1002,23 +985,6 @@ unexpected_eof (void) msg (FE, _("Unexpected end of file.")); } -/* Returns the proper token type, either T_ID or a reserved keyword - enum, for ID[], which must contain LEN characters. */ -static inline int -check_id (const char *id, size_t len) -{ - const char **kwp; - - if (len < 2 || len > 4) - return T_ID; - - for (kwp = keywords; *kwp; kwp++) - if (!strcmp (*kwp, id)) - return T_FIRST_KEYWORD + (kwp - keywords); - - return T_ID; -} - /* When invoked, tokstr contains a string of binary, octal, or hex digits, for values of TYPE of 0, 1, or 2, respectively. The string is converted to characters having the specified values. */