X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Fdata-list.c;h=f68b2e1b4d058e2f71585b5742d8ad98e1baa8dc;hb=eb06da6a334bc37108cdce9bfc7f26cfcb2003ee;hp=d43af347a701693224980ea18281eaf72d6c0e60;hpb=bd17d2af982332ee1791998361b1ac6731fe14fa;p=pspp diff --git a/src/language/data-io/data-list.c b/src/language/data-io/data-list.c index d43af347a7..f68b2e1b4d 100644 --- a/src/language/data-io/data-list.c +++ b/src/language/data-io/data-list.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013 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 @@ -22,33 +22,34 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xsize.h" -#include "xalloc.h" +#include "data/case.h" +#include "data/casereader.h" +#include "data/data-in.h" +#include "data/dataset.h" +#include "data/dictionary.h" +#include "data/format.h" +#include "data/settings.h" +#include "data/transformations.h" +#include "data/variable.h" +#include "language/command.h" +#include "language/data-io/data-parser.h" +#include "language/data-io/data-reader.h" +#include "language/data-io/file-handle.h" +#include "language/data-io/inpt-pgm.h" +#include "language/data-io/placement-parser.h" +#include "language/lexer/format-parser.h" +#include "language/lexer/lexer.h" +#include "language/lexer/variable-parser.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/i18n.h" +#include "libpspp/message.h" +#include "libpspp/misc.h" +#include "libpspp/pool.h" +#include "libpspp/str.h" + +#include "gl/xsize.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -77,7 +78,7 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) struct dfm_reader *reader; struct variable *end = NULL; struct file_handle *fh = NULL; - struct string encoding = DS_EMPTY_INITIALIZER; + char *encoding = NULL; int table; enum data_parser_type type; @@ -85,46 +86,49 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) struct pool *tmp_pool; bool ok; - dict = in_input_program () ? dataset_dict (ds) : dict_create (); + dict = (in_input_program () + ? dataset_dict (ds) + : dict_create (get_default_encoding ())); parser = data_parser_create (dict); reader = NULL; table = -1; /* Print table if nonzero, -1=undecided. */ has_type = false; - while (lex_token (lexer) != '/') + while (lex_token (lexer) != T_SLASH) { if (lex_match_id (lexer, "FILE")) { - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); fh_unref (fh); - fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE); + fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE, NULL); if (fh == NULL) goto error; } else if (lex_match_id (lexer, "ENCODING")) { - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); if (!lex_force_string (lexer)) goto error; - ds_init_string (&encoding, lex_tokstr (lexer)); + free (encoding); + encoding = ss_xstrdup (lex_tokss (lexer)); lex_get (lexer); } else if (lex_match_id (lexer, "RECORDS")) { - lex_match (lexer, '='); - lex_match (lexer, '('); + lex_match (lexer, T_EQUALS); + lex_match (lexer, T_LPAREN); if (!lex_force_int (lexer)) goto error; data_parser_set_records (parser, lex_integer (lexer)); lex_get (lexer); - lex_match (lexer, ')'); + lex_match (lexer, T_RPAREN); } else if (lex_match_id (lexer, "SKIP")) { - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); if (!lex_force_int (lexer)) goto error; data_parser_set_skip (parser, lex_integer (lexer)); @@ -134,22 +138,21 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) { if (!in_input_program ()) { - msg (SE, _("The END subcommand may only be used within " - "INPUT PROGRAM.")); + msg (SE, _("The %s subcommand may only be used within %s."), "END", "INPUT PROGRAM"); goto error; } if (end) { - msg (SE, _("The END subcommand may only be specified once.")); + msg (SE, _("The %s subcommand may only be specified once."), "END"); goto error; } - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); if (!lex_force_id (lexer)) goto error; - end = dict_lookup_var (dict, lex_tokid (lexer)); + end = dict_lookup_var (dict, lex_tokcstr (lexer)); if (!end) - end = dict_create_var_assert (dict, lex_tokid (lexer), 0); + end = dict_create_var_assert (dict, lex_tokcstr (lexer), 0); lex_get (lexer); } else if (lex_match_id (lexer, "NOTABLE")) @@ -186,31 +189,32 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) if (data_parser_get_type (parser) == DP_DELIMITED) { - if (lex_match (lexer, '(')) + if (lex_match (lexer, T_LPAREN)) { struct string delims = DS_EMPTY_INITIALIZER; - while (!lex_match (lexer, ')')) + while (!lex_match (lexer, T_RPAREN)) { int delim; if (lex_match_id (lexer, "TAB")) delim = '\t'; - else if (lex_token (lexer) == T_STRING - && ds_length (lex_tokstr (lexer)) == 1) + else if (lex_is_string (lexer) + && ss_length (lex_tokss (lexer)) == 1) { - delim = ds_first (lex_tokstr (lexer)); + delim = ss_first (lex_tokss (lexer)); lex_get (lexer); } else { + /* XXX should support multibyte UTF-8 characters */ lex_error (lexer, NULL); ds_destroy (&delims); goto error; } - ds_put_char (&delims, delim); + ds_put_byte (&delims, delim); - lex_match (lexer, ','); + lex_match (lexer, T_COMMA); } data_parser_set_empty_line_has_field (parser, true); @@ -237,13 +241,9 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) } type = data_parser_get_type (parser); - if (! ds_is_empty (&encoding)) - { - if ( NULL == fh) - msg (MW, _("Encoding should not be specified for inline data. It will be ignored.")); - else - dict_set_encoding (dict, ds_cstr (&encoding)); - } + if (encoding && NULL == fh) + msg (MW, _("Encoding should not be specified for inline data. It will be " + "ignored.")); if (fh == NULL) fh = fh_inline_file (); @@ -251,7 +251,7 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) if (type != DP_FIXED && end != NULL) { - msg (SE, _("The END subcommand may be used only with DATA LIST FIXED.")); + msg (SE, _("The %s subcommand may be used only with %s."), "END", "DATA LIST FIXED"); goto error; } @@ -278,7 +278,7 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) if (table) data_parser_output_description (parser, fh); - reader = dfm_open_reader (fh, lexer); + reader = dfm_open_reader (fh, lexer, encoding); if (reader == NULL) goto error; @@ -294,16 +294,16 @@ cmd_data_list (struct lexer *lexer, struct dataset *ds) data_parser_make_active_file (parser, ds, reader, dict); fh_unref (fh); - ds_destroy (&encoding); + free (encoding); - return CMD_SUCCESS; + return CMD_DATA_LIST; error: data_parser_destroy (parser); if (!in_input_program ()) dict_destroy (dict); fh_unref (fh); - ds_destroy (&encoding); + free (encoding); return CMD_CASCADING_FAILURE; } @@ -321,7 +321,7 @@ parse_fixed (struct lexer *lexer, struct dictionary *dict, int record = 0; int column = 1; - while (lex_token (lexer) != '.') + while (lex_token (lexer) != T_ENDCMD) { char **names; size_t name_cnt, name_idx; @@ -330,9 +330,9 @@ parse_fixed (struct lexer *lexer, struct dictionary *dict, /* Parse everything. */ if (!parse_record_placement (lexer, &record, &column) - || !parse_DATA_LIST_vars_pool (lexer, tmp_pool, + || !parse_DATA_LIST_vars_pool (lexer, dict, tmp_pool, &names, &name_cnt, PV_NONE) - || !parse_var_placements (lexer, tmp_pool, name_cnt, true, + || !parse_var_placements (lexer, tmp_pool, name_cnt, FMT_FOR_INPUT, &formats, &format_cnt)) return false; @@ -415,22 +415,41 @@ parse_free (struct lexer *lexer, struct dictionary *dict, struct pool *tmp_pool, struct data_parser *parser) { lex_get (lexer); - while (lex_token (lexer) != '.') + while (lex_token (lexer) != T_ENDCMD) { struct fmt_spec input, output; char **name; size_t name_cnt; size_t i; - if (!parse_DATA_LIST_vars_pool (lexer, tmp_pool, + if (!parse_DATA_LIST_vars_pool (lexer, dict, tmp_pool, &name, &name_cnt, PV_NONE)) return false; - if (lex_match (lexer, '(')) + if (lex_match (lexer, T_LPAREN)) { - if (!parse_format_specifier (lexer, &input) - || !fmt_check_input (&input) - || !lex_force_match (lexer, ')')) + char type[FMT_TYPE_LEN_MAX + 1]; + + if (!parse_abstract_format_specifier (lexer, type, &input.w, + &input.d)) + return NULL; + if (!fmt_from_name (type, &input.type)) + { + msg (SE, _("Unknown format type `%s'."), type); + return NULL; + } + + /* If no width was included, use the minimum width for the type. + This isn't quite right, because DATETIME by itself seems to become + DATETIME20 (see bug #30690), whereas this will become + DATETIME17. The correct behavior is not documented. */ + if (input.w == 0) + { + input.w = fmt_min_input_width (input.type); + input.d = 0; + } + + if (!fmt_check_input (&input) || !lex_force_match (lexer, T_RPAREN)) return NULL; /* As a special case, N format is treated as F format @@ -442,7 +461,7 @@ parse_free (struct lexer *lexer, struct dictionary *dict, } else { - lex_match (lexer, '*'); + lex_match (lexer, T_ASTERISK); input = fmt_for_input (FMT_F, 8, 0); output = *settings_get_format (); }