X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fpspp-dump-sav.c;h=307add8db3b56b339afe79f3d0e7d732c6c21236;hb=41f83a8f1c88489e4fc458fb7661430ff91d8a61;hp=50173b95de6cb1369f984eec94a5363f74c892b1;hpb=038c2e5f1e1a742d7c7731e33df4e9fe63cb5b72;p=pspp diff --git a/utilities/pspp-dump-sav.c b/utilities/pspp-dump-sav.c index 50173b95de..307add8db3 100644 --- a/utilities/pspp-dump-sav.c +++ b/utilities/pspp-dump-sav.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 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 @@ -18,11 +18,14 @@ #include #include +#include #include +#include #include #include #include "data/val-type.h" +#include "libpspp/cast.h" #include "libpspp/compiler.h" #include "libpspp/float-format.h" #include "libpspp/integer-format.h" @@ -31,6 +34,7 @@ #include "gl/error.h" #include "gl/minmax.h" #include "gl/progname.h" +#include "gl/version-etc.h" #include "gl/xalloc.h" #define ID_MAX_LEN 64 @@ -61,6 +65,8 @@ static void read_machine_integer_info (struct sfm_reader *, size_t size, size_t count); static void read_machine_float_info (struct sfm_reader *, size_t size, size_t count); +static void read_extra_product_info (struct sfm_reader *, + size_t size, size_t count); static void read_mrsets (struct sfm_reader *, size_t size, size_t count); static void read_display_parameters (struct sfm_reader *, size_t size, size_t count); @@ -79,7 +85,7 @@ static void read_long_string_value_labels (struct sfm_reader *r, size_t size, size_t count); static void read_unknown_extension (struct sfm_reader *, size_t size, size_t count); -static void read_compressed_data (struct sfm_reader *); +static void read_compressed_data (struct sfm_reader *, int max_cases); static struct text_record *open_text_record ( struct sfm_reader *, size_t size); @@ -90,8 +96,9 @@ static char *text_tokenize (struct text_record *, int delimiter); static bool text_match (struct text_record *text, int c); static const char *text_parse_counted_string (struct text_record *); static size_t text_pos (const struct text_record *); +static const char *text_get_all (const struct text_record *); -static void usage (int exit_code); +static void usage (void); static void sys_warn (struct sfm_reader *, const char *, ...) PRINTF_FORMAT (2, 3); static void sys_error (struct sfm_reader *, const char *, ...) @@ -107,17 +114,58 @@ static void read_string (struct sfm_reader *, char *, size_t); static void skip_bytes (struct sfm_reader *, size_t); static void trim_spaces (char *); +static void print_string (const char *s, size_t len); + int main (int argc, char *argv[]) { + int max_cases = 0; struct sfm_reader r; int i; set_program_name (argv[0]); - if (argc < 2) - usage (EXIT_FAILURE); - for (i = 1; i < argc; i++) + for (;;) + { + static const struct option long_options[] = + { + { "data", optional_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 }, + }; + + int c; + + c = getopt_long (argc, argv, "d::hv", long_options, NULL); + if (c == -1) + break; + + switch (c) + { + case 'd': + max_cases = optarg ? atoi (optarg) : INT_MAX; + break; + + case 'v': + version_etc (stdout, "pspp-dump-sav", PACKAGE_NAME, PACKAGE_VERSION, + "Ben Pfaff", "John Darrington", NULL_SENTINEL); + exit (EXIT_SUCCESS); + + case 'h': + usage (); + exit (EXIT_SUCCESS); + + default: + exit (EXIT_FAILURE); + } + } + + if (optind == argc) + error (1, 0, "at least one non-option argument is required; " + "use --help for help"); + + for (i = optind; i < argc; i++) { int rec_type; @@ -132,7 +180,7 @@ main (int argc, char *argv[]) r.var_widths = 0; r.compressed = false; - if (argc > 2) + if (argc - optind > 1) printf ("Reading \"%s\":\n", r.file_name); read_header (&r); @@ -168,8 +216,8 @@ main (int argc, char *argv[]) (long long int) ftello (r.file), (long long int) ftello (r.file) + 4); - if (r.compressed) - read_compressed_data (&r); + if (r.compressed && max_cases > 0) + read_compressed_data (&r, max_cases); fclose (r.file); } @@ -184,7 +232,6 @@ read_header (struct sfm_reader *r) char eye_catcher[61]; uint8_t raw_layout_code[4]; int32_t layout_code; - int32_t nominal_case_size; int32_t compressed; int32_t weight_index; int32_t ncases; @@ -211,7 +258,7 @@ read_header (struct sfm_reader *r) layout_code = integer_get (r->integer_format, raw_layout_code, sizeof raw_layout_code); - nominal_case_size = read_int (r); + read_int (r); /* Nominal case size (not actually useful). */ compressed = read_int (r); weight_index = read_int (r); ncases = read_int (r); @@ -416,7 +463,7 @@ print_untyped_value (struct sfm_reader *r, char raw_value[8]) double value; value = float_get_double (r->float_format, raw_value); - for (n_printable = 0; n_printable < sizeof raw_value; n_printable++) + for (n_printable = 0; n_printable < 8; n_printable++) if (!isprint (raw_value[n_printable])) break; @@ -532,6 +579,10 @@ read_extension_record (struct sfm_reader *r) read_mrsets (r, size, count); return; + case 10: + read_extra_product_info (r, size, count); + return; + case 11: read_display_parameters (r, size, count); return; @@ -621,20 +672,34 @@ read_machine_float_info (struct sfm_reader *r, size_t size, size_t count) sys_error (r, "Bad size (%zu) or count (%zu) on extension 4.", size, count); - printf ("\tsysmis: %g\n", sysmis); + printf ("\tsysmis: %g (%a)\n", sysmis, sysmis); if (sysmis != SYSMIS) - sys_warn (r, "File specifies unexpected value %g as %s.", - sysmis, "SYSMIS"); + sys_warn (r, "File specifies unexpected value %g (%a) as %s.", + sysmis, sysmis, "SYSMIS"); - printf ("\thighest: %g\n", highest); + printf ("\thighest: %g (%a)\n", highest, highest); if (highest != HIGHEST) - sys_warn (r, "File specifies unexpected value %g as %s.", - highest, "HIGHEST"); + sys_warn (r, "File specifies unexpected value %g (%a) as %s.", + highest, highest, "HIGHEST"); - printf ("\tlowest: %g\n", lowest); - if (lowest != LOWEST) - sys_warn (r, "File specifies unexpected value %g as %s.", - lowest, "LOWEST"); + printf ("\tlowest: %g (%a)\n", lowest, lowest); + if (lowest != LOWEST && lowest != SYSMIS) + sys_warn (r, "File specifies unexpected value %g (%a) as %s.", + lowest, lowest, "LOWEST"); +} + +static void +read_extra_product_info (struct sfm_reader *r, + size_t size, size_t count) +{ + struct text_record *text; + const char *s; + + printf ("%08llx: extra product info\n", (long long int) ftello (r->file)); + text = open_text_record (r, size * count); + s = text_get_all (text); + print_string (s, strlen (s)); + close_text_record (text); } /* Read record type 7, subtype 7. */ @@ -1027,20 +1092,7 @@ read_unknown_extension (struct sfm_reader *r, size_t size, size_t count) { buffer = xmalloc (count); read_bytes (r, buffer, count); - if (memchr (buffer, 0, count) == 0) - for (i = 0; i < count; i++) - { - unsigned char c = buffer[i]; - - if (c == '\\') - printf ("\\\\"); - else if (c == '\n' || isprint (c)) - putchar (c); - else - printf ("\\%02x", c); - } - else - hex_dump (0, buffer, count); + print_string (CHAR_CAST (char *, buffer), count); free (buffer); } } @@ -1062,7 +1114,7 @@ read_variable_attributes (struct sfm_reader *r, size_t size, size_t count) } static void -read_compressed_data (struct sfm_reader *r) +read_compressed_data (struct sfm_reader *r, int max_cases) { enum { N_OPCODES = 8 }; uint8_t opcodes[N_OPCODES]; @@ -1077,7 +1129,7 @@ read_compressed_data (struct sfm_reader *r) opcode_idx = N_OPCODES; opcode_ofs = 0; case_num = 0; - for (case_num = 0; ; case_num++) + for (case_num = 0; case_num < max_cases; case_num++) { printf ("%08llx: case %d's uncompressible data begins\n", (long long int) ftello (r->file), case_num); @@ -1288,14 +1340,26 @@ text_pos (const struct text_record *text) { return text->pos; } + +static const char * +text_get_all (const struct text_record *text) +{ + return text->buffer; +} static void -usage (int exit_code) +usage (void) { - printf ("usage: %s SYSFILE...\n" - "where each SYSFILE is the name of a system file\n", - program_name); - exit (exit_code); + printf ("\ +%s, a utility for dissecting system files.\n\ +Usage: %s [OPTION]... SYSFILE...\n\ +where each SYSFILE is the name of a system file.\n\ +\n\ +Options:\n\ + --data[=MAXCASES] print (up to MAXCASES cases of) compressed data\n\ + --help display this help and exit\n\ + --version output version information and exit\n", + program_name, program_name); } /* Displays a corruption message. */ @@ -1434,3 +1498,27 @@ trim_spaces (char *s) end--; *end = '\0'; } + +static void +print_string (const char *s, size_t len) +{ + if (memchr (s, 0, len) == 0) + { + size_t i; + + for (i = 0; i < len; i++) + { + unsigned char c = s[i]; + + if (c == '\\') + printf ("\\\\"); + else if (c == '\n' || isprint (c)) + putchar (c); + else + printf ("\\%02x", c); + } + putchar ('\n'); + } + else + hex_dump (0, s, len); +}