From 950da6e5aec7a0e0f282798604e708cb77a6dd5b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 23 Apr 2012 21:20:22 -0700 Subject: [PATCH] work on PRINT encoding --- src/language/data-io/placement-parser.c | 9 +- src/language/data-io/print.c | 126 +++++++++++++----------- 2 files changed, 77 insertions(+), 58 deletions(-) diff --git a/src/language/data-io/placement-parser.c b/src/language/data-io/placement-parser.c index cf9981de8f..64bdeec1e6 100644 --- a/src/language/data-io/placement-parser.c +++ b/src/language/data-io/placement-parser.c @@ -52,6 +52,13 @@ static bool fixed_parse_fortran (struct lexer *l, struct pool *, enum fmt_use, formats like those parsed by DATA LIST or PRINT. Returns true only if successful. + The formats parsed are either input or output formats, according + to USE. + + If USE is FMT_FOR_INPUT, then T, X, and / "formats" are parsed, + in addition to regular formats. If USE is FMT_FOR_OUTPUT, then + T and X "formats" are parsed but not /. + If successful, formats for VAR_CNT variables are stored in *FORMATS, and the number of formats required is stored in *FORMAT_CNT. *FORMAT_CNT may be greater than VAR_CNT because @@ -204,7 +211,7 @@ fixed_parse_fortran (struct lexer *lexer, struct pool *pool, enum fmt_use use, { new_formats = &f; new_format_cnt = 1; - if (lex_match (lexer, T_SLASH)) + if (use == FMT_FOR_INPUT && lex_match (lexer, T_SLASH)) f.type = PRS_TYPE_NEW_REC; else { diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index 71791ba595..9768c4535a 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -50,7 +50,11 @@ enum field_type { PRT_LITERAL, /* Literal string. */ - PRT_VAR /* Variable. */ + PRT_VAR, /* Variable. */ + PRT_ADVANCE, /* Skip forward N positions. */ + PRT_GOTO, /* Go to absolute position N. */ + PRT_NEWLINE, /* Output the constructed line. */ + PRT_EJECT /* Eject the output page. */ }; /* Describes how to output one field. */ @@ -59,13 +63,11 @@ struct prt_out_spec /* All fields. */ struct ll ll; /* In struct print_trns `specs' list. */ enum field_type type; /* What type of field this is. */ - int record; /* 1-based record number. */ int first_column; /* 0-based first column. */ /* PRT_VAR only. */ const struct variable *var; /* Associated variable. */ struct fmt_spec format; /* Output spec. */ - bool add_space; /* Add trailing space? */ bool sysmis_as_spaces; /* Output SYSMIS as spaces? */ /* PRT_LITERAL only. */ @@ -82,12 +84,9 @@ ll_to_prt_out_spec (struct ll *ll) struct print_trns { struct pool *pool; /* Stores related data. */ - bool eject; /* Eject page before printing? */ - bool include_prefix; /* Prefix lines with space? */ const char *encoding; /* Encoding to use for output. */ struct dfm_writer *writer; /* Output file, NULL=listing file. */ struct ll_list specs; /* List of struct prt_out_specs. */ - size_t record_cnt; /* Number of records to write. */ struct u8_line line; /* Output buffer. */ int unit; /* Unit width, in bytes. */ @@ -142,12 +141,12 @@ internal_cmd_print (struct lexer *lexer, struct dataset *ds, struct file_handle *fh = NULL; char *encoding = NULL; struct pool *tmp_pool; + int record_cnt = 0; /* Fill in prt to facilitate error-handling. */ trns = pool_create_container (struct print_trns, pool); trns->eject = eject; trns->writer = NULL; - trns->record_cnt = 0; ll_init (&trns->specs); u8_line_init (&trns->line); u8_line_register_pool (&trns->line, trns->pool); @@ -182,7 +181,7 @@ internal_cmd_print (struct lexer *lexer, struct dataset *ds, lex_match (lexer, T_LPAREN); if (!lex_force_int (lexer)) goto error; - trns->record_cnt = lex_integer (lexer); + record_cnt = lex_integer (lexer); lex_get (lexer); lex_match (lexer, T_RPAREN); } @@ -197,10 +196,6 @@ internal_cmd_print (struct lexer *lexer, struct dataset *ds, } } - /* When PRINT or PRINT EJECT writes to an external file, we - prefix each line with a space for compatibility. */ - trns->include_prefix = which_formats == PRINT && fh != NULL; - /* Parse variables and strings. */ if (!parse_specs (lexer, tmp_pool, trns, dataset_dict (ds), which_formats)) goto error; @@ -461,64 +456,88 @@ dump_table (struct print_trns *trns, const struct file_handle *fh) /* Transformation. */ -static void flush_records (struct print_trns *, int target_record, - bool *eject, int *record); +static void +print_literal (struct print_trns *trns, const struct prt_out_spec *spec) +{ + const char *s = ds_data (&spec->string); + int n = ds_length (&spec->string); + int width = u8_width (s, n, UTF8); + + u8_line_put (&trns->line, x0, x0 + width, s, n); +} + +static void +print_var (struct print_trns *trns, const struct prt_out_spec *spec, + const union value *value) +{ + int x0 = spec->first_column; + + if (!spec->sysmis_as_spaces || input->f != SYSMIS) + { + char *s = data_out (input, var_get_encoding (spec->var), &spec->format); + size_t n = strlen (s); + + x1 = ; + u8_line_put (&trns->line, x0, x1, s, n); + free (s); + } + else + { + x1 = x0 + spec->format.w; + memset (u8_line_reserve (&trns->line, x0, x1, x1 - x0), + ' ', x1 - x0); + } + + +} /* Performs the transformation inside print_trns T on case C. */ static int print_trns_proc (void *trns_, struct ccase **c, casenumber case_num UNUSED) { struct print_trns *trns = trns_; - bool eject = trns->eject; - char encoded_space = recode_byte (trns->encoding, C_ENCODING, ' '); - int record = 1; struct prt_out_spec *spec; u8_line_clear (&trns->line); - ds_put_byte (&trns->line.s, ' '); - trns->line.width = 0; - ll_for_each (spec, struct prt_out_spec, ll, &trns->specs) + switch (spec->type) + { + case PRT_LITERAL: + print_literal (trns, spec); + break; + + case PRT_VAR: + print_var (trns, spec, case_data (*c, spec->var)); + break; + + case PRT_NEWLINE: + if (trns->writer == NULL) + tab_output_text (TAB_FIX, ds_cstr (&trns->line.s)); + else + dfm_put_record (trns->writer, ds_data (&trns->line.s), + ds_length (&trns->line.s)); + u8_line_clear (&trns->line); + break; + + case PRT_EJECT: + text_item_submit (text_item_create (TEXT_ITEM_EJECT_PAGE, "")); + break; + } + { - flush_records (trns, spec->record, &eject, &record); + int x0 = spec->first_column; if (spec->type == PRT_VAR) { - const union value *input = case_data (*c, spec->var); - if (!spec->sysmis_as_spaces || input->f != SYSMIS) - { - char *s = data_out (input, var_get_encoding (spec->var), - &spec->format); - int width = u8_strwidth (s); - size_t n = strlen (s); - u8_line_put (&trns->line, spec->first_column, - spec->first_column + width, s, n); - free (s); - } - else - { - memset (u8_line-record + const union value *input = ; + int x1; - } - ds_put_byte_multiple (&trns->line, encoded_space, spec->format.w); - if (spec->add_space) - ds_put_byte (&trns->line, encoded_space); } else { - ds_put_substring (&trns->line, ds_ss (&spec->string)); - if (0 != strcmp (trns->encoding, UTF8)) - { - size_t length = ds_length (&spec->string); - char *data = ss_data (ds_tail (&trns->line, length)); - char *s = recode_string (trns->encoding, UTF8, data, length); - memcpy (data, s, length); - free (s); - } } } - flush_records (trns, trns->record_cnt + 1, &eject, &record); if (trns->writer != NULL && dfm_write_error (trns->writer)) return TRNS_ERROR; @@ -552,14 +571,7 @@ flush_records (struct print_trns *trns, int target_record, if (trns->writer == NULL) tab_output_text (TAB_FIX, &line[1]); else - { - if (!trns->include_prefix) - { - line++; - length--; - } - dfm_put_record (trns->writer, line, length); - } + dfm_put_record (trns->writer, line, length); ds_truncate (&trns->line, 1); } -- 2.30.2