#include "libpspp/str.h"
#include "libpspp/u8-istream.h"
#include "output/journal.h"
-#include "output/text-item.h"
+#include "output/output-item.h"
#include "gl/c-ctype.h"
#include "gl/minmax.h"
lex_reader_set_file_name (struct lex_reader *reader, const char *file_name)
{
free (reader->file_name);
- reader->file_name = file_name != NULL ? xstrdup (file_name) : NULL;
+ reader->file_name = xstrdup_if_nonnull (file_name);
}
\f
/* Creates and returns a new lexer. */
/* Prints a syntax error message saying that OPTION0 or one of the other
strings following it, up to the first NULL, is expected. */
void
-lex_error_expecting (struct lexer *lexer, const char *option0, ...)
+(lex_error_expecting) (struct lexer *lexer, const char *option0, ...)
{
enum { MAX_OPTIONS = 8 };
const char *options[MAX_OPTIONS + 1];
/* Returns true if the current token is a number. */
bool
-lex_is_number (struct lexer *lexer)
+lex_is_number (const struct lexer *lexer)
{
return lex_next_is_number (lexer, 0);
}
/* Returns true if the current token is a string. */
bool
-lex_is_string (struct lexer *lexer)
+lex_is_string (const struct lexer *lexer)
{
return lex_next_is_string (lexer, 0);
}
/* Returns the value of the current token, which must be a
floating point number. */
double
-lex_number (struct lexer *lexer)
+lex_number (const struct lexer *lexer)
{
return lex_next_number (lexer, 0);
}
/* Returns true iff the current token is an integer. */
bool
-lex_is_integer (struct lexer *lexer)
+lex_is_integer (const struct lexer *lexer)
{
return lex_next_is_integer (lexer, 0);
}
/* Returns the value of the current token, which must be an
integer. */
long
-lex_integer (struct lexer *lexer)
+lex_integer (const struct lexer *lexer)
{
return lex_next_integer (lexer, 0);
}
/* Returns true if the token N ahead of the current token is a number. */
bool
-lex_next_is_number (struct lexer *lexer, int n)
+lex_next_is_number (const struct lexer *lexer, int n)
{
enum token_type next_token = lex_next_token (lexer, n);
return next_token == T_POS_NUM || next_token == T_NEG_NUM;
/* Returns true if the token N ahead of the current token is a string. */
bool
-lex_next_is_string (struct lexer *lexer, int n)
+lex_next_is_string (const struct lexer *lexer, int n)
{
return lex_next_token (lexer, n) == T_STRING;
}
/* Returns the value of the token N ahead of the current token, which must be a
floating point number. */
double
-lex_next_number (struct lexer *lexer, int n)
+lex_next_number (const struct lexer *lexer, int n)
{
assert (lex_next_is_number (lexer, n));
return lex_next_tokval (lexer, n);
/* Returns true if the token N ahead of the current token is an integer. */
bool
-lex_next_is_integer (struct lexer *lexer, int n)
+lex_next_is_integer (const struct lexer *lexer, int n)
{
double value;
/* Returns the value of the token N ahead of the current token, which must be
an integer. */
long
-lex_next_integer (struct lexer *lexer, int n)
+lex_next_integer (const struct lexer *lexer, int n)
{
assert (lex_next_is_integer (lexer, n));
return lex_next_tokval (lexer, n);
return true;
else
{
- lex_error_expecting (lexer, identifier, NULL_SENTINEL);
+ lex_error_expecting (lexer, identifier);
return false;
}
}
if (type_string)
{
char *s = xasprintf ("`%s'", type_string);
- lex_error_expecting (lexer, s, NULL_SENTINEL);
+ lex_error_expecting (lexer, s);
free (s);
}
else
- lex_error_expecting (lexer, token_type_to_name (type), NULL_SENTINEL);
+ lex_error_expecting (lexer, token_type_to_name (type));
return false;
}
int mblen;
assert (out_size >= 16);
- out_maxlen = out_size - (in.length >= out_size ? 3 : 0) - 1;
+ out_maxlen = out_size - 1;
+ if (in.length > out_maxlen - 3)
+ out_maxlen -= 3;
+
for (out_len = 0; out_len < in.length; out_len += mblen)
{
if (in.string[out_len] == '\n'
mblen = u8_mblen (CHAR_CAST (const uint8_t *, in.string + out_len),
in.length - out_len);
+
+ if (mblen < 0)
+ break;
+
if (out_len + mblen > out_maxlen)
break;
}
{
const struct lex_token *token;
struct string s;
- struct msg m;
ds_init_empty (&s);
}
ds_put_byte (&s, '.');
- m.category = MSG_C_SYNTAX;
- m.severity = MSG_S_ERROR;
- m.file_name = src->reader->file_name;
- m.first_line = lex_source_get_first_line_number (src, n0);
- m.last_line = lex_source_get_last_line_number (src, n1);
- m.first_column = lex_source_get_first_column (src, n0);
- m.last_column = lex_source_get_last_column (src, n1);
- m.text = ds_steal_cstr (&s);
+ struct msg m = {
+ .category = MSG_C_SYNTAX,
+ .severity = MSG_S_ERROR,
+ .file_name = src->reader->file_name,
+ .first_line = lex_source_get_first_line_number (src, n0),
+ .last_line = lex_source_get_last_line_number (src, n1),
+ .first_column = lex_source_get_first_column (src, n0),
+ .last_column = lex_source_get_last_column (src, n1),
+ .text = ds_steal_cstr (&s),
+ };
msg_emit (&m);
}
if (copy_len > 0 && line[copy_len - 1] == '\r')
copy_len--;
- /* Make a copy of the line with \n end-of-line and null terminator. */
- char *syntax = xmalloc (copy_len + 2);
- memcpy (syntax, line, copy_len);
- syntax[copy_len] = '\n';
- syntax[copy_len + 1] = '\0';
-
- text_item_submit (text_item_create_nocopy (TEXT_ITEM_SYNTAX, syntax));
+ /* Submit the line as syntax. */
+ output_item_submit (text_item_create_nocopy (TEXT_ITEM_SYNTAX,
+ xmemdup0 (line, copy_len),
+ NULL));
src->journal_pos += line_len;
}
r->reader.syntax = syntax;
r->reader.error = error;
r->reader.file_name = xstrdup (file_name);
- r->reader.encoding = encoding ? xstrdup (encoding) : NULL;
+ r->reader.encoding = xstrdup_if_nonnull (encoding);
r->reader.line_number = 1;
r->istream = istream;
r = xmalloc (sizeof *r);
lex_reader_init (&r->reader, &lex_string_reader_class);
r->reader.syntax = LEX_SYNTAX_AUTO;
- r->reader.encoding = encoding ? xstrdup (encoding) : NULL;
+ r->reader.encoding = xstrdup_if_nonnull (encoding);
r->s = s;
r->offset = 0;