X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fprint.c;h=8cb7b1d432d92f2bac609ad108d9c6a0894ef899;hb=4255c7e5a693e09a97dc7a3cca0634bb2adaba2d;hp=e1f7f6eff67ba7b67f3a0bd444c07e69f3f29626;hpb=6bc566408707e018674d1776d835c78368b6b5a3;p=pspp diff --git a/src/print.c b/src/print.c index e1f7f6eff6..8cb7b1d432 100644 --- a/src/print.c +++ b/src/print.c @@ -17,14 +17,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* FIXME: seems like a lot of code duplication with data-list.c. */ + #include -#include +#include "error.h" #include #include "alloc.h" +#include "case.h" #include "command.h" -#include "dfm.h" +#include "dfm-write.h" #include "error.h" -#include "expr.h" +#include "expressions/public.h" #include "file-handle.h" #include "lexer.h" #include "misc.h" @@ -32,8 +35,6 @@ #include "tab.h" #include "var.h" -#include "debug-print.h" - /* Describes what to do when an output field is encountered. */ enum { @@ -69,20 +70,19 @@ enum PRT_CMD_MASK = 1, /* Command type mask. */ PRT_PRINT = 0, /* PRINT transformation identifier. */ PRT_WRITE = 1, /* WRITE transformation identifier. */ - PRT_EJECT = 002 /* Can be combined with CMD_PRINT only. */ + PRT_EJECT = 002, /* Can be combined with CMD_PRINT only. */ + PRT_BINARY = 004 /* File is binary, omit newlines. */ }; /* PRINT, PRINT EJECT, WRITE private data structure. */ struct print_trns { struct trns_header h; - struct file_handle *handle; /* Output file, NULL=listing file. */ + struct dfm_writer *writer; /* Output file, NULL=listing file. */ int options; /* PRT_* bitmapped field. */ struct prt_out_spec *spec; /* Output specifications. */ int max_width; /* Maximum line width including null. */ -#if !PAGED_STACK char *line; /* Buffer for sticking lines in. */ -#endif }; /* PRT_PRINT or PRT_WRITE. */ @@ -98,16 +98,12 @@ static struct prt_out_spec *next; static int nrec; static int internal_cmd_print (int flags); -static int print_trns_proc (struct trns_header *, struct ccase *); -static void print_trns_free (struct trns_header *); +static trns_proc_func print_trns_proc; +static trns_free_func print_trns_free; static int parse_specs (void); -static void dump_table (void); -static void append_var_spec (struct prt_out_spec *spec); +static void dump_table (const struct file_handle *); +static void append_var_spec (struct prt_out_spec *); static void alloc_line (void); - -#if DEBUGGING -void debug_print (void); -#endif /* Basic parsing. */ @@ -115,7 +111,6 @@ void debug_print (void); int cmd_print (void) { - lex_match_id ("PRINT"); return internal_cmd_print (PRT_PRINT); } @@ -123,7 +118,6 @@ cmd_print (void) int cmd_print_eject (void) { - lex_match_id ("EJECT"); return internal_cmd_print (PRT_PRINT | PRT_EJECT); } @@ -131,7 +125,6 @@ cmd_print_eject (void) int cmd_write (void) { - lex_match_id ("WRITE"); return internal_cmd_print (PRT_WRITE); } @@ -140,21 +133,17 @@ cmd_write (void) static int internal_cmd_print (int f) { - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = 0; - - /* malloc()'d transformation. */ - struct print_trns *trns; + int table = 0; /* Print table? */ + struct print_trns *trns; /* malloc()'d transformation. */ + struct file_handle *fh = NULL; /* Fill in prt to facilitate error-handling. */ prt.h.proc = print_trns_proc; prt.h.free = print_trns_free; - prt.handle = NULL; + prt.writer = NULL; prt.options = f; prt.spec = NULL; -#if !PAGED_STACK prt.line = NULL; -#endif next = NULL; nrec = 0; @@ -167,16 +156,16 @@ internal_cmd_print (int f) { lex_match ('='); - prt.handle = fh_parse_file_handle (); - if (!prt.handle) - goto lossage; + fh = fh_parse (); + if (fh == NULL) + goto error; } else if (lex_match_id ("RECORDS")) { lex_match ('='); lex_match ('('); if (!lex_force_int ()) - goto lossage; + goto error; nrec = lex_integer (); lex_get (); lex_match (')'); @@ -188,17 +177,27 @@ internal_cmd_print (int f) else { lex_error (_("expecting a valid subcommand")); - goto lossage; + goto error; } } /* Parse variables and strings. */ if (!parse_specs ()) - goto lossage; - + goto error; + + if (fh != NULL) + { + prt.writer = dfm_open_writer (fh); + if (prt.writer == NULL) + goto error; + + if (handle_get_mode (fh) == MODE_BINARY) + prt.options |= PRT_BINARY; + } + /* Output the variable table if requested. */ if (table) - dump_table (); + dump_table (fh); /* Count the maximum line width. Allocate linebuffer if applicable. */ @@ -209,13 +208,9 @@ internal_cmd_print (int f) memcpy (trns, &prt, sizeof *trns); add_transformation ((struct trns_header *) trns); -#if 0 && DEBUGGING - debug_print (); -#endif - return CMD_SUCCESS; - lossage: + error: print_trns_free ((struct trns_header *) & prt); return CMD_FAILURE; } @@ -292,7 +287,7 @@ parse_specs (void) int prev_recno = fx.recno; fx.recno++; - if (token == T_NUM) + if (lex_is_number ()) { if (!lex_force_int ()) return 0; @@ -350,11 +345,11 @@ parse_string_argument (void) { fx.spec.type = PRT_CONST; fx.spec.fc = fx.sc - 1; - fx.spec.u.c = xstrdup (ds_value (&tokstr)); + fx.spec.u.c = xstrdup (ds_c_str (&tokstr)); lex_get (); /* Parse the included column range. */ - if (token == T_NUM) + if (lex_is_number ()) { /* Width of column range in characters. */ int c_len; @@ -365,7 +360,7 @@ parse_string_argument (void) /* 1-based index of last column in range. */ int lc; - if (!lex_integer_p () || lex_integer () <= 0) + if (!lex_is_integer () || lex_integer () <= 0) { msg (SE, _("%g is not a valid column location."), tokval); goto fail; @@ -376,7 +371,7 @@ parse_string_argument (void) lex_negative_to_dash (); if (lex_match ('-')) { - if (!lex_integer_p ()) + if (!lex_is_integer ()) { msg (SE, _("Column location expected following `%d-'."), fx.spec.fc + 1); @@ -439,7 +434,7 @@ parse_variable_argument (void) if (!parse_variables (default_dict, &fx.v, &fx.nv, PV_DUPLICATE)) return 0; - if (token == T_NUM) + if (lex_is_number ()) { if (!fixed_parse_compatible ()) goto fail; @@ -558,7 +553,7 @@ fixed_parse_compatible (void) else fx.spec.u.v.f.type = FMT_F; - if (token == T_NUM) + if (lex_is_number ()) { if (!lex_force_int ()) return 0; @@ -604,7 +599,7 @@ fixed_parse_compatible (void) dividend = (fx.lc - fx.fc + 1) / fx.nv; fx.spec.u.v.f.w = dividend; - if (!check_output_specifier (&fx.spec.u.v.f)) + if (!check_output_specifier (&fx.spec.u.v.f, 1)) return 0; if ((type == ALPHA) ^ (formats[fx.spec.u.v.f.type].cat & FCAT_STRING)) { @@ -721,7 +716,7 @@ dump_fmt_list (struct fmt_list * f) static struct fmt_list * fixed_parse_fortran (void) { - struct fmt_list *head; + struct fmt_list *head = NULL; struct fmt_list *fl = NULL; lex_get (); /* skip opening parenthesis */ @@ -732,9 +727,9 @@ fixed_parse_fortran (void) else head = fl = xmalloc (sizeof *fl); - if (token == T_NUM) + if (lex_is_number ()) { - if (!lex_integer_p ()) + if (!lex_is_integer ()) goto fail; fl->count = lex_integer (); lex_get (); @@ -753,8 +748,8 @@ fixed_parse_fortran (void) } else if (lex_match ('/')) fl->f.type = FMT_NEWREC; - else if (!parse_format_specifier (&fl->f, 1) - || !check_output_specifier (&fl->f)) + else if (!parse_format_specifier (&fl->f, FMTP_ALLOW_XT) + || !check_output_specifier (&fl->f, 1)) goto fail; lex_match (','); @@ -786,10 +781,9 @@ fail: /* Prints the table produced by the TABLE subcommand to the listing file. */ static void -dump_table (void) +dump_table (const struct file_handle *fh) { struct prt_out_spec *spec; - const char *filename; struct tab_table *t; int recno; int nspec; @@ -843,25 +837,23 @@ dump_table (void) assert (0); } - filename = fh_handle_name (prt.handle); - tab_title (t, 1, (prt.handle != NULL - ? _("Writing %3d records to file %s.") - : _("Writing %3d records to the listing file.")), - recno, filename); + if (fh != NULL) + tab_title (t, 1, _("Writing %d record(s) to file %s."), + recno, handle_get_filename (fh)); + else + tab_title (t, 1, _("Writing %d record(s) to the listing file."), recno); tab_submit (t); - fh_handle_name (NULL); } /* PORTME: The number of characters in a line terminator. */ -#if __MSDOS__ +#ifdef __MSDOS__ #define LINE_END_WIDTH 2 /* \r\n */ #else #define LINE_END_WIDTH 1 /* \n */ #endif /* Calculates the maximum possible line width and allocates a buffer - big enough to contain it, if necessary (otherwise sets max_width). - (The action taken depends on compiler & OS as detected by pref.h.) */ + big enough to contain it */ static void alloc_line (void) { @@ -891,23 +883,23 @@ alloc_line (void) pot_w = i->fc + 1; break; case PRT_ERROR: + default: assert (0); - break; + abort (); } if (pot_w > w) w = pot_w; } prt.max_width = w + LINE_END_WIDTH + 1; -#if !PAGED_STACK prt.line = xmalloc (prt.max_width); -#endif } /* Transformation. */ /* Performs the transformation inside print_trns T on case C. */ static int -print_trns_proc (struct trns_header * trns, struct ccase * c) +print_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num UNUSED) { /* Transformation. */ struct print_trns *t = (struct print_trns *) trns; @@ -916,15 +908,7 @@ print_trns_proc (struct trns_header * trns, struct ccase * c) struct prt_out_spec *i; /* Line buffer. */ -#if PAGED_STACK -#if __GNUC__ && !__STRICT_ANSI__ - char buf[t->max_width]; -#else /* !__GNUC__ */ - char *buf = alloca (t->max_width); -#endif /* !__GNUC__ */ -#else /* !PAGED_STACK */ char *buf = t->line; -#endif /* !PAGED_STACK */ /* Length of the line in buf. */ int len = 0; @@ -933,15 +917,14 @@ print_trns_proc (struct trns_header * trns, struct ccase * c) if (t->options & PRT_EJECT) som_eject_page (); - /* Note that a field written to a place where a field has already - been written truncates the record. `PRINT /A B (T10,F8,T1,F8).' - only outputs B. This is an example of bug-for-bug compatibility, - in the author's opinion. */ + /* Note that a field written to a place where a field has + already been written truncates the record. `PRINT /A B + (T10,F8,T1,F8).' only outputs B. */ for (i = t->spec; i; i = i->next) switch (i->type) { case PRT_NEWLINE: - if (t->handle == NULL) + if (t->writer == NULL) { buf[len] = 0; tab_output_text (TAT_FIX | TAT_NOWRAP, buf); @@ -949,16 +932,16 @@ print_trns_proc (struct trns_header * trns, struct ccase * c) else { if ((t->options & PRT_CMD_MASK) == PRT_PRINT - || t->handle->mode != FH_MD_BINARY) + || !(t->options & PRT_BINARY)) { /* PORTME: Line ends. */ -#if __MSDOS__ +#ifdef __MSDOS__ buf[len++] = '\r'; #endif buf[len++] = '\n'; } - dfm_put_record (t->handle, buf, len); + dfm_put_record (t->writer, buf, len); } memset (buf, ' ', t->max_width); @@ -973,14 +956,7 @@ print_trns_proc (struct trns_header * trns, struct ccase * c) break; case PRT_VAR: - if (i->u.v.v->type == NUMERIC) - data_out (&buf[i->fc], &i->u.v.f, &c->data[i->u.v.v->fv]); - else - { - union value t; - t.c = c->data[i->u.v.v->fv].s; - data_out (&buf[i->fc], &i->u.v.f, &t); - } + data_out (&buf[i->fc], &i->u.v.f, case_data (c, i->u.v.v->fv)); len = i->fc + i->u.v.f.w; break; @@ -1001,9 +977,10 @@ print_trns_proc (struct trns_header * trns, struct ccase * c) static void print_trns_free (struct trns_header * t) { + struct print_trns *prt = (struct print_trns *) t; struct prt_out_spec *i, *n; - for (i = ((struct print_trns *) t)->spec; i; i = n) + for (i = prt->spec; i; i = n) { switch (i->type) { @@ -1022,9 +999,9 @@ print_trns_free (struct trns_header * t) n = i->next; free (i); } -#if !PAGED_STACK - free (((struct print_trns *) t)->line); -#endif + if (prt->writer != NULL) + dfm_close_writer (prt->writer); + free (prt->line); } /* PRINT SPACE. */ @@ -1034,47 +1011,37 @@ struct print_space_trns { struct trns_header h; - struct file_handle *handle; /* Output file, NULL=listing file. */ + struct dfm_writer *writer; /* Output data file. */ struct expression *e; /* Number of lines; NULL=1. */ } print_space_trns; -static int print_space_trns_proc (struct trns_header *, struct ccase *); -static void print_space_trns_free (struct trns_header *); +static trns_proc_func print_space_trns_proc; +static trns_free_func print_space_trns_free; int cmd_print_space (void) { struct print_space_trns *t; - struct file_handle *handle; + struct file_handle *fh; struct expression *e; + struct dfm_writer *writer; - lex_match_id ("SPACE"); if (lex_match_id ("OUTFILE")) { lex_match ('='); - if (token == T_ID) - handle = fh_get_handle_by_name (tokid); - else if (token == T_STRING) - handle = fh_get_handle_by_filename (tokid); - else - { - msg (SE, _("A file name or handle was expected in the " - "OUTFILE subcommand.")); - return CMD_FAILURE; - } - - if (!handle) + fh = fh_parse (); + if (fh == NULL) return CMD_FAILURE; lex_get (); } else - handle = NULL; + fh = NULL; if (token != '.') { - e = expr_parse (PXP_NUMERIC); + e = expr_parse (default_dict, EXPR_NUMBER); if (token != '.') { expr_free (e); @@ -1085,13 +1052,25 @@ cmd_print_space (void) else e = NULL; + if (fh != NULL) + { + writer = dfm_open_writer (fh); + if (writer == NULL) + { + expr_free (e); + return CMD_FAILURE; + } + } + else + writer = NULL; + t = xmalloc (sizeof *t); t->h.proc = print_space_trns_proc; if (e) t->h.free = print_space_trns_free; else t->h.free = NULL; - t->handle = handle; + t->writer = writer; t->e = e; add_transformation ((struct trns_header *) t); @@ -1099,30 +1078,24 @@ cmd_print_space (void) } static int -print_space_trns_proc (struct trns_header * trns, struct ccase * c) +print_space_trns_proc (struct trns_header * trns, struct ccase * c, + int case_num UNUSED) { struct print_space_trns *t = (struct print_space_trns *) trns; - int n; + double n = 1.; if (t->e) { - union value v; - - expr_evaluate (t->e, c, &v); - n = v.f; - if (n < 0) - { - msg (SW, _("The expression on PRINT SPACE evaluated to %d. It's " - "not possible to PRINT SPACE a negative number of " - "lines."), - n); - n = 1; - } + n = expr_evaluate_num (t->e, c, case_num); + if (n == SYSMIS) + msg (SW, _("The expression on PRINT SPACE evaluated to the " + "system-missing value.")); + else if (n < 0) + msg (SW, _("The expression on PRINT SPACE evaluated to %g."), n); + n = 1.; } - else - n = 1; - if (t->handle == NULL) + if (t->writer == NULL) while (n--) som_blank_line (); else @@ -1130,14 +1103,14 @@ print_space_trns_proc (struct trns_header * trns, struct ccase * c) char buf[LINE_END_WIDTH]; /* PORTME: Line ends. */ -#if __MSDOS__ +#ifdef __MSDOS__ buf[0] = '\r'; buf[1] = '\n'; #else buf[0] = '\n'; #endif while (n--) - dfm_put_record (t->handle, buf, LINE_END_WIDTH); + dfm_put_record (t->writer, buf, LINE_END_WIDTH); } return -1; @@ -1148,45 +1121,3 @@ print_space_trns_free (struct trns_header * trns) { expr_free (((struct print_space_trns *) trns)->e); } - -/* Debugging code. */ - -#if 0 && DEBUGGING -void -debug_print (void) -{ - struct prt_out_spec *p; - - if (prt.handle == NULL) - { - printf ("PRINT"); - if (prt.eject) - printf (" EJECT"); - } - else - printf ("WRITE OUTFILE=%s", handle_name (prt.handle)); - printf (" MAX_WIDTH=%d", prt.max_width); - printf (" /"); - for (p = prt.spec; p; p = p->next) - switch (p->type) - { - case PRT_ERROR: - printf (_("")); - break; - case PRT_NEWLINE: - printf ("\n /"); - break; - case PRT_CONST: - printf (" \"%s\" %d-%d", p->u.c, p->fc + 1, p->fc + strlen (p->u.c)); - break; - case PRT_VAR: - printf (" %s %d %d-%d (%s)", p->u.v.v->name, p->u.v.v->fv, p->fc + 1, - p->fc + p->u.v.v->print.w, fmt_to_string (&p->u.v.v->print)); - break; - case PRT_SPACE: - printf (" \" \" %d", p->fc + 1); - break; - } - printf (".\n"); -} -#endif /* DEBUGGING */